@@ -339,6 +339,7 @@ struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
339339
340340enum FfiResult {
341341 FfiSafe ,
342+ FfiPhantom ,
342343 FfiUnsafe ( & ' static str ) ,
343344 FfiBadStruct ( DefId , & ' static str ) ,
344345 FfiBadUnion ( DefId , & ' static str ) ,
@@ -383,8 +384,11 @@ fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
383384impl < ' a , ' tcx > ImproperCTypesVisitor < ' a , ' tcx > {
384385 /// Check if the given type is "ffi-safe" (has a stable, well-defined
385386 /// representation which can be exported to C code).
386- fn check_type_for_ffi ( & self , cache : & mut FxHashSet < Ty < ' tcx > > , ty : Ty < ' tcx > ) -> FfiResult {
387+ fn check_type_for_ffi ( & self ,
388+ cache : & mut FxHashSet < Ty < ' tcx > > ,
389+ ty : Ty < ' tcx > ) -> FfiResult {
387390 use self :: FfiResult :: * ;
391+
388392 let cx = self . cx . tcx ;
389393
390394 // Protect against infinite recursion, for example
@@ -397,6 +401,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
397401
398402 match ty. sty {
399403 ty:: TyAdt ( def, substs) => {
404+ if def. is_phantom_data ( ) {
405+ return FfiPhantom ;
406+ }
400407 match def. adt_kind ( ) {
401408 AdtKind :: Struct => {
402409 if !cx. lookup_repr_hints ( def. did ) . contains ( & attr:: ReprExtern ) {
@@ -405,18 +412,22 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
405412 consider adding a #[repr(C)] attribute to the type") ;
406413 }
407414
408- // We can't completely trust repr(C) markings; make sure the
409- // fields are actually safe.
410415 if def. struct_variant ( ) . fields . is_empty ( ) {
411416 return FfiUnsafe ( "found zero-size struct in foreign module, consider \
412417 adding a member to this struct") ;
413418 }
414419
420+ // We can't completely trust repr(C) markings; make sure the
421+ // fields are actually safe.
422+ let mut all_phantom = true ;
415423 for field in & def. struct_variant ( ) . fields {
416424 let field_ty = cx. normalize_associated_type ( & field. ty ( cx, substs) ) ;
417425 let r = self . check_type_for_ffi ( cache, field_ty) ;
418426 match r {
419- FfiSafe => { }
427+ FfiSafe => {
428+ all_phantom = false ;
429+ }
430+ FfiPhantom => { }
420431 FfiBadStruct ( ..) | FfiBadUnion ( ..) | FfiBadEnum ( ..) => {
421432 return r;
422433 }
@@ -425,7 +436,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
425436 }
426437 }
427438 }
428- FfiSafe
439+
440+ if all_phantom { FfiPhantom } else { FfiSafe }
429441 }
430442 AdtKind :: Union => {
431443 if !cx. lookup_repr_hints ( def. did ) . contains ( & attr:: ReprExtern ) {
@@ -434,11 +446,20 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
434446 consider adding a #[repr(C)] attribute to the type") ;
435447 }
436448
449+ if def. struct_variant ( ) . fields . is_empty ( ) {
450+ return FfiUnsafe ( "found zero-size union in foreign module, consider \
451+ adding a member to this union") ;
452+ }
453+
454+ let mut all_phantom = true ;
437455 for field in & def. struct_variant ( ) . fields {
438456 let field_ty = cx. normalize_associated_type ( & field. ty ( cx, substs) ) ;
439457 let r = self . check_type_for_ffi ( cache, field_ty) ;
440458 match r {
441- FfiSafe => { }
459+ FfiSafe => {
460+ all_phantom = false ;
461+ }
462+ FfiPhantom => { }
442463 FfiBadStruct ( ..) | FfiBadUnion ( ..) | FfiBadEnum ( ..) => {
443464 return r;
444465 }
@@ -447,7 +468,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
447468 }
448469 }
449470 }
450- FfiSafe
471+
472+ if all_phantom { FfiPhantom } else { FfiSafe }
451473 }
452474 AdtKind :: Enum => {
453475 if def. variants . is_empty ( ) {
@@ -498,6 +520,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
498520 FfiBadStruct ( ..) | FfiBadUnion ( ..) | FfiBadEnum ( ..) => {
499521 return r;
500522 }
523+ FfiPhantom => {
524+ return FfiBadEnum ( def. did ,
525+ "Found phantom data in enum variant" ) ;
526+ }
501527 FfiUnsafe ( s) => {
502528 return FfiBadEnum ( def. did , s) ;
503529 }
@@ -591,6 +617,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
591617
592618 match self . check_type_for_ffi ( & mut FxHashSet ( ) , ty) {
593619 FfiResult :: FfiSafe => { }
620+ FfiResult :: FfiPhantom => {
621+ self . cx . span_lint ( IMPROPER_CTYPES ,
622+ sp,
623+ & format ! ( "found zero-sized type composed only \
624+ of phantom-data in a foreign-function.") ) ;
625+ }
594626 FfiResult :: FfiUnsafe ( s) => {
595627 self . cx . span_lint ( IMPROPER_CTYPES , sp, s) ;
596628 }
0 commit comments