@@ -312,6 +312,7 @@ These helpers mark down, as we traverse the projection, what `Place` we are curr
312312
313313 // retains information about the value that was deconstructed by a projection
314314 syntax Context ::= CtxField( VariantIdx, List, Int , Ty )
315+ | CtxFieldUnion( FieldIdx, Value, Ty )
315316 | CtxIndex( List , Int ) // array index constant or has been read before
316317 | CtxSubslice( List , Int , Int ) // start and end always counted from beginning
317318 | CtxPointerOffset( List, Int, Int ) // pointer offset for accessing elements with an offset (Offset, Origin Length)
@@ -329,6 +330,10 @@ These helpers mark down, as we traverse the projection, what `Place` we are curr
329330 => #buildUpdate(Aggregate(IDX, ARGS[I <- VAL]), CTXS)
330331 [preserves-definedness] // valid list indexing checked upon context construction
331332
333+ rule #buildUpdate(VAL, CtxFieldUnion(FIELD_IDX, _ARG, _TY) CTXS)
334+ => #buildUpdate(Union(FIELD_IDX, VAL), CTXS)
335+ [preserves-definedness]
336+
332337 rule #buildUpdate(VAL, CtxIndex(ELEMS, I) CTXS)
333338 => #buildUpdate(Range(ELEMS[I <- VAL]), CTXS)
334339 [preserves-definedness] // valid list indexing checked upon context construction
@@ -400,7 +405,7 @@ These helpers mark down, as we traverse the projection, what `Place` we are curr
400405 rule originSize(dynamicSize(SIZE)) => SIZE
401406```
402407
403- #### Aggregates
408+ #### Aggregates (not Union)
404409
405410A ` Field ` access projection operates on ` struct ` s and tuples, which are represented as ` Aggregate ` values.
406411The field is numbered from zero (in source order), and the field type is provided (not checked here).
@@ -445,6 +450,28 @@ This is done without consideration of the validity of the Downcast[^downcast].
445450 </k>
446451```
447452
453+ #### Unions
454+ ``` k
455+ // Case: Union is in same state as field projection
456+ rule <k> #traverseProjection(
457+ DEST,
458+ Union(FIELD_IDX, ARG),
459+ projectionElemField(FIELD_IDX, TY) PROJS,
460+ CTXTS
461+ )
462+ => #traverseProjection(
463+ DEST,
464+ ARG,
465+ PROJS,
466+ CtxFieldUnion(FIELD_IDX, ARG, TY) CTXTS
467+ )
468+ ...
469+ </k>
470+ [preserves-definedness]
471+
472+ // TODO: Case: Union is in different state as field projection
473+ ```
474+
448475#### Ranges
449476
450477An ` Index ` projection operates on an array or slice (` Range ` ) value, to access an element of the array.
@@ -934,6 +961,7 @@ Literal arrays are also built using this RValue.
934961
935962 // #mkAggregate produces an aggregate TypedLocal value of given kind from a preceeding list of values
936963 syntax Value ::= #mkAggregate ( AggregateKind )
964+ | #mkUnion ( FieldIdx )
937965
938966 rule <k> ARGS:List ~> #mkAggregate(aggregateKindAdt(_ADTDEF, VARIDX, _, _, _))
939967 =>
@@ -977,6 +1005,26 @@ Literal arrays are also built using this RValue.
9771005 </k>
9781006```
9791007
1008+ While Unions are Aggregate in the MIR, we distinguish between them because the semantics
1009+ are different. For example, field accesses to not access different data, but interpret
1010+ that data as a different type.
1011+ ``` k
1012+ syntax Rvalue ::= #evalUnion ( Rvalue )
1013+
1014+ rule <k> #evalUnion(rvalueAggregate(aggregateKindAdt( _, _, _, _, someFieldIdx ( FIELD )), ARGS))
1015+ =>
1016+ #readOperands(ARGS) ~> #mkUnion(FIELD)
1017+ ...
1018+ </k>
1019+
1020+ rule <k> ListItem(ARG) .List ~> #mkUnion(FIELD)
1021+ =>
1022+ Union(FIELD, ARG)
1023+ ...
1024+ </k>
1025+
1026+ ```
1027+
9801028The ` AggregateKind::RawPtr ` , somewhat as a special case of a ` struct ` aggregate, constructs a raw pointer
9811029from a given data pointer and metadata[ ^ rawPtrAgg ] . In case of a _ thin_ pointer, the metadata is a unit value,
9821030for _ fat_ pointers it is a ` usize ` value indicating the data length.
@@ -1063,6 +1111,7 @@ This eliminates any `Deref` projections from the place, and also resolves `Index
10631111 rule #projectionsFor( CtxSubslice(_, I, J) CTXS, PROJS) => #projectionsFor(CTXS, projectionElemSubslice(I, J, false) PROJS)
10641112 // rule #projectionsFor(CtxPointerOffset(OFFSET, ORIGIN_LENGTH) CTXS, PROJS) => #projectionsFor(CTXS, projectionElemSubslice(OFFSET, ORIGIN_LENGTH, false) PROJS)
10651113 rule #projectionsFor(CtxPointerOffset( _, OFFSET, ORIGIN_LENGTH) CTXS, PROJS) => #projectionsFor(CTXS, PointerOffset(OFFSET, ORIGIN_LENGTH) PROJS)
1114+ rule #projectionsFor(CtxFieldUnion(F_IDX, _, TY) CTXS, PROJS) => #projectionsFor(CTXS, projectionElemField(F_IDX, TY) PROJS)
10661115
10671116 // Borrowing a zero-sized local that is still `NewLocal`: initialise it, then reuse the regular rule.
10681117 rule <k> rvalueRef(REGION, KIND, place(local(I), PROJS))
0 commit comments