Skip to content

Commit 7f92237

Browse files
committed
Stop expanding type aliases during name resolution (Phase 2)
names_typealias() now creates TK_TYPEALIASREF nodes instead of expanding aliases inline. The alias identity is preserved throughout the compiler pipeline — type system, reach, and codegen unfold on demand at each dispatch point. All 1423 C++ compiler tests pass. All tools (pony-lsp, pony-lint, pony-doc) and the full-program test runner build successfully. Key changes across 24 files: Names pass: - names_typealias() creates TK_TYPEALIASREF via REPLACE instead of reify+applycap+replace (names_applycap removed as dead code) Expression pass: - pass_expr handles TK_TYPEALIASREF constraint checking - expr_nominal keeps TK_TYPEALIASREF in place (no unfold) - find_infer_type unfolds aliases for tuple destructuring inference - entity_access unfolds aliases for tuple element access (._1, ._2) - check_auto_recover_newref unfolds aliases for auto-recovery eligibility Refer pass: - is_constructed_from unfolds aliases for "let x: Alias = x.create()" Type system: - subtype.c: is_literal unfolds TK_TYPEALIASREF so is_machine_word, is_pointer, etc. correctly identify aliased builtin types - viewpoint.c: unfold-and-redispatch in viewpoint_type/upper/lower - cap.c: unfold in cap_dispatch and modified_cap - safeto.c: unfold in safe_field_move, safe_to_autorecover, safe_to_move - typeparam.c: unfold in cap_from_constraint, apply_cap, constraint_cap; TK_TUPLETYPE fallback for invalid tuple constraints exposed by unfolding - reify.c: unfold in check_constraints for struct-as-typearg detection - alias.c: unfold in sendable() only (other alias.c functions keep Phase 1 behavior — compound alias cap handling deferred to follow-up) Flatten pass: - constraint_contains_tuple passes unfolded type as both constraint and scan to fix union member iteration Lambda/object: - find_possible_fun_defs: don't free unfolded AST (caller stores pointers) - catch_up_provides: unfold TK_TYPE alias definitions for ast_passes_type Array: - find_possible_element_types and iterator variant: don't free unfolded AST (caller stores element type pointers) Reach: - add_type: unfold-and-redispatch - trace_kind_append: unfold-and-redispatch - set_method_types: unfold for param cap extraction Codegen: - genname.c, gentrace.c, genmatch.c, gencall.c, genexpr.c: unfold at all TK_TYPEALIASREF dispatch points - gentrace.c: unfold in TRACE_MACHINE_WORD case for correct boxed/unboxed decision on aliased primitive types Design: #5007
1 parent d6f3873 commit 7f92237

File tree

23 files changed

+587
-138
lines changed

23 files changed

+587
-138
lines changed

src/libponyc/codegen/gencall.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "../pkg/platformfuns.h"
1111
#include "../type/cap.h"
1212
#include "../type/subtype.h"
13+
#include "../type/typealias.h"
1314
#include "../ast/stringtab.h"
1415
#include "../pass/expr.h"
1516
#include "../../libponyrt/mem/pool.h"
@@ -651,6 +652,16 @@ static bool contains_boxable(ast_t* type)
651652
return false;
652653
}
653654

655+
case TK_TYPEALIASREF:
656+
{
657+
ast_t* unfolded = typealias_unfold(type);
658+
pony_assert(unfolded != NULL);
659+
660+
bool ok = contains_boxable(unfolded);
661+
ast_free_unattached(unfolded);
662+
return ok;
663+
}
664+
654665
default:
655666
pony_assert(0);
656667
return false;

src/libponyc/codegen/genexpr.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "genoperator.h"
1010
#include "genreference.h"
1111
#include "../type/subtype.h"
12+
#include "../type/typealias.h"
1213
#include "../../libponyrt/mem/pool.h"
1314
#include "ponyassert.h"
1415

@@ -313,6 +314,19 @@ LLVMValueRef gen_assign_cast(compile_t* c, LLVMTypeRef l_type,
313314

314315
pony_assert(r_value != GEN_NOTNEEDED);
315316

317+
// Unfold type aliases so downstream dispatch sees concrete types.
318+
if(ast_id(type) == TK_TYPEALIASREF)
319+
{
320+
ast_t* unfolded = typealias_unfold(type);
321+
322+
if(unfolded != NULL)
323+
{
324+
LLVMValueRef result = gen_assign_cast(c, l_type, r_value, unfolded);
325+
ast_free_unattached(unfolded);
326+
return result;
327+
}
328+
}
329+
316330
LLVMTypeRef r_type = LLVMTypeOf(r_value);
317331

318332
if(r_type == l_type)

src/libponyc/codegen/genmatch.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "../type/subtype.h"
1111
#include "../type/matchtype.h"
1212
#include "../type/alias.h"
13+
#include "../type/typealias.h"
1314
#include "../type/viewpoint.h"
1415
#include "../type/lookup.h"
1516
#include "ponyassert.h"
@@ -214,6 +215,16 @@ static bool check_type(compile_t* c, LLVMValueRef ptr, LLVMValueRef desc,
214215
return check_type(c, ptr, desc, ast_childidx(pattern_type, 1),
215216
next_block, weight);
216217

218+
case TK_TYPEALIASREF:
219+
{
220+
ast_t* unfolded = typealias_unfold(pattern_type);
221+
pony_assert(unfolded != NULL);
222+
223+
bool ok = check_type(c, ptr, desc, unfolded, next_block, weight);
224+
ast_free_unattached(unfolded);
225+
return ok;
226+
}
227+
217228
default: {}
218229
}
219230

@@ -593,6 +604,16 @@ static bool static_tuple(compile_t* c, LLVMValueRef value, ast_t* type,
593604
return static_tuple(c, value, ast_childidx(type, 1), pattern,
594605
next_block);
595606

607+
case TK_TYPEALIASREF:
608+
{
609+
ast_t* unfolded = typealias_unfold(type);
610+
pony_assert(unfolded != NULL);
611+
612+
bool ok = static_tuple(c, value, unfolded, pattern, next_block);
613+
ast_free_unattached(unfolded);
614+
return ok;
615+
}
616+
596617
default: {}
597618
}
598619

src/libponyc/codegen/genname.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "genname.h"
22
#include "../pkg/package.h"
3+
#include "../type/typealias.h"
34
#include "../ast/stringtab.h"
45
#include "../ast/lexer.h"
56
#include "../../libponyrt/mem/pool.h"
@@ -57,6 +58,16 @@ static void type_append(printbuf_t* buf, ast_t* type, bool first)
5758
return;
5859
}
5960

61+
case TK_TYPEALIASREF:
62+
{
63+
ast_t* unfolded = typealias_unfold(type);
64+
pony_assert(unfolded != NULL);
65+
66+
type_append(buf, unfolded, first);
67+
ast_free_unattached(unfolded);
68+
return;
69+
}
70+
6071
default: {}
6172
}
6273

src/libponyc/codegen/gentrace.c

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "../type/cap.h"
88
#include "../type/matchtype.h"
99
#include "../type/subtype.h"
10+
#include "../type/typealias.h"
1011
#include "ponyassert.h"
1112

1213
// Arranged from most specific to least specific.
@@ -292,7 +293,9 @@ static trace_t trace_type_isect(ast_t* type)
292293
static trace_t trace_type_nominal(ast_t* type)
293294
{
294295
if(is_bare(type))
296+
{
295297
return TRACE_PRIMITIVE;
298+
}
296299

297300
ast_t* def = (ast_t*)ast_data(type);
298301
switch(ast_id(def))
@@ -364,6 +367,16 @@ static trace_t trace_type(ast_t* type)
364367
case TK_NOMINAL:
365368
return trace_type_nominal(type);
366369

370+
case TK_TYPEALIASREF:
371+
{
372+
ast_t* unfolded = typealias_unfold(type);
373+
pony_assert(unfolded != NULL);
374+
375+
trace_t result = trace_type(unfolded);
376+
ast_free_unattached(unfolded);
377+
return result;
378+
}
379+
367380
default: {}
368381
}
369382

@@ -931,6 +944,18 @@ static void trace_dynamic(compile_t* c, LLVMValueRef ctx, LLVMValueRef object,
931944
trace_dynamic_nominal(c, ctx, object, type, orig, tuple, next_block);
932945
break;
933946

947+
case TK_TYPEALIASREF:
948+
{
949+
ast_t* unfolded = typealias_unfold(type);
950+
951+
if(unfolded != NULL)
952+
{
953+
trace_dynamic(c, ctx, object, unfolded, orig, tuple, next_block);
954+
ast_free_unattached(unfolded);
955+
}
956+
break;
957+
}
958+
934959
default: {}
935960
}
936961
}
@@ -945,12 +970,31 @@ bool gentrace_needed(compile_t* c, ast_t* src_type, ast_t* dst_type)
945970

946971
case TRACE_MACHINE_WORD:
947972
{
948-
if(ast_id(dst_type) == TK_NOMINAL)
973+
ast_t* check_type = dst_type;
974+
ast_t* unfolded = NULL;
975+
976+
if(ast_id(check_type) == TK_TYPEALIASREF)
977+
{
978+
unfolded = typealias_unfold(check_type);
979+
check_type = unfolded;
980+
}
981+
982+
if((check_type != NULL) && (ast_id(check_type) == TK_NOMINAL))
949983
{
950-
ast_t* def = (ast_t*)ast_data(dst_type);
984+
ast_t* def = (ast_t*)ast_data(check_type);
985+
951986
if(ast_id(def) == TK_PRIMITIVE)
987+
{
988+
if(unfolded != NULL)
989+
ast_free_unattached(unfolded);
990+
952991
return false;
992+
}
953993
}
994+
995+
if(unfolded != NULL)
996+
ast_free_unattached(unfolded);
997+
954998
return true;
955999
}
9561000

@@ -1038,13 +1082,28 @@ void gentrace(compile_t* c, LLVMValueRef ctx, LLVMValueRef src_value,
10381082
case TRACE_MACHINE_WORD:
10391083
{
10401084
bool boxed = true;
1041-
if(ast_id(dst_type) == TK_NOMINAL)
1085+
1086+
ast_t* check_dst = dst_type;
1087+
ast_t* dst_unfolded = NULL;
1088+
1089+
if(ast_id(check_dst) == TK_TYPEALIASREF)
10421090
{
1043-
ast_t* def = (ast_t*)ast_data(dst_type);
1091+
dst_unfolded = typealias_unfold(check_dst);
1092+
1093+
if(dst_unfolded != NULL)
1094+
check_dst = dst_unfolded;
1095+
}
1096+
1097+
if(ast_id(check_dst) == TK_NOMINAL)
1098+
{
1099+
ast_t* def = (ast_t*)ast_data(check_dst);
10441100
if(ast_id(def) == TK_PRIMITIVE)
10451101
boxed = false;
10461102
}
10471103

1104+
if(dst_unfolded != NULL)
1105+
ast_free_unattached(dst_unfolded);
1106+
10481107
if(boxed)
10491108
trace_known(c, ctx, dst_value, src_type, PONY_TRACE_IMMUTABLE);
10501109

src/libponyc/expr/array.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,13 +192,14 @@ static void find_possible_element_types(pass_opt_t* opt, ast_t* ast,
192192

193193
case TK_TYPEALIASREF:
194194
{
195+
// Don't free the unfolded AST: the TK_NOMINAL case stores pointers
196+
// into it (ast_child(typeargs) for Array element types) that the
197+
// caller uses.
195198
ast_t* unfolded = typealias_unfold(ast);
196199

197200
if(unfolded != NULL)
198-
{
199201
find_possible_element_types(opt, unfolded, list);
200-
ast_free_unattached(unfolded);
201-
}
202+
202203
return;
203204
}
204205

@@ -245,13 +246,12 @@ static void find_possible_iterator_element_types(pass_opt_t* opt, ast_t* ast,
245246

246247
case TK_TYPEALIASREF:
247248
{
249+
// Don't free: same reason as find_possible_element_types above.
248250
ast_t* unfolded = typealias_unfold(ast);
249251

250252
if(unfolded != NULL)
251-
{
252253
find_possible_iterator_element_types(opt, unfolded, list);
253-
ast_free_unattached(unfolded);
254-
}
254+
255255
return;
256256
}
257257

src/libponyc/expr/call.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "../type/safeto.h"
1919
#include "../type/sanitise.h"
2020
#include "../type/subtype.h"
21+
#include "../type/typealias.h"
2122
#include "../type/viewpoint.h"
2223
#include "ponyassert.h"
2324

@@ -201,7 +202,20 @@ static ast_t* method_receiver_type(ast_t* method);
201202
bool check_auto_recover_newref(ast_t* dest_type, ast_t* ast)
202203
{
203204
// we're not going to try auto-recovering to a complex type
204-
if (ast_id(dest_type) != TK_NOMINAL)
205+
token_id dest_id = ast_id(dest_type);
206+
207+
if(dest_id == TK_TYPEALIASREF)
208+
{
209+
ast_t* unfolded = typealias_unfold(dest_type);
210+
211+
if(unfolded != NULL)
212+
{
213+
dest_id = ast_id(unfolded);
214+
ast_free_unattached(unfolded);
215+
}
216+
}
217+
218+
if(dest_id != TK_NOMINAL)
205219
return false;
206220

207221
while (ast != NULL && ast_id(ast) != TK_CALL)

src/libponyc/expr/lambda.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,13 @@ static void find_possible_fun_defs(pass_opt_t* opt, ast_t* ast,
213213

214214
case TK_TYPEALIASREF:
215215
{
216+
// Don't free the unfolded AST: find_possible_fun_defs stores pointers
217+
// into it (the obj_cap at child 3 of the nominal) that the caller uses.
216218
ast_t* unfolded = typealias_unfold(ast);
217219

218220
if(unfolded != NULL)
219-
{
220221
find_possible_fun_defs(opt, unfolded, fun_defs, obj_caps);
221-
ast_free_unattached(unfolded);
222-
}
222+
223223
break;
224224
}
225225

@@ -683,6 +683,27 @@ static bool catch_up_provides(pass_opt_t* opt, ast_t* provides, ast_t* obj_ast)
683683

684684
ast_t* def = (ast_t*)ast_data(child);
685685

686+
// For type aliases, unfold to get the concrete type definition.
687+
// ast_data on TK_TYPEALIASREF points to TK_TYPE, not a class/trait.
688+
if((def != NULL) && (ast_id(child) == TK_TYPEALIASREF))
689+
{
690+
ast_t* unfolded = typealias_unfold(child);
691+
692+
if(unfolded != NULL)
693+
{
694+
if(ast_id(unfolded) == TK_NOMINAL)
695+
def = (ast_t*)ast_data(unfolded);
696+
else
697+
def = NULL;
698+
699+
ast_free_unattached(unfolded);
700+
}
701+
else
702+
{
703+
def = NULL;
704+
}
705+
}
706+
686707
if(def != NULL)
687708
{
688709
// If the provided type definition is an ancestor of the original object

0 commit comments

Comments
 (0)