Skip to content

const_eval: JoinSemiLattice::join short-circuits with || skipping borrow state update #447

@SebTardif

Description

@SebTardif

Bug

In compiler/rustc_const_eval/src/check_consts/resolver.rs:321-322, the JoinSemiLattice::join implementation for State uses short-circuit ||:

fn join(&mut self, other: &Self) -> bool {
    self.qualif.join(&other.qualif) || self.borrow.join(&other.borrow)
}

When self.qualif.join() returns true (qualif state changed), the || operator short-circuits and self.borrow.join() is never called. This means borrow state from other is silently dropped at dataflow merge points.

The JoinSemiLattice::join contract says: "Computes the least upper bound of two elements, storing the result in self and returning true if self has changed." The borrow join has a side effect (mutating self.borrow) that must always execute.

Fix

Replace || with | (non-short-circuit or), or use separate let bindings:

let a = self.qualif.join(&other.qualif);
let b = self.borrow.join(&other.borrow);
a | b

Impact

Const fn with branching control flow may miss borrow constraints at merge points, potentially allowing const evaluation to proceed with incomplete borrow tracking.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-const-evalConst evaluationI-wrongWrong result or data corruptionP-mediumMedium impact: affects specific usage patternsbugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions