@@ -2727,6 +2727,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2727
2727
2728
2728
let tcx = self . tcx ;
2729
2729
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
+ } ;
2730
2744
match * cause_code {
2731
2745
ObligationCauseCode :: ExprAssignable
2732
2746
| ObligationCauseCode :: MatchExpressionArm { .. }
@@ -2773,6 +2787,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2773
2787
| ObligationCauseCode :: WhereClauseInExpr ( item_def_id, span, ..)
2774
2788
if !span. is_dummy ( ) =>
2775
2789
{
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
+ }
2776
2803
let item_name = tcx. def_path_str ( item_def_id) ;
2777
2804
let short_item_name = with_forced_trimmed_paths ! ( tcx. def_path_str( item_def_id) ) ;
2778
2805
let mut multispan = MultiSpan :: from ( span) ;
@@ -2970,6 +2997,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2970
2997
) ) ;
2971
2998
err. downgrade_to_delayed_bug ( ) ;
2972
2999
}
3000
+ let mut local = true ;
2973
3001
match tcx. parent_hir_node ( hir_id) {
2974
3002
Node :: LetStmt ( hir:: LetStmt { ty : Some ( ty) , .. } ) => {
2975
3003
err. span_suggestion_verbose (
@@ -2978,7 +3006,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2978
3006
"&" ,
2979
3007
Applicability :: MachineApplicable ,
2980
3008
) ;
2981
- err. note ( "all local variables must have a statically known size" ) ;
2982
3009
}
2983
3010
Node :: LetStmt ( hir:: LetStmt {
2984
3011
init : Some ( hir:: Expr { kind : hir:: ExprKind :: Index ( ..) , span, .. } ) ,
@@ -2993,7 +3020,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2993
3020
"&" ,
2994
3021
Applicability :: MachineApplicable ,
2995
3022
) ;
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) ;
2997
3028
}
2998
3029
Node :: Param ( param) => {
2999
3030
err. span_suggestion_verbose (
@@ -3003,10 +3034,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
3003
3034
"&" ,
3004
3035
Applicability :: MachineApplicable ,
3005
3036
) ;
3037
+ local = false ;
3006
3038
}
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" ) ;
3010
3043
}
3011
3044
if !tcx. features ( ) . unsized_locals {
3012
3045
err. help ( "unsized locals are gated as an unstable feature" ) ;
@@ -3529,14 +3562,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
3529
3562
) ;
3530
3563
}
3531
3564
ObligationCauseCode :: OpaqueReturnType ( expr_info) => {
3532
- if let Some ( ( expr_ty, expr_span ) ) = expr_info {
3565
+ if let Some ( ( expr_ty, hir_id ) ) = expr_info {
3533
3566
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) ;
3534
3568
err. span_label (
3535
- expr_span ,
3569
+ expr . span ,
3536
3570
with_forced_trimmed_paths ! ( format!(
3537
3571
"return type was inferred to be `{expr_ty}` here" ,
3538
3572
) ) ,
3539
3573
) ;
3574
+ suggest_remove_deref ( err, & expr) ;
3540
3575
}
3541
3576
}
3542
3577
}
0 commit comments