diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_hir_typeck/src/demand.rs (renamed from compiler/rustc_typeck/src/check/demand.rs) | 135 |
1 files changed, 87 insertions, 48 deletions
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index e1d55ff82..16febfc46 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1,21 +1,20 @@ -use crate::check::FnCtxt; -use rustc_infer::infer::InferOk; -use rustc_middle::middle::stability::EvalResult; -use rustc_trait_selection::infer::InferCtxtExt as _; -use rustc_trait_selection::traits::ObligationCause; - +use crate::FnCtxt; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_hir::{is_range_literal, Node}; +use rustc_infer::infer::InferOk; use rustc_middle::lint::in_external_macro; +use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{BytePos, Span}; +use rustc_trait_selection::infer::InferCtxtExt as _; +use rustc_trait_selection::traits::ObligationCause; use super::method::probe; @@ -32,17 +31,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error: Option<TypeError<'tcx>>, ) { self.annotate_expected_due_to_let_ty(err, expr, error); - self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr); - self.suggest_compatible_variants(err, expr, expected, expr_ty); - self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty); - if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) { - return; - } - self.suggest_no_capture_closure(err, expected, expr_ty); - self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty); - self.suggest_missing_parentheses(err, expr); - self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected); - self.suggest_copied_or_cloned(err, expr, expr_ty, expected); + + // Use `||` to give these suggestions a precedence + let _ = self.suggest_missing_parentheses(err, expr) + || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr) + || self.suggest_compatible_variants(err, expr, expected, expr_ty) + || self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty) + || self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) + || self.suggest_no_capture_closure(err, expected, expr_ty) + || self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty) + || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected) + || self.suggest_copied_or_cloned(err, expr, expr_ty, expected) + || self.suggest_into(err, expr, expr_ty, expected); + self.note_type_is_not_clone(err, expected, expr_ty, expr); self.note_need_for_fn_pointer(err, expected, expr_ty); self.note_internal_mutation_in_method(err, expr, expected, expr_ty); @@ -77,7 +78,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.register_predicates(obligations); None } - Err(e) => Some(self.report_mismatched_types(&cause, expected, actual, e)), + Err(e) => Some(self.err_ctxt().report_mismatched_types(&cause, expected, actual, e)), } } @@ -107,7 +108,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.register_predicates(obligations); None } - Err(e) => Some(self.report_mismatched_types(cause, expected, actual, e)), + Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)), } } @@ -151,7 +152,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expr = expr.peel_drop_temps(); let cause = self.misc(expr.span); let expr_ty = self.resolve_vars_with_obligations(checked_ty); - let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e.clone()); + let mut err = self.err_ctxt().report_mismatched_types(&cause, expected, expr_ty, e.clone()); let is_insufficiently_polymorphic = matches!(e, TypeError::RegionsInsufficientlyPolymorphic(..)); @@ -286,7 +287,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'_>, expected: Ty<'tcx>, expr_ty: Ty<'tcx>, - ) { + ) -> bool { if let ty::Adt(expected_adt, substs) = expected.kind() { if let hir::ExprKind::Field(base, ident) = expr.kind { let base_ty = self.typeck_results.borrow().expr_ty(base); @@ -299,7 +300,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "", Applicability::MaybeIncorrect, ); - return + return true; } } @@ -338,7 +339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if self.tcx.is_diagnostic_item(sym::Option, expected_adt.did()) { vec!["None", "Some(())"] } else { - return; + return false; }; if let Some(indent) = self.tcx.sess.source_map().indentation_before(span.shrink_to_lo()) @@ -358,7 +359,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); } - return; + return true; } } } @@ -375,7 +376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let field_is_local = sole_field.did.is_local(); let field_is_accessible = - sole_field.vis.is_accessible_from(expr.hir_id.owner, self.tcx) + sole_field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx) // Skip suggestions for unstable public fields (for example `Pin::pointer`) && matches!(self.tcx.eval_stability(sole_field.did, None, expr.span, None), EvalResult::Allow | EvalResult::Unmarked); @@ -417,6 +418,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::def::CtorKind::Const => unreachable!(), }; + // Suggest constructor as deep into the block tree as possible. + // This fixes https://github.com/rust-lang/rust/issues/101065, + // and also just helps make the most minimal suggestions. + let mut expr = expr; + while let hir::ExprKind::Block(block, _) = &expr.kind + && let Some(expr_) = &block.expr + { + expr = expr_ + } + vec![ (expr.span.shrink_to_lo(), format!("{prefix}{variant}{open}")), (expr.span.shrink_to_hi(), close.to_owned()), @@ -435,6 +446,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { suggestions_for(&**variant, *ctor_kind, *field_name), Applicability::MaybeIncorrect, ); + return true; } _ => { // More than one matching variant. @@ -450,9 +462,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), Applicability::MaybeIncorrect, ); + return true; } } } + + false } fn suggest_non_zero_new_unwrap( @@ -461,19 +476,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'_>, expected: Ty<'tcx>, expr_ty: Ty<'tcx>, - ) { + ) -> bool { let tcx = self.tcx; let (adt, unwrap) = match expected.kind() { // In case Option<NonZero*> is wanted, but * is provided, suggest calling new ty::Adt(adt, substs) if tcx.is_diagnostic_item(sym::Option, adt.did()) => { // Unwrap option - let ty::Adt(adt, _) = substs.type_at(0).kind() else { return }; + let ty::Adt(adt, _) = substs.type_at(0).kind() else { return false; }; (adt, "") } // In case NonZero* is wanted, but * is provided also add `.unwrap()` to satisfy types ty::Adt(adt, _) => (adt, ".unwrap()"), - _ => return, + _ => return false, }; let map = [ @@ -492,7 +507,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some((s, _)) = map .iter() .find(|&&(s, t)| self.tcx.is_diagnostic_item(s, adt.did()) && self.can_coerce(expr_ty, t)) - else { return }; + else { return false; }; let path = self.tcx.def_path_str(adt.non_enum_variant().def_id); @@ -504,6 +519,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ], Applicability::MaybeIncorrect, ); + + true } pub fn get_conversion_methods( @@ -513,24 +530,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { checked_ty: Ty<'tcx>, hir_id: hir::HirId, ) -> Vec<AssocItem> { - let mut methods = - self.probe_for_return_type(span, probe::Mode::MethodCall, expected, checked_ty, hir_id); - methods.retain(|m| { - self.has_only_self_parameter(m) - && self - .tcx - // This special internal attribute is used to permit - // "identity-like" conversion methods to be suggested here. - // - // FIXME (#46459 and #46460): ideally - // `std::convert::Into::into` and `std::borrow:ToOwned` would - // also be `#[rustc_conversion_suggestion]`, if not for - // method-probing false-positives and -negatives (respectively). - // - // FIXME? Other potential candidate methods: `as_ref` and - // `as_mut`? - .has_attr(m.def_id, sym::rustc_conversion_suggestion) - }); + let methods = self.probe_for_return_type( + span, + probe::Mode::MethodCall, + expected, + checked_ty, + hir_id, + |m| { + self.has_only_self_parameter(m) + && self + .tcx + // This special internal attribute is used to permit + // "identity-like" conversion methods to be suggested here. + // + // FIXME (#46459 and #46460): ideally + // `std::convert::Into::into` and `std::borrow:ToOwned` would + // also be `#[rustc_conversion_suggestion]`, if not for + // method-probing false-positives and -negatives (respectively). + // + // FIXME? Other potential candidate methods: `as_ref` and + // `as_mut`? + .has_attr(m.def_id, sym::rustc_conversion_suggestion) + }, + ); methods } @@ -697,7 +719,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'tcx>, checked_ty: Ty<'tcx>, expected: Ty<'tcx>, - ) -> Option<(Span, String, String, Applicability, bool /* verbose */)> { + ) -> Option<( + Span, + String, + String, + Applicability, + bool, /* verbose */ + bool, /* suggest `&` or `&mut` type annotation */ + )> { let sess = self.sess(); let sp = expr.span; @@ -729,6 +758,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, true, + false, )); } } @@ -743,6 +773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "b".to_string(), Applicability::MachineApplicable, true, + false, )); } } @@ -800,6 +831,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sugg.2, Applicability::MachineApplicable, false, + false, )); } @@ -827,6 +859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("{prefix}&mut {sugg_expr}"), Applicability::MachineApplicable, false, + false, ), hir::Mutability::Not => ( sp, @@ -834,6 +867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("{prefix}&{sugg_expr}"), Applicability::MachineApplicable, false, + false, ), }); } @@ -863,6 +897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, true, + true )); } return None; @@ -876,6 +911,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, true, + true, )); } } @@ -942,6 +978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { src, applicability, true, + false, )); } } @@ -982,6 +1019,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable }, true, + false, )); } @@ -1033,6 +1071,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { suggestion, Applicability::MachineApplicable, true, + false, )); } } |