Fix missing fields not warning in structs

This commit is contained in:
Sofia 2025-07-25 23:30:57 +03:00
parent 45d381f865
commit 4c9633132f
4 changed files with 21 additions and 3 deletions

View File

@ -53,7 +53,7 @@ Currently missing big features (TODOs) are:
- Importable binops?
Big features that I want later but are not necessary:
- Associated functions
- Associated functions (for e.g. sizeof)
- ~~User-defined binary operations~~ (DONE)
- ~~Asymmetric binary operations (e.g. string + u32)~~ (DONE)
- Error handling

View File

@ -7,11 +7,10 @@ struct Test {
fn main() -> u32 {
let mut value = Test {
field: 5,
second: 3,
field: 5,
};
value.second = 17;
return value.second;
}

View File

@ -50,6 +50,8 @@ pub enum ErrorKind {
TriedAccessingNonStruct(TypeKind),
#[error("No such struct-field on type {0}")]
NoSuchField(String),
#[error("Missing definition for field \"{0}\"")]
MissingStructField(String),
#[error("Struct field declared twice {0}")]
DuplicateStructField(String),
#[error("Type declared twice {0}")]

View File

@ -632,6 +632,13 @@ impl Expression {
.get_struct_type(&type_key)
.ok_or(ErrorKind::NoSuchType(struct_name.clone(), type_key.1))?
.clone();
let mut expected_fields = if let Some(struct_ty) = state.scope.get_struct_type(&type_key) {
struct_ty.0.iter().map(|f| f.0.clone()).collect()
} else {
HashSet::new()
};
for (field_name, field_expr) in items {
// Get expected type, or error if field does not exist
let expected_ty = state.or_else(
@ -641,6 +648,7 @@ impl Expression {
&TypeKind::Vague(VagueType::Unknown),
field_expr.1,
);
expected_fields.remove(field_name);
// Typecheck the actual expression
let expr_res = field_expr.typecheck(state, typerefs, HintKind::Coerce(expected_ty.clone()));
@ -649,6 +657,15 @@ impl Expression {
// Make sure both are the same type, report error if not
state.ok(expr_ty.narrow_into(&expr_ty), field_expr.1);
}
state.note_errors(
&expected_fields
.into_iter()
.map(|v| ErrorKind::MissingStructField(v))
.collect(),
self.1,
);
Ok(TypeKind::CustomType(type_key))
}
ExprKind::Borrow(var_ref, mutable) => {