compiler: Validate type metadata through safe helpers
a9b9845068e20ec968437c139ee092f815ec5ef62834837177698970d2f53436
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 |