Skip to content

Commit

Permalink
lint/ctypes: only try normalize
Browse files Browse the repository at this point in the history
Now that this lint runs on any external-ABI fn-ptr, normalization won't
always succeed, so use `try_normalize_erasing_regions` instead.

Signed-off-by: David Wood <[email protected]>
  • Loading branch information
davidtwco committed Jul 21, 2023
1 parent c06b2b9 commit 09434a2
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 12 deletions.
21 changes: 9 additions & 12 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -966,12 +966,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
args: GenericArgsRef<'tcx>,
) -> FfiResult<'tcx> {
let field_ty = field.ty(self.cx.tcx, args);
if field_ty.has_opaque_types() {
self.check_type_for_ffi(cache, field_ty)
} else {
let field_ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, field_ty);
self.check_type_for_ffi(cache, field_ty)
}
let field_ty = self
.cx
.tcx
.try_normalize_erasing_regions(self.cx.param_env, field_ty)
.unwrap_or(field_ty);
self.check_type_for_ffi(cache, field_ty)
}

/// Checks if the given `VariantDef`'s field types are "ffi-safe".
Expand Down Expand Up @@ -1320,7 +1320,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
if let Some(ty) = self
.cx
.tcx
.normalize_erasing_regions(self.cx.param_env, ty)
.try_normalize_erasing_regions(self.cx.param_env, ty)
.unwrap_or(ty)
.visit_with(&mut ProhibitOpaqueTypes)
.break_value()
{
Expand All @@ -1338,16 +1339,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
is_static: bool,
is_return_type: bool,
) {
// We have to check for opaque types before `normalize_erasing_regions`,
// which will replace opaque types with their underlying concrete type.
if self.check_for_opaque_ty(sp, ty) {
// We've already emitted an error due to an opaque type.
return;
}

// it is only OK to use this function because extern fns cannot have
// any generic types right now:
let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty);
let ty = self.cx.tcx.try_normalize_erasing_regions(self.cx.param_env, ty).unwrap_or(ty);

// C doesn't really support passing arrays by value - the only way to pass an array by value
// is through a struct. So, first test that the top level isn't an array, and then
Expand Down
12 changes: 12 additions & 0 deletions tests/ui/lint/lint-ctypes-113900.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// check-pass

// Extending `improper_ctypes` to check external-ABI fn-ptrs means that it can encounter
// projections which cannot be normalized - unsurprisingly, this shouldn't crash the compiler.

trait Bar {
type Assoc;
}

type Foo<T> = extern "C" fn() -> <T as Bar>::Assoc;

fn main() {}

0 comments on commit 09434a2

Please sign in to comment.