@@ -2725,6 +2725,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2725
2725
2726
2726
let tcx = self . tcx ;
2727
2727
let predicate = predicate. upcast ( tcx) ;
2728
+ let suggest_remove_deref = |err : & mut Diag < ' _ , G > , expr : & hir:: Expr < ' _ > | {
2729
+ if let Some ( pred) = predicate. as_trait_clause ( )
2730
+ && tcx. is_lang_item ( pred. def_id ( ) , LangItem :: Sized )
2731
+ && let hir:: ExprKind :: Unary ( hir:: UnOp :: Deref , inner) = expr. kind
2732
+ {
2733
+ err. span_suggestion_verbose (
2734
+ expr. span . until ( inner. span ) ,
2735
+ "references are always `Sized`, even if they point to unsized data; consider \
2736
+ not dereferencing the expression",
2737
+ String :: new ( ) ,
2738
+ Applicability :: MaybeIncorrect ,
2739
+ ) ;
2740
+ }
2741
+ } ;
2728
2742
match * cause_code {
2729
2743
ObligationCauseCode :: ExprAssignable
2730
2744
| ObligationCauseCode :: MatchExpressionArm { .. }
@@ -2771,6 +2785,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2771
2785
| ObligationCauseCode :: WhereClauseInExpr ( item_def_id, span, ..)
2772
2786
if !span. is_dummy ( ) =>
2773
2787
{
2788
+ if let ObligationCauseCode :: WhereClauseInExpr ( _, _, hir_id, pos) = & cause_code {
2789
+ if let Node :: Expr ( expr) = tcx. parent_hir_node ( * hir_id)
2790
+ && let hir:: ExprKind :: Call ( _, args) = expr. kind
2791
+ && let Some ( expr) = args. get ( * pos)
2792
+ {
2793
+ suggest_remove_deref ( err, & expr) ;
2794
+ } else if let Node :: Expr ( expr) = self . tcx . hir_node ( * hir_id)
2795
+ && let hir:: ExprKind :: MethodCall ( _, _, args, _) = expr. kind
2796
+ && let Some ( expr) = args. get ( * pos)
2797
+ {
2798
+ suggest_remove_deref ( err, & expr) ;
2799
+ }
2800
+ }
2774
2801
let item_name = tcx. def_path_str ( item_def_id) ;
2775
2802
let short_item_name = with_forced_trimmed_paths ! ( tcx. def_path_str( item_def_id) ) ;
2776
2803
let mut multispan = MultiSpan :: from ( span) ;
@@ -2968,6 +2995,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2968
2995
) ) ;
2969
2996
err. downgrade_to_delayed_bug ( ) ;
2970
2997
}
2998
+ let mut local = true ;
2971
2999
match tcx. parent_hir_node ( hir_id) {
2972
3000
Node :: LetStmt ( hir:: LetStmt { ty : Some ( ty) , .. } ) => {
2973
3001
err. span_suggestion_verbose (
@@ -2976,7 +3004,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2976
3004
"&" ,
2977
3005
Applicability :: MachineApplicable ,
2978
3006
) ;
2979
- err. note ( "all local variables must have a statically known size" ) ;
2980
3007
}
2981
3008
Node :: LetStmt ( hir:: LetStmt {
2982
3009
init : Some ( hir:: Expr { kind : hir:: ExprKind :: Index ( ..) , span, .. } ) ,
@@ -2991,7 +3018,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
2991
3018
"&" ,
2992
3019
Applicability :: MachineApplicable ,
2993
3020
) ;
2994
- err. note ( "all local variables must have a statically known size" ) ;
3021
+ }
3022
+ Node :: LetStmt ( hir:: LetStmt { init : Some ( expr) , .. } ) => {
3023
+ // When encountering an assignment of an unsized trait, like `let x = *"";`,
3024
+ // we check if the RHS is a deref operation, to suggest removing it.
3025
+ suggest_remove_deref ( err, & expr) ;
2995
3026
}
2996
3027
Node :: Param ( param) => {
2997
3028
err. span_suggestion_verbose (
@@ -3001,10 +3032,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
3001
3032
"&" ,
3002
3033
Applicability :: MachineApplicable ,
3003
3034
) ;
3035
+ local = false ;
3004
3036
}
3005
- _ => {
3006
- err. note ( "all local variables must have a statically known size" ) ;
3007
- }
3037
+ _ => { }
3038
+ }
3039
+ if local {
3040
+ err. note ( "all local variables must have a statically known size" ) ;
3008
3041
}
3009
3042
if !tcx. features ( ) . unsized_locals {
3010
3043
err. help ( "unsized locals are gated as an unstable feature" ) ;
@@ -3527,14 +3560,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
3527
3560
) ;
3528
3561
}
3529
3562
ObligationCauseCode :: OpaqueReturnType ( expr_info) => {
3530
- if let Some ( ( expr_ty, expr_span ) ) = expr_info {
3563
+ if let Some ( ( expr_ty, hir_id ) ) = expr_info {
3531
3564
let expr_ty = self . tcx . short_ty_string ( expr_ty, & mut long_ty_file) ;
3565
+ let expr = self . infcx . tcx . hir ( ) . expect_expr ( hir_id) ;
3532
3566
err. span_label (
3533
- expr_span ,
3567
+ expr . span ,
3534
3568
with_forced_trimmed_paths ! ( format!(
3535
3569
"return type was inferred to be `{expr_ty}` here" ,
3536
3570
) ) ,
3537
3571
) ;
3572
+ suggest_remove_deref ( err, & expr) ;
3538
3573
}
3539
3574
}
3540
3575
}
0 commit comments