@@ -3011,35 +3011,44 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
3011
3011
) ;
3012
3012
}
3013
3013
}
3014
- let descr = format ! ( "required by a bound in `{item_name}`" ) ;
3015
- if span. is_visible ( sm) {
3016
- let msg = format ! ( "required by this bound in `{short_item_name}`" ) ;
3017
- multispan. push_span_label ( span, msg) ;
3018
- err. span_note ( multispan, descr) ;
3019
- if let ty:: PredicateKind :: Clause ( clause) = predicate. kind ( ) . skip_binder ( )
3020
- && let ty:: ClauseKind :: Trait ( trait_pred) = clause
3021
- {
3022
- let def_id = trait_pred. def_id ( ) ;
3023
- let visible_item = if let Some ( local) = def_id. as_local ( ) {
3024
- // Check for local traits being reachable.
3025
- let vis = & self . tcx . resolutions ( ( ) ) . effective_visibilities ;
3026
- // Account for non-`pub` traits in the root of the local crate.
3027
- let is_locally_reachable = self . tcx . parent ( def_id) . is_crate_root ( ) ;
3028
- vis. is_reachable ( local) || is_locally_reachable
3029
- } else {
3030
- // Check for foreign traits being reachable.
3031
- self . tcx . visible_parent_map ( ( ) ) . get ( & def_id) . is_some ( )
3032
- } ;
3033
- if Some ( def_id) == self . tcx . lang_items ( ) . sized_trait ( )
3034
- && let Some ( hir:: Node :: TraitItem ( hir:: TraitItem {
3035
- ident,
3036
- kind : hir:: TraitItemKind :: Type ( bounds, None ) ,
3037
- ..
3038
- } ) ) = tcx. hir ( ) . get_if_local ( item_def_id)
3039
- // Do not suggest relaxing if there is an explicit `Sized` obligation.
3040
- && !bounds. iter ( )
3041
- . filter_map ( |bound| bound. trait_ref ( ) )
3042
- . any ( |tr| tr. trait_def_id ( ) == self . tcx . lang_items ( ) . sized_trait ( ) )
3014
+ let mut a = "a" ;
3015
+ let mut this = "this" ;
3016
+ let mut note = None ;
3017
+ let mut help = None ;
3018
+ if let ty:: PredicateKind :: Clause ( clause) = predicate. kind ( ) . skip_binder ( )
3019
+ && let ty:: ClauseKind :: Trait ( trait_pred) = clause
3020
+ {
3021
+ let def_id = trait_pred. def_id ( ) ;
3022
+ let visible_item = if let Some ( local) = def_id. as_local ( ) {
3023
+ // Check for local traits being reachable.
3024
+ let vis = & self . tcx . resolutions ( ( ) ) . effective_visibilities ;
3025
+ // Account for non-`pub` traits in the root of the local crate.
3026
+ let is_locally_reachable = self . tcx . parent ( def_id) . is_crate_root ( ) ;
3027
+ vis. is_reachable ( local) || is_locally_reachable
3028
+ } else {
3029
+ // Check for foreign traits being reachable.
3030
+ self . tcx . visible_parent_map ( ( ) ) . get ( & def_id) . is_some ( )
3031
+ } ;
3032
+ if Some ( def_id) == self . tcx . lang_items ( ) . sized_trait ( ) {
3033
+ // Check if this is an implicit bound, even in foreign crates.
3034
+ if tcx
3035
+ . generics_of ( item_def_id)
3036
+ . params
3037
+ . iter ( )
3038
+ . any ( |param| tcx. def_span ( param. def_id ) == span)
3039
+ {
3040
+ a = "an implicit `Sized`" ;
3041
+ this = "the implicit `Sized` requirement on this" ;
3042
+ }
3043
+ if let Some ( hir:: Node :: TraitItem ( hir:: TraitItem {
3044
+ ident,
3045
+ kind : hir:: TraitItemKind :: Type ( bounds, None ) ,
3046
+ ..
3047
+ } ) ) = tcx. hir ( ) . get_if_local ( item_def_id)
3048
+ // Do not suggest relaxing if there is an explicit `Sized` obligation.
3049
+ && !bounds. iter ( )
3050
+ . filter_map ( |bound| bound. trait_ref ( ) )
3051
+ . any ( |tr| tr. trait_def_id ( ) == self . tcx . lang_items ( ) . sized_trait ( ) )
3043
3052
{
3044
3053
let ( span, separator) = if let [ .., last] = bounds {
3045
3054
( last. span ( ) . shrink_to_hi ( ) , " +" )
@@ -3053,52 +3062,64 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
3053
3062
Applicability :: MachineApplicable ,
3054
3063
) ;
3055
3064
}
3056
- if let DefKind :: Trait = tcx. def_kind ( item_def_id)
3057
- && !visible_item
3058
- {
3059
- err. note ( format ! (
3060
- "`{short_item_name}` is a \" sealed trait\" , because to implement \
3061
- it you also need to implement `{}`, which is not accessible; \
3062
- this is usually done to force you to use one of the provided \
3063
- types that already implement it",
3064
- with_no_trimmed_paths!( tcx. def_path_str( def_id) ) ,
3065
- ) ) ;
3066
- let impls_of = tcx. trait_impls_of ( def_id) ;
3067
- let impls = impls_of
3068
- . non_blanket_impls ( )
3069
- . values ( )
3070
- . flatten ( )
3071
- . chain ( impls_of. blanket_impls ( ) . iter ( ) )
3065
+ }
3066
+ if let DefKind :: Trait = tcx. def_kind ( item_def_id)
3067
+ && !visible_item
3068
+ {
3069
+ note = Some ( format ! (
3070
+ "`{short_item_name}` is a \" sealed trait\" , because to implement it \
3071
+ you also need to implement `{}`, which is not accessible; this is \
3072
+ usually done to force you to use one of the provided types that \
3073
+ already implement it",
3074
+ with_no_trimmed_paths!( tcx. def_path_str( def_id) ) ,
3075
+ ) ) ;
3076
+ let impls_of = tcx. trait_impls_of ( def_id) ;
3077
+ let impls = impls_of
3078
+ . non_blanket_impls ( )
3079
+ . values ( )
3080
+ . flatten ( )
3081
+ . chain ( impls_of. blanket_impls ( ) . iter ( ) )
3082
+ . collect :: < Vec < _ > > ( ) ;
3083
+ if !impls. is_empty ( ) {
3084
+ let len = impls. len ( ) ;
3085
+ let mut types = impls
3086
+ . iter ( )
3087
+ . map ( |t| {
3088
+ with_no_trimmed_paths ! ( format!(
3089
+ " {}" ,
3090
+ tcx. type_of( * t) . instantiate_identity( ) ,
3091
+ ) )
3092
+ } )
3072
3093
. collect :: < Vec < _ > > ( ) ;
3073
- if !impls. is_empty ( ) {
3074
- let len = impls. len ( ) ;
3075
- let mut types = impls
3076
- . iter ( )
3077
- . map ( |t| {
3078
- with_no_trimmed_paths ! ( format!(
3079
- " {}" ,
3080
- tcx. type_of( * t) . instantiate_identity( ) ,
3081
- ) )
3082
- } )
3083
- . collect :: < Vec < _ > > ( ) ;
3084
- let post = if types. len ( ) > 9 {
3085
- types. truncate ( 8 ) ;
3086
- format ! ( "\n and {} others" , len - 8 )
3087
- } else {
3088
- String :: new ( )
3089
- } ;
3090
- err. help ( format ! (
3091
- "the following type{} implement{} the trait:\n {}{post}" ,
3092
- pluralize!( len) ,
3093
- if len == 1 { "s" } else { "" } ,
3094
- types. join( "\n " ) ,
3095
- ) ) ;
3096
- }
3094
+ let post = if types. len ( ) > 9 {
3095
+ types. truncate ( 8 ) ;
3096
+ format ! ( "\n and {} others" , len - 8 )
3097
+ } else {
3098
+ String :: new ( )
3099
+ } ;
3100
+ help = Some ( format ! (
3101
+ "the following type{} implement{} the trait:\n {}{post}" ,
3102
+ pluralize!( len) ,
3103
+ if len == 1 { "s" } else { "" } ,
3104
+ types. join( "\n " ) ,
3105
+ ) ) ;
3097
3106
}
3098
3107
}
3108
+ } ;
3109
+ let descr = format ! ( "required by {a} bound in `{item_name}`" ) ;
3110
+ if span. is_visible ( sm) {
3111
+ let msg = format ! ( "required by {this} bound in `{short_item_name}`" ) ;
3112
+ multispan. push_span_label ( span, msg) ;
3113
+ err. span_note ( multispan, descr) ;
3099
3114
} else {
3100
3115
err. span_note ( tcx. def_span ( item_def_id) , descr) ;
3101
3116
}
3117
+ if let Some ( note) = note {
3118
+ err. note ( note) ;
3119
+ }
3120
+ if let Some ( help) = help {
3121
+ err. help ( help) ;
3122
+ }
3102
3123
}
3103
3124
ObligationCauseCode :: Coercion { source, target } => {
3104
3125
let mut file = None ;
0 commit comments