@@ -19,11 +19,10 @@ use rustc_errors::{
19
19
use rustc_hir as hir;
20
20
use rustc_hir:: def:: { DefKind , Res } ;
21
21
use rustc_hir:: def_id:: DefId ;
22
- use rustc_hir:: intravisit:: Visitor ;
22
+ use rustc_hir:: intravisit:: { Map , Visitor } ;
23
23
use rustc_hir:: is_range_literal;
24
24
use rustc_hir:: lang_items:: LangItem ;
25
- use rustc_hir:: { CoroutineDesugaring , CoroutineKind , CoroutineSource , Node } ;
26
- use rustc_hir:: { Expr , HirId } ;
25
+ use rustc_hir:: { CoroutineDesugaring , CoroutineKind , CoroutineSource , Expr , HirId , Node } ;
27
26
use rustc_infer:: infer:: error_reporting:: TypeErrCtxt ;
28
27
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
29
28
use rustc_infer:: infer:: { BoundRegionConversionTime , DefineOpaqueTypes , InferOk } ;
@@ -3054,63 +3053,80 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
3054
3053
err. help ( "unsized locals are gated as an unstable feature" ) ;
3055
3054
}
3056
3055
}
3057
- ObligationCauseCode :: SizedArgumentType ( ty_span) => {
3058
- if let Some ( span) = ty_span {
3059
- let trait_len = if let ty:: PredicateKind :: Clause ( clause) =
3060
- predicate. kind ( ) . skip_binder ( )
3061
- && let ty:: ClauseKind :: Trait ( trait_pred) = clause
3062
- && let ty:: Dynamic ( preds, ..) = trait_pred. self_ty ( ) . kind ( )
3063
- {
3064
- let span = if let Ok ( snippet) =
3065
- self . tcx . sess . source_map ( ) . span_to_snippet ( span)
3066
- && snippet. starts_with ( "dyn " )
3067
- {
3068
- let pos = snippet. len ( ) - snippet[ 3 ..] . trim_start ( ) . len ( ) ;
3069
- span. with_hi ( span. lo ( ) + BytePos ( pos as u32 ) )
3070
- } else {
3071
- span. shrink_to_lo ( )
3072
- } ;
3073
- err. span_suggestion_verbose (
3074
- span,
3075
- "you can use `impl Trait` as the argument type" ,
3076
- "impl " . to_string ( ) ,
3077
- Applicability :: MaybeIncorrect ,
3078
- ) ;
3079
- preds
3080
- . iter ( )
3081
- . filter ( |pred| {
3082
- // We only want to count `dyn Foo + Bar`, not `dyn Foo<Bar>`,
3083
- // because the later doesn't need parentheses.
3084
- matches ! (
3085
- pred. skip_binder( ) ,
3086
- ty:: ExistentialPredicate :: Trait ( _)
3087
- | ty:: ExistentialPredicate :: AutoTrait ( _)
3088
- )
3089
- } )
3090
- . count ( )
3091
- } else {
3092
- 1
3093
- } ;
3094
- let sugg = if trait_len == 1 {
3095
- vec ! [ ( span. shrink_to_lo( ) , "&" . to_string( ) ) ]
3096
- } else if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( span)
3097
- && snippet. starts_with ( '(' )
3098
- {
3099
- // We don't want to suggest `&((dyn Foo + Bar))` when we have
3100
- // `(dyn Foo + Bar)`.
3101
- vec ! [ ( span. shrink_to_lo( ) , "&" . to_string( ) ) ]
3102
- } else {
3103
- vec ! [
3104
- ( span. shrink_to_lo( ) , "&(" . to_string( ) ) ,
3105
- ( span. shrink_to_hi( ) , ")" . to_string( ) ) ,
3106
- ]
3107
- } ;
3108
- err. multipart_suggestion_verbose (
3109
- "function arguments must have a statically known size, borrowed types \
3110
- always have a known size",
3111
- sugg,
3112
- Applicability :: MachineApplicable ,
3113
- ) ;
3056
+ ObligationCauseCode :: SizedArgumentType ( hir_id) => {
3057
+ let mut ty = None ;
3058
+ let borrowed_msg = "function arguments must have a statically known size, borrowed \
3059
+ types always have a known size";
3060
+ if let Some ( hir_id) = hir_id
3061
+ && let Some ( hir:: Node :: Param ( param) ) = self . tcx . hir ( ) . find ( hir_id)
3062
+ && let Some ( item) = self . tcx . hir ( ) . find_parent ( hir_id)
3063
+ && let Some ( decl) = item. fn_decl ( )
3064
+ && let Some ( t) = decl. inputs . iter ( ) . find ( |t| param. ty_span . contains ( t. span ) )
3065
+ {
3066
+ // We use `contains` because the type might be surrounded by parentheses,
3067
+ // which makes `ty_span` and `t.span` disagree with each other, but one
3068
+ // fully contains the other: `foo: (dyn Foo + Bar)`
3069
+ // ^-------------^
3070
+ // ||
3071
+ // |t.span
3072
+ // param._ty_span
3073
+ ty = Some ( t) ;
3074
+ } else if let Some ( hir_id) = hir_id
3075
+ && let Some ( hir:: Node :: Ty ( t) ) = self . tcx . hir ( ) . find ( hir_id)
3076
+ {
3077
+ ty = Some ( t) ;
3078
+ }
3079
+ if let Some ( ty) = ty {
3080
+ match ty. kind {
3081
+ hir:: TyKind :: TraitObject ( traits, _, _) => {
3082
+ let ( span, kw) = match traits {
3083
+ [ first, ..] if first. span . lo ( ) == ty. span . lo ( ) => {
3084
+ // Missing `dyn` in front of trait object.
3085
+ ( ty. span . shrink_to_lo ( ) , "dyn " )
3086
+ }
3087
+ [ first, ..] => ( ty. span . until ( first. span ) , "" ) ,
3088
+ [ ] => span_bug ! ( ty. span, "trait object with no traits: {ty:?}" ) ,
3089
+ } ;
3090
+ let needs_parens = traits. len ( ) != 1 ;
3091
+ err. span_suggestion_verbose (
3092
+ span,
3093
+ "you can use `impl Trait` as the argument type" ,
3094
+ "impl " . to_string ( ) ,
3095
+ Applicability :: MaybeIncorrect ,
3096
+ ) ;
3097
+ let sugg = if !needs_parens {
3098
+ vec ! [ ( span. shrink_to_lo( ) , format!( "&{kw}" ) ) ]
3099
+ } else {
3100
+ vec ! [
3101
+ ( span. shrink_to_lo( ) , format!( "&({kw}" ) ) ,
3102
+ ( ty. span. shrink_to_hi( ) , ")" . to_string( ) ) ,
3103
+ ]
3104
+ } ;
3105
+ err. multipart_suggestion_verbose (
3106
+ borrowed_msg,
3107
+ sugg,
3108
+ Applicability :: MachineApplicable ,
3109
+ ) ;
3110
+ }
3111
+ hir:: TyKind :: Slice ( _ty) => {
3112
+ err. span_suggestion_verbose (
3113
+ ty. span . shrink_to_lo ( ) ,
3114
+ "function arguments must have a statically known size, borrowed \
3115
+ slices always have a known size",
3116
+ "&" ,
3117
+ Applicability :: MachineApplicable ,
3118
+ ) ;
3119
+ }
3120
+ hir:: TyKind :: Path ( _) => {
3121
+ err. span_suggestion_verbose (
3122
+ ty. span . shrink_to_lo ( ) ,
3123
+ borrowed_msg,
3124
+ "&" ,
3125
+ Applicability :: MachineApplicable ,
3126
+ ) ;
3127
+ }
3128
+ _ => { }
3129
+ }
3114
3130
} else {
3115
3131
err. note ( "all function arguments must have a statically known size" ) ;
3116
3132
}
0 commit comments