compiler: Check optional and slice construction
8841bacd63c519d3fd1d9e14a05338e316d49451a01870e6b652d8110da6dbfc
1 parent
22ef7605
lib/std/lang/lower.rad
+12 -8
| 4530 | 4530 | /// Wrap a value in an optional type. |
|
| 4531 | 4531 | /// |
|
| 4532 | 4532 | /// For optional pointers (`?*T`), the value is returned as-is since pointers |
|
| 4533 | 4533 | /// use zero to represent `nil`. For other optionals, builds a tagged aggregate. |
|
| 4534 | 4534 | /// with the tag set to `1`, and the value as payload. |
|
| 4535 | - | unsafe fn wrapInOptional 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, val: il::Val, optType: resolver::Type) -> il::Val throws (LowerError) where 'arena: 'phase, 'phase: 'function { |
|
| 4535 | + | fn wrapInOptional 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, val: il::Val, optType: resolver::Type) -> il::Val throws (LowerError) where 'arena: 'phase, 'phase: 'function { |
|
| 4536 | 4536 | let case resolver::Type::Optional(inner) = optType else { |
|
| 4537 | 4537 | throw LowerError::ExpectedOptional; |
|
| 4538 | 4538 | }; |
|
| 4539 | 4539 | // Null-pointer-optimized (NPO) types are used as-is -- valid values are never null. |
|
| 4540 | 4540 | if resolver::isNullableType(*inner) { |
|
| 4541 | 4541 | return val; |
|
| 4542 | 4542 | } |
|
| 4543 | - | let layout = resolver::getTypeLayout(optType); |
|
| 4544 | - | let valOffset = resolver::getOptionalValOffset(resolver::getTypeLayout(*inner)) as i32; |
|
| 4543 | + | unsafe { |
|
| 4544 | + | let layout = resolver::getTypeLayout(optType); |
|
| 4545 | + | let valOffset = resolver::getOptionalValOffset(resolver::getTypeLayout(*inner)) as i32; |
|
| 4545 | 4546 | ||
| 4546 | - | return try buildTagged(self, layout, 1, val, *inner, 1, valOffset); |
|
| 4547 | + | return try buildTagged(self, layout, 1, val, *inner, 1, valOffset); |
|
| 4548 | + | } |
|
| 4547 | 4549 | } |
|
| 4548 | 4550 | ||
| 4549 | 4551 | /// Build a `nil` value for an optional type. |
|
| 4550 | 4552 | /// |
|
| 4551 | 4553 | /// For optional pointers (`?*T`), returns an immediate `0` (null pointer). |
|
| 4552 | 4554 | /// For other optionals, builds a tagged aggregate with tag set to `0` (absent). |
|
| 4553 | - | unsafe fn buildNilOptional 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, optType: resolver::Type) -> il::Val throws (LowerError) where 'arena: 'phase, 'phase: 'function { |
|
| 4555 | + | fn buildNilOptional 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, optType: resolver::Type) -> il::Val throws (LowerError) where 'arena: 'phase, 'phase: 'function { |
|
| 4554 | 4556 | let case resolver::Type::Optional(inner) = optType |
|
| 4555 | 4557 | else throw LowerError::ExpectedOptional; |
|
| 4556 | 4558 | if let case resolver::Type::Pointer { .. } = *inner { |
|
| 4557 | 4559 | return il::Val::Imm(0); |
|
| 4558 | 4560 | } |
|
| 4559 | 4561 | if let case resolver::Type::Slice { item, mutable, .. } = *inner { |
|
| 4560 | 4562 | return try buildSliceValue( |
|
| 4561 | 4563 | self, item, mutable, il::Val::Imm(0), il::Val::Imm(0), il::Val::Imm(0) |
|
| 4562 | 4564 | ); |
|
| 4563 | 4565 | } |
|
| 4564 | - | let valOffset = resolver::getOptionalValOffset(resolver::getTypeLayout(*inner)) as i32; |
|
| 4565 | - | return try buildTagged(self, resolver::getTypeLayout(optType), 0, nil, *inner, 1, valOffset); |
|
| 4566 | + | unsafe { |
|
| 4567 | + | let valOffset = resolver::getOptionalValOffset(resolver::getTypeLayout(*inner)) as i32; |
|
| 4568 | + | return try buildTagged(self, resolver::getTypeLayout(optType), 0, nil, *inner, 1, valOffset); |
|
| 4569 | + | } |
|
| 4566 | 4570 | } |
|
| 4567 | 4571 | ||
| 4568 | 4572 | /// Build a result value for throwing functions. |
|
| 4569 | 4573 | unsafe fn buildResult 'arena 'phase 'function ( |
|
| 4570 | 4574 | self: &mut FnLowerer 'arena 'phase 'function, |
| 4578 | 4582 | ); |
|
| 4579 | 4583 | return try buildTagged(self, layout, tag, payload, payloadType, resolver::PTR_SIZE as i32, RESULT_VAL_OFFSET); |
|
| 4580 | 4584 | } |
|
| 4581 | 4585 | ||
| 4582 | 4586 | /// Build a slice aggregate from a data pointer, length and capacity. |
|
| 4583 | - | unsafe fn buildSliceValue 'arena 'phase 'function ( |
|
| 4587 | + | fn buildSliceValue 'arena 'phase 'function ( |
|
| 4584 | 4588 | self: &mut FnLowerer 'arena 'phase 'function, |
|
| 4585 | 4589 | elemTy: *resolver::Type, |
|
| 4586 | 4590 | mutable: bool, |
|
| 4587 | 4591 | ptrVal: il::Val, |
|
| 4588 | 4592 | lenVal: il::Val, |