Skip to content

Allow references to extern types to be tagged pointers? #356

Open
@madsmtm

Description

@madsmtm

Problem statement

When using extern types to interface with opaque types from C libraries, I often find it natural to use a reference to this type (the foreign-types crate captures this idea as well).

However, in C it can be considered an implementation detail whether an opaque pointer uses tagged pointers under the hood or not, which means that for a Rust library to be sound, it cannot work with references to extern types, they must always be accessed as raw pointers.

Proposed solution

While workable, I think this is overly restrictive, so I would like to propose that we allow any bit-pattern other than NULL in references to extern types.

That is, we guarantee that &ExternType is bit-wise compatible with NonNull<ExternType>: It has no alignment requirements, and may be a tagged or dangling pointer.

TODO: Unsure about aliasing requirements, they would probably still hold somewhat in the same way they do now.

Consequences

I don't think this would impact optimization potential, extern types are only directly accessed from code that already knows the concrete size of the type (and in that case, will just convert the extern type to the concrete type).

However, there are two negatives:

  • The pointer part of &dyn Trait would be subject to the same restrictions (since one may coerce an extern type to that) - this need not be guaranteed to the user though.
  • &dyn Trait and &ExternType can't use other niche-optimizations than the usual null-pointer optimization.

Just to clarify, &Foo in the following example would still be subject to the usual dereferenceability restrictions, but &Bar would not.

extern "C" {
    type Opaque;
}

#[repr(C)]
struct Foo {
    a: i16,
    b: Opaque,
}

#[repr(C)]
struct Bar {
    a: PhantomData<i32>, // ZST
    b: Opaque,
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions