Skip to content

Commit 14fb427

Browse files
committed
Address various comments and change some details around place to value conversions
1 parent 8ef4af7 commit 14fb427

File tree

3 files changed

+37
-36
lines changed

3 files changed

+37
-36
lines changed

compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
682682
TerminatorKind::Resume | TerminatorKind::Abort => {
683683
let bb = location.block;
684684
if !self.body.basic_blocks()[bb].is_cleanup {
685-
self.fail(location, "Cannot `Resume` from non-cleanup basic block")
685+
self.fail(location, "Cannot `Resume` or `Abort` from non-cleanup basic block")
686686
}
687687
}
688688
TerminatorKind::Return => {

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1644,16 +1644,15 @@ pub enum StatementKind<'tcx> {
16441644
/// statements are not required. If the entire MIR body contains no `StorageLive`/`StorageDead`
16451645
/// statements for a particular local, the local is always considered live.
16461646
///
1647-
/// More precisely, the MIR validator currently does a `MaybeLiveLocals` analysis to check
1648-
/// validity of each use of a local. I believe this is equivalent to requiring for every use of
1649-
/// a local, there exist at least one path from the root to that use that contains a
1647+
/// More precisely, the MIR validator currently does a `MaybeStorageLiveLocals` analysis to
1648+
/// check validity of each use of a local. I believe this is equivalent to requiring for every
1649+
/// use of a local, there exist at least one path from the root to that use that contains a
16501650
/// `StorageLive` more recently than a `StorageDead`.
16511651
///
1652-
/// **Needs clarification**: Is it permitted to `StorageLive` a local for which we previously
1653-
/// executed `StorageDead`? How about two `StorageLive`s without an intervening `StorageDead`?
1654-
/// Two `StorageDead`s without an intervening `StorageLive`? LLVM says yes, poison, yes. If the
1655-
/// answer to any of these is "no," is breaking that rule UB or is it an error to have a path in
1656-
/// the CFG that might do this?
1652+
/// **Needs clarification**: Is it permitted to have two `StorageLive`s without an intervening
1653+
/// `StorageDead`? Two `StorageDead`s without an intervening `StorageLive`? LLVM says poison,
1654+
/// yes. If the answer to any of these is "no," is breaking that rule UB or is it an error to
1655+
/// have a path in the CFG that might do this?
16571656
StorageLive(Local),
16581657

16591658
/// See `StorageLive` above.
@@ -1666,7 +1665,7 @@ pub enum StatementKind<'tcx> {
16661665
/// <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/> for
16671666
/// more details.
16681667
///
1669-
/// For code that is not specific to stacked borrows, you should consider statements to read
1668+
/// For code that is not specific to stacked borrows, you should consider retags to read
16701669
/// and modify the place in an opaque way.
16711670
Retag(RetagKind, Box<Place<'tcx>>),
16721671

@@ -1695,7 +1694,7 @@ pub enum StatementKind<'tcx> {
16951694
/// executed.
16961695
Coverage(Box<Coverage>),
16971696

1698-
/// Denotes a call to the intrinsic function `copy_overlapping`.
1697+
/// Denotes a call to the intrinsic function `copy_nonoverlapping`.
16991698
///
17001699
/// First, all three operands are evaluated. `src` and `dest` must each be a reference, pointer,
17011700
/// or `Box` pointing to the same type `T`. `count` must evaluate to a `usize`. Then, `src` and
@@ -1909,7 +1908,7 @@ pub struct CopyNonOverlapping<'tcx> {
19091908
/// **Needs clarification**: What about metadata resulting from dereferencing wide pointers (and
19101909
/// possibly from accessing unsized locals - not sure how those work)? That probably deserves to go
19111910
/// on the list above and be discussed too. It is also probably necessary for making the indexing
1912-
/// stuff lass hand-wavey.
1911+
/// stuff less hand-wavey.
19131912
///
19141913
/// **Needs clarification**: When it says "part of memory" what does that mean precisely, and how
19151914
/// does it interact with the metadata?
@@ -2324,13 +2323,13 @@ pub struct SourceScopeLocalData {
23242323
///
23252324
/// The most common way to create values is via a place to value conversion. A place to value
23262325
/// conversion is an operation which reads the memory of the place and converts it to a value. This
2327-
/// is a fundamentally *typed* operation. Different types will do different things. These are some
2328-
/// possible examples of what Rust may - but will not necessarily - decide to do on place to value
2329-
/// conversions:
2326+
/// is a fundamentally *typed* operation. The nature of the value produced depends on the type of
2327+
/// the conversion. Furthermore, there may be other effects: if the type has a validity constraint
2328+
/// the place to value conversion might be UB if the validity constraint is not met.
23302329
///
2331-
/// 1. Types with validity constraints cause UB if the validity constraint is not met
2332-
/// 2. References/pointers may have their provenance change or cause other provenance related
2333-
/// side-effects.
2330+
/// **Needs clarification:** Ralf proposes that place to value conversions not have side-effects.
2331+
/// This is what is implemented in miri today. Are these the semantics we want for MIR? Is this
2332+
/// something we can even decide without knowing more about Rust's memory model?
23342333
///
23352334
/// A place to value conversion on a place that has its variant index set is not well-formed.
23362335
/// However, note that this rule only applies to places appearing in MIR bodies. Many functions,
@@ -2462,15 +2461,17 @@ impl<'tcx> Operand<'tcx> {
24622461
///
24632462
/// Not all of these are allowed at every [`MirPhase`] - when this is the case, it's stated below.
24642463
///
2465-
/// Computing any rvalue begins by evaluating the places and operands in the rvalue in the order in
2466-
/// which they appear. These are then used to produce a "value" - the same kind of value that an
2467-
/// [`Operand`] is.
2464+
/// Computing any rvalue begins by evaluating the places and operands in some order (**Needs
2465+
/// clarification**: Which order?). These are then used to produce a "value" - the same kind of
2466+
/// value that an [`Operand`] is.
24682467
pub enum Rvalue<'tcx> {
24692468
/// Yields the operand unchanged
24702469
Use(Operand<'tcx>),
24712470

2472-
/// Creates an array where each element is the value of the operand. This currently does not
2473-
/// drop the value even if the number of repetitions is zero, see [#74836].
2471+
/// Creates an array where each element is the value of the operand.
2472+
///
2473+
/// This is the cause of a bug in the case where the repetition count is zero because the value
2474+
/// is not dropped, see [#74836].
24742475
///
24752476
/// Corresponds to source code like `[x; 32]`.
24762477
///
@@ -2524,12 +2525,12 @@ pub enum Rvalue<'tcx> {
25242525
Cast(CastKind, Operand<'tcx>, Ty<'tcx>),
25252526

25262527
/// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second
2527-
/// paramter may be a `usize` as well.
2528+
/// parameter may be a `usize` as well.
25282529
/// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats,
25292530
/// raw pointers, or function pointers and return a `bool`.
25302531
/// * Left and right shift operations accept signed or unsigned integers not necessarily of the
25312532
/// same type and return a value of the same type as their LHS. For all other operations, the
2532-
/// types of the operands must match.
2533+
/// types of the operands must match. Like in Rust, the RHS is truncated as needed.
25332534
/// * The `Bit*` operations accept signed integers, unsigned integers, or bools and return a
25342535
/// value of that type.
25352536
/// * The remaining operations accept signed integers, unsigned integers, or floats of any
@@ -2538,21 +2539,19 @@ pub enum Rvalue<'tcx> {
25382539

25392540
/// Same as `BinaryOp`, but yields `(T, bool)` instead of `T`. In addition to performing the
25402541
/// same computation as the matching `BinaryOp`, checks if the infinite precison result would be
2541-
/// unequal to the actual result and sets the `bool` if this is the case. `BinOp::Offset` is not
2542-
/// allowed here.
2542+
/// unequal to the actual result and sets the `bool` if this is the case.
25432543
///
2544-
/// **FIXME**: What about division/modulo? Are they allowed here at all? Are zero divisors still
2545-
/// UB? Also, which other combinations of types are disallowed?
2544+
/// This only supports addition, subtraction, multiplication, and shift operations.
25462545
CheckedBinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),
25472546

2548-
/// Yields the size or alignment of the type as a `usize`.
2547+
/// Computes a value as described by the operation.
25492548
NullaryOp(NullOp, Ty<'tcx>),
25502549

25512550
/// Exactly like `BinaryOp`, but less operands.
25522551
///
2553-
/// Also does two's-complement arithmetic. Negation requires a signed integer or a float; binary
2554-
/// not requires a signed integer, unsigned integer, or bool. Both operation kinds return a
2555-
/// value with the same type as their operand.
2552+
/// Also does two's-complement arithmetic. Negation requires a signed integer or a float;
2553+
/// bitwise not requires a signed integer, unsigned integer, or bool. Both operation kinds
2554+
/// return a value with the same type as their operand.
25562555
UnaryOp(UnOp, Operand<'tcx>),
25572556

25582557
/// Computes the discriminant of the place, returning it as an integer of type

compiler/rustc_middle/src/mir/terminator.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,12 @@ pub enum TerminatorKind<'tcx> {
234234

235235
/// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of
236236
/// the referred to function. The operand types must match the argument types of the function.
237-
/// The return place type must exactly match the return type. The type of the `func` operand
238-
/// must be callable, meaning either a function pointer, a function type, or a closure type.
237+
/// The return place type must match the return type. The type of the `func` operand must be
238+
/// callable, meaning either a function pointer, a function type, or a closure type.
239239
///
240-
/// **Needs clarification**: The exact semantics of this, see [#71117].
240+
/// **Needs clarification**: The exact semantics of this. Current backends rely on `move`
241+
/// operands not aliasing the return place. It is unclear how this is justified in MIR, see
242+
/// [#71117].
241243
///
242244
/// [#71117]: https://github.com/rust-lang/rust/issues/71117
243245
Call {

0 commit comments

Comments
 (0)