@@ -353,13 +353,18 @@ struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
353
353
cx : & ' a LateContext < ' a , ' tcx > ,
354
354
}
355
355
356
+ struct FfiError {
357
+ message : & ' static str ,
358
+ help : Option < & ' static str > ,
359
+ }
360
+
356
361
enum FfiResult {
357
362
FfiSafe ,
358
363
FfiPhantom ,
359
- FfiUnsafe ( & ' static str ) ,
360
- FfiBadStruct ( DefId , & ' static str ) ,
361
- FfiBadUnion ( DefId , & ' static str ) ,
362
- FfiBadEnum ( DefId , & ' static str ) ,
364
+ FfiUnsafe ( FfiError ) ,
365
+ FfiBadStruct ( DefId , FfiError ) ,
366
+ FfiBadUnion ( DefId , FfiError ) ,
367
+ FfiBadEnum ( DefId , FfiError ) ,
363
368
}
364
369
365
370
/// Check if this enum can be safely exported based on the
@@ -434,14 +439,18 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
434
439
match def. adt_kind ( ) {
435
440
AdtKind :: Struct => {
436
441
if !def. repr . c ( ) && !def. repr . transparent ( ) {
437
- return FfiUnsafe ( "found struct without foreign-function-safe \
438
- representation annotation in foreign module, \
439
- consider adding a #[repr(C)] attribute to the type") ;
442
+ return FfiUnsafe ( FfiError {
443
+ message : "found struct without foreign-function-safe \
444
+ representation annotation in foreign module",
445
+ help : Some ( "consider adding a #[repr(C)] attribute to the type" ) ,
446
+ } ) ;
440
447
}
441
448
442
449
if def. non_enum_variant ( ) . fields . is_empty ( ) {
443
- return FfiUnsafe ( "found zero-size struct in foreign module, consider \
444
- adding a member to this struct") ;
450
+ return FfiUnsafe ( FfiError {
451
+ message : "found zero-size struct in foreign module" ,
452
+ help : Some ( "consider adding a member to this struct" ) ,
453
+ } ) ;
445
454
}
446
455
447
456
// We can't completely trust repr(C) and repr(transparent) markings;
@@ -471,8 +480,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
471
480
FfiBadStruct ( ..) | FfiBadUnion ( ..) | FfiBadEnum ( ..) => {
472
481
return r;
473
482
}
474
- FfiUnsafe ( s ) => {
475
- return FfiBadStruct ( def. did , s ) ;
483
+ FfiUnsafe ( err ) => {
484
+ return FfiBadStruct ( def. did , err ) ;
476
485
}
477
486
}
478
487
}
@@ -481,14 +490,18 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
481
490
}
482
491
AdtKind :: Union => {
483
492
if !def. repr . c ( ) {
484
- return FfiUnsafe ( "found union without foreign-function-safe \
485
- representation annotation in foreign module, \
486
- consider adding a #[repr(C)] attribute to the type") ;
493
+ return FfiUnsafe ( FfiError {
494
+ message : "found union without foreign-function-safe \
495
+ representation annotation in foreign module",
496
+ help : Some ( "consider adding a #[repr(C)] attribute to the type" ) ,
497
+ } ) ;
487
498
}
488
499
489
500
if def. non_enum_variant ( ) . fields . is_empty ( ) {
490
- return FfiUnsafe ( "found zero-size union in foreign module, consider \
491
- adding a member to this union") ;
501
+ return FfiUnsafe ( FfiError {
502
+ message : "found zero-size union in foreign module" ,
503
+ help : Some ( "consider adding a member to this union" ) ,
504
+ } ) ;
492
505
}
493
506
494
507
let mut all_phantom = true ;
@@ -505,8 +518,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
505
518
FfiBadStruct ( ..) | FfiBadUnion ( ..) | FfiBadEnum ( ..) => {
506
519
return r;
507
520
}
508
- FfiUnsafe ( s ) => {
509
- return FfiBadUnion ( def. did , s ) ;
521
+ FfiUnsafe ( err ) => {
522
+ return FfiBadUnion ( def. did , err ) ;
510
523
}
511
524
}
512
525
}
@@ -524,18 +537,23 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
524
537
if !def. repr . c ( ) && def. repr . int . is_none ( ) {
525
538
// Special-case types like `Option<extern fn()>`.
526
539
if !is_repr_nullable_ptr ( cx, def, substs) {
527
- return FfiUnsafe ( "found enum without foreign-function-safe \
528
- representation annotation in foreign \
529
- module, consider adding a #[repr(...)] \
530
- attribute to the type") ;
540
+ return FfiUnsafe ( FfiError {
541
+ message : "found enum without foreign-function-safe \
542
+ representation annotation in foreign module",
543
+ help : Some ( "consider adding a #[repr(...)] attribute \
544
+ to the type") ,
545
+ } ) ;
531
546
}
532
547
}
533
548
534
549
if let Some ( int_ty) = def. repr . int {
535
550
if !is_ffi_safe ( int_ty) {
536
551
// FIXME: This shouldn't be reachable: we should check
537
552
// this earlier.
538
- return FfiUnsafe ( "enum has unexpected #[repr(...)] attribute" ) ;
553
+ return FfiUnsafe ( FfiError {
554
+ message : "enum has unexpected #[repr(...)] attribute" ,
555
+ help : None ,
556
+ } ) ;
539
557
}
540
558
541
559
// Enum with an explicitly sized discriminant; either
@@ -558,11 +576,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
558
576
return r;
559
577
}
560
578
FfiPhantom => {
561
- return FfiBadEnum ( def. did ,
562
- "Found phantom data in enum variant" ) ;
579
+ return FfiBadEnum ( def. did , FfiError {
580
+ message : "Found phantom data in enum variant" ,
581
+ help : None ,
582
+ } ) ;
563
583
}
564
- FfiUnsafe ( s ) => {
565
- return FfiBadEnum ( def. did , s ) ;
584
+ FfiUnsafe ( err ) => {
585
+ return FfiBadEnum ( def. did , err ) ;
566
586
}
567
587
}
568
588
}
@@ -573,43 +593,57 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
573
593
}
574
594
575
595
ty:: TyChar => {
576
- FfiUnsafe ( "found Rust type `char` in foreign module, while \
577
- `u32` or `libc::wchar_t` should be used")
596
+ FfiUnsafe ( FfiError {
597
+ message : "found Rust type `char` in foreign module" ,
598
+ help : Some ( "consider using `u32` or `libc::wchar_t`" ) ,
599
+ } )
578
600
}
579
601
580
602
ty:: TyInt ( ast:: IntTy :: I128 ) => {
581
- FfiUnsafe ( "found Rust type `i128` in foreign module, but \
582
- 128-bit integers don't currently have a known \
583
- stable ABI")
603
+ FfiUnsafe ( FfiError {
604
+ message : "found Rust type `i128` in foreign module, but 128-bit \
605
+ integers don't currently have a known stable ABI",
606
+ help : None ,
607
+ } )
584
608
}
585
609
586
610
ty:: TyUint ( ast:: UintTy :: U128 ) => {
587
- FfiUnsafe ( "found Rust type `u128` in foreign module, but \
588
- 128-bit integers don't currently have a known \
589
- stable ABI")
611
+ FfiUnsafe ( FfiError {
612
+ message : "found Rust type `u128` in foreign module, but 128-bit \
613
+ integers don't currently have a known stable ABI",
614
+ help : None ,
615
+ } )
590
616
}
591
617
592
618
// Primitive types with a stable representation.
593
619
ty:: TyBool | ty:: TyInt ( ..) | ty:: TyUint ( ..) | ty:: TyFloat ( ..) | ty:: TyNever => FfiSafe ,
594
620
595
621
ty:: TySlice ( _) => {
596
- FfiUnsafe ( "found Rust slice type in foreign module, \
597
- consider using a raw pointer instead")
622
+ FfiUnsafe ( FfiError {
623
+ message : "found Rust slice type in foreign module" ,
624
+ help : Some ( "consider using a raw pointer instead" ) ,
625
+ } )
598
626
}
599
627
600
628
ty:: TyDynamic ( ..) => {
601
- FfiUnsafe ( "found Rust trait type in foreign module, \
602
- consider using a raw pointer instead")
629
+ FfiUnsafe ( FfiError {
630
+ message : "found Rust trait type in foreign module" ,
631
+ help : Some ( "consider using a raw pointer instead" ) ,
632
+ } )
603
633
}
604
634
605
635
ty:: TyStr => {
606
- FfiUnsafe ( "found Rust type `str` in foreign module; \
607
- consider using a `*const libc::c_char`")
636
+ FfiUnsafe ( FfiError {
637
+ message : "found Rust type `str` in foreign module" ,
638
+ help : Some ( "consider using a `*const libc::c_char`" ) ,
639
+ } )
608
640
}
609
641
610
642
ty:: TyTuple ( ..) => {
611
- FfiUnsafe ( "found Rust tuple type in foreign module; \
612
- consider using a struct instead")
643
+ FfiUnsafe ( FfiError {
644
+ message : "found Rust tuple type in foreign module" ,
645
+ help : Some ( "consider using a struct instead" ) ,
646
+ } )
613
647
}
614
648
615
649
ty:: TyRawPtr ( ref m) |
@@ -620,9 +654,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
620
654
ty:: TyFnPtr ( sig) => {
621
655
match sig. abi ( ) {
622
656
Abi :: Rust | Abi :: RustIntrinsic | Abi :: PlatformIntrinsic | Abi :: RustCall => {
623
- return FfiUnsafe ( "found function pointer with Rust calling convention in \
624
- foreign module; consider using an `extern` function \
625
- pointer")
657
+ return FfiUnsafe ( FfiError {
658
+ message : "found function pointer with Rust calling convention in \
659
+ foreign module",
660
+ help : Some ( "consider using an `extern` function pointer" ) ,
661
+ } )
626
662
}
627
663
_ => { }
628
664
}
@@ -676,34 +712,45 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
676
712
& format ! ( "found zero-sized type composed only \
677
713
of phantom-data in a foreign-function.") ) ;
678
714
}
679
- FfiResult :: FfiUnsafe ( s) => {
680
- self . cx . span_lint ( IMPROPER_CTYPES , sp, s) ;
715
+ FfiResult :: FfiUnsafe ( err) => {
716
+ let mut diag = self . cx . struct_span_lint ( IMPROPER_CTYPES , sp, err. message ) ;
717
+ if let Some ( s) = err. help {
718
+ diag. help ( s) ;
719
+ }
720
+ diag. emit ( ) ;
681
721
}
682
- FfiResult :: FfiBadStruct ( _, s ) => {
722
+ FfiResult :: FfiBadStruct ( _, err ) => {
683
723
// FIXME: This diagnostic is difficult to read, and doesn't
684
724
// point at the relevant field.
685
- self . cx . span_lint ( IMPROPER_CTYPES ,
686
- sp,
687
- & format ! ( "found non-foreign-function-safe member in struct \
688
- marked #[repr(C)]: {}",
689
- s) ) ;
725
+ let msg = format ! ( "found non-foreign-function-safe member in struct \
726
+ marked #[repr(C)]: {}", err. message) ;
727
+ let mut diag = self . cx . struct_span_lint ( IMPROPER_CTYPES , sp, & msg) ;
728
+ if let Some ( s) = err. help {
729
+ diag. help ( s) ;
730
+ }
731
+ diag. emit ( ) ;
690
732
}
691
- FfiResult :: FfiBadUnion ( _, s ) => {
733
+ FfiResult :: FfiBadUnion ( _, err ) => {
692
734
// FIXME: This diagnostic is difficult to read, and doesn't
693
735
// point at the relevant field.
694
- self . cx . span_lint ( IMPROPER_CTYPES ,
695
- sp,
696
- & format ! ( "found non-foreign-function-safe member in union \
697
- marked #[repr(C)]: {}",
698
- s) ) ;
736
+ let msg = format ! ( "found non-foreign-function-safe member in union \
737
+ marked #[repr(C)]: {}", err. message) ;
738
+ let mut diag = self . cx . struct_span_lint ( IMPROPER_CTYPES , sp, & msg) ;
739
+ if let Some ( s) = err. help {
740
+ diag. help ( s) ;
741
+ }
742
+ diag. emit ( ) ;
699
743
}
700
- FfiResult :: FfiBadEnum ( _, s ) => {
744
+ FfiResult :: FfiBadEnum ( _, err ) => {
701
745
// FIXME: This diagnostic is difficult to read, and doesn't
702
746
// point at the relevant variant.
703
- self . cx . span_lint ( IMPROPER_CTYPES ,
704
- sp,
705
- & format ! ( "found non-foreign-function-safe member in enum: {}" ,
706
- s) ) ;
747
+ let msg = format ! ( "found non-foreign-function-safe member in enum: {}" ,
748
+ err. message) ;
749
+ let mut diag = self . cx . struct_span_lint ( IMPROPER_CTYPES , sp, & msg) ;
750
+ if let Some ( s) = err. help {
751
+ diag. help ( s) ;
752
+ }
753
+ diag. emit ( ) ;
707
754
}
708
755
}
709
756
}
0 commit comments