@@ -148,61 +148,25 @@ impl<'tcx> FfiResult<'tcx> {
148
148
}
149
149
150
150
impl < ' tcx > std:: ops:: AddAssign < FfiResult < ' tcx > > for FfiResult < ' tcx > {
151
- fn add_assign ( & mut self , mut other : Self ) {
151
+ fn add_assign ( & mut self , other : Self ) {
152
152
// note: we shouldn't really encounter FfiPhantoms here, they should be dealt with beforehand
153
153
// still, this function deals with them in a reasonable way, I think
154
154
155
- // this function is awful to look but that's because matching mutable references consumes them (?!)
156
- // the function itself imitates the following piece of non-compiling code:
157
-
158
- // match (self, other) {
159
- // (Self::FfiUnsafe(_), _) => {
160
- // // nothing to do
161
- // },
162
- // (_, Self::FfiUnsafe(_)) => {
163
- // *self = other;
164
- // },
165
- // (Self::FfiPhantom(ref ty1),Self::FfiPhantom(ty2)) => {
166
- // println!("whoops, both FfiPhantom: self({:?}) += other({:?})", ty1, ty2);
167
- // },
168
- // (Self::FfiSafe,Self::FfiPhantom(_)) => {
169
- // *self = other;
170
- // },
171
- // (_, Self::FfiSafe) => {
172
- // // nothing to do
173
- // },
174
- // }
175
-
176
- let s_disc = std:: mem:: discriminant ( self ) ;
177
- let o_disc = std:: mem:: discriminant ( & other) ;
178
- if s_disc == o_disc {
179
- match ( self , & mut other) {
180
- ( Self :: FfiUnsafe ( s_inner) , Self :: FfiUnsafe ( o_inner) ) => {
181
- s_inner. append ( o_inner) ;
182
- }
183
- ( Self :: FfiPhantom ( ty1) , Self :: FfiPhantom ( ty2) ) => {
184
- debug ! ( "whoops: both FfiPhantom, self({:?}) += other({:?})" , ty1, ty2) ;
185
- }
186
- ( Self :: FfiSafe , Self :: FfiSafe ) => { }
187
- _ => unreachable ! ( ) ,
155
+ match ( self , other) {
156
+ ( Self :: FfiUnsafe ( _) , _) => {
157
+ // nothing to do
188
158
}
189
- } else {
190
- if let Self :: FfiUnsafe ( _) = self {
191
- return ;
159
+ ( myself, other @ Self :: FfiUnsafe ( _) ) => {
160
+ * myself = other;
192
161
}
193
- match other {
194
- Self :: FfiUnsafe ( o_inner) => {
195
- // self is Safe or Phantom: Unsafe wins
196
- * self = Self :: FfiUnsafe ( o_inner) ;
197
- }
198
- Self :: FfiSafe => {
199
- // self is always "wins"
200
- return ;
201
- }
202
- Self :: FfiPhantom ( o_inner) => {
203
- // self is Safe: Phantom wins
204
- * self = Self :: FfiPhantom ( o_inner) ;
205
- }
162
+ ( Self :: FfiPhantom ( ty1) , Self :: FfiPhantom ( ty2) ) => {
163
+ debug ! ( "whoops, both FfiPhantom: self({:?}) += other({:?})" , ty1, ty2) ;
164
+ }
165
+ ( myself @ Self :: FfiSafe , other @ Self :: FfiPhantom ( _) ) => {
166
+ * myself = other;
167
+ }
168
+ ( _, Self :: FfiSafe ) => {
169
+ // nothing to do
206
170
}
207
171
}
208
172
}
@@ -215,7 +179,7 @@ impl<'tcx> std::ops::Add<FfiResult<'tcx>> for FfiResult<'tcx> {
215
179
}
216
180
}
217
181
218
- /// Determine if a type is sized or not, and wether it affects references/pointers/boxes to it
182
+ /// Determine if a type is sized or not, and whether it affects references/pointers/boxes to it
219
183
#[ derive( Clone , Copy ) ]
220
184
enum TypeSizedness {
221
185
/// type of definite size (pointers are C-compatible)
@@ -354,51 +318,63 @@ fn get_type_sizedness<'tcx, 'a>(cx: &'a LateContext<'tcx>, ty: Ty<'tcx>) -> Type
354
318
}
355
319
}
356
320
321
+ #[ allow( non_snake_case) ]
322
+ mod CTypesVisitorStateFlags {
323
+ pub ( super ) const NO_FLAGS : u8 = 0b0000 ;
324
+ /// for static variables (not used in functions)
325
+ pub ( super ) const STATIC : u8 = 0b0010 ;
326
+ /// for variables in function returns (implicitly: not for static variables)
327
+ pub ( super ) const FN_RETURN : u8 = 0b0100 ;
328
+ /// for variables in functions which are defined in rust (implicitly: not for static variables)
329
+ pub ( super ) const FN_DECLARED : u8 = 0b1000 ;
330
+ }
331
+
357
332
#[ repr( u8 ) ]
358
333
#[ derive( Clone , Copy , Debug ) ]
359
334
enum CTypesVisitorState {
360
- // bitflags:
361
- // 0010: static
362
- // 0100: function return
363
- // 1000: used in declared function
364
- StaticTy = 0b0010 ,
365
- ArgumentTyInDefinition = 0b1000 ,
366
- ReturnTyInDefinition = 0b1100 ,
367
- ArgumentTyInDeclaration = 0b0000 ,
368
- ReturnTyInDeclaration = 0b0100 ,
335
+ // uses bitflags from CTypesVisitorStateFlags
336
+ StaticTy = CTypesVisitorStateFlags :: STATIC ,
337
+ ArgumentTyInDefinition = CTypesVisitorStateFlags :: FN_DECLARED ,
338
+ ReturnTyInDefinition =
339
+ CTypesVisitorStateFlags :: FN_DECLARED | CTypesVisitorStateFlags :: FN_RETURN ,
340
+ ArgumentTyInDeclaration = CTypesVisitorStateFlags :: NO_FLAGS ,
341
+ ReturnTyInDeclaration = CTypesVisitorStateFlags :: FN_RETURN ,
369
342
}
370
343
371
344
impl CTypesVisitorState {
372
- /// wether the type is used (directly or not) in a static variable
345
+ /// whether the type is used (directly or not) in a static variable
373
346
fn is_in_static ( self ) -> bool {
374
- ( ( self as u8 ) & 0b0010 ) != 0
347
+ use CTypesVisitorStateFlags :: * ;
348
+ ( ( self as u8 ) & STATIC ) != 0
375
349
}
376
- /// wether the type is used (directly or not) in a function, in return position
350
+ /// whether the type is used (directly or not) in a function, in return position
377
351
fn is_in_function_return ( self ) -> bool {
378
- let ret = ( ( self as u8 ) & 0b0100 ) != 0 ;
352
+ use CTypesVisitorStateFlags :: * ;
353
+ let ret = ( ( self as u8 ) & FN_RETURN ) != 0 ;
379
354
#[ cfg( debug_assertions) ]
380
355
if ret {
381
356
assert ! ( !self . is_in_static( ) ) ;
382
357
}
383
358
ret
384
359
}
385
- /// wether the type is used (directly or not) in a defined function
386
- /// in other words, wether or not we allow non-FFI-safe types behind a C pointer,
360
+ /// whether the type is used (directly or not) in a defined function
361
+ /// in other words, whether or not we allow non-FFI-safe types behind a C pointer,
387
362
/// to be treated as an opaque type on the other side of the FFI boundary
388
363
fn is_in_defined_function ( self ) -> bool {
389
- let ret = ( ( self as u8 ) & 0b1000 ) != 0 ;
364
+ use CTypesVisitorStateFlags :: * ;
365
+ let ret = ( ( self as u8 ) & FN_DECLARED ) != 0 ;
390
366
#[ cfg( debug_assertions) ]
391
367
if ret {
392
368
assert ! ( !self . is_in_static( ) ) ;
393
369
}
394
370
ret
395
371
}
396
372
397
- /// wether the value for that type might come from the non-rust side of a FFI boundary
373
+ /// whether the value for that type might come from the non-rust side of a FFI boundary
398
374
fn value_may_be_unchecked ( self ) -> bool {
399
375
// function declarations are assumed to be rust-caller, non-rust-callee
400
376
// function definitions are assumed to be maybe-not-rust-caller, rust-callee
401
- // FnPtrs are... well, nothing's certain about anything. (TODO need more flags in enum?)
377
+ // FnPtrs are... well, nothing's certain about anything. (FIXME need more flags in enum?)
402
378
// Same with statics.
403
379
if self . is_in_static ( ) {
404
380
true
@@ -411,7 +387,7 @@ impl CTypesVisitorState {
411
387
}
412
388
413
389
impl < ' a , ' tcx > ImproperCTypesVisitor < ' a , ' tcx > {
414
- /// Checks wether an `extern "ABI" fn` function pointer is indeed FFI-safe to call
390
+ /// Checks whether an `extern "ABI" fn` function pointer is indeed FFI-safe to call
415
391
fn visit_fnptr ( & mut self , mode : CItemKind , ty : Ty < ' tcx > , sig : Sig < ' tcx > ) -> FfiResult < ' tcx > {
416
392
use FfiResult :: * ;
417
393
debug_assert ! ( !sig. abi( ) . is_rustic_abi( ) ) ;
@@ -534,7 +510,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
534
510
// there are three remaining concerns with the pointer:
535
511
// - is the pointer compatible with a C pointer in the first place? (if not, only send that error message)
536
512
// - is the pointee FFI-safe? (it might not matter, see mere lines below)
537
- // - does the pointer type contain a non-zero assumption, but a value given by non-rust code?
513
+ // - does the pointer type contain a non-zero assumption, but has a value given by non-rust code?
538
514
// this block deals with the first two.
539
515
let mut ffi_res = match get_type_sizedness ( self . cx , inner_ty) {
540
516
TypeSizedness :: UnsizedWithExternType | TypeSizedness :: Definite => {
@@ -583,7 +559,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
583
559
// 'fake' declarations (in traits, needed to be implemented elsewhere), and definitions.
584
560
// (for instance, definitions should worry about &self with Self:?Sized, but fake declarations shouldn't)
585
561
586
- // wether they are FFI-safe or not does not depend on the indirections involved (&Self, &T, Box<impl Trait>),
562
+ // whether they are FFI-safe or not does not depend on the indirections involved (&Self, &T, Box<impl Trait>),
587
563
// so let's not wrap the current context around a potential FfiUnsafe type param.
588
564
self . visit_type ( state, Some ( ty) , inner_ty)
589
565
}
@@ -603,6 +579,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
603
579
} ;
604
580
605
581
// and now the third concern (does the pointer type contain a non-zero assumption, and is the value given by non-rust code?)
582
+ // technically, pointers with non-rust-given values could also be misaligned, pointing to the wrong thing, or outright dangling, but we assume they never are
606
583
ffi_res += if state. value_may_be_unchecked ( ) {
607
584
let has_nonnull_assumption = match indirection_type {
608
585
IndirectionType :: RawPtr => false ,
@@ -758,18 +735,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
758
735
759
736
if def. variants ( ) . is_empty ( ) {
760
737
// Empty enums are implicitely handled as the never type:
761
- // TODO think about the FFI-safety of functions that use that
738
+ // FIXME think about the FFI-safety of functions that use that
762
739
return FfiSafe ;
763
740
}
764
741
// Check for a repr() attribute to specify the size of the
765
742
// discriminant.
766
743
if !def. repr ( ) . c ( ) && !def. repr ( ) . transparent ( ) && def. repr ( ) . int . is_none ( ) {
767
744
// Special-case types like `Option<extern fn()>` and `Result<extern fn(), ()>`
768
- if let Some ( inner_ty) = repr_nullable_ptr (
769
- self . cx . tcx ,
770
- self . cx . typing_env ( ) ,
771
- ty,
772
- ) {
745
+ if let Some ( inner_ty) = repr_nullable_ptr ( self . cx . tcx , self . cx . typing_env ( ) , ty) {
773
746
return self . visit_type ( state, Some ( ty) , inner_ty) ;
774
747
}
775
748
@@ -781,11 +754,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
781
754
}
782
755
783
756
if let Some ( IntegerType :: Fixed ( Integer :: I128 , _) ) = def. repr ( ) . int {
784
- return FfiResult :: new_with_reason (
785
- ty,
786
- fluent:: lint_improper_ctypes_128bit,
787
- None ,
788
- ) ;
757
+ return FfiResult :: new_with_reason ( ty, fluent:: lint_improper_ctypes_128bit, None ) ;
789
758
}
790
759
791
760
let non_exhaustive = def. variant_list_has_applicable_non_exhaustive ( ) ;
@@ -811,7 +780,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
811
780
. iter ( )
812
781
. map ( |variant| {
813
782
self . visit_variant_fields ( state, ty, def, variant, args)
814
- // TODO : check that enums allow any (up to all) variants to be phantoms?
783
+ // FIXME : check that enums allow any (up to all) variants to be phantoms?
815
784
// (previous code says no, but I don't know why? the problem with phantoms is that they're ZSTs, right?)
816
785
. forbid_phantom ( )
817
786
} )
@@ -856,11 +825,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
856
825
}
857
826
match def. adt_kind ( ) {
858
827
AdtKind :: Struct | AdtKind :: Union => {
859
- // I thought CStr (not CString) could not be reached here :
860
- // - not using an indirection would cause a compile error prior to this lint
828
+ // I thought CStr (not CString) here could only be reached in non-compiling code :
829
+ // - not using an indirection would cause a compile error (this lint *currently* seems to not get triggered on such non-compiling code)
861
830
// - and using one would cause the lint to catch on the indirection before reaching its pointee
862
- // but for some reason one can just go and write function *pointers* like that:
863
- // `type Foo = extern "C" fn(::std::ffi::CStr);`
831
+ // but function *pointers* don't seem to have the same no-unsized-parameters requirement to compile
864
832
if let Some ( sym:: cstring_type | sym:: cstr_type) =
865
833
tcx. get_diagnostic_name ( def. did ( ) )
866
834
{
@@ -1107,10 +1075,7 @@ struct ImproperCTypesLint<'c, 'tcx> {
1107
1075
}
1108
1076
1109
1077
impl < ' c , ' tcx > ImproperCTypesLint < ' c , ' tcx > {
1110
- fn check_arg_for_power_alignment (
1111
- & mut self ,
1112
- ty : Ty < ' tcx > ,
1113
- ) -> bool {
1078
+ fn check_arg_for_power_alignment ( & mut self , ty : Ty < ' tcx > ) -> bool {
1114
1079
let tcx = self . cx . tcx ;
1115
1080
assert ! ( tcx. sess. target. os == "aix" ) ;
1116
1081
// Structs (under repr(C)) follow the power alignment rule if:
@@ -1141,10 +1106,7 @@ impl<'c, 'tcx> ImproperCTypesLint<'c, 'tcx> {
1141
1106
return false ;
1142
1107
}
1143
1108
1144
- fn check_struct_for_power_alignment (
1145
- & mut self ,
1146
- item : & ' tcx hir:: Item < ' tcx > ,
1147
- ) {
1109
+ fn check_struct_for_power_alignment ( & mut self , item : & ' tcx hir:: Item < ' tcx > ) {
1148
1110
let tcx = self . cx . tcx ;
1149
1111
let adt_def = tcx. adt_def ( item. owner_id . to_def_id ( ) ) ;
1150
1112
// repr(C) structs also with packed or aligned representation
@@ -1228,7 +1190,7 @@ impl<'c, 'tcx> ImproperCTypesLint<'c, 'tcx> {
1228
1190
( span, ffi_res)
1229
1191
} )
1230
1192
// even in function *definitions*, `FnPtr`s are always function declarations ...right?
1231
- // (TODO : we can't do that yet because one of rustc's crates can't compile if we do)
1193
+ // (FIXME : we can't do that yet because one of rustc's crates can't compile if we do)
1232
1194
. for_each ( |( span, ffi_res) | self . process_ffi_result ( span, ffi_res, fn_mode) ) ;
1233
1195
//.drain();
1234
1196
}
@@ -1316,12 +1278,8 @@ impl<'c, 'tcx> ImproperCTypesLint<'c, 'tcx> {
1316
1278
1317
1279
// this whole while block converts the arbitrarily-deep
1318
1280
// FfiResult stack to an ImproperCTypesLayer Vec
1319
- while let ControlFlow :: Continue ( FfiUnsafeReason {
1320
- ty,
1321
- reason,
1322
- help,
1323
- inner,
1324
- } ) = ffiresult_recursor
1281
+ while let ControlFlow :: Continue ( FfiUnsafeReason { ty, reason, help, inner } ) =
1282
+ ffiresult_recursor
1325
1283
{
1326
1284
if let Some ( layer) = cimproper_layers. last_mut ( ) {
1327
1285
layer. inner_ty = Some ( ty. clone ( ) ) ;
@@ -1384,7 +1342,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
1384
1342
1385
1343
match it. kind {
1386
1344
hir:: ForeignItemKind :: Fn ( sig, _, _) => {
1387
- if abi. is_rustic_abi ( ) {
1345
+ if abi. is_rustic_abi ( ) {
1388
1346
lint. check_fn_for_external_abi_fnptr (
1389
1347
CItemKind :: Declaration ,
1390
1348
it. owner_id . def_id ,
@@ -1426,7 +1384,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
1426
1384
// Structs are checked based on if they follow the power alignment
1427
1385
// rule (under repr(C)).
1428
1386
hir:: ItemKind :: Struct ( ..) => {
1429
- ImproperCTypesLint { cx } . check_struct_for_power_alignment ( item) ;
1387
+ ImproperCTypesLint { cx } . check_struct_for_power_alignment ( item) ;
1430
1388
}
1431
1389
// See `check_field_def`..
1432
1390
hir:: ItemKind :: Union ( ..) | hir:: ItemKind :: Enum ( ..) => { }
0 commit comments