X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=compiler%2Frustc_hir_typeck%2Fsrc%2Ffn_ctxt%2Fsuggestions.rs;fp=compiler%2Frustc_hir_typeck%2Fsrc%2Ffn_ctxt%2Fsuggestions.rs;h=c4add4dbdfb2fb29038f464931cfe04bbabe71f1;hb=49aad94119d25b430197b727bebdda4d621b54f6;hp=5fda4e191c2a003f447f0016f6659295de62a002;hpb=0a29b90ccc7c1e14248b21f179ce57ed92135a6a;p=rustc.git diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 5fda4e191c..c4add4dbdf 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1,6 +1,6 @@ use super::FnCtxt; -use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel}; +use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel, SuggestBoxing}; use crate::fluent_generated as fluent; use crate::method::probe::{IsSuggestion, Mode, ProbeScope}; use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX}; @@ -9,7 +9,8 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ - Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate, + AsyncGeneratorKind, Expr, ExprKind, GeneratorKind, GenericBound, HirId, Node, Path, QPath, + Stmt, StmtKind, TyKind, WherePredicate, }; use rustc_hir_analysis::astconv::AstConv; use rustc_infer::traits::{self, StatementAsExpression}; @@ -274,13 +275,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, ) -> bool { let expr = expr.peel_blocks(); - if let Some((sp, msg, suggestion, applicability, verbose, annotation)) = - self.check_ref(expr, found, expected) + if let Some((suggestion, msg, applicability, verbose, annotation)) = + self.suggest_deref_or_ref(expr, found, expected) { if verbose { - err.span_suggestion_verbose(sp, &msg, suggestion, applicability); + err.multipart_suggestion_verbose(msg, suggestion, applicability); } else { - err.span_suggestion(sp, &msg, suggestion, applicability); + err.multipart_suggestion(msg, suggestion, applicability); } if annotation { let suggest_annotation = match expr.peel_drop_temps().kind { @@ -342,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(sp, format!("{descr} `{name}` defined here")); } return true; - } else if self.check_for_cast(err, expr, found, expected, expected_ty_expr) { + } else if self.suggest_cast(err, expr, found, expected, expected_ty_expr) { return true; } else { let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id); @@ -438,33 +439,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn suggest_boxing_when_appropriate( &self, err: &mut Diagnostic, - expr: &hir::Expr<'_>, + span: Span, + hir_id: HirId, expected: Ty<'tcx>, found: Ty<'tcx>, ) -> bool { - if self.tcx.hir().is_inside_const_context(expr.hir_id) { - // Do not suggest `Box::new` in const context. - return false; - } - if !expected.is_box() || found.is_box() { + // Do not suggest `Box::new` in const context. + if self.tcx.hir().is_inside_const_context(hir_id) || !expected.is_box() || found.is_box() { return false; } - let boxed_found = self.tcx.mk_box(found); - if self.can_coerce(boxed_found, expected) { - err.multipart_suggestion( - "store this in the heap by calling `Box::new`", - vec![ - (expr.span.shrink_to_lo(), "Box::new(".to_string()), - (expr.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ); - err.note( - "for more on the distinction between the stack and the heap, read \ - https://doc.rust-lang.org/book/ch15-01-box.html, \ - https://doc.rust-lang.org/rust-by-example/std/box.html, and \ - https://doc.rust-lang.org/std/boxed/index.html", - ); + if self.can_coerce(self.tcx.mk_box(found), expected) { + let suggest_boxing = match found.kind() { + ty::Tuple(tuple) if tuple.is_empty() => { + SuggestBoxing::Unit { start: span.shrink_to_lo(), end: span } + } + ty::Generator(def_id, ..) + if matches!( + self.tcx.generator_kind(def_id), + Some(GeneratorKind::Async(AsyncGeneratorKind::Closure)) + ) => + { + SuggestBoxing::AsyncBody + } + _ => SuggestBoxing::Other { start: span.shrink_to_lo(), end: span.shrink_to_hi() }, + }; + err.subdiagnostic(suggest_boxing); + true } else { false @@ -794,7 +794,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; }; - // get all where BoundPredicates here, because they are used in to cases below + // get all where BoundPredicates here, because they are used in two cases below let where_predicates = predicates .iter() .filter_map(|p| match p { @@ -1096,10 +1096,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx, self.misc(expr.span), self.param_env, - ty::Binder::dummy(self.tcx.mk_trait_ref( + ty::TraitRef::new(self.tcx, into_def_id, [expr_ty, expected_ty] - )), + ), )) { let sugg = if expr.precedence().order() >= PREC_POSTFIX { @@ -1252,7 +1252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { node: rustc_ast::LitKind::Int(lit, rustc_ast::LitIntType::Unsuffixed), span, }) => { - let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) else { return false; }; + let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(*span) else { return false; }; if !(snippet.starts_with("0x") || snippet.starts_with("0X")) { return false; } @@ -1311,7 +1311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We have satisfied all requirements to provide a suggestion. Emit it. err.span_suggestion( - span, + *span, format!("if you meant to create a null pointer, use `{null_path_str}()`"), null_path_str + "()", Applicability::MachineApplicable, @@ -1384,7 +1384,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let item_ty = self.tcx.type_of(item.def_id).subst_identity(); // FIXME(compiler-errors): This check is *so* rudimentary - if item_ty.needs_subst() { + if item_ty.has_param() { return false; } if self.can_coerce(item_ty, expected_ty) { @@ -1438,7 +1438,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..))) // Check that we're in fact trying to clone into the expected type && self.can_coerce(*pointee_ty, expected_ty) - && let trait_ref = ty::Binder::dummy(self.tcx.mk_trait_ref(clone_trait_did, [expected_ty])) + && let trait_ref = ty::TraitRef::new(self.tcx, clone_trait_did, [expected_ty]) // And the expected type doesn't implement `Clone` && !self.predicate_must_hold_considering_regions(&traits::Obligation::new( self.tcx, @@ -1449,7 +1449,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { diag.span_note( callee_expr.span, - &format!( + format!( "`{expected_ty}` does not implement `Clone`, so `{found_ty}` was cloned instead" ), );