@@ -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 ( ) . 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) ;
407
328
}
408
329
} else {
409
330
let parent = tcx. impl_parent ( impl_def_id) . unwrap_or ( trait_id) ;
@@ -414,6 +335,170 @@ 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 =
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
+
417
502
/// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a
418
503
/// string.
419
504
fn to_pretty_impl_header ( tcx : TyCtxt < ' _ > , impl_def_id : DefId ) -> Option < String > {
0 commit comments