Lower record destructuring patterns
cbc895eb5c6c569c7648e51c5e4ff0579de8b925415ceb368100d07370b9fd7e
1 parent
f5aa0434
lib/std/lang/lower.rad
+11 -0
| 2408 | 2408 | } |
|
| 2409 | 2409 | if let case ast::NodeValue::ArrayLit(_) = pattern.value { |
|
| 2410 | 2410 | try emitJmp(self, matchBlock); |
|
| 2411 | 2411 | return; |
|
| 2412 | 2412 | } |
|
| 2413 | + | if let case resolver::Type::Nominal(resolver::NominalType::Record(_)) = subject.type { |
|
| 2414 | + | if let case ast::NodeValue::RecordLit(_) = pattern.value { |
|
| 2415 | + | try emitJmp(self, matchBlock); |
|
| 2416 | + | return; |
|
| 2417 | + | } |
|
| 2418 | + | } |
|
| 2413 | 2419 | let isNil = pattern.value == ast::NodeValue::Nil; |
|
| 2414 | 2420 | ||
| 2415 | 2421 | match subject.kind { |
|
| 2416 | 2422 | case MatchSubjectKind::OptionalPtr if isNil => { |
|
| 2417 | 2423 | // Null pointer optimization: branch on the data pointer being null. |
| 3356 | 3362 | // `emitPatternMatch`; unlike union record patterns, they have no payload |
|
| 3357 | 3363 | // bindings to extract here. |
|
| 3358 | 3364 | if let case MatchSubjectKind::OptionalAggregate = subject.kind { |
|
| 3359 | 3365 | return; |
|
| 3360 | 3366 | } |
|
| 3367 | + | if let recInfo = resolver::getRecord(subject.type) { |
|
| 3368 | + | let base = emitValToReg(self, subject.val); |
|
| 3369 | + | try bindNestedRecordFields(self, base, lit, recInfo, subject.by, failBlock); |
|
| 3370 | + | return; |
|
| 3371 | + | } |
|
| 3361 | 3372 | // Get the union type info from the subject. |
|
| 3362 | 3373 | let case MatchSubjectKind::Union(unionInfo) = subject.kind |
|
| 3363 | 3374 | else panic "bindRecordPatternFields: expected union subject"; |
|
| 3364 | 3375 | ||
| 3365 | 3376 | // Get the variant index from the pattern node. |
test/tests/pointer.move.record.rad
added
+21 -0
| 1 | + | //! returns: 0 |
|
| 2 | + | //! Move a mutable pointer out of a record through destructuring. |
|
| 3 | + | ||
| 4 | + | /// An exclusive pointer to the test value. |
|
| 5 | + | record Holder { |
|
| 6 | + | /// Value changed by the test. |
|
| 7 | + | pointer: *mut u32, |
|
| 8 | + | } |
|
| 9 | + | ||
| 10 | + | /// Storage owned by the test. |
|
| 11 | + | static VALUE: u32 = 0; |
|
| 12 | + | ||
| 13 | + | /// Transfer the pointer and use the destination binding. |
|
| 14 | + | @default fn main() -> i32 { |
|
| 15 | + | let holder = Holder { pointer: &mut VALUE }; |
|
| 16 | + | let case Holder { pointer } = holder else panic "expected holder"; |
|
| 17 | + | let moved = pointer; |
|
| 18 | + | set *moved = 42; |
|
| 19 | + | assert *moved == 42; |
|
| 20 | + | return 0; |
|
| 21 | + | } |