@@ -2725,6 +2725,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
27252725
27262726 let tcx = self . tcx ;
27272727 let predicate = predicate. upcast ( tcx) ;
2728+ info ! ( ?predicate, ?cause_code) ;
2729+ let suggest_remove_deref = |err : & mut Diag < ' _ , G > , expr : & hir:: Expr < ' _ > | {
2730+ if let Some ( pred) = predicate. as_trait_clause ( )
2731+ && tcx. is_lang_item ( pred. def_id ( ) , LangItem :: Sized )
2732+ && let hir:: ExprKind :: Unary ( hir:: UnOp :: Deref , inner) = expr. kind
2733+ {
2734+ err. span_suggestion_verbose (
2735+ expr. span . until ( inner. span ) ,
2736+ "references are always `Sized`, even if they point to unsized data; consider \
2737+ not dereferencing the expression",
2738+ String :: new ( ) ,
2739+ Applicability :: MaybeIncorrect ,
2740+ ) ;
2741+ }
2742+ } ;
27282743 match * cause_code {
27292744 ObligationCauseCode :: ExprAssignable
27302745 | ObligationCauseCode :: MatchExpressionArm { .. }
@@ -2771,6 +2786,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
27712786 | ObligationCauseCode :: WhereClauseInExpr ( item_def_id, span, ..)
27722787 if !span. is_dummy ( ) =>
27732788 {
2789+ if let ObligationCauseCode :: WhereClauseInExpr ( _, _, hir_id, pos) = & cause_code {
2790+ if let Node :: Expr ( expr) = tcx. parent_hir_node ( * hir_id)
2791+ && let hir:: ExprKind :: Call ( _, args) = expr. kind
2792+ && let Some ( expr) = args. get ( * pos)
2793+ {
2794+ suggest_remove_deref ( err, & expr) ;
2795+ } else if let Node :: Expr ( expr) = self . tcx . hir_node ( * hir_id)
2796+ && let hir:: ExprKind :: MethodCall ( _, _, args, _) = expr. kind
2797+ && let Some ( expr) = args. get ( * pos)
2798+ {
2799+ suggest_remove_deref ( err, & expr) ;
2800+ }
2801+ }
27742802 let item_name = tcx. def_path_str ( item_def_id) ;
27752803 let short_item_name = with_forced_trimmed_paths ! ( tcx. def_path_str( item_def_id) ) ;
27762804 let mut multispan = MultiSpan :: from ( span) ;
@@ -2968,6 +2996,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
29682996 ) ) ;
29692997 err. downgrade_to_delayed_bug ( ) ;
29702998 }
2999+ let mut local = true ;
29713000 match tcx. parent_hir_node ( hir_id) {
29723001 Node :: LetStmt ( hir:: LetStmt { ty : Some ( ty) , .. } ) => {
29733002 err. span_suggestion_verbose (
@@ -2976,7 +3005,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
29763005 "&" ,
29773006 Applicability :: MachineApplicable ,
29783007 ) ;
2979- err. note ( "all local variables must have a statically known size" ) ;
29803008 }
29813009 Node :: LetStmt ( hir:: LetStmt {
29823010 init : Some ( hir:: Expr { kind : hir:: ExprKind :: Index ( ..) , span, .. } ) ,
@@ -2991,7 +3019,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
29913019 "&" ,
29923020 Applicability :: MachineApplicable ,
29933021 ) ;
2994- err. note ( "all local variables must have a statically known size" ) ;
3022+ }
3023+ Node :: LetStmt ( hir:: LetStmt { init : Some ( expr) , .. } ) => {
3024+ // When encountering an assignment of an unsized trait, like `let x = *"";`,
3025+ // we check if the RHS is a deref operation, to suggest removing it.
3026+ suggest_remove_deref ( err, & expr) ;
29953027 }
29963028 Node :: Param ( param) => {
29973029 err. span_suggestion_verbose (
@@ -3001,10 +3033,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
30013033 "&" ,
30023034 Applicability :: MachineApplicable ,
30033035 ) ;
3036+ local = false ;
30043037 }
3005- _ => {
3006- err. note ( "all local variables must have a statically known size" ) ;
3007- }
3038+ _ => { }
3039+ }
3040+ if local {
3041+ err. note ( "all local variables must have a statically known size" ) ;
30083042 }
30093043 if !tcx. features ( ) . unsized_locals {
30103044 err. help ( "unsized locals are gated as an unstable feature" ) ;
@@ -3527,14 +3561,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
35273561 ) ;
35283562 }
35293563 ObligationCauseCode :: OpaqueReturnType ( expr_info) => {
3530- if let Some ( ( expr_ty, expr_span ) ) = expr_info {
3564+ if let Some ( ( expr_ty, hir_id ) ) = expr_info {
35313565 let expr_ty = self . tcx . short_ty_string ( expr_ty, & mut long_ty_file) ;
3566+ let expr = self . infcx . tcx . hir ( ) . expect_expr ( hir_id) ;
35323567 err. span_label (
3533- expr_span ,
3568+ expr . span ,
35343569 with_forced_trimmed_paths ! ( format!(
35353570 "return type was inferred to be `{expr_ty}` here" ,
35363571 ) ) ,
35373572 ) ;
3573+ suggest_remove_deref ( err, & expr) ;
35383574 }
35393575 }
35403576 }
0 commit comments