@@ -1573,18 +1573,44 @@ impl Statement<'_> {
1573
1573
/// causing an ICE if they are violated.
1574
1574
#[ derive( Clone , Debug , PartialEq , TyEncodable , TyDecodable , Hash , HashStable , TypeFoldable ) ]
1575
1575
pub enum StatementKind < ' tcx > {
1576
- /// Write the RHS Rvalue to the LHS Place.
1576
+ /// Assign statements roughly correspond to an assignment in Rust proper (`x = ...`) except
1577
+ /// without the possibility of dropping the previous value (that must be done separately, if at
1578
+ /// all). The *exact* way this works is undecided. It probably does something like evaluating
1579
+ /// the LHS and RHS, and then doing the inverse of a place to value conversion to write the
1580
+ /// resulting value into memory. Various parts of this may do type specific things that are more
1581
+ /// complicated than simply copying over the bytes depending on the types.
1577
1582
///
1578
- /// The LHS place may not overlap with any memory accessed on the RHS.
1583
+ /// **Needs clarification**: The implication of the above idea would be that assignment implies
1584
+ /// that the resulting value is initialized. I believe we could commit to this separately from
1585
+ /// committing to whatever part of the memory model we would need to decide on to make the above
1586
+ /// paragragh precise. Do we want to?
1587
+ ///
1588
+ /// Assignments in which the types of the place and rvalue differ are not well-formed.
1589
+ ///
1590
+ /// **Needs clarification**: Do we ever want to worry about non-free (in the body) lifetimes for
1591
+ /// the typing requirement in post drop-elaboration MIR? I think probably not - I'm not sure we
1592
+ /// could meaningfully require this anyway. How about free lifetimes? Is ignoring this
1593
+ /// interesting for optimizations? Do we want to allow such optimizations?
1594
+ ///
1595
+ /// **Needs clarification**: We currently require that the LHS place not overlap with any place
1596
+ /// read as part of computation of the RHS. This requirement is under discussion in [#68364]. As
1597
+ /// a part of this discussion, it is also unclear in what order the components are evaluated.
1598
+ ///
1599
+ /// [#68364]: https://github.com/rust-lang/rust/issues/68364
1600
+ ///
1601
+ /// See [`Rvalue`] documentation for details on each of those.
1579
1602
Assign ( Box < ( Place < ' tcx > , Rvalue < ' tcx > ) > ) ,
1580
1603
1581
- /// This represents all the reading that a pattern match may do
1582
- /// (e.g., inspecting constants and discriminant values), and the
1583
- /// kind of pattern it comes from. This is in order to adapt potential
1584
- /// error messages to these specific patterns.
1604
+ /// This represents all the reading that a pattern match may do (e.g., inspecting constants and
1605
+ /// discriminant values), and the kind of pattern it comes from. This is in order to adapt
1606
+ /// potential error messages to these specific patterns.
1585
1607
///
1586
1608
/// Note that this also is emitted for regular `let` bindings to ensure that locals that are
1587
1609
/// never accessed still get some sanity checks for, e.g., `let x: ! = ..;`
1610
+ ///
1611
+ /// When executed at runtime this is a nop.
1612
+ ///
1613
+ /// Disallowed after drop elaboration.
1588
1614
FakeRead ( Box < ( FakeReadCause , Place < ' tcx > ) > ) ,
1589
1615
1590
1616
/// Write the discriminant for a variant to the enum Place.
@@ -1599,17 +1625,36 @@ pub enum StatementKind<'tcx> {
1599
1625
/// This writes `uninit` bytes to the entire place.
1600
1626
Deinit ( Box < Place < ' tcx > > ) ,
1601
1627
1602
- /// Start a live range for the storage of the local.
1628
+ /// `StorageLive` and `StorageDead` statements mark the live range of a local.
1629
+ ///
1630
+ /// Using a local before a `StorageLive` or after a `StorageDead` is not well-formed. These
1631
+ /// statements are not required. If the entire MIR body contains no `StorageLive`/`StorageDead`
1632
+ /// statements for a particular local, the local is always considered live.
1633
+ ///
1634
+ /// More precisely, the MIR validator currently does a `MaybeLiveLocals` analysis to check
1635
+ /// validity of each use of a local. I believe this is equivalent to requiring for every use of
1636
+ /// a local, there exist at least one path from the root to that use that contains a
1637
+ /// `StorageLive` more recently than a `StorageDead`.
1638
+ ///
1639
+ /// **Needs clarification**: Is it permitted to `StorageLive` a local for which we previously
1640
+ /// executed `StorageDead`? How about two `StorageLive`s without an intervening `StorageDead`?
1641
+ /// Two `StorageDead`s without an intervening `StorageLive`? LLVM says yes, poison, yes. If the
1642
+ /// answer to any of these is "no," is breaking that rule UB or is it an error to have a path in
1643
+ /// the CFG that might do this?
1603
1644
StorageLive ( Local ) ,
1604
1645
1605
- /// End the current live range for the storage of the local .
1646
+ /// See `StorageLive` above .
1606
1647
StorageDead ( Local ) ,
1607
1648
1608
- /// Retag references in the given place, ensuring they got fresh tags. This is
1609
- /// part of the Stacked Borrows model. These statements are currently only interpreted
1610
- /// by miri and only generated when "-Z mir-emit-retag" is passed.
1611
- /// See <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/>
1612
- /// for more details.
1649
+ /// Retag references in the given place, ensuring they got fresh tags.
1650
+ ///
1651
+ /// This is part of the Stacked Borrows model. These statements are currently only interpreted
1652
+ /// by miri and only generated when `-Z mir-emit-retag` is passed. See
1653
+ /// <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/> for
1654
+ /// more details.
1655
+ ///
1656
+ /// For code that is not specific to stacked borrows, you should consider statements to read
1657
+ /// and modify the place in an opaque way.
1613
1658
Retag ( RetagKind , Box < Place < ' tcx > > ) ,
1614
1659
1615
1660
/// Encodes a user's type ascription. These need to be preserved
@@ -1624,6 +1669,10 @@ pub enum StatementKind<'tcx> {
1624
1669
/// - `Contravariant` -- requires that `T_y :> T`
1625
1670
/// - `Invariant` -- requires that `T_y == T`
1626
1671
/// - `Bivariant` -- no effect
1672
+ ///
1673
+ /// When executed at runtime this is a nop.
1674
+ ///
1675
+ /// Disallowed after drop elaboration.
1627
1676
AscribeUserType ( Box < ( Place < ' tcx > , UserTypeProjection ) > , ty:: Variance ) ,
1628
1677
1629
1678
/// Marks the start of a "coverage region", injected with '-Cinstrument-coverage'. A
@@ -1633,9 +1682,20 @@ pub enum StatementKind<'tcx> {
1633
1682
/// executed.
1634
1683
Coverage ( Box < Coverage > ) ,
1635
1684
1636
- /// Denotes a call to the intrinsic function copy_overlapping, where `src_dst` denotes the
1637
- /// memory being read from and written to(one field to save memory), and size
1638
- /// indicates how many bytes are being copied over.
1685
+ /// Denotes a call to the intrinsic function `copy_overlapping`.
1686
+ ///
1687
+ /// First, all three operands are evaluated. `src` and `dest` must each be a reference, pointer,
1688
+ /// or `Box` pointing to the same type `T`. `count` must evaluate to a `usize`. Then, `src` and
1689
+ /// `dest` are dereferenced, and `count * size_of::<T>()` bytes beginning with the first byte of
1690
+ /// the `src` place are copied to the continguous range of bytes beginning with the first byte
1691
+ /// of `dest`.
1692
+ ///
1693
+ /// **Needs clarification**: In what order are operands computed and dereferenced? It should
1694
+ /// probably match the order for assignment, but that is also undecided.
1695
+ ///
1696
+ /// **Needs clarification**: Is this typed or not, ie is there a place to value and back
1697
+ /// conversion involved? I vaguely remember Ralf saying somewhere that he thought it should not
1698
+ /// be.
1639
1699
CopyNonOverlapping ( Box < CopyNonOverlapping < ' tcx > > ) ,
1640
1700
1641
1701
/// No-op. Useful for deleting instructions without affecting statement indices.
0 commit comments