mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Correct the type aliasing problem, caused by aliases (of aliases)+
This commit is contained in:
@@ -387,6 +387,7 @@ void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init,
|
|||||||
if (init != nullptr) {
|
if (init != nullptr) {
|
||||||
Entity *entity = check_entity_from_ident_or_selector(ctx, init);
|
Entity *entity = check_entity_from_ident_or_selector(ctx, init);
|
||||||
if (entity != nullptr && entity->kind == Entity_TypeName) {
|
if (entity != nullptr && entity->kind == Entity_TypeName) {
|
||||||
|
// @TypeAliasingProblem
|
||||||
// NOTE(bill, 2022-02-03): This is used to solve the problem caused by type aliases
|
// NOTE(bill, 2022-02-03): This is used to solve the problem caused by type aliases
|
||||||
// being "confused" as constants
|
// being "confused" as constants
|
||||||
//
|
//
|
||||||
|
|||||||
+4
-1
@@ -4088,7 +4088,7 @@ Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *node) {
|
|||||||
return scope_lookup(c->scope, name);
|
return scope_lookup(c->scope, name);
|
||||||
} else if (node->kind == Ast_SelectorExpr) {
|
} else if (node->kind == Ast_SelectorExpr) {
|
||||||
ast_node(se, SelectorExpr, node);
|
ast_node(se, SelectorExpr, node);
|
||||||
if (!c->allow_arrow_right_selector_expr && se->token.kind == Token_ArrowRight) {
|
if (se->token.kind == Token_ArrowRight) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4108,6 +4108,9 @@ Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *node) {
|
|||||||
if (op_expr->kind == Ast_Ident) {
|
if (op_expr->kind == Ast_Ident) {
|
||||||
String op_name = op_expr->Ident.token.string;
|
String op_name = op_expr->Ident.token.string;
|
||||||
Entity *e = scope_lookup(c->scope, op_name);
|
Entity *e = scope_lookup(c->scope, op_name);
|
||||||
|
if (e == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
add_entity_use(c, op_expr, e);
|
add_entity_use(c, op_expr, e);
|
||||||
expr_entity = e;
|
expr_entity = e;
|
||||||
|
|
||||||
|
|||||||
+65
-1
@@ -3665,6 +3665,59 @@ void check_add_foreign_block_decl(CheckerContext *ctx, Ast *decl) {
|
|||||||
check_collect_entities(&c, block->stmts);
|
check_collect_entities(&c, block->stmts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool correct_single_type_alias(CheckerContext *c, Entity *e) {
|
||||||
|
if (e->kind == Entity_Constant) {
|
||||||
|
DeclInfo *d = e->decl_info;
|
||||||
|
if (d != nullptr && d->init_expr != nullptr) {
|
||||||
|
Ast *init = d->init_expr;
|
||||||
|
Entity *alias_of = check_entity_from_ident_or_selector(c, init);
|
||||||
|
if (alias_of != nullptr && alias_of->kind == Entity_TypeName) {
|
||||||
|
e->kind = Entity_TypeName;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool correct_type_alias_in_scope_backwards(CheckerContext *c, Scope *s) {
|
||||||
|
isize n = s->elements.entries.count;
|
||||||
|
bool correction = false;
|
||||||
|
for (isize i = n-1; i >= 0; i--) {
|
||||||
|
correction |= correct_single_type_alias(c, s->elements.entries[i].value);
|
||||||
|
}
|
||||||
|
return correction;
|
||||||
|
}
|
||||||
|
bool correct_type_alias_in_scope_forwards(CheckerContext *c, Scope *s) {
|
||||||
|
isize n = s->elements.entries.count;
|
||||||
|
bool correction = false;
|
||||||
|
for (isize i = 0; i < n; i++) {
|
||||||
|
correction |= correct_single_type_alias(c, s->elements.entries[i].value);
|
||||||
|
}
|
||||||
|
return correction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void correct_type_aliases_in_scope(CheckerContext *c, Scope *s) {
|
||||||
|
// NOTE(bill, 2022-02-04): This is used to solve the problem caused by type aliases
|
||||||
|
// of type aliases being "confused" as constants
|
||||||
|
//
|
||||||
|
// A :: C
|
||||||
|
// B :: A
|
||||||
|
// C :: struct {b: ^B}
|
||||||
|
//
|
||||||
|
// See @TypeAliasingProblem for more information
|
||||||
|
for (;;) {
|
||||||
|
bool corrections = false;
|
||||||
|
corrections |= correct_type_alias_in_scope_backwards(c, s);
|
||||||
|
corrections |= correct_type_alias_in_scope_forwards(c, s);
|
||||||
|
if (!corrections) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// NOTE(bill): If file_scopes == nullptr, this will act like a local scope
|
// NOTE(bill): If file_scopes == nullptr, this will act like a local scope
|
||||||
void check_collect_entities(CheckerContext *c, Slice<Ast *> const &nodes) {
|
void check_collect_entities(CheckerContext *c, Slice<Ast *> const &nodes) {
|
||||||
AstFile *curr_file = nullptr;
|
AstFile *curr_file = nullptr;
|
||||||
@@ -3736,6 +3789,7 @@ void check_collect_entities(CheckerContext *c, Slice<Ast *> const &nodes) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// correct_type_aliases(c);
|
||||||
|
|
||||||
// NOTE(bill): 'when' stmts need to be handled after the other as the condition may refer to something
|
// NOTE(bill): 'when' stmts need to be handled after the other as the condition may refer to something
|
||||||
// declared after this stmt in source
|
// declared after this stmt in source
|
||||||
@@ -4381,10 +4435,11 @@ bool collect_file_decls(CheckerContext *ctx, Slice<Ast *> const &decls) {
|
|||||||
|
|
||||||
for_array(i, decls) {
|
for_array(i, decls) {
|
||||||
if (collect_file_decl(ctx, decls[i])) {
|
if (collect_file_decl(ctx, decls[i])) {
|
||||||
|
correct_type_aliases_in_scope(ctx, ctx->scope);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
correct_type_aliases_in_scope(ctx, ctx->scope);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4654,6 +4709,15 @@ void check_import_entities(Checker *c) {
|
|||||||
}
|
}
|
||||||
add_untyped_expressions(ctx.info, &untyped);
|
add_untyped_expressions(ctx.info, &untyped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for_array(i, pkg->files) {
|
||||||
|
AstFile *f = pkg->files[i];
|
||||||
|
reset_checker_context(&ctx, f, &untyped);
|
||||||
|
ctx.collect_delayed_decls = false;
|
||||||
|
|
||||||
|
correct_type_aliases_in_scope(&ctx, pkg->scope);
|
||||||
|
}
|
||||||
|
|
||||||
for_array(i, pkg->files) {
|
for_array(i, pkg->files) {
|
||||||
AstFile *f = pkg->files[i];
|
AstFile *f = pkg->files[i];
|
||||||
reset_checker_context(&ctx, f, &untyped);
|
reset_checker_context(&ctx, f, &untyped);
|
||||||
|
|||||||
Reference in New Issue
Block a user