@@ -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 } ;
@@ -3200,63 +3199,80 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
3200
3199
err. help ( "unsized locals are gated as an unstable feature" ) ;
3201
3200
}
3202
3201
}
3203
- ObligationCauseCode :: SizedArgumentType ( ty_span) => {
3204
- if let Some ( span) = ty_span {
3205
- let trait_len = if let ty:: PredicateKind :: Clause ( clause) =
3206
- predicate. kind ( ) . skip_binder ( )
3207
- && let ty:: ClauseKind :: Trait ( trait_pred) = clause
3208
- && let ty:: Dynamic ( preds, ..) = trait_pred. self_ty ( ) . kind ( )
3209
- {
3210
- let span = if let Ok ( snippet) =
3211
- self . tcx . sess . source_map ( ) . span_to_snippet ( span)
3212
- && snippet. starts_with ( "dyn " )
3213
- {
3214
- let pos = snippet. len ( ) - snippet[ 3 ..] . trim_start ( ) . len ( ) ;
3215
- span. with_hi ( span. lo ( ) + BytePos ( pos as u32 ) )
3216
- } else {
3217
- span. shrink_to_lo ( )
3218
- } ;
3219
- err. span_suggestion_verbose (
3220
- span,
3221
- "you can use `impl Trait` as the argument type" ,
3222
- "impl " . to_string ( ) ,
3223
- Applicability :: MaybeIncorrect ,
3224
- ) ;
3225
- preds
3226
- . iter ( )
3227
- . filter ( |pred| {
3228
- // We only want to count `dyn Foo + Bar`, not `dyn Foo<Bar>`,
3229
- // because the later doesn't need parentheses.
3230
- matches ! (
3231
- pred. skip_binder( ) ,
3232
- ty:: ExistentialPredicate :: Trait ( _)
3233
- | ty:: ExistentialPredicate :: AutoTrait ( _)
3234
- )
3235
- } )
3236
- . count ( )
3237
- } else {
3238
- 1
3239
- } ;
3240
- let sugg = if trait_len == 1 {
3241
- vec ! [ ( span. shrink_to_lo( ) , "&" . to_string( ) ) ]
3242
- } else if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( span)
3243
- && snippet. starts_with ( '(' )
3244
- {
3245
- // We don't want to suggest `&((dyn Foo + Bar))` when we have
3246
- // `(dyn Foo + Bar)`.
3247
- vec ! [ ( span. shrink_to_lo( ) , "&" . to_string( ) ) ]
3248
- } else {
3249
- vec ! [
3250
- ( span. shrink_to_lo( ) , "&(" . to_string( ) ) ,
3251
- ( span. shrink_to_hi( ) , ")" . to_string( ) ) ,
3252
- ]
3253
- } ;
3254
- err. multipart_suggestion_verbose (
3255
- "function arguments must have a statically known size, borrowed types \
3256
- always have a known size",
3257
- sugg,
3258
- Applicability :: MachineApplicable ,
3259
- ) ;
3202
+ ObligationCauseCode :: SizedArgumentType ( hir_id) => {
3203
+ let mut ty = None ;
3204
+ let borrowed_msg = "function arguments must have a statically known size, borrowed \
3205
+ types always have a known size";
3206
+ if let Some ( hir_id) = hir_id
3207
+ && let Some ( hir:: Node :: Param ( param) ) = self . tcx . hir ( ) . find ( hir_id)
3208
+ && let Some ( item) = self . tcx . hir ( ) . find_parent ( hir_id)
3209
+ && let Some ( decl) = item. fn_decl ( )
3210
+ && let Some ( t) = decl. inputs . iter ( ) . find ( |t| param. ty_span . contains ( t. span ) )
3211
+ {
3212
+ // We use `contains` because the type might be surrounded by parentheses,
3213
+ // which makes `ty_span` and `t.span` disagree with each other, but one
3214
+ // fully contains the other: `foo: (dyn Foo + Bar)`
3215
+ // ^-------------^
3216
+ // ||
3217
+ // |t.span
3218
+ // param._ty_span
3219
+ ty = Some ( t) ;
3220
+ } else if let Some ( hir_id) = hir_id
3221
+ && let Some ( hir:: Node :: Ty ( t) ) = self . tcx . hir ( ) . find ( hir_id)
3222
+ {
3223
+ ty = Some ( t) ;
3224
+ }
3225
+ if let Some ( ty) = ty {
3226
+ match ty. kind {
3227
+ hir:: TyKind :: TraitObject ( traits, _, _) => {
3228
+ let ( span, kw) = match traits {
3229
+ [ first, ..] if first. span . lo ( ) == ty. span . lo ( ) => {
3230
+ // Missing `dyn` in front of trait object.
3231
+ ( ty. span . shrink_to_lo ( ) , "dyn " )
3232
+ }
3233
+ [ first, ..] => ( ty. span . until ( first. span ) , "" ) ,
3234
+ [ ] => span_bug ! ( ty. span, "trait object with no traits: {ty:?}" ) ,
3235
+ } ;
3236
+ let needs_parens = traits. len ( ) != 1 ;
3237
+ err. span_suggestion_verbose (
3238
+ span,
3239
+ "you can use `impl Trait` as the argument type" ,
3240
+ "impl " . to_string ( ) ,
3241
+ Applicability :: MaybeIncorrect ,
3242
+ ) ;
3243
+ let sugg = if !needs_parens {
3244
+ vec ! [ ( span. shrink_to_lo( ) , format!( "&{kw}" ) ) ]
3245
+ } else {
3246
+ vec ! [
3247
+ ( span. shrink_to_lo( ) , format!( "&({kw}" ) ) ,
3248
+ ( ty. span. shrink_to_hi( ) , ")" . to_string( ) ) ,
3249
+ ]
3250
+ } ;
3251
+ err. multipart_suggestion_verbose (
3252
+ borrowed_msg,
3253
+ sugg,
3254
+ Applicability :: MachineApplicable ,
3255
+ ) ;
3256
+ }
3257
+ hir:: TyKind :: Slice ( _ty) => {
3258
+ err. span_suggestion_verbose (
3259
+ ty. span . shrink_to_lo ( ) ,
3260
+ "function arguments must have a statically known size, borrowed \
3261
+ slices always have a known size",
3262
+ "&" ,
3263
+ Applicability :: MachineApplicable ,
3264
+ ) ;
3265
+ }
3266
+ hir:: TyKind :: Path ( _) => {
3267
+ err. span_suggestion_verbose (
3268
+ ty. span . shrink_to_lo ( ) ,
3269
+ borrowed_msg,
3270
+ "&" ,
3271
+ Applicability :: MachineApplicable ,
3272
+ ) ;
3273
+ }
3274
+ _ => { }
3275
+ }
3260
3276
} else {
3261
3277
err. note ( "all function arguments must have a statically known size" ) ;
3262
3278
}
0 commit comments