@@ -927,22 +927,33 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { |
|
|
927 |
927 |
fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { |
928 |
928 |
use rustc_middle::ty::TypeFoldable; |
929 |
929 |
|
930 |
|
-struct ProhibitOpaqueTypes<'tcx> { |
|
930 |
+struct ProhibitOpaqueTypes<'a, 'tcx> { |
|
931 |
+cx: &'a LateContext<'a, 'tcx>, |
931 |
932 |
ty: Option<Ty<'tcx>>, |
932 |
933 |
}; |
933 |
934 |
|
934 |
|
-impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'tcx> { |
|
935 |
+impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> { |
935 |
936 |
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { |
936 |
|
-if let ty::Opaque(..) = ty.kind { |
937 |
|
-self.ty = Some(ty); |
938 |
|
-true |
939 |
|
-} else { |
940 |
|
- ty.super_visit_with(self) |
|
937 |
+match ty.kind { |
|
938 |
+ ty::Opaque(..) => { |
|
939 |
+self.ty = Some(ty); |
|
940 |
+true |
|
941 |
+} |
|
942 |
+// Consider opaque types within projections FFI-safe if they do not normalize |
|
943 |
+// to more opaque types. |
|
944 |
+ ty::Projection(..) => { |
|
945 |
+let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty); |
|
946 |
+ |
|
947 |
+// If `ty` is a opaque type directly then `super_visit_with` won't invoke |
|
948 |
+// this function again. |
|
949 |
+if ty.has_opaque_types() { self.visit_ty(ty) } else { false } |
|
950 |
+} |
|
951 |
+ _ => ty.super_visit_with(self), |
941 |
952 |
} |
942 |
953 |
} |
943 |
954 |
} |
944 |
955 |
|
945 |
|
-let mut visitor = ProhibitOpaqueTypes { ty: None }; |
|
956 |
+let mut visitor = ProhibitOpaqueTypes { cx: self.cx, ty: None }; |
946 |
957 |
ty.visit_with(&mut visitor); |
947 |
958 |
if let Some(ty) = visitor.ty { |
948 |
959 |
self.emit_ffi_unsafe_type_lint(ty, sp, "opaque types have no C equivalent", None); |