lint: normalize projections using opaque types · rust-lang/rust@2e781dd (original) (raw)

Original file line number Diff line number Diff line change
@@ -895,22 +895,33 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
895 895 }
896 896
897 897 fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
898 -struct ProhibitOpaqueTypes<'tcx> {
898 +struct ProhibitOpaqueTypes<'a, 'tcx> {
899 +cx: &'a LateContext<'a, 'tcx>,
899 900 ty: Option<Ty<'tcx>>,
900 901 };
901 902
902 -impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'tcx> {
903 +impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
903 904 fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
904 -if let ty::Opaque(..) = ty.kind {
905 -self.ty = Some(ty);
906 -true
907 -} else {
908 - ty.super_visit_with(self)
905 +match ty.kind {
906 + ty::Opaque(..) => {
907 +self.ty = Some(ty);
908 +true
909 +}
910 +// Consider opaque types within projections FFI-safe if they do not normalize
911 +// to more opaque types.
912 + ty::Projection(..) => {
913 +let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty);
914 +
915 +// If `ty` is a opaque type directly then `super_visit_with` won't invoke
916 +// this function again.
917 +if ty.has_opaque_types() { self.visit_ty(ty) } else { false }
918 +}
919 + _ => ty.super_visit_with(self),
909 920 }
910 921 }
911 922 }
912 923
913 -let mut visitor = ProhibitOpaqueTypes { ty: None };
924 +let mut visitor = ProhibitOpaqueTypes { cx: self.cx, ty: None };
914 925 ty.visit_with(&mut visitor);
915 926 if let Some(ty) = visitor.ty {
916 927 self.emit_ffi_unsafe_type_lint(ty, sp, "opaque types have no C equivalent", None);