@@ -324,86 +324,7 @@ pub(super) fn specialization_graph_provider(
324
324
} ;
325
325
326
326
if let Some ( overlap) = overlap {
327
- let impl_span =
328
- tcx. sess . source_map ( ) . def_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 ( ) . def_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) ;
407
328
}
408
329
} else {
409
330
let parent = tcx. impl_parent ( impl_def_id) . unwrap_or ( trait_id) ;
@@ -414,6 +335,168 @@ pub(super) fn specialization_graph_provider(
414
335
tcx. arena . alloc ( sg)
415
336
}
416
337
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 = tcx. sess . source_map ( ) . def_span ( tcx. span_of_impl ( local_impl_def_id) . unwrap ( ) ) ;
385
+ let mut err = struct_span_err ! (
386
+ tcx. sess,
387
+ impl_span,
388
+ E0748 ,
389
+ "found both positive and negative implementation of trait `{}`{}:" ,
390
+ overlap. trait_desc,
391
+ overlap. self_desc. clone( ) . map_or( String :: new( ) , |ty| format!( " for type `{}`" , ty) )
392
+ ) ;
393
+
394
+ match tcx. span_of_impl ( negative_impl_def_id) {
395
+ Ok ( span) => {
396
+ err. span_label (
397
+ tcx. sess . source_map ( ) . def_span ( span) ,
398
+ "negative implementation here" . to_string ( ) ,
399
+ ) ;
400
+ }
401
+ Err ( cname) => {
402
+ err. note ( & format ! ( "negative implementation in crate `{}`" , cname) ) ;
403
+ }
404
+ }
405
+
406
+ match tcx. span_of_impl ( positive_impl_def_id) {
407
+ Ok ( span) => {
408
+ err. span_label (
409
+ tcx. sess . source_map ( ) . def_span ( span) ,
410
+ "positive implementation here" . to_string ( ) ,
411
+ ) ;
412
+ }
413
+ Err ( cname) => {
414
+ err. note ( & format ! ( "positive implementation in crate `{}`" , cname) ) ;
415
+ }
416
+ }
417
+
418
+ sg. has_errored = true ;
419
+ err. emit ( ) ;
420
+ }
421
+
422
+ fn report_conflicting_impls (
423
+ tcx : TyCtxt < ' _ > ,
424
+ overlap : OverlapError ,
425
+ impl_def_id : DefId ,
426
+ used_to_be_allowed : Option < FutureCompatOverlapErrorKind > ,
427
+ sg : & mut specialization_graph:: Graph ,
428
+ ) {
429
+ let impl_span = tcx. sess . source_map ( ) . def_span ( tcx. span_of_impl ( impl_def_id) . unwrap ( ) ) ;
430
+
431
+ // Work to be done after we've built the DiagnosticBuilder. We have to define it
432
+ // now because the struct_lint methods don't return back the DiagnosticBuilder
433
+ // that's passed in.
434
+ let decorate = |err : LintDiagnosticBuilder < ' _ > | {
435
+ let msg = format ! (
436
+ "conflicting implementations of trait `{}`{}:{}" ,
437
+ overlap. trait_desc,
438
+ overlap. self_desc. clone( ) . map_or( String :: new( ) , |ty| { format!( " for type `{}`" , ty) } ) ,
439
+ match used_to_be_allowed {
440
+ Some ( FutureCompatOverlapErrorKind :: Issue33140 ) => " (E0119)" ,
441
+ _ => "" ,
442
+ }
443
+ ) ;
444
+ let mut err = err. build ( & msg) ;
445
+ match tcx. span_of_impl ( overlap. with_impl ) {
446
+ Ok ( span) => {
447
+ err. span_label (
448
+ tcx. sess . source_map ( ) . def_span ( span) ,
449
+ "first implementation here" . to_string ( ) ,
450
+ ) ;
451
+
452
+ err. span_label (
453
+ impl_span,
454
+ format ! (
455
+ "conflicting implementation{}" ,
456
+ overlap. self_desc. map_or( String :: new( ) , |ty| format!( " for `{}`" , ty) )
457
+ ) ,
458
+ ) ;
459
+ }
460
+ Err ( cname) => {
461
+ let msg = match to_pretty_impl_header ( tcx, overlap. with_impl ) {
462
+ Some ( s) => format ! ( "conflicting implementation in crate `{}`:\n - {}" , cname, s) ,
463
+ None => format ! ( "conflicting implementation in crate `{}`" , cname) ,
464
+ } ;
465
+ err. note ( & msg) ;
466
+ }
467
+ }
468
+
469
+ for cause in & overlap. intercrate_ambiguity_causes {
470
+ cause. add_intercrate_ambiguity_hint ( & mut err) ;
471
+ }
472
+
473
+ if overlap. involves_placeholder {
474
+ coherence:: add_placeholder_note ( & mut err) ;
475
+ }
476
+ err. emit ( )
477
+ } ;
478
+
479
+ match used_to_be_allowed {
480
+ None => {
481
+ sg. has_errored = true ;
482
+ let err = struct_span_err ! ( tcx. sess, impl_span, E0119 , "" ) ;
483
+ decorate ( LintDiagnosticBuilder :: new ( err) ) ;
484
+ }
485
+ Some ( kind) => {
486
+ let lint = match kind {
487
+ FutureCompatOverlapErrorKind :: Issue33140 => ORDER_DEPENDENT_TRAIT_OBJECTS ,
488
+ FutureCompatOverlapErrorKind :: LeakCheck => COHERENCE_LEAK_CHECK ,
489
+ } ;
490
+ tcx. struct_span_lint_hir (
491
+ lint,
492
+ tcx. hir ( ) . as_local_hir_id ( impl_def_id) . unwrap ( ) ,
493
+ impl_span,
494
+ decorate,
495
+ )
496
+ }
497
+ } ;
498
+ }
499
+
417
500
/// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a
418
501
/// string.
419
502
fn to_pretty_impl_header ( tcx : TyCtxt < ' _ > , impl_def_id : DefId ) -> Option < String > {
0 commit comments