@@ -324,86 +324,7 @@ pub(super) fn specialization_graph_provider(
324324 } ;
325325
326326 if let Some ( overlap) = overlap {
327- let impl_span =
328- tcx. sess . source_map ( ) . guess_head_span ( tcx. span_of_impl ( impl_def_id) . unwrap ( ) ) ;
329-
330- // Work to be done after we've built the DiagnosticBuilder. We have to define it
331- // now because the struct_lint methods don't return back the DiagnosticBuilder
332- // that's passed in.
333- let decorate = |err : LintDiagnosticBuilder < ' _ > | {
334- let msg = format ! (
335- "conflicting implementations of trait `{}`{}:{}" ,
336- overlap. trait_desc,
337- overlap
338- . self_desc
339- . clone( )
340- . map_or( String :: new( ) , |ty| { format!( " for type `{}`" , ty) } ) ,
341- match used_to_be_allowed {
342- Some ( FutureCompatOverlapErrorKind :: Issue33140 ) => " (E0119)" ,
343- _ => "" ,
344- }
345- ) ;
346- let mut err = err. build ( & msg) ;
347- match tcx. span_of_impl ( overlap. with_impl ) {
348- Ok ( span) => {
349- err. span_label (
350- tcx. sess . source_map ( ) . guess_head_span ( span) ,
351- "first implementation here" . to_string ( ) ,
352- ) ;
353-
354- err. span_label (
355- impl_span,
356- format ! (
357- "conflicting implementation{}" ,
358- overlap
359- . self_desc
360- . map_or( String :: new( ) , |ty| format!( " for `{}`" , ty) )
361- ) ,
362- ) ;
363- }
364- Err ( cname) => {
365- let msg = match to_pretty_impl_header ( tcx, overlap. with_impl ) {
366- Some ( s) => format ! (
367- "conflicting implementation in crate `{}`:\n - {}" ,
368- cname, s
369- ) ,
370- None => format ! ( "conflicting implementation in crate `{}`" , cname) ,
371- } ;
372- err. note ( & msg) ;
373- }
374- }
375-
376- for cause in & overlap. intercrate_ambiguity_causes {
377- cause. add_intercrate_ambiguity_hint ( & mut err) ;
378- }
379-
380- if overlap. involves_placeholder {
381- coherence:: add_placeholder_note ( & mut err) ;
382- }
383- err. emit ( )
384- } ;
385-
386- match used_to_be_allowed {
387- None => {
388- sg. has_errored = true ;
389- let err = struct_span_err ! ( tcx. sess, impl_span, E0119 , "" ) ;
390- decorate ( LintDiagnosticBuilder :: new ( err) ) ;
391- }
392- Some ( kind) => {
393- let lint = match kind {
394- FutureCompatOverlapErrorKind :: Issue33140 => {
395- ORDER_DEPENDENT_TRAIT_OBJECTS
396- }
397- FutureCompatOverlapErrorKind :: LeakCheck => COHERENCE_LEAK_CHECK ,
398- } ;
399- tcx. struct_span_lint_hir (
400- lint,
401- tcx. hir ( ) . as_local_hir_id ( impl_def_id) . unwrap ( ) ,
402- impl_span,
403- decorate,
404- )
405- }
406- } ;
327+ report_overlap_conflict ( tcx, overlap, impl_def_id, used_to_be_allowed, & mut sg) ;
407328 }
408329 } else {
409330 let parent = tcx. impl_parent ( impl_def_id) . unwrap_or ( trait_id) ;
@@ -414,6 +335,170 @@ pub(super) fn specialization_graph_provider(
414335 tcx. arena . alloc ( sg)
415336}
416337
338+ fn report_overlap_conflict (
339+ tcx : TyCtxt < ' _ > ,
340+ overlap : OverlapError ,
341+ impl_def_id : DefId ,
342+ used_to_be_allowed : Option < FutureCompatOverlapErrorKind > ,
343+ sg : & mut specialization_graph:: Graph ,
344+ ) {
345+ let impl_polarity = tcx. impl_polarity ( impl_def_id) ;
346+ let other_polarity = tcx. impl_polarity ( overlap. with_impl ) ;
347+ match ( impl_polarity, other_polarity) {
348+ ( ty:: ImplPolarity :: Negative , ty:: ImplPolarity :: Positive ) => {
349+ report_negative_positive_conflict (
350+ tcx,
351+ & overlap,
352+ impl_def_id,
353+ impl_def_id,
354+ overlap. with_impl ,
355+ sg,
356+ ) ;
357+ }
358+
359+ ( ty:: ImplPolarity :: Positive , ty:: ImplPolarity :: Negative ) => {
360+ report_negative_positive_conflict (
361+ tcx,
362+ & overlap,
363+ impl_def_id,
364+ overlap. with_impl ,
365+ impl_def_id,
366+ sg,
367+ ) ;
368+ }
369+
370+ _ => {
371+ report_conflicting_impls ( tcx, overlap, impl_def_id, used_to_be_allowed, sg) ;
372+ }
373+ }
374+ }
375+
376+ fn report_negative_positive_conflict (
377+ tcx : TyCtxt < ' _ > ,
378+ overlap : & OverlapError ,
379+ local_impl_def_id : DefId ,
380+ negative_impl_def_id : DefId ,
381+ positive_impl_def_id : DefId ,
382+ sg : & mut specialization_graph:: Graph ,
383+ ) {
384+ let impl_span =
385+ tcx. sess . source_map ( ) . guess_head_span ( tcx. span_of_impl ( local_impl_def_id) . unwrap ( ) ) ;
386+
387+ let mut err = struct_span_err ! (
388+ tcx. sess,
389+ impl_span,
390+ E0748 ,
391+ "found both positive and negative implementation of trait `{}`{}:" ,
392+ overlap. trait_desc,
393+ overlap. self_desc. clone( ) . map_or( String :: new( ) , |ty| format!( " for type `{}`" , ty) )
394+ ) ;
395+
396+ match tcx. span_of_impl ( negative_impl_def_id) {
397+ Ok ( span) => {
398+ err. span_label (
399+ tcx. sess . source_map ( ) . guess_head_span ( span) ,
400+ "negative implementation here" . to_string ( ) ,
401+ ) ;
402+ }
403+ Err ( cname) => {
404+ err. note ( & format ! ( "negative implementation in crate `{}`" , cname) ) ;
405+ }
406+ }
407+
408+ match tcx. span_of_impl ( positive_impl_def_id) {
409+ Ok ( span) => {
410+ err. span_label (
411+ tcx. sess . source_map ( ) . guess_head_span ( span) ,
412+ "positive implementation here" . to_string ( ) ,
413+ ) ;
414+ }
415+ Err ( cname) => {
416+ err. note ( & format ! ( "positive implementation in crate `{}`" , cname) ) ;
417+ }
418+ }
419+
420+ sg. has_errored = true ;
421+ err. emit ( ) ;
422+ }
423+
424+ fn report_conflicting_impls (
425+ tcx : TyCtxt < ' _ > ,
426+ overlap : OverlapError ,
427+ impl_def_id : DefId ,
428+ used_to_be_allowed : Option < FutureCompatOverlapErrorKind > ,
429+ sg : & mut specialization_graph:: Graph ,
430+ ) {
431+ let impl_span = tcx. sess . source_map ( ) . guess_head_span ( tcx. span_of_impl ( impl_def_id) . unwrap ( ) ) ;
432+
433+ // Work to be done after we've built the DiagnosticBuilder. We have to define it
434+ // now because the struct_lint methods don't return back the DiagnosticBuilder
435+ // that's passed in.
436+ let decorate = |err : LintDiagnosticBuilder < ' _ > | {
437+ let msg = format ! (
438+ "conflicting implementations of trait `{}`{}:{}" ,
439+ overlap. trait_desc,
440+ overlap. self_desc. clone( ) . map_or( String :: new( ) , |ty| { format!( " for type `{}`" , ty) } ) ,
441+ match used_to_be_allowed {
442+ Some ( FutureCompatOverlapErrorKind :: Issue33140 ) => " (E0119)" ,
443+ _ => "" ,
444+ }
445+ ) ;
446+ let mut err = err. build ( & msg) ;
447+ match tcx. span_of_impl ( overlap. with_impl ) {
448+ Ok ( span) => {
449+ err. span_label (
450+ tcx. sess . source_map ( ) . guess_head_span ( span) ,
451+ "first implementation here" . to_string ( ) ,
452+ ) ;
453+
454+ err. span_label (
455+ impl_span,
456+ format ! (
457+ "conflicting implementation{}" ,
458+ overlap. self_desc. map_or( String :: new( ) , |ty| format!( " for `{}`" , ty) )
459+ ) ,
460+ ) ;
461+ }
462+ Err ( cname) => {
463+ let msg = match to_pretty_impl_header ( tcx, overlap. with_impl ) {
464+ Some ( s) => format ! ( "conflicting implementation in crate `{}`:\n - {}" , cname, s) ,
465+ None => format ! ( "conflicting implementation in crate `{}`" , cname) ,
466+ } ;
467+ err. note ( & msg) ;
468+ }
469+ }
470+
471+ for cause in & overlap. intercrate_ambiguity_causes {
472+ cause. add_intercrate_ambiguity_hint ( & mut err) ;
473+ }
474+
475+ if overlap. involves_placeholder {
476+ coherence:: add_placeholder_note ( & mut err) ;
477+ }
478+ err. emit ( )
479+ } ;
480+
481+ match used_to_be_allowed {
482+ None => {
483+ sg. has_errored = true ;
484+ let err = struct_span_err ! ( tcx. sess, impl_span, E0119 , "" ) ;
485+ decorate ( LintDiagnosticBuilder :: new ( err) ) ;
486+ }
487+ Some ( kind) => {
488+ let lint = match kind {
489+ FutureCompatOverlapErrorKind :: Issue33140 => ORDER_DEPENDENT_TRAIT_OBJECTS ,
490+ FutureCompatOverlapErrorKind :: LeakCheck => COHERENCE_LEAK_CHECK ,
491+ } ;
492+ tcx. struct_span_lint_hir (
493+ lint,
494+ tcx. hir ( ) . as_local_hir_id ( impl_def_id) . unwrap ( ) ,
495+ impl_span,
496+ decorate,
497+ )
498+ }
499+ } ;
500+ }
501+
417502/// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a
418503/// string.
419504fn to_pretty_impl_header ( tcx : TyCtxt < ' _ > , impl_def_id : DefId ) -> Option < String > {
0 commit comments