@@ -148,61 +148,25 @@ impl<'tcx> FfiResult<'tcx> {
148148}
149149
150150impl < ' 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 ) {
152152 // note: we shouldn't really encounter FfiPhantoms here, they should be dealt with beforehand
153153 // still, this function deals with them in a reasonable way, I think
154154
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
188158 }
189- } else {
190- if let Self :: FfiUnsafe ( _) = self {
191- return ;
159+ ( myself, other @ Self :: FfiUnsafe ( _) ) => {
160+ * myself = other;
192161 }
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
206170 }
207171 }
208172 }
@@ -215,7 +179,7 @@ impl<'tcx> std::ops::Add<FfiResult<'tcx>> for FfiResult<'tcx> {
215179 }
216180}
217181
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
219183#[ derive( Clone , Copy ) ]
220184enum TypeSizedness {
221185 /// 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
354318 }
355319}
356320
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+
357332#[ repr( u8 ) ]
358333#[ derive( Clone , Copy , Debug ) ]
359334enum 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 ,
369342}
370343
371344impl 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
373346 fn is_in_static ( self ) -> bool {
374- ( ( self as u8 ) & 0b0010 ) != 0
347+ use CTypesVisitorStateFlags :: * ;
348+ ( ( self as u8 ) & STATIC ) != 0
375349 }
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
377351 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 ;
379354 #[ cfg( debug_assertions) ]
380355 if ret {
381356 assert ! ( !self . is_in_static( ) ) ;
382357 }
383358 ret
384359 }
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,
387362 /// to be treated as an opaque type on the other side of the FFI boundary
388363 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 ;
390366 #[ cfg( debug_assertions) ]
391367 if ret {
392368 assert ! ( !self . is_in_static( ) ) ;
393369 }
394370 ret
395371 }
396372
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
398374 fn value_may_be_unchecked ( self ) -> bool {
399375 // function declarations are assumed to be rust-caller, non-rust-callee
400376 // 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?)
402378 // Same with statics.
403379 if self . is_in_static ( ) {
404380 true
@@ -411,7 +387,7 @@ impl CTypesVisitorState {
411387}
412388
413389impl < ' 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
415391 fn visit_fnptr ( & mut self , mode : CItemKind , ty : Ty < ' tcx > , sig : Sig < ' tcx > ) -> FfiResult < ' tcx > {
416392 use FfiResult :: * ;
417393 debug_assert ! ( !sig. abi( ) . is_rustic_abi( ) ) ;
@@ -534,7 +510,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
534510 // there are three remaining concerns with the pointer:
535511 // - is the pointer compatible with a C pointer in the first place? (if not, only send that error message)
536512 // - 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?
538514 // this block deals with the first two.
539515 let mut ffi_res = match get_type_sizedness ( self . cx , inner_ty) {
540516 TypeSizedness :: UnsizedWithExternType | TypeSizedness :: Definite => {
@@ -583,7 +559,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
583559 // 'fake' declarations (in traits, needed to be implemented elsewhere), and definitions.
584560 // (for instance, definitions should worry about &self with Self:?Sized, but fake declarations shouldn't)
585561
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>),
587563 // so let's not wrap the current context around a potential FfiUnsafe type param.
588564 self . visit_type ( state, Some ( ty) , inner_ty)
589565 }
@@ -603,6 +579,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
603579 } ;
604580
605581 // 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
606583 ffi_res += if state. value_may_be_unchecked ( ) {
607584 let has_nonnull_assumption = match indirection_type {
608585 IndirectionType :: RawPtr => false ,
@@ -758,18 +735,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
758735
759736 if def. variants ( ) . is_empty ( ) {
760737 // 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
762739 return FfiSafe ;
763740 }
764741 // Check for a repr() attribute to specify the size of the
765742 // discriminant.
766743 if !def. repr ( ) . c ( ) && !def. repr ( ) . transparent ( ) && def. repr ( ) . int . is_none ( ) {
767744 // 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) {
773746 return self . visit_type ( state, Some ( ty) , inner_ty) ;
774747 }
775748
@@ -781,11 +754,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
781754 }
782755
783756 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 ) ;
789758 }
790759
791760 let non_exhaustive = def. variant_list_has_applicable_non_exhaustive ( ) ;
@@ -811,7 +780,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
811780 . iter ( )
812781 . map ( |variant| {
813782 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?
815784 // (previous code says no, but I don't know why? the problem with phantoms is that they're ZSTs, right?)
816785 . forbid_phantom ( )
817786 } )
@@ -856,11 +825,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
856825 }
857826 match def. adt_kind ( ) {
858827 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)
861830 // - 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
864832 if let Some ( sym:: cstring_type | sym:: cstr_type) =
865833 tcx. get_diagnostic_name ( def. did ( ) )
866834 {
@@ -1107,10 +1075,7 @@ struct ImproperCTypesLint<'c, 'tcx> {
11071075}
11081076
11091077impl < ' 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 {
11141079 let tcx = self . cx . tcx ;
11151080 assert ! ( tcx. sess. target. os == "aix" ) ;
11161081 // Structs (under repr(C)) follow the power alignment rule if:
@@ -1141,10 +1106,7 @@ impl<'c, 'tcx> ImproperCTypesLint<'c, 'tcx> {
11411106 return false ;
11421107 }
11431108
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 > ) {
11481110 let tcx = self . cx . tcx ;
11491111 let adt_def = tcx. adt_def ( item. owner_id . to_def_id ( ) ) ;
11501112 // repr(C) structs also with packed or aligned representation
@@ -1228,7 +1190,7 @@ impl<'c, 'tcx> ImproperCTypesLint<'c, 'tcx> {
12281190 ( span, ffi_res)
12291191 } )
12301192 // 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)
12321194 . for_each ( |( span, ffi_res) | self . process_ffi_result ( span, ffi_res, fn_mode) ) ;
12331195 //.drain();
12341196 }
@@ -1316,12 +1278,8 @@ impl<'c, 'tcx> ImproperCTypesLint<'c, 'tcx> {
13161278
13171279 // this whole while block converts the arbitrarily-deep
13181280 // 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
13251283 {
13261284 if let Some ( layer) = cimproper_layers. last_mut ( ) {
13271285 layer. inner_ty = Some ( ty. clone ( ) ) ;
@@ -1384,7 +1342,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
13841342
13851343 match it. kind {
13861344 hir:: ForeignItemKind :: Fn ( sig, _, _) => {
1387- if abi. is_rustic_abi ( ) {
1345+ if abi. is_rustic_abi ( ) {
13881346 lint. check_fn_for_external_abi_fnptr (
13891347 CItemKind :: Declaration ,
13901348 it. owner_id . def_id ,
@@ -1426,7 +1384,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
14261384 // Structs are checked based on if they follow the power alignment
14271385 // rule (under repr(C)).
14281386 hir:: ItemKind :: Struct ( ..) => {
1429- ImproperCTypesLint { cx } . check_struct_for_power_alignment ( item) ;
1387+ ImproperCTypesLint { cx } . check_struct_for_power_alignment ( item) ;
14301388 }
14311389 // See `check_field_def`..
14321390 hir:: ItemKind :: Union ( ..) | hir:: ItemKind :: Enum ( ..) => { }
0 commit comments