Lower record destructuring patterns

cbc895eb5c6c569c7648e51c5e4ff0579de8b925415ceb368100d07370b9fd7e
Alexis Sellier committed ago 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 +
}