1+ use crate :: errors:: { ActualImplExplNotes , TraitPlaceholderMismatch } ;
12use crate :: infer:: error_reporting:: nice_region_error:: NiceRegionError ;
23use crate :: infer:: lexical_region_resolve:: RegionResolutionError ;
34use crate :: infer:: ValuePairs ;
45use crate :: infer:: { SubregionOrigin , TypeTrace } ;
56use crate :: traits:: { ObligationCause , ObligationCauseCode } ;
67use rustc_data_structures:: intern:: Interned ;
7- use rustc_errors:: { Diagnostic , DiagnosticBuilder , ErrorGuaranteed } ;
8+ use rustc_errors:: { DiagnosticBuilder , ErrorGuaranteed } ;
89use rustc_hir:: def:: Namespace ;
910use rustc_hir:: def_id:: DefId ;
1011use rustc_middle:: ty:: error:: ExpectedFound ;
1112use rustc_middle:: ty:: print:: { FmtPrinter , Print , RegionHighlightMode } ;
1213use rustc_middle:: ty:: subst:: SubstsRef ;
1314use rustc_middle:: ty:: { self , RePlaceholder , ReVar , Region , TyCtxt } ;
1415
15- use std:: fmt:: { self , Write } ;
16+ use std:: fmt;
1617
1718impl < ' tcx > NiceRegionError < ' _ , ' tcx > {
1819 /// When given a `ConcreteFailure` for a function with arguments containing a named region and
@@ -205,26 +206,21 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
205206 actual_substs : SubstsRef < ' tcx > ,
206207 ) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
207208 let span = cause. span ( ) ;
208- let msg = format ! (
209- "implementation of `{}` is not general enough" ,
210- self . tcx( ) . def_path_str( trait_def_id) ,
211- ) ;
212- let mut err = self . tcx ( ) . sess . struct_span_err ( span, & msg) ;
213209
214- let leading_ellipsis = if let ObligationCauseCode :: ItemObligation ( def_id)
215- | ObligationCauseCode :: ExprItemObligation ( def_id, .. ) =
216- * cause. code ( )
217- {
218- err . span_label ( span , "doesn't satisfy where-clause" ) ;
219- err . span_label (
220- self . tcx ( ) . def_span ( def_id ) ,
221- & format ! ( "due to a where-clause on `{}`..." , self . tcx( ) . def_path_str ( def_id) ) ,
222- ) ;
223- true
224- } else {
225- err . span_label ( span , & msg ) ;
226- false
227- } ;
210+ let ( leading_ellipsis, satisfy_span , where_span , dup_span , def_id) =
211+ if let ObligationCauseCode :: ItemObligation ( def_id)
212+ | ObligationCauseCode :: ExprItemObligation ( def_id , .. ) = * cause. code ( )
213+ {
214+ (
215+ true ,
216+ Some ( span ) ,
217+ Some ( self . tcx ( ) . def_span ( def_id) ) ,
218+ None ,
219+ self . tcx ( ) . def_path_str ( def_id ) ,
220+ )
221+ } else {
222+ ( false , None , None , Some ( span ) , String :: new ( ) )
223+ } ;
228224
229225 let expected_trait_ref = self
230226 . cx
@@ -284,8 +280,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
284280 ?expected_self_ty_has_vid,
285281 ) ;
286282
287- self . explain_actual_impl_that_was_found (
288- & mut err,
283+ let actual_impl_expl_notes = self . explain_actual_impl_that_was_found (
289284 sub_placeholder,
290285 sup_placeholder,
291286 has_sub,
@@ -299,7 +294,17 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
299294 leading_ellipsis,
300295 ) ;
301296
302- err
297+ let diag = TraitPlaceholderMismatch {
298+ span,
299+ satisfy_span,
300+ where_span,
301+ dup_span,
302+ def_id,
303+ trait_def_id : self . tcx ( ) . def_path_str ( trait_def_id) ,
304+ actual_impl_expl_notes,
305+ } ;
306+
307+ self . tcx ( ) . sess . create_err ( diag)
303308 }
304309
305310 /// Add notes with details about the expected and actual trait refs, with attention to cases
@@ -309,7 +314,6 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
309314 /// due to the number of combinations we have to deal with.
310315 fn explain_actual_impl_that_was_found (
311316 & self ,
312- err : & mut Diagnostic ,
313317 sub_placeholder : Option < Region < ' tcx > > ,
314318 sup_placeholder : Option < Region < ' tcx > > ,
315319 has_sub : Option < usize > ,
@@ -321,7 +325,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
321325 actual_has_vid : Option < usize > ,
322326 any_self_ty_has_vid : bool ,
323327 leading_ellipsis : bool ,
324- ) {
328+ ) -> Vec < ActualImplExplNotes > {
325329 // HACK(eddyb) maybe move this in a more central location.
326330 #[ derive( Copy , Clone ) ]
327331 struct Highlighted < ' tcx , T > {
@@ -380,120 +384,107 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
380384 let mut expected_trait_ref = highlight_trait_ref ( expected_trait_ref) ;
381385 expected_trait_ref. highlight . maybe_highlighting_region ( sub_placeholder, has_sub) ;
382386 expected_trait_ref. highlight . maybe_highlighting_region ( sup_placeholder, has_sup) ;
383- err. note ( & {
384- let passive_voice = match ( has_sub, has_sup) {
385- ( Some ( _) , _) | ( _, Some ( _) ) => any_self_ty_has_vid,
386- ( None , None ) => {
387- expected_trait_ref. highlight . maybe_highlighting_region ( vid, expected_has_vid) ;
388- match expected_has_vid {
389- Some ( _) => true ,
390- None => any_self_ty_has_vid,
391- }
392- }
393- } ;
394387
395- let mut note = if same_self_type {
396- let mut self_ty = expected_trait_ref. map ( |tr| tr. self_ty ( ) ) ;
397- self_ty. highlight . maybe_highlighting_region ( vid, actual_has_vid) ;
398-
399- if self_ty. value . is_closure ( )
400- && self . tcx ( ) . is_fn_trait ( expected_trait_ref. value . def_id )
401- {
402- let closure_sig = self_ty. map ( |closure| {
403- if let ty:: Closure ( _, substs) = closure. kind ( ) {
404- self . tcx ( ) . signature_unclosure (
405- substs. as_closure ( ) . sig ( ) ,
406- rustc_hir:: Unsafety :: Normal ,
407- )
408- } else {
409- bug ! ( "type is not longer closure" ) ;
410- }
411- } ) ;
412-
413- format ! (
414- "{}closure with signature `{}` must implement `{}`" ,
415- if leading_ellipsis { "..." } else { "" } ,
416- closure_sig,
417- expected_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
418- )
419- } else {
420- format ! (
421- "{}`{}` must implement `{}`" ,
422- if leading_ellipsis { "..." } else { "" } ,
423- self_ty,
424- expected_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
425- )
388+ let passive_voice = match ( has_sub, has_sup) {
389+ ( Some ( _) , _) | ( _, Some ( _) ) => any_self_ty_has_vid,
390+ ( None , None ) => {
391+ expected_trait_ref. highlight . maybe_highlighting_region ( vid, expected_has_vid) ;
392+ match expected_has_vid {
393+ Some ( _) => true ,
394+ None => any_self_ty_has_vid,
426395 }
427- } else if passive_voice {
428- format ! (
429- "{}`{}` would have to be implemented for the type `{}`" ,
430- if leading_ellipsis { "..." } else { "" } ,
431- expected_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
432- expected_trait_ref. map( |tr| tr. self_ty( ) ) ,
396+ }
397+ } ;
398+
399+ let ( kind, ty_or_sig, trait_path) = if same_self_type {
400+ let mut self_ty = expected_trait_ref. map ( |tr| tr. self_ty ( ) ) ;
401+ self_ty. highlight . maybe_highlighting_region ( vid, actual_has_vid) ;
402+
403+ if self_ty. value . is_closure ( )
404+ && self . tcx ( ) . is_fn_trait ( expected_trait_ref. value . def_id )
405+ {
406+ let closure_sig = self_ty. map ( |closure| {
407+ if let ty:: Closure ( _, substs) = closure. kind ( ) {
408+ self . tcx ( ) . signature_unclosure (
409+ substs. as_closure ( ) . sig ( ) ,
410+ rustc_hir:: Unsafety :: Normal ,
411+ )
412+ } else {
413+ bug ! ( "type is not longer closure" ) ;
414+ }
415+ } ) ;
416+ (
417+ "signature" ,
418+ closure_sig. to_string ( ) ,
419+ expected_trait_ref. map ( |tr| tr. print_only_trait_path ( ) ) . to_string ( ) ,
433420 )
434421 } else {
435- format ! (
436- "{}`{}` must implement `{}`" ,
437- if leading_ellipsis { "..." } else { "" } ,
438- expected_trait_ref. map( |tr| tr. self_ty( ) ) ,
439- expected_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
422+ (
423+ "other" ,
424+ self_ty. to_string ( ) ,
425+ expected_trait_ref. map ( |tr| tr. print_only_trait_path ( ) ) . to_string ( ) ,
440426 )
441- } ;
427+ }
428+ } else if passive_voice {
429+ (
430+ "passive" ,
431+ expected_trait_ref. map ( |tr| tr. self_ty ( ) ) . to_string ( ) ,
432+ expected_trait_ref. map ( |tr| tr. print_only_trait_path ( ) ) . to_string ( ) ,
433+ )
434+ } else {
435+ (
436+ "other" ,
437+ expected_trait_ref. map ( |tr| tr. self_ty ( ) ) . to_string ( ) ,
438+ expected_trait_ref. map ( |tr| tr. print_only_trait_path ( ) ) . to_string ( ) ,
439+ )
440+ } ;
442441
443- match ( has_sub, has_sup) {
444- ( Some ( n1) , Some ( n2) ) => {
445- let _ = write ! (
446- note,
447- ", for any two lifetimes `'{}` and `'{}`..." ,
448- std:: cmp:: min( n1, n2) ,
449- std:: cmp:: max( n1, n2) ,
450- ) ;
451- }
452- ( Some ( n) , _) | ( _, Some ( n) ) => {
453- let _ = write ! ( note, ", for any lifetime `'{}`..." , n, ) ;
454- }
455- ( None , None ) => {
456- if let Some ( n) = expected_has_vid {
457- let _ = write ! ( note, ", for some specific lifetime `'{}`..." , n, ) ;
458- }
442+ let ( lt_kind, lifetime_1, lifetime_2) = match ( has_sub, has_sup) {
443+ ( Some ( n1) , Some ( n2) ) => ( "two" , std:: cmp:: min ( n1, n2) , std:: cmp:: max ( n1, n2) ) ,
444+ ( Some ( n) , _) | ( _, Some ( n) ) => ( "any" , n, 0 ) ,
445+ ( None , None ) => {
446+ if let Some ( n) = expected_has_vid {
447+ ( "some" , n, 0 )
448+ } else {
449+ ( "nothing" , 0 , 0 )
459450 }
460451 }
452+ } ;
461453
462- note
463- } ) ;
454+ let note_1 = ActualImplExplNotes :: NoteOne {
455+ leading_ellipsis,
456+ kind,
457+ ty_or_sig,
458+ trait_path,
459+ lt_kind,
460+ lifetime_1,
461+ lifetime_2,
462+ } ;
464463
465464 let mut actual_trait_ref = highlight_trait_ref ( actual_trait_ref) ;
466465 actual_trait_ref. highlight . maybe_highlighting_region ( vid, actual_has_vid) ;
467- err. note ( & {
468- let passive_voice = match actual_has_vid {
469- Some ( _) => any_self_ty_has_vid,
470- None => true ,
471- } ;
472466
473- let mut note = if same_self_type {
474- format ! (
475- "...but it actually implements `{}`" ,
476- actual_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
477- )
478- } else if passive_voice {
479- format ! (
480- "...but `{}` is actually implemented for the type `{}`" ,
481- actual_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
482- actual_trait_ref. map( |tr| tr. self_ty( ) ) ,
483- )
484- } else {
485- format ! (
486- "...but `{}` actually implements `{}`" ,
487- actual_trait_ref. map( |tr| tr. self_ty( ) ) ,
488- actual_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
489- )
490- } ;
467+ let passive_voice = match actual_has_vid {
468+ Some ( _) => any_self_ty_has_vid,
469+ None => true ,
470+ } ;
491471
492- if let Some ( n) = actual_has_vid {
493- let _ = write ! ( note, ", for some specific lifetime `'{}`" , n) ;
494- }
472+ let trait_path_2 = actual_trait_ref. map ( |tr| tr. print_only_trait_path ( ) ) . to_string ( ) ;
473+ let ty = actual_trait_ref. map ( |tr| tr. self_ty ( ) ) . to_string ( ) ;
474+ let kind_2 = if same_self_type {
475+ "implements_trait"
476+ } else if passive_voice {
477+ "implemented_for_ty"
478+ } else {
479+ "ty_implements"
480+ } ;
495481
496- note
497- } ) ;
482+ let has_lifetime = actual_has_vid. is_some ( ) ;
483+ let lifetime = actual_has_vid. unwrap_or_default ( ) ;
484+
485+ let note_2 =
486+ ActualImplExplNotes :: NoteTwo { kind_2, trait_path_2, ty, has_lifetime, lifetime } ;
487+
488+ vec ! [ note_1, note_2]
498489 }
499490}
0 commit comments