fix: P1审查修复 — error.c arena化 + Self类型解析 + trait查找加固 + 缓冲区安全
P1-①: error_init/add 从 malloc/realloc/strdup 改为 arena_alloc/arena_strdup P1-②: impl 方法中 Self 类型在 sema 解析为实际结构体名 P1-③: trait 方法 fallback 增加前缀校验(strncmp),method_name 统一更新 P1-④: codegen args[16] 增加溢出检查,移除 parser 未使用的 mods/uses 数组 新增: 36_self_type.l 集成测试(Self 类型 + trait 方法) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
trait Eq {
|
||||
fn eq(self: Self, other: Self) -> bool;
|
||||
}
|
||||
|
||||
struct Point { x: i64, y: i64 }
|
||||
|
||||
extend Eq Point {
|
||||
fn eq(self: Point, other: Point) -> bool {
|
||||
return self.x == other.x && self.y == other.y;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> i64 {
|
||||
let p1 = Point { x: 10, y: 20 };
|
||||
let p2 = Point { x: 10, y: 20 };
|
||||
let p3 = Point { x: 99, y: 1 };
|
||||
if p1.eq(p2) {
|
||||
print_str("same");
|
||||
} else {
|
||||
print_str("diff");
|
||||
}
|
||||
if p1.eq(p3) {
|
||||
print_str("same");
|
||||
} else {
|
||||
print_str("diff");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+1
-1
@@ -491,7 +491,7 @@ void test_codegen_match() {
|
||||
AstNode* fns[] = { main_fn };
|
||||
AstNode* prog = ast_make_program(&a, fns, 1, NULL, 0, NULL, 0, enums, 1, NULL, 0, loc_at(1, 1));
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(prog, &errors, &a);
|
||||
ASSERT(errors.count == 0);
|
||||
|
||||
|
||||
+24
-24
@@ -14,7 +14,7 @@ void test_type_error() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count > 0);
|
||||
arena_destroy(&a);
|
||||
@@ -29,7 +29,7 @@ void test_undefined_var() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count > 0);
|
||||
arena_destroy(&a);
|
||||
@@ -45,7 +45,7 @@ void test_simple_ok() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0);
|
||||
arena_destroy(&a);
|
||||
@@ -61,7 +61,7 @@ void test_let_mut_assign_ok() {
|
||||
ErrorInfo parse_err = {0};
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0);
|
||||
arena_destroy(&a);
|
||||
@@ -77,7 +77,7 @@ void test_assign_immutable_error() {
|
||||
ErrorInfo parse_err = {0};
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count > 0); // 不可变变量赋值应报错
|
||||
arena_destroy(&a);
|
||||
@@ -93,7 +93,7 @@ void test_str_type_ok() {
|
||||
ErrorInfo parse_err = {0};
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0);
|
||||
arena_destroy(&a);
|
||||
@@ -109,7 +109,7 @@ void test_str_concat_type_ok() {
|
||||
ErrorInfo parse_err = {0};
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0);
|
||||
arena_destroy(&a);
|
||||
@@ -128,7 +128,7 @@ void test_struct_field_type_mismatch() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count > 0); // y 字段类型不匹配: true 是 bool, 不是 i64
|
||||
arena_destroy(&a);
|
||||
@@ -145,7 +145,7 @@ void test_struct_undefined() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count > 0); // Unknown 未定义
|
||||
arena_destroy(&a);
|
||||
@@ -162,7 +162,7 @@ void test_struct_field_count_mismatch() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count > 0); // 缺少字段 'y'
|
||||
arena_destroy(&a);
|
||||
@@ -182,7 +182,7 @@ void test_type_alias_ok() {
|
||||
ASSERT(ast != NULL);
|
||||
ASSERT(ast->as.program.alias_count == 1);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0);
|
||||
arena_destroy(&a);
|
||||
@@ -200,7 +200,7 @@ void test_type_alias_struct() {
|
||||
ASSERT(ast != NULL);
|
||||
ASSERT(ast->as.program.alias_count == 1);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0);
|
||||
arena_destroy(&a);
|
||||
@@ -217,7 +217,7 @@ void test_struct_nested_type_ok() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0); // 嵌套结构体类型检查应通过
|
||||
arena_destroy(&a);
|
||||
@@ -236,7 +236,7 @@ void test_enum_ok() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0);
|
||||
arena_destroy(&a);
|
||||
@@ -253,7 +253,7 @@ void test_enum_bad_variant() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count > 0); // Yellow 不存在
|
||||
arena_destroy(&a);
|
||||
@@ -272,7 +272,7 @@ void test_array_ok() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0);
|
||||
arena_destroy(&a);
|
||||
@@ -289,7 +289,7 @@ void test_array_index_type_error() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count > 0); // true 不是 i64
|
||||
arena_destroy(&a);
|
||||
@@ -306,7 +306,7 @@ void test_array_not_indexable() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count > 0); // i64 不是数组
|
||||
arena_destroy(&a);
|
||||
@@ -323,7 +323,7 @@ void test_array_assign_ok() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0);
|
||||
arena_destroy(&a);
|
||||
@@ -342,7 +342,7 @@ void test_method_call_ok() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0);
|
||||
arena_destroy(&a);
|
||||
@@ -359,7 +359,7 @@ void test_method_undefined() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count > 0); // nope 不是 Point 的方法
|
||||
arena_destroy(&a);
|
||||
@@ -378,7 +378,7 @@ void test_match_enum_sema_ok() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0); // match 去糖后应通过类型检查
|
||||
arena_destroy(&a);
|
||||
@@ -395,7 +395,7 @@ void test_match_int_sema_ok() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0);
|
||||
arena_destroy(&a);
|
||||
@@ -412,7 +412,7 @@ void test_match_wildcard_only_sema_ok() {
|
||||
AstNode* ast = parse(&a, toks, tc, "test", &parse_err);
|
||||
ASSERT(ast != NULL);
|
||||
|
||||
ErrorList errors; error_init(&errors);
|
||||
ErrorList errors; error_init(&errors, &a);
|
||||
sema_analyze(ast, &errors, &a);
|
||||
ASSERT(errors.count == 0); // 纯通配符 match 应通过
|
||||
arena_destroy(&a);
|
||||
|
||||
Reference in New Issue
Block a user