compiler: Validate type metadata through safe helpers

a9b9845068e20ec968437c139ee092f815ec5ef62834837177698970d2f53436
Alexis Sellier committed ago 1 parent b72fe736
lib/std/lang/lower.rad +1 -1
4219 4219
4220 4220
/// Return the effective type of a node after any coercion applied by
4221 4221
/// the resolver. `lowerExpr` already materializes the coercion in the
4222 4222
/// IL value, so the lowerer must use the post-coercion type when
4223 4223
/// choosing how to compare or store that value.
4224 -
unsafe fn effectiveType 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, node: *ast::Node) -> resolver::Type throws (LowerError) where 'arena: 'phase, 'phase: 'function {
4224 +
fn effectiveType 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, node: *ast::Node) -> resolver::Type throws (LowerError) where 'arena: 'phase, 'phase: 'function {
4225 4225
    let ty = try typeOf(self, node);
4226 4226
    if let coerce = resolver::coercionFor(self.low.resolver, node) {
4227 4227
        if let case resolver::Coercion::OptionalLift(optTy) = coerce {
4228 4228
            return optTy;
4229 4229
        }
lib/std/lang/resolver.rad +6 -9
4433 4433
/// Verifies argument count matches field count, and that each argument is
4434 4434
/// assignable to its corresponding field type.
4435 4435
unsafe fn checkRecordConstructorArgs 'arena (self: &mut Resolver 'arena, node: *ast::Node, args: *[*ast::Node], recInfo: RecordType)
4436 4436
    throws (ResolveError)
4437 4437
{
4438 -
    try checkRecordArity(self, args, recInfo, node);
4438 +
    try checkRecordArity(self, CountMismatch { expected: recInfo.fields.len, actual: args.len }, node);
4439 4439
    for arg, i in args {
4440 4440
        let fieldType = recInfo.fields[i].fieldType;
4441 4441
        try checkAssignable(self, arg, fieldType);
4442 4442
    }
4443 4443
}
4444 4444
4445 4445
/// Check that the argument count of a constructor pattern or call matches the record field count.
4446 -
unsafe fn checkRecordArity 'arena (self: &mut Resolver 'arena, args: *[*ast::Node], recInfo: RecordType, pattern: *ast::Node) throws (ResolveError) {
4447 -
    if args.len <> recInfo.fields.len {
4448 -
        throw emitError(self, pattern, ErrorKind::RecordFieldCountMismatch(CountMismatch {
4449 -
            expected: recInfo.fields.len as u32,
4450 -
            actual: args.len,
4451 -
        }));
4446 +
fn checkRecordArity 'arena (self: &mut Resolver 'arena, counts: CountMismatch, pattern: *ast::Node) throws (ResolveError) {
4447 +
    if counts.actual <> counts.expected {
4448 +
        throw emitError(self, pattern, ErrorKind::RecordFieldCountMismatch(counts));
4452 4449
    }
4453 4450
}
4454 4451
4455 4452
/// Helper for analyzing `constant` and `static` declarations.
4456 4453
unsafe fn resolveConstOrStatic 'arena (
6573 6570
    matchBy: MatchBy
6574 6571
) throws (ResolveError) {
6575 6572
    match pattern.value {
6576 6573
        case ast::NodeValue::Call(call) => {
6577 6574
            // Unlabeled patterns: `S(x, y)`.
6578 -
            try checkRecordArity(self, call.args, recInfo, pattern);
6575 +
            try checkRecordArity(self, CountMismatch { expected: recInfo.fields.len, actual: call.args.len }, pattern);
6579 6576
6580 6577
            for binding, i in call.args {
6581 6578
                let fieldType = recInfo.fields[i].fieldType;
6582 6579
                try bindPatternVar(self, binding, fieldType, matchBy);
6583 6580
            }
6584 6581
        }
6585 6582
        case ast::NodeValue::RecordLit(lit) => {
6586 6583
            // Labeled patterns: `T { x, y }` or `T { x: binding }`.
6587 6584
            if not lit.ignoreRest {
6588 -
                try checkRecordArity(self, lit.fields, recInfo, pattern);
6585 +
                try checkRecordArity(self, CountMismatch { expected: recInfo.fields.len, actual: lit.fields.len }, pattern);
6589 6586
            }
6590 6587
            for fieldNode in lit.fields {
6591 6588
                let case ast::NodeValue::RecordLitField(field) = fieldNode.value
6592 6589
                    else panic "expected RecordLitField";
6593 6590