Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Self-referential generators vs dereferenceable #381

Copy link
Copy link
@RalfJung

Description

@RalfJung
Issue body actions

Miri recently started checking the dereferenceable attribute of &mut !Unpin references by doing "fake reads" when such functions start executing. Interestingly, that makes this safe piece of code fail.

This makes sense, I think, for the same reason that we cannot do "fake reads" of &!Freeze references: when doing such reads, we might invalidate other aliasing references. In the case of this future, what happens is that

  • a reference to the field where Delay::new(1) is stored gets created
  • next time poll gets called, we do a "fake read" of the entire future, which invalidates the previously created reference (a noalias reference doesn't like other pointers being used for reads, that's kind of the point)
  • then we access the reference, causing UB

What I do not fully understand yet is why something like this is not sufficient to cause the issue.

How could we solve this? I am honestly not entirely sure, but see two avenues worth pursuing:

  • Figure out whether these "fake reads" are really needed to model dereferenceable. I think they are, because otherwise I don't think we get the right interaction between noalias and dereferenceable, but I asked the LLVM folks about this.
  • Remove dereferenceable from &mut !Unpin references. This is obviously correct but codegen/optimization people will probably be unhappy...

The latter point might be what we have to do, and somewhat mirrors the fact that we remove dereferenceable from &!Freeze references, but not really -- for shared references we thought dereferenceable_on_entry would still be a sound attribute to add, but with this problem it looks like that might not be the case (neither for &mut !Unpin nor for &!Freeze), at least if the "fake read" model of dereferenceable prevails.

The problematic code condenses to something like this:

struct NotUnpinType {
  delay: usize,
  delay_ref: &mut usize, // points to `delay`
}

fn poll(self: &mut NotUnpinType) {
  let fake_read = *self;
  self.delay_ref -= 1; // self.delay_ref is a noalias reference
  // so we should be able to reorder the last two lines, but that changes the value stored in fake_read.
}
zetanumbers

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-dereferenceableTopic: when exactly does a reference need to point to regular dereferenceable memory?Topic: when exactly does a reference need to point to regular dereferenceable memory?

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.