@@ -19,11 +19,10 @@ use rustc_errors::{
1919use rustc_hir as hir;
2020use rustc_hir:: def:: { DefKind , Res } ;
2121use rustc_hir:: def_id:: DefId ;
22- use rustc_hir:: intravisit:: Visitor ;
22+ use rustc_hir:: intravisit:: { Map , Visitor } ;
2323use rustc_hir:: is_range_literal;
2424use 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 } ;
2726use rustc_infer:: infer:: error_reporting:: TypeErrCtxt ;
2827use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
2928use rustc_infer:: infer:: { BoundRegionConversionTime , DefineOpaqueTypes , InferOk } ;
@@ -3054,63 +3053,80 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
30543053 err. help ( "unsized locals are gated as an unstable feature" ) ;
30553054 }
30563055 }
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+ }
31143130 } else {
31153131 err. note ( "all function arguments must have a statically known size" ) ;
31163132 }
0 commit comments