Skip to content

regression: encountered mutable pointer in final value when "outer scope" rule applies in const/static with interior mutability #121610

Closed

Activity

  1. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Feb 25, 2024
  2. added this to the 1.77.0 milestone on Feb 25, 2024
  3. added
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Feb 25, 2024
  4. apiraino commented on Feb 26, 2024

    @apiraino
    Contributor

    bisection seems to point to #119044 ? cc @RalfJung @oli-obk

    searched nightlies: from nightly-2024-01-01 to nightly-2024-02-26
    regressed nightly: nightly-2024-01-24
    searched commit range: d5fd099...5d3d347
    regressed commit: 6265a95

    bisected with cargo-bisect-rustc v0.6.8

    Host triple: x86_64-unknown-linux-gnu
    Reproduce with:

    cargo bisect-rustc --start=2024-01-01 -- test 
  5. RalfJung commented on Feb 26, 2024

    @RalfJung
    Member

    Oh strange, this landed a while ago and so far we got no reports I think...

    Boa-0.13.0/src/builtins/map/mod.rs:341:9

    That seems to be a deprecated crate, the repo has moved on to a new version. Not sure how to get source code for it.

    The epo crate also regresses via boa

    [INFO] [stdout] error: encountered mutable pointer in final value of constant
    [INFO] [stdout]    --> /opt/rustwide/cargo-home/registry/src/index.crates.io-6f17d22bba15001f/boa_engine-0.14.0/src/builtins/mod.rs:205:9
    [INFO] [stdout]     |
    [INFO] [stdout] 205 |         const UNDEFINED: &JsValue = &JsValue::Undefined;
    [INFO] [stdout]     |    
    

    That code I found here. (The current version of the crate on master doesn't have this any more, at least not in that file.) But so far my attempts at extracting an example that reproduces the issue failed. I assume it has to do with that JsObject type, that mentions some Gc things so it might be particularly tricky.

  6. added
    S-needs-reproStatus: This issue has no reproduction and needs a reproduction to make progress.
    on Feb 26, 2024
  7. apiraino commented on Feb 27, 2024

    @apiraino
    Contributor

    I can reproduce the crash by compiling an old tarball of the boa crate (v0.13). But it also crashes stops compiling on rustc stable (1.76) for other reasons (glob imports), so unsure how helpful can that be.

    I have the feeling that trying to get to a reproducer would be expensive in terms of time vs. benefit 🤔 But I am unsure if behind this crash compile error lies something useful for us to know

  8. RalfJung commented on Feb 27, 2024

    @RalfJung
    Member

    "crash"? It doesn't crash for any of them I hope, just show this error?

    I am certainly surprised that there is a regression at all, in particular given that an earlier version of that PR (#116745) has been cratered and didn't find anything. So in that sense it would be interesting to extract a testcase here.

  9. apiraino commented on Feb 27, 2024

    @apiraino
    Contributor

    "crash"? It doesn't crash for any of them I hope, just show this error?

    I stand corrected. Compile stops and exits with the error reported in this issues (sorry for mixing up apple and oranges).

  10. RalfJung commented on Feb 28, 2024

    @RalfJung
    Member

    I copied more of the type definition into its own file, still no luck.

    But I think the only way this can happen is if different parts of the compiler disagree on whether a type has interior mutability, which is quite concerning.

  11. RalfJung commented on Feb 28, 2024

    @RalfJung
    Member

    Aah! I finally got it:

    use std::cell::Cell;
    
    pub enum JsValue {
        Undefined,
        Object(Cell<bool>),
    }
    
    impl ::std::ops::Drop for JsValue {
        fn drop(&mut self) {}
    }
    
    const UNDEFINED: &JsValue = &JsValue::Undefined;
    
    fn main() {
    }

    The Drop is key. In boa it's generated by a derive which made this hard to spot...

    So, I think what happens here is that we don't do promotion because of the Drop, but the "outer scope" rule still applies. The reference is created to JsValue::Undefined and some analysis concludes that this is fine since while the type has interior mutability, the value doesn't. But when we actually evaluate the initializer for UNDEFINED we just see a shared reference created to a type that has interior mutability so we mark it as potentially mutable, and then interning sees that and rejects it.

    Honestly my preference would be to reject this in const-checking, IMO we shouldn't allow references to interior mutable types under the "outer scope" rule. Note that both Stacked Borrows and Tree Borrows actually currently allow writing through &JsValue::Undefined (or they would if we turned off promotion, which changes the code in a way that UB arises without even involving the aliasing model). In that sense both promotion and const-checking are really playing with fire when they accept enum variants of enums where other variants have interior mutability.

  12. RalfJung commented on Feb 29, 2024

    @RalfJung
    Member

    So... actually allowing this code again will be quite tricky. Not sure if we want to do that.

    What I would prefer to do is make this check entirely type-based, and thus give a nicer error for when this happens:

    let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
    self.ccx,
    &mut |local| self.qualifs.has_mut_interior(self.ccx, local, location),
    place.as_ref(),
    );

    But that is quite the departure from our attempts to handle interior mutability in a value-based way, i.e. with these "qualifs".

    EDIT: That's now implemented in #121786.

  13. RalfJung commented on Feb 29, 2024

    @RalfJung
    Member

    So... what shall we do here? Retroactively ask T-lang to approve the part of #119044 that is a breaking change? That PR went through FCP but we didn't realize it would be a breaking change.

  14. 25 remaining items

  15. removed
    S-needs-reproStatus: This issue has no reproduction and needs a reproduction to make progress.
    on Mar 17, 2024
  16. changed the title [-]regression: encountered mutable pointer in final value[/-] [+]regression: encountered mutable pointer in final value when "outer scope" rule applies in const/static with interior mutability[/+] on Mar 17, 2024
  17. RalfJung commented on Mar 20, 2024

    @RalfJung
    Member

    This was downgraded in #122204 and beta-backported in #122524.

    Tracking issue for that: #122153.

  18. RalfJung commented on Mar 20, 2024

    @RalfJung
    Member

    This was discussed in a T-lang meeting.

    There was general sympathy with the t-opsem desire to not do value-based reasoning for interior mutability. But there also wasn't a clear idea for how value-based reasoning could be removed from both promotion and tail-expression checking. The one thing everyone agreed on was to at least do a crater run to see how bad it'd be. Then based on that, maybe there could be an edition-based transition plan.

    For this concrete issue, the goal is to monitor the tracking issue of the future compat lint (#122153) to see if anyone speaks up -- to see if there's notable code out there not covered by crater that would regress if we just made the current check a hard error. Depending on that we could either take the hit and break old versions of boa, or do value-based reasoning in const-eval when determining the mutability of shared references (at least in the "root frame" of const-eval, i.e. the initializer expression of the const itself).

  19. traviscross commented on Mar 20, 2024

    @traviscross
    Contributor

    @rustbot labels -I-lang-nominated

    Thanks to @RalfJung and @oli-obk for joining us in the meeting to talk through this. As @RalfJung mentioned, there are some next steps here, so please renominate when we have more data and a new proposal for how to move forward based on that.

  20. removed
    I-lang-nominatedNominated for discussion during a lang team meeting.
    on Mar 20, 2024
  21. RalfJung commented on Mar 31, 2024

    @RalfJung
    Member

    The crater experiment in #122789 which entirely removed value-based reasoning for interior mutability had almost 4000 regressions. I think we can conclude that this is not an option.^^

  22. RalfJung commented on Aug 2, 2024

    @RalfJung
    Member

    I'm proposing we fix this by removing the lint and just accepting the code, unfortunate as that is. See #128543.

  23. Diggsey commented on Aug 18, 2024

    @Diggsey
    Contributor

    Mutating a non-internally-mutable type is UB, but that doesn't necessarily mean that mutating an internally-mutable type is not UB.

    Presumably there could just be a second rule that mutating read-only memory is also UB, even if the type being mutated is internally mutable.

    As long as safe code is prevented from mutating these values, then the only danger is that of people not realising this is UB when writing unsafe code - this could be mitigated by a compiler lint, which does a "best effort" attempt at detecting writes to read-only memory.

  24. RalfJung commented on Aug 18, 2024

    @RalfJung
    Member

    Presumably there could just be a second rule that mutating read-only memory is also UB, even if the type being mutated is internally mutable.

    Yes, we already have such a rule. I was just hoping it would not be necessary...

    Also see rust-lang/unsafe-code-guidelines#493, which has the same root cause but is worse because it is not at all clear to the user that there's any "read-only memory" here.

  25. added a commit that references this issue on Sep 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

T-langRelevant to the language team

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions