Skip to content

Use std::ptr::null_mut::<T>() instead of 0 as *mut T #202

Open
@samuela

Description

@samuela

c2rust current transpiles NULL pointers as 0 as *mut T, but it would be a bit cleaner and more rust-y to instead produce std::ptr::null_mut::<T>().

Activity

ahomescu

ahomescu commented on Nov 18, 2019

@ahomescu
Contributor

This keeps coming up in our internal discussion occasionally, but there are some corner cases where they're not equivalent (I think in static initializers, I have to look up the original discussion for details). Meanwhile, you can do the following with c2rust-refactor:

rewrite_expr '0 as *const $t:Ty' 'std::ptr::null()' ;
rewrite_expr '0 as *mut $t:Ty' 'std::ptr::null_mut()' ;
TheDan64

TheDan64 commented on Nov 18, 2019

@TheDan64
Contributor

I also recall the two not being equivalent. I wonder if it was just because it wasn't a const fn at the time? Maybe it'd be viable now, but I'm not certain

ahomescu

ahomescu commented on Nov 18, 2019

@ahomescu
Contributor

I checked last night, null and null_mut have been const fns since 2015.

TheDan64

TheDan64 commented on Nov 18, 2019

@TheDan64
Contributor

Hmm. Guess it wasn't that, lol

afetisov

afetisov commented on May 23, 2022

@afetisov
Contributor

One reason why they wouldn't be equivalent is static promotion. 0 as *mut T can be directly promoted to consts and statics. On the other hand, ptr::null_mut is a const fn, and const fn calls in general cannot be safely promoted. The specific functions ptr::null and ptr::null_mut are rustc_promotable, but this may change in the future and is harder to track for the refactoring tools. I think it's unlikely that the transpiled code will depend on static promotion (it's more of a syntactic sugar), but avoiding such code is still reasonable.

Also, being function calls they may be harder in general to analyze. Knowing that they are really null requires either interprocedural analysis (which may be intractable in general) or special-casing.

Finally, these function calls shouldn't even normally appear in idiomatic Rust code. They are generally an artifact of partial initialization, redundant default-initialization (which should be folded away) or nullable pointers (which are better expressed as Option<&T> or Option<NotNull<T>>). For this reason optimizing for their readability seems counterproductive, they should be optimized for easy elimination.

added
enhancementNew feature or request
wontfixThis will not be worked on
and removed
enhancementNew feature or request
on Jun 29, 2022
kkysen

kkysen commented on Aug 26, 2022

@kkysen
Contributor

I think this should be re-considered, as 0 as *const T and null() are no longer equivalent under strict provenance. We should prefer null() and null_mut() where possible to avoid the int-to-ptr casts. For example, miri warns about this, and can't catch all UB under permissive provenance. Where we do need an int-to-ptr cast, we should use the ptr::from_exposed_addr API to make this explicit, not just an as cast.

reopened this on Aug 26, 2022

2 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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

        Participants

        @samuela@LegNeato@ahomescu@TheDan64@afetisov

        Issue actions

          Use `std::ptr::null_mut::<T>()` instead of `0 as *mut T` · Issue #202 · immunant/c2rust