@@ -2727,6 +2727,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
27272727
27282728 let tcx = self . tcx ;
27292729 let predicate = predicate. upcast ( tcx) ;
2730+ let suggest_remove_deref = |err : & mut Diag < ' _ , G > , expr : & hir:: Expr < ' _ > | {
2731+ if let Some ( pred) = predicate. as_trait_clause ( )
2732+ && tcx. is_lang_item ( pred. def_id ( ) , LangItem :: Sized )
2733+ && let hir:: ExprKind :: Unary ( hir:: UnOp :: Deref , inner) = expr. kind
2734+ {
2735+ err. span_suggestion_verbose (
2736+ expr. span . until ( inner. span ) ,
2737+ "references are always `Sized`, even if they point to unsized data; consider \
2738+ not dereferencing the expression",
2739+ String :: new ( ) ,
2740+ Applicability :: MaybeIncorrect ,
2741+ ) ;
2742+ }
2743+ } ;
27302744 match * cause_code {
27312745 ObligationCauseCode :: ExprAssignable
27322746 | ObligationCauseCode :: MatchExpressionArm { .. }
@@ -2773,6 +2787,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
27732787 | ObligationCauseCode :: WhereClauseInExpr ( item_def_id, span, ..)
27742788 if !span. is_dummy ( ) =>
27752789 {
2790+ if let ObligationCauseCode :: WhereClauseInExpr ( _, _, hir_id, pos) = & cause_code {
2791+ if let Node :: Expr ( expr) = tcx. parent_hir_node ( * hir_id)
2792+ && let hir:: ExprKind :: Call ( _, args) = expr. kind
2793+ && let Some ( expr) = args. get ( * pos)
2794+ {
2795+ suggest_remove_deref ( err, & expr) ;
2796+ } else if let Node :: Expr ( expr) = self . tcx . hir_node ( * hir_id)
2797+ && let hir:: ExprKind :: MethodCall ( _, _, args, _) = expr. kind
2798+ && let Some ( expr) = args. get ( * pos)
2799+ {
2800+ suggest_remove_deref ( err, & expr) ;
2801+ }
2802+ }
27762803 let item_name = tcx. def_path_str ( item_def_id) ;
27772804 let short_item_name = with_forced_trimmed_paths ! ( tcx. def_path_str( item_def_id) ) ;
27782805 let mut multispan = MultiSpan :: from ( span) ;
@@ -2970,6 +2997,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
29702997 ) ) ;
29712998 err. downgrade_to_delayed_bug ( ) ;
29722999 }
3000+ let mut local = true ;
29733001 match tcx. parent_hir_node ( hir_id) {
29743002 Node :: LetStmt ( hir:: LetStmt { ty : Some ( ty) , .. } ) => {
29753003 err. span_suggestion_verbose (
@@ -2978,7 +3006,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
29783006 "&" ,
29793007 Applicability :: MachineApplicable ,
29803008 ) ;
2981- err. note ( "all local variables must have a statically known size" ) ;
29823009 }
29833010 Node :: LetStmt ( hir:: LetStmt {
29843011 init : Some ( hir:: Expr { kind : hir:: ExprKind :: Index ( ..) , span, .. } ) ,
@@ -2993,7 +3020,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
29933020 "&" ,
29943021 Applicability :: MachineApplicable ,
29953022 ) ;
2996- err. note ( "all local variables must have a statically known size" ) ;
3023+ }
3024+ Node :: LetStmt ( hir:: LetStmt { init : Some ( expr) , .. } ) => {
3025+ // When encountering an assignment of an unsized trait, like `let x = *"";`,
3026+ // we check if the RHS is a deref operation, to suggest removing it.
3027+ suggest_remove_deref ( err, & expr) ;
29973028 }
29983029 Node :: Param ( param) => {
29993030 err. span_suggestion_verbose (
@@ -3003,10 +3034,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
30033034 "&" ,
30043035 Applicability :: MachineApplicable ,
30053036 ) ;
3037+ local = false ;
30063038 }
3007- _ => {
3008- err. note ( "all local variables must have a statically known size" ) ;
3009- }
3039+ _ => { }
3040+ }
3041+ if local {
3042+ err. note ( "all local variables must have a statically known size" ) ;
30103043 }
30113044 if !tcx. features ( ) . unsized_locals {
30123045 err. help ( "unsized locals are gated as an unstable feature" ) ;
@@ -3529,14 +3562,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
35293562 ) ;
35303563 }
35313564 ObligationCauseCode :: OpaqueReturnType ( expr_info) => {
3532- if let Some ( ( expr_ty, expr_span ) ) = expr_info {
3565+ if let Some ( ( expr_ty, hir_id ) ) = expr_info {
35333566 let expr_ty = self . tcx . short_ty_string ( expr_ty, & mut long_ty_file) ;
3567+ let expr = self . infcx . tcx . hir ( ) . expect_expr ( hir_id) ;
35343568 err. span_label (
3535- expr_span ,
3569+ expr . span ,
35363570 with_forced_trimmed_paths ! ( format!(
35373571 "return type was inferred to be `{expr_ty}` here" ,
35383572 ) ) ,
35393573 ) ;
3574+ suggest_remove_deref ( err, & expr) ;
35403575 }
35413576 }
35423577 }
0 commit comments