diff --git a/src/ast.c b/src/ast.c index 5e470b7606b3e..068d082f14aa6 100644 --- a/src/ast.c +++ b/src/ast.c @@ -43,8 +43,7 @@ jl_sym_t *exc_sym; jl_sym_t *error_sym; jl_sym_t *new_sym; jl_sym_t *using_sym; jl_sym_t *splatnew_sym; jl_sym_t *const_sym; jl_sym_t *thunk_sym; -jl_sym_t *abstracttype_sym; jl_sym_t *primtype_sym; -jl_sym_t *structtype_sym; jl_sym_t *foreigncall_sym; +jl_sym_t *foreigncall_sym; jl_sym_t *global_sym; jl_sym_t *list_sym; jl_sym_t *dot_sym; jl_sym_t *newvar_sym; jl_sym_t *boundscheck_sym; jl_sym_t *inbounds_sym; @@ -62,7 +61,7 @@ jl_sym_t *throw_undef_if_not_sym; jl_sym_t *getfield_undefref_sym; jl_sym_t *gc_preserve_begin_sym; jl_sym_t *gc_preserve_end_sym; jl_sym_t *coverageeffect_sym; jl_sym_t *escape_sym; jl_sym_t *aliasscope_sym; jl_sym_t *popaliasscope_sym; -jl_sym_t *optlevel_sym; +jl_sym_t *optlevel_sym; jl_sym_t *thismodule_sym; static uint8_t flisp_system_image[] = { #include @@ -357,9 +356,6 @@ void jl_init_frontend(void) const_sym = jl_symbol("const"); global_sym = jl_symbol("global"); thunk_sym = jl_symbol("thunk"); - abstracttype_sym = jl_symbol("abstract_type"); - primtype_sym = jl_symbol("primitive_type"); - structtype_sym = jl_symbol("struct_type"); toplevel_sym = jl_symbol("toplevel"); dot_sym = jl_symbol("."); colon_sym = jl_symbol(":"); @@ -395,6 +391,7 @@ void jl_init_frontend(void) coverageeffect_sym = jl_symbol("code_coverage_effect"); aliasscope_sym = jl_symbol("aliasscope"); popaliasscope_sym = jl_symbol("popaliasscope"); + thismodule_sym = jl_symbol("thismodule"); } JL_DLLEXPORT void jl_lisp_prompt(void) @@ -577,6 +574,9 @@ static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, jl_module_t *m assert(jl_is_symbol(ex)); temp = jl_module_globalref(jl_core_module, (jl_sym_t*)ex); } + else if (sym == thismodule_sym) { + temp = (jl_value_t*)mod; + } else if (iscons(e) && (sym == inert_sym || (sym == quote_sym && (!iscons(car_(e)))))) { ex = scm_to_julia_(fl_ctx, car_(e), mod); temp = jl_new_struct(jl_quotenode_type, ex); diff --git a/src/ast.scm b/src/ast.scm index 663e845a309a6..a37da4eed387d 100644 --- a/src/ast.scm +++ b/src/ast.scm @@ -358,12 +358,15 @@ (define (globalref? e) (and (pair? e) (eq? (car e) 'globalref))) +(define (outerref? e) + (and (pair? e) (eq? (car e) 'outerref))) + (define (symbol-like? e) (or (symbol? e) (ssavalue? e))) (define (simple-atom? x) (or (number? x) (string? x) (char? x) - (and (pair? x) (memq (car x) '(ssavalue null true false))) + (and (pair? x) (memq (car x) '(ssavalue null true false thismodule))) (eq? (typeof x) 'julia_value))) ;; identify some expressions that are safe to repeat diff --git a/src/builtin_proto.h b/src/builtin_proto.h index 85762ce2f9ffa..a13cebdace3b1 100644 --- a/src/builtin_proto.h +++ b/src/builtin_proto.h @@ -33,9 +33,14 @@ DECLARE_BUILTIN(arrayset); DECLARE_BUILTIN(arraysize); DECLARE_BUILTIN(apply_type); DECLARE_BUILTIN(applicable); DECLARE_BUILTIN(invoke); DECLARE_BUILTIN(_expr); DECLARE_BUILTIN(typeassert); DECLARE_BUILTIN(ifelse); -DECLARE_BUILTIN(_typevar); +DECLARE_BUILTIN(_typevar); DECLARE_BUILTIN(_typebody); JL_CALLABLE(jl_f_invoke_kwsorter); +JL_CALLABLE(jl_f__structtype); +JL_CALLABLE(jl_f__abstracttype); +JL_CALLABLE(jl_f__primitivetype); +JL_CALLABLE(jl_f__setsuper); +JL_CALLABLE(jl_f__equiv_typedef); #ifdef __cplusplus } diff --git a/src/builtins.c b/src/builtins.c index a783460d5d8f8..a3c3d55ce1255 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1181,6 +1181,188 @@ JL_CALLABLE(jl_f_arrayset) return args[1]; } +// type definition ------------------------------------------------------------ + +JL_CALLABLE(jl_f__structtype) +{ + JL_NARGS(_structtype, 6, 6); + JL_TYPECHK(_structtype, module, args[0]); + JL_TYPECHK(_structtype, symbol, args[1]); + JL_TYPECHK(_structtype, simplevector, args[2]); + JL_TYPECHK(_structtype, simplevector, args[3]); + JL_TYPECHK(_structtype, bool, args[4]); + JL_TYPECHK(_structtype, long, args[5]); + jl_value_t *fieldnames = args[3]; + jl_datatype_t *dt = NULL; + dt = jl_new_datatype((jl_sym_t*)args[1], (jl_module_t*)args[0], NULL, (jl_svec_t*)args[2], + (jl_svec_t*)fieldnames, NULL, + 0, args[4]==jl_true ? 1 : 0, jl_unbox_long(args[5])); + return dt->name->wrapper; +} + +JL_CALLABLE(jl_f__abstracttype) +{ + JL_NARGS(_abstracttype, 3, 3); + JL_TYPECHK(_abstracttype, module, args[0]); + JL_TYPECHK(_abstracttype, symbol, args[1]); + JL_TYPECHK(_abstracttype, simplevector, args[2]); + jl_datatype_t *dt = jl_new_abstracttype(args[1], (jl_module_t*)args[0], NULL, (jl_svec_t*)args[2]); + return dt->name->wrapper; +} + +JL_CALLABLE(jl_f__primitivetype) +{ + JL_NARGS(_primitivetype, 4, 4); + JL_TYPECHK(_primitivetype, module, args[0]); + JL_TYPECHK(_primitivetype, symbol, args[1]); + JL_TYPECHK(_primitivetype, simplevector, args[2]); + jl_sym_t *name = (jl_sym_t*)args[1]; + jl_value_t *vnb = args[3]; + if (!jl_is_long(vnb)) + jl_errorf("invalid declaration of primitive type %s", + jl_symbol_name((jl_sym_t*)name)); + ssize_t nb = jl_unbox_long(vnb); + if (nb < 1 || nb >= (1 << 23) || (nb & 7) != 0) + jl_errorf("invalid number of bits in primitive type %s", + jl_symbol_name((jl_sym_t*)name)); + jl_datatype_t *dt = jl_new_primitivetype(args[1], (jl_module_t*)args[0], NULL, (jl_svec_t*)args[2], nb); + return dt->name->wrapper; +} + +void jl_set_datatype_super(jl_datatype_t *tt, jl_value_t *super) +{ + if (!jl_is_datatype(super) || !jl_is_abstracttype(super) || + tt->super != NULL || + tt->name == ((jl_datatype_t*)super)->name || + jl_subtype(super, (jl_value_t*)jl_vararg_type) || + jl_is_tuple_type(super) || + jl_is_namedtuple_type(super) || + jl_subtype(super, (jl_value_t*)jl_type_type) || + jl_subtype(super, (jl_value_t*)jl_builtin_type)) { + jl_errorf("invalid subtyping in definition of %s", + jl_symbol_name(tt->name->name)); + } + tt->super = (jl_datatype_t*)super; + jl_gc_wb(tt, tt->super); +} + +JL_CALLABLE(jl_f__setsuper) +{ + JL_NARGS(_setsuper!, 2, 2); + jl_datatype_t *dt = (jl_datatype_t*)jl_unwrap_unionall(args[0]); + JL_TYPECHK(_setsuper!, datatype, (jl_value_t*)dt); + jl_set_datatype_super(dt, args[1]); + return jl_nothing; +} + +void jl_reinstantiate_inner_types(jl_datatype_t *t); + +JL_CALLABLE(jl_f__typebody) +{ + JL_NARGS(_typebody!, 1, 2); + jl_datatype_t *dt = (jl_datatype_t*)jl_unwrap_unionall(args[0]); + JL_TYPECHK(_typebody!, datatype, (jl_value_t*)dt); + if (nargs == 2) { + jl_value_t *ft = args[1]; + JL_TYPECHK(_typebody!, simplevector, ft); + dt->types = (jl_svec_t*)ft; + jl_gc_wb(dt, ft); + for (size_t i = 0; i < jl_svec_len(dt->types); i++) { + jl_value_t *elt = jl_svecref(dt->types, i); + if ((!jl_is_type(elt) && !jl_is_typevar(elt)) || jl_is_vararg_type(elt)) { + jl_type_error_rt(jl_symbol_name(dt->name->name), + "type definition", + (jl_value_t*)jl_type_type, elt); + } + } + } + + JL_TRY { + jl_reinstantiate_inner_types(dt); + } + JL_CATCH { + dt->name->partial = NULL; + jl_rethrow(); + } + + if (jl_is_structtype(dt)) + jl_compute_field_offsets(dt); + return jl_nothing; +} + +// this is a heuristic for allowing "redefining" a type to something identical +static int equiv_type(jl_value_t *ta, jl_value_t *tb) +{ + jl_datatype_t *dta = (jl_datatype_t*)jl_unwrap_unionall(ta); + if (!jl_is_datatype(dta)) + return 0; + jl_datatype_t *dtb = (jl_datatype_t*)jl_unwrap_unionall(tb); + if (!(jl_typeof(dta) == jl_typeof(dtb) && + dta->name->name == dtb->name->name && + dta->abstract == dtb->abstract && + dta->mutabl == dtb->mutabl && + dta->size == dtb->size && + dta->ninitialized == dtb->ninitialized && + jl_egal((jl_value_t*)jl_field_names(dta), (jl_value_t*)jl_field_names(dtb)) && + jl_nparams(dta) == jl_nparams(dtb) && + jl_svec_len(dta->types) == jl_svec_len(dtb->types))) + return 0; + jl_value_t *a=NULL, *b=NULL; + int ok = 1; + size_t i, nf = jl_svec_len(dta->types); + JL_GC_PUSH2(&a, &b); + a = jl_rewrap_unionall((jl_value_t*)dta->super, dta->name->wrapper); + b = jl_rewrap_unionall((jl_value_t*)dtb->super, dtb->name->wrapper); + if (!jl_types_equal(a, b)) + goto no; + JL_TRY { + a = jl_apply_type(dtb->name->wrapper, jl_svec_data(dta->parameters), jl_nparams(dta)); + } + JL_CATCH { + ok = 0; + } + if (!ok) + goto no; + assert(jl_is_datatype(a)); + a = dta->name->wrapper; + b = dtb->name->wrapper; + while (jl_is_unionall(a)) { + jl_unionall_t *ua = (jl_unionall_t*)a; + jl_unionall_t *ub = (jl_unionall_t*)b; + if (!jl_egal(ua->var->lb, ub->var->lb) || !jl_egal(ua->var->ub, ub->var->ub) || + ua->var->name != ub->var->name) + goto no; + a = jl_instantiate_unionall(ua, (jl_value_t*)ub->var); + b = ub->body; + } + assert(jl_is_datatype(a) && jl_is_datatype(b)); + a = (jl_value_t*)jl_get_fieldtypes((jl_datatype_t*)a); + b = (jl_value_t*)jl_get_fieldtypes((jl_datatype_t*)b); + for (i = 0; i < nf; i++) { + jl_value_t *ta = jl_svecref(a, i); + jl_value_t *tb = jl_svecref(b, i); + if (jl_has_free_typevars(ta)) { + if (!jl_has_free_typevars(tb) || !jl_egal(ta, tb)) + goto no; + } + else if (jl_has_free_typevars(tb) || jl_typeof(ta) != jl_typeof(tb) || + !jl_types_equal(ta, tb)) { + goto no; + } + } + JL_GC_POP(); + return 1; + no: + JL_GC_POP(); + return 0; +} + +JL_CALLABLE(jl_f__equiv_typedef) +{ + JL_NARGS(_equiv_typedef, 2, 2); + return equiv_type(args[0], args[1]) ? jl_true : jl_false; +} + // IntrinsicFunctions --------------------------------------------------------- static void (*runtime_fp[num_intrinsics])(void); @@ -1343,6 +1525,12 @@ void jl_init_primitives(void) JL_GC_DISABLED add_builtin_func("_apply_pure", jl_f__apply_pure); add_builtin_func("_apply_latest", jl_f__apply_latest); add_builtin_func("_typevar", jl_f__typevar); + add_builtin_func("_structtype", jl_f__structtype); + add_builtin_func("_abstracttype", jl_f__abstracttype); + add_builtin_func("_primitivetype", jl_f__primitivetype); + add_builtin_func("_setsuper!", jl_f__setsuper); + jl_builtin__typebody = add_builtin_func("_typebody!", jl_f__typebody); + add_builtin_func("_equiv_typedef", jl_f__equiv_typedef); // builtin types add_builtin("Any", (jl_value_t*)jl_any_type); diff --git a/src/codegen.cpp b/src/codegen.cpp index 26722855b92c2..7bb97b9fbaff9 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3855,14 +3855,8 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval) ctx.builder.CreateCall(prepare_call(jltopeval_func), args); return ghostValue(jl_nothing_type); } - if (head == abstracttype_sym || head == structtype_sym || - head == primtype_sym) { - jl_errorf("type definition not allowed inside a local scope"); - } - else { - jl_errorf("unsupported or misplaced expression \"%s\" in function %s", - jl_symbol_name(head), ctx.name); - } + jl_errorf("unsupported or misplaced expression \"%s\" in function %s", + jl_symbol_name(head), ctx.name); } return jl_cgval_t(); } diff --git a/src/datatype.c b/src/datatype.c index b2b1731c12c7a..657108fc20dd8 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -73,6 +73,7 @@ JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *modu tn->names = NULL; tn->hash = bitmix(bitmix(module ? module->build_id : 0, name->hash), 0xa1ada1da); tn->mt = NULL; + tn->partial = NULL; return tn; } diff --git a/src/dump.c b/src/dump.c index 822083888c34f..34459e38d99d7 100644 --- a/src/dump.c +++ b/src/dump.c @@ -2022,6 +2022,7 @@ static jl_value_t *jl_deserialize_value_any(jl_serializer_state *s, uint8_t tag, memset(tn, 0, sizeof(jl_typename_t)); tn->cache = jl_emptysvec; // the cache is refilled later (tag 5) tn->linearcache = jl_emptysvec; // the cache is refilled later (tag 5) + tn->partial = NULL; if (usetable) backref_list.items[pos] = tn; } diff --git a/src/gc.c b/src/gc.c index 5b81785130ed4..85163067f6895 100644 --- a/src/gc.c +++ b/src/gc.c @@ -2682,8 +2682,6 @@ static void mark_roots(jl_gc_mark_cache_t *gc_cache, jl_gc_mark_sp_t *sp) // constants gc_mark_queue_obj(gc_cache, sp, jl_typetype_type); gc_mark_queue_obj(gc_cache, sp, jl_emptytuple_type); - - gc_mark_queue_finlist(gc_cache, sp, &partial_inst, 0); } // find unmarked objects that need to be finalized from the finalizer list "list". diff --git a/src/init.c b/src/init.c index 43b2f8abd2234..f1050564f8f74 100644 --- a/src/init.c +++ b/src/init.c @@ -719,7 +719,6 @@ void _julia_init(JL_IMAGE_SEARCH rel) if (jl_options.cpu_target == NULL) jl_options.cpu_target = "native"; - arraylist_new(&partial_inst, 0); if (jl_options.image_file) { jl_restore_system_image(jl_options.image_file); } diff --git a/src/interpreter.c b/src/interpreter.c index 0e7f00cf4a245..7f52019e90d38 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -73,258 +73,6 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, size_t ip, int jl_is_toplevel_only_expr(jl_value_t *e); -// type definition forms - -extern int inside_typedef; - -// this is a heuristic for allowing "redefining" a type to something identical -static int equiv_type(jl_datatype_t *dta, jl_datatype_t *dtb) -{ - if (!(jl_typeof(dta) == jl_typeof(dtb) && - dta->name->name == dtb->name->name && - dta->abstract == dtb->abstract && - dta->mutabl == dtb->mutabl && - dta->size == dtb->size && - dta->ninitialized == dtb->ninitialized && - jl_egal((jl_value_t*)jl_field_names(dta), (jl_value_t*)jl_field_names(dtb)) && - jl_nparams(dta) == jl_nparams(dtb) && - jl_svec_len(dta->types) == jl_svec_len(dtb->types))) - return 0; - jl_value_t *a=NULL, *b=NULL; - int ok = 1; - size_t i, nf = jl_svec_len(dta->types); - JL_GC_PUSH2(&a, &b); - a = jl_rewrap_unionall((jl_value_t*)dta->super, dta->name->wrapper); - b = jl_rewrap_unionall((jl_value_t*)dtb->super, dtb->name->wrapper); - if (!jl_types_equal(a, b)) - goto no; - JL_TRY { - a = jl_apply_type(dtb->name->wrapper, jl_svec_data(dta->parameters), jl_nparams(dta)); - } - JL_CATCH { - ok = 0; - } - if (!ok) - goto no; - assert(jl_is_datatype(a)); - a = dta->name->wrapper; - b = dtb->name->wrapper; - while (jl_is_unionall(a)) { - jl_unionall_t *ua = (jl_unionall_t*)a; - jl_unionall_t *ub = (jl_unionall_t*)b; - if (!jl_egal(ua->var->lb, ub->var->lb) || !jl_egal(ua->var->ub, ub->var->ub) || - ua->var->name != ub->var->name) - goto no; - a = jl_instantiate_unionall(ua, (jl_value_t*)ub->var); - b = ub->body; - } - assert(jl_is_datatype(a) && jl_is_datatype(b)); - a = (jl_value_t*)jl_get_fieldtypes((jl_datatype_t*)a); - b = (jl_value_t*)jl_get_fieldtypes((jl_datatype_t*)b); - for (i = 0; i < nf; i++) { - jl_value_t *ta = jl_svecref(a, i); - jl_value_t *tb = jl_svecref(b, i); - if (jl_has_free_typevars(ta)) { - if (!jl_has_free_typevars(tb) || !jl_egal(ta, tb)) - goto no; - } - else if (jl_has_free_typevars(tb) || jl_typeof(ta) != jl_typeof(tb) || - !jl_types_equal(ta, tb)) { - goto no; - } - } - JL_GC_POP(); - return 1; - no: - JL_GC_POP(); - return 0; -} - -static void check_can_assign_type(jl_binding_t *b, jl_value_t *rhs) -{ - if (b->constp && b->value != NULL && jl_typeof(b->value) != jl_typeof(rhs)) - jl_errorf("invalid redefinition of constant %s", - jl_symbol_name(b->name)); -} - -void jl_reinstantiate_inner_types(jl_datatype_t *t); -void jl_reset_instantiate_inner_types(jl_datatype_t *t); - -void jl_set_datatype_super(jl_datatype_t *tt, jl_value_t *super) -{ - if (!jl_is_datatype(super) || !jl_is_abstracttype(super) || - tt->name == ((jl_datatype_t*)super)->name || - jl_subtype(super, (jl_value_t*)jl_vararg_type) || - jl_is_tuple_type(super) || - jl_is_namedtuple_type(super) || - jl_subtype(super, (jl_value_t*)jl_type_type) || - jl_subtype(super, (jl_value_t*)jl_builtin_type)) { - jl_errorf("invalid subtyping in definition of %s", - jl_symbol_name(tt->name->name)); - } - tt->super = (jl_datatype_t*)super; - jl_gc_wb(tt, tt->super); -} - -static void eval_abstracttype(jl_expr_t *ex, interpreter_state *s) -{ - jl_value_t **args = jl_array_ptr_data(ex->args); - if (inside_typedef) - jl_error("cannot eval a new abstract type definition while defining another type"); - jl_value_t *name = args[0]; - jl_value_t *para = eval_value(args[1], s); - jl_value_t *super = NULL; - jl_value_t *temp = NULL; - jl_datatype_t *dt = NULL; - jl_value_t *w = NULL; - jl_module_t *modu = s->module; - JL_GC_PUSH5(¶, &super, &temp, &w, &dt); - assert(jl_is_svec(para)); - if (jl_is_globalref(name)) { - modu = jl_globalref_mod(name); - name = (jl_value_t*)jl_globalref_name(name); - } - assert(jl_is_symbol(name)); - dt = jl_new_abstracttype(name, modu, NULL, (jl_svec_t*)para); - w = dt->name->wrapper; - jl_binding_t *b = jl_get_binding_wr(modu, (jl_sym_t*)name, 1); - temp = b->value; - check_can_assign_type(b, w); - b->value = w; - jl_gc_wb_binding(b, w); - JL_TRY { - inside_typedef = 1; - super = eval_value(args[2], s); - jl_set_datatype_super(dt, super); - jl_reinstantiate_inner_types(dt); - } - JL_CATCH { - jl_reset_instantiate_inner_types(dt); - b->value = temp; - jl_rethrow(); - } - b->value = temp; - if (temp == NULL || !equiv_type(dt, (jl_datatype_t*)jl_unwrap_unionall(temp))) { - jl_checked_assignment(b, w); - } - JL_GC_POP(); -} - -static void eval_primitivetype(jl_expr_t *ex, interpreter_state *s) -{ - jl_value_t **args = (jl_value_t**)jl_array_ptr_data(ex->args); - if (inside_typedef) - jl_error("cannot eval a new primitive type definition while defining another type"); - jl_value_t *name = args[0]; - jl_value_t *super = NULL, *para = NULL, *vnb = NULL, *temp = NULL; - jl_datatype_t *dt = NULL; - jl_value_t *w = NULL; - jl_module_t *modu = s->module; - JL_GC_PUSH5(¶, &super, &temp, &w, &dt); - if (jl_is_globalref(name)) { - modu = jl_globalref_mod(name); - name = (jl_value_t*)jl_globalref_name(name); - } - assert(jl_is_symbol(name)); - para = eval_value(args[1], s); - assert(jl_is_svec(para)); - vnb = eval_value(args[2], s); - if (!jl_is_long(vnb)) - jl_errorf("invalid declaration of primitive type %s", - jl_symbol_name((jl_sym_t*)name)); - ssize_t nb = jl_unbox_long(vnb); - if (nb < 1 || nb >= (1 << 23) || (nb & 7) != 0) - jl_errorf("invalid number of bits in primitive type %s", - jl_symbol_name((jl_sym_t*)name)); - dt = jl_new_primitivetype(name, modu, NULL, (jl_svec_t*)para, nb); - w = dt->name->wrapper; - jl_binding_t *b = jl_get_binding_wr(modu, (jl_sym_t*)name, 1); - temp = b->value; - check_can_assign_type(b, w); - b->value = w; - jl_gc_wb_binding(b, w); - JL_TRY { - inside_typedef = 1; - super = eval_value(args[3], s); - jl_set_datatype_super(dt, super); - jl_reinstantiate_inner_types(dt); - } - JL_CATCH { - jl_reset_instantiate_inner_types(dt); - b->value = temp; - jl_rethrow(); - } - b->value = temp; - if (temp == NULL || !equiv_type(dt, (jl_datatype_t*)jl_unwrap_unionall(temp))) { - jl_checked_assignment(b, w); - } - JL_GC_POP(); -} - -static void eval_structtype(jl_expr_t *ex, interpreter_state *s) -{ - jl_value_t **args = jl_array_ptr_data(ex->args); - if (inside_typedef) - jl_error("cannot eval a new struct type definition while defining another type"); - jl_value_t *name = args[0]; - jl_value_t *para = eval_value(args[1], s); - jl_value_t *temp = NULL; - jl_value_t *super = NULL; - jl_datatype_t *dt = NULL; - jl_value_t *w = NULL; - jl_module_t *modu = s->module; - JL_GC_PUSH5(¶, &super, &temp, &w, &dt); - if (jl_is_globalref(name)) { - modu = jl_globalref_mod(name); - name = (jl_value_t*)jl_globalref_name(name); - } - assert(jl_is_symbol(name)); - assert(jl_is_svec(para)); - temp = eval_value(args[2], s); // field names - dt = jl_new_datatype((jl_sym_t*)name, modu, NULL, (jl_svec_t*)para, - (jl_svec_t*)temp, NULL, - 0, args[5]==jl_true ? 1 : 0, jl_unbox_long(args[6])); - w = dt->name->wrapper; - - jl_binding_t *b = jl_get_binding_wr(modu, (jl_sym_t*)name, 1); - temp = b->value; // save old value - // temporarily assign so binding is available for field types - check_can_assign_type(b, w); - b->value = w; - jl_gc_wb_binding(b, w); - - JL_TRY { - inside_typedef = 1; - // operations that can fail - super = eval_value(args[3], s); - jl_set_datatype_super(dt, super); - dt->types = (jl_svec_t*)eval_value(args[4], s); - jl_gc_wb(dt, dt->types); - for (size_t i = 0; i < jl_svec_len(dt->types); i++) { - jl_value_t *elt = jl_svecref(dt->types, i); - if ((!jl_is_type(elt) && !jl_is_typevar(elt)) || jl_is_vararg_type(elt)) { - jl_type_error_rt(jl_symbol_name(dt->name->name), - "type definition", - (jl_value_t*)jl_type_type, elt); - } - } - jl_reinstantiate_inner_types(dt); - } - JL_CATCH { - jl_reset_instantiate_inner_types(dt); - b->value = temp; - jl_rethrow(); - } - jl_compute_field_offsets(dt); - - b->value = temp; - if (temp == NULL || !equiv_type(dt, (jl_datatype_t*)jl_unwrap_unionall(temp))) { - jl_checked_assignment(b, w); - } - - JL_GC_POP(); -} - // method definition form static jl_value_t *eval_methoddef(jl_expr_t *ex, interpreter_state *s) @@ -775,15 +523,6 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, size_t ip, if (head == method_sym && jl_expr_nargs(stmt) > 1) { eval_methoddef((jl_expr_t*)stmt, s); } - else if (head == abstracttype_sym) { - eval_abstracttype((jl_expr_t*)stmt, s); - } - else if (head == primtype_sym) { - eval_primitivetype((jl_expr_t*)stmt, s); - } - else if (head == structtype_sym) { - eval_structtype((jl_expr_t*)stmt, s); - } else if (head == toplevel_sym) { jl_value_t *res = jl_toplevel_eval(s->module, stmt); s->locals[jl_source_nslots(s->src) + s->ip] = res; diff --git a/src/jltypes.c b/src/jltypes.c index bf38e0320ad81..1803cbf1dfbc2 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1079,9 +1079,6 @@ static void check_datatype_parameters(jl_typename_t *tn, jl_value_t **params, si JL_GC_POP(); } -arraylist_t partial_inst; -int inside_typedef = 0; - static jl_value_t *extract_wrapper(jl_value_t *t JL_PROPAGATES_ROOT) { t = jl_unwrap_unionall(t); @@ -1342,8 +1339,11 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value if (ftypes == NULL || dt->super == NULL) { // in the process of creating this type definition: // need to instantiate the super and types fields later - assert((inside_typedef || primarydt->super) && !istuple && !isnamedtuple); - arraylist_push(&partial_inst, ndt); + if (tn->partial == NULL) { + tn->partial = jl_alloc_vec_any(0); + jl_gc_wb(tn, tn->partial); + } + jl_array_ptr_1d_push(tn->partial, (jl_value_t*)ndt); } else if (!isnamedtuple && !istuple) { assert(ftypes != jl_emptysvec || jl_field_names(ndt) == jl_emptysvec); @@ -1648,14 +1648,16 @@ JL_DLLEXPORT jl_svec_t *jl_compute_fieldtypes(jl_datatype_t *st JL_PROPAGATES_RO void jl_reinstantiate_inner_types(jl_datatype_t *t) // can throw! { - inside_typedef = 0; assert(jl_is_datatype(t)); jl_typestack_t top; top.tt = t; top.prev = NULL; size_t i, j, n = jl_svec_len(t->parameters); + jl_array_t *partial = t->name->partial; + if (partial == NULL) + return; if (n == 0) { - assert(partial_inst.len == 0); + assert(jl_array_len(partial) == 0); return; } @@ -1666,8 +1668,8 @@ void jl_reinstantiate_inner_types(jl_datatype_t *t) // can throw! env[i].prev = i == 0 ? NULL : &env[i - 1]; } - for (j = 0; j < partial_inst.len; j++) { - jl_datatype_t *ndt = (jl_datatype_t*)partial_inst.items[j]; + for (j = 0; j < jl_array_len(partial); j++) { + jl_datatype_t *ndt = (jl_datatype_t*)jl_array_ptr_ref(partial, j); assert(jl_unwrap_unionall(ndt->name->wrapper) == (jl_value_t*)t); for (i = 0; i < n; i++) env[i].val = jl_svecref(ndt->parameters, i); @@ -1677,8 +1679,8 @@ void jl_reinstantiate_inner_types(jl_datatype_t *t) // can throw! } if (t->types != jl_emptysvec) { - for (j = 0; j < partial_inst.len; j++) { - jl_datatype_t *ndt = (jl_datatype_t*)partial_inst.items[j]; + for (j = 0; j < jl_array_len(partial); j++) { + jl_datatype_t *ndt = (jl_datatype_t*)jl_array_ptr_ref(partial, j); for (i = 0; i < n; i++) env[i].val = jl_svecref(ndt->parameters, i); assert(ndt->types == NULL); @@ -1692,14 +1694,6 @@ void jl_reinstantiate_inner_types(jl_datatype_t *t) // can throw! else { assert(jl_field_names(t) == jl_emptysvec); } - partial_inst.len = 0; -} - -void jl_reset_instantiate_inner_types(jl_datatype_t *t) -{ - // the declaration of `t` is invalid, forget about all of the WIP - inside_typedef = 0; - partial_inst.len = 0; } // initialization ------------------------------------------------------------- @@ -1786,13 +1780,13 @@ void jl_init_types(void) JL_GC_DISABLED jl_typename_type->name->mt = jl_nonfunction_mt; jl_typename_type->super = jl_any_type; jl_typename_type->parameters = jl_emptysvec; - jl_typename_type->name->names = jl_perm_symsvec(8, "name", "module", + jl_typename_type->name->names = jl_perm_symsvec(9, "name", "module", "names", "wrapper", "cache", "linearcache", - "hash", "mt"); - jl_typename_type->types = jl_svec(8, jl_symbol_type, jl_any_type, jl_simplevector_type, + "hash", "mt", "partial"); + jl_typename_type->types = jl_svec(9, jl_symbol_type, jl_any_type, jl_simplevector_type, jl_type_type, jl_simplevector_type, jl_simplevector_type, - jl_any_type, jl_any_type); + jl_any_type, jl_any_type, jl_any_type); jl_typename_type->instance = NULL; jl_typename_type->abstract = 0; jl_typename_type->mutabl = 1; diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index f069ecbe032eb..d1905fbc1a647 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -889,11 +889,20 @@ (global ,name) (const ,name) (scope-block (block + (local-def ,name) ,@(map (lambda (v) `(local ,v)) params) ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v #t))) params bounds) - (struct_type ,name (call (core svec) ,@params) - (call (core svec) ,@(map quotify field-names)) - ,super (call (core svec) ,@field-types) ,mut ,min-initialized))) + (toplevel-only struct) + (= ,name (call (core _structtype) (thismodule) (inert ,name) (call (core svec) ,@params) + (call (core svec) ,@(map quotify field-names)) + ,mut ,min-initialized)) + (call (core _setsuper!) ,name ,super) + (call (core _typebody!) ,name (call (core svec) ,@field-types)) + (if (&& (isdefined (outerref ,name)) + (call (core _equiv_typedef) (outerref ,name) ,name)) + (null) + (= (outerref ,name) ,name)) + (null))) ;; "inner" constructors (scope-block (block @@ -930,9 +939,18 @@ (global ,name) (const ,name) (scope-block (block + (local-def ,name) ,@(map (lambda (v) `(local ,v)) params) ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v #t))) params bounds) - (abstract_type ,name (call (core svec) ,@params) ,super)))))) + (toplevel-only abstract_type) + (= ,name (call (core _abstracttype) (thismodule) (inert ,name) (call (core svec) ,@params))) + (call (core _setsuper!) ,name ,super) + (call (core _typebody!) ,name) + (if (&& (isdefined (outerref ,name)) + (call (core _equiv_typedef) (outerref ,name) ,name)) + (null) + (= (outerref ,name) ,name)) + (null)))))) (define (primitive-type-def-expr n name params super) (receive @@ -941,9 +959,18 @@ (global ,name) (const ,name) (scope-block (block + (local-def ,name) ,@(map (lambda (v) `(local ,v)) params) ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v #t))) params bounds) - (primitive_type ,name (call (core svec) ,@params) ,n ,super)))))) + (toplevel-only primitive_type) + (= ,name (call (core _primitivetype) (thismodule) (inert ,name) (call (core svec) ,@params) ,n)) + (call (core _setsuper!) ,name ,super) + (call (core _typebody!) ,name) + (if (&& (isdefined (outerref ,name)) + (call (core _equiv_typedef) (outerref ,name) ,name)) + (null) + (= (outerref ,name) ,name)) + (null)))))) ;; take apart a type signature, e.g. T{X} <: S{Y} (define (analyze-type-sig ex) @@ -1857,7 +1884,7 @@ `(= ,lhs ,rhs))) (define (expand-forms e) - (if (or (atom? e) (memq (car e) '(quote inert top core globalref outerref module toplevel ssavalue null true false meta using import export))) + (if (or (atom? e) (memq (car e) '(quote inert top core globalref outerref module toplevel ssavalue null true false meta using import export thismodule toplevel-only))) e (let ((ex (get expand-table (car e) #f))) (if ex @@ -1946,7 +1973,7 @@ lhss) (unnecessary ,rr))))))) ((or (and (symbol-like? lhs) (valid-name? lhs)) - (globalref? lhs)) + (globalref? lhs) (outerref? lhs)) (sink-assignment lhs (expand-forms (caddr e)))) ((atom? lhs) (error (string "invalid assignment location \"" (deparse lhs) "\""))) @@ -2454,7 +2481,7 @@ ((=) (let ((v (decl-var (cadr e))) (rest (find-assigned-vars (caddr e)))) - (if (or (ssavalue? v) (globalref? v) (underscore-symbol? v)) + (if (or (ssavalue? v) (globalref? v) (outerref? v) (underscore-symbol? v)) rest (cons v rest)))) (else @@ -2553,7 +2580,7 @@ (if (underscore-symbol? e) e `(outerref ,e))))) - ((or (not (pair? e)) (quoted? e) (memq (car e) '(toplevel symbolicgoto symboliclabel))) + ((or (not (pair? e)) (quoted? e) (memq (car e) '(toplevel symbolicgoto symboliclabel toplevel-only))) e) ((eq? (car e) 'global) (check-valid-name (cadr e)) @@ -2888,29 +2915,34 @@ f(x) = yt(x) |# (define (type-for-closure-parameterized name P names fields types super) - (let ((n (length P))) + (let ((n (length P)) + (s (make-ssavalue))) `((thunk - (lambda () - (() () 0 ()) - (block (global ,name) (const ,name) - ,@(map (lambda (p n) `(= ,p (call (core TypeVar) ',n (core Any)))) P names) - (struct_type ,name (call (core svec) ,@P) + (lambda () + (() () 0 ()) + (block (global ,name) (const ,name) + ,@(map (lambda (p n) `(= ,p (call (core TypeVar) ',n (core Any)))) P names) + (= ,s (call (core _structtype) (thismodule) (inert ,name) (call (core svec) ,@P) (call (core svec) ,@(map quotify fields)) - ,super - (call (core svec) ,@types) (false) ,(length fields)) - (return (null)))))))) + (false) ,(length fields))) + (= (outerref ,name) ,s) + (call (core _setsuper!) ,name ,super) + (call (core _typebody!) ,name (call (core svec) ,@types)) + (return (null)))))))) (define (type-for-closure name fields super) - `((thunk (lambda () - (() () 0 ()) - (block (global ,name) (const ,name) - (struct_type ,name (call (core svec)) - (call (core svec) ,@(map quotify fields)) - ,super - (call (core svec) ,@(map (lambda (v) '(core Box)) fields)) - (false) ,(length fields)) - (return (null))))))) - + (let ((s (make-ssavalue))) + `((thunk (lambda () + (() () 0 ()) + (block (global ,name) (const ,name) + (= ,s (call (core _structtype) (thismodule) (inert ,name) (call (core svec)) + (call (core svec) ,@(map quotify fields)) + (false) ,(length fields))) + (= (outerref ,name) ,s) + (call (core _setsuper!) ,name ,super) + (call (core _typebody!) ,name + (call (core svec) ,@(map (lambda (v) '(core Box)) fields))) + (return (null)))))))) ;; better versions of above, but they get handled wrong in many places ;; need to fix that in order to handle #265 fully (and use the definitions) @@ -3124,8 +3156,8 @@ f(x) = yt(x) (define lambda-opt-ignored-exprs (Set '(quote top core line inert local local-def unnecessary copyast meta inbounds boundscheck loopinfo decl aliasscope popaliasscope - struct_type abstract_type primitive_type thunk with-static-parameters - global globalref outerref const-if-global + thunk with-static-parameters toplevel-only + global globalref outerref const-if-global thismodule const null true false ssavalue isdefined toplevel module lambda error gc_preserve_begin gc_preserve_end import using export))) @@ -3313,7 +3345,7 @@ f(x) = yt(x) ((atom? e) e) (else (case (car e) - ((quote top core globalref outerref line break inert module toplevel null true false meta) e) + ((quote top core globalref outerref thismodule toplevel-only line break inert module toplevel null true false meta) e) ((=) (let ((var (cadr e)) (rhs (cl-convert (caddr e) fname lam namemap defined toplevel interp))) @@ -3360,7 +3392,7 @@ f(x) = yt(x) (vis (if short '(() () ()) (lam:vinfo lam2))) (cvs (map car (cadr vis))) (local? (lambda (s) (and lam (symbol? s) (local-in? s lam)))) - (local (local? name)) + (local (and (not (outerref? (cadr e))) (local? name))) (sig (and (not short) (caddr e))) (sp-inits (if (or short (not (eq? (car sig) 'block))) '() @@ -3394,7 +3426,7 @@ f(x) = yt(x) ((null? cvs) `(block ,@sp-inits - (method ,name ,(cl-convert + (method ,(cadr e) ,(cl-convert ;; anonymous functions with keyword args generate global ;; functions that refer to the type of a local function (rename-sig-types sig namemap) @@ -3499,7 +3531,7 @@ f(x) = yt(x) (make-ssavalue))) capt-vars)) (para (append closure-param-syms - (filter (lambda (v) (ssavalue? v)) fieldtypes))) + (filter ssavalue? fieldtypes))) (fieldnames (append closure-param-names (filter (lambda (v) (not (is-var-boxed? v lam))) capt-vars)))) (if (null? para) (type-for-closure type-name capt-vars '(core Function)) @@ -3589,10 +3621,6 @@ f(x) = yt(x) ((with-static-parameters) (cl-convert (cadr e) fname lam namemap defined toplevel interp)) (else - (if (eq? (car e) 'struct_type) - ;; struct_type has the effect of defining a name, so we don't try to - ;; emit a defining (method x) expr. - (put! defined (cadr e) #t)) (cons (car e) (map-cl-convert (cdr e) fname lam namemap defined toplevel interp)))))))) @@ -3600,9 +3628,6 @@ f(x) = yt(x) ;; pass 5: convert to linear IR -;; with this enabled, all nested calls are assigned to numbered locations -(define *very-linear-mode* #t) - (define (linearize e) (cond ((or (not (pair? e)) (quoted? e)) e) ((eq? (car e) 'lambda) @@ -3733,15 +3758,9 @@ f(x) = yt(x) (if (not (null? (cadr lam))) (error (string (head-to-text (car e)) " expression not at top level")))) ;; evaluate the arguments of a call, creating temporary locations as needed - (define (compile-args lst break-labels (linearize #t)) + (define (compile-args lst break-labels) (if (null? lst) '() - (let ((temps? (or *very-linear-mode* - (any (lambda (e) - (expr-contains-p (lambda (x) (or (and (assignment? x) (symbol? (cadr x))) - (and (pair? x) (eq? (car x) 'block)))) - e)) - (cdr lst)))) - (simple? (every (lambda (x) (or (simple-atom? x) (symbol? x) + (let ((simple? (every (lambda (x) (or (simple-atom? x) (symbol? x) (and (pair? x) (memq (car x) '(quote inert top core globalref outerref boundscheck))))) lst))) @@ -3750,11 +3769,11 @@ f(x) = yt(x) (if (null? lst) (reverse! vals) (let* ((arg (car lst)) - (aval (or (compile arg break-labels #t #f linearize) + (aval (or (compile arg break-labels #t #f) ;; TODO: argument exprs that don't yield a value? '(null)))) (loop (cdr lst) - (cons (if (and temps? linearize (not simple?) + (cons (if (and (not simple?) (not (simple-atom? arg)) (not (simple-atom? aval)) (not (and (pair? arg) @@ -3773,8 +3792,7 @@ f(x) = yt(x) (let ((cnd (or (compile ex break-labels #t #f) ;; TODO: condition exprs that don't yield a value? '(null)))) - (if (and *very-linear-mode* - (not (valid-ir-argument? cnd))) + (if (not (valid-ir-argument? cnd)) (let ((tmp (make-ssavalue))) (emit `(= ,tmp ,cnd)) tmp) @@ -3793,9 +3811,9 @@ f(x) = yt(x) ;; value must be returned. ;; `tail` means we are in tail position, where a value needs to be `return`ed ;; from the current function. - (define (compile e break-labels value tail (linearize-args #t)) + (define (compile e break-labels value tail) (if (or (not (pair? e)) (memq (car e) '(null true false ssavalue quote inert top core copyast the_exception $ - globalref outerref cdecl stdcall fastcall thiscall llvmcall))) + globalref outerref thismodule cdecl stdcall fastcall thiscall llvmcall))) (let ((e1 (if (and arg-map (symbol? e)) (get arg-map e e) e))) @@ -3821,23 +3839,23 @@ f(x) = yt(x) (not (and (length> fptr 1) (eq? (car fptr) 'call) (equal? (cadr fptr) '(core tuple)))))) - (compile-args (list (cadr e)) break-labels linearize-args) + (compile-args (list (cadr e)) break-labels) (list (cadr e))) (list-head (cddr e) 4) - (compile-args (list-tail e 6) break-labels linearize-args))) + (compile-args (list-tail e 6) break-labels))) ;; NOTE: arguments of cfunction must be left in place ;; except for argument 2 (fptr) ((eq? (car e) 'cfunction) - (let ((fptr (car (compile-args (list (caddr e)) break-labels linearize-args)))) + (let ((fptr (car (compile-args (list (caddr e)) break-labels)))) (cons (cadr e) (cons fptr (cdddr e))))) ;; TODO: evaluate first argument to cglobal some other way ((and (length> e 2) (or (eq? (cadr e) 'cglobal) (equal? (cadr e) '(outerref cglobal)))) (list* (cadr e) (caddr e) - (compile-args (cdddr e) break-labels linearize-args))) + (compile-args (cdddr e) break-labels))) (else - (compile-args (cdr e) break-labels linearize-args)))) + (compile-args (cdr e) break-labels)))) (callex (cons (car e) args))) (cond (tail (emit-return callex)) (value callex) @@ -4097,34 +4115,15 @@ f(x) = yt(x) (value temp) (else (emit temp))))) - ;; top level expressions that return nothing, or `module` which - ;; cannot be nested inside other forms. - ((abstract_type primitive_type struct_type thunk module) + ;; top level expressions + ((thunk module) (check-top-level e) - (with-bindings - ((*very-linear-mode* #f)) ;; type defs use nonstandard evaluation order - (case (car e) - ((abstract_type) - (let* ((para (compile (caddr e) break-labels #t #f)) - (supe (compile (cadddr e) break-labels #t #f))) - (emit `(abstract_type ,(cadr e) ,para ,supe)))) - ((primitive_type) - (let* ((para (compile (caddr e) break-labels #t #f)) - (supe (compile (list-ref e 4) break-labels #t #f))) - (emit `(primitive_type ,(cadr e) ,para ,(cadddr e) ,supe)))) - ((struct_type) - (let* ((para (compile (caddr e) break-labels #t #f)) - (supe (compile (list-ref e 4) break-labels #t #f)) - ;; struct_type has an unconventional evaluation rule that - ;; needs to do work around the evaluation of the field types, - ;; so the field type expressions need to be kept in place as - ;; much as possible. (part of issue #21923) - (ftys (compile (list-ref e 5) break-labels #t #f #f))) - (emit `(struct_type ,(cadr e) ,para ,(cadddr e) ,supe ,ftys ,@(list-tail e 6))))) - (else - (emit e)))) + (emit e) (if tail (emit-return '(null))) '(null)) + ((toplevel-only) + (check-top-level (cdr e)) + '(null)) ((toplevel) (check-top-level e) @@ -4143,7 +4142,7 @@ f(x) = yt(x) '(null)) ((gc_preserve_begin) - (let ((args (compile-args (cdr e) break-labels linearize-args))) + (let ((args (compile-args (cdr e) break-labels))) (cons (car e) args))) ;; metadata expressions diff --git a/src/julia.h b/src/julia.h index 772bfd8558b5d..997c8a04c6cd0 100644 --- a/src/julia.h +++ b/src/julia.h @@ -391,6 +391,7 @@ typedef struct { jl_svec_t *linearcache; // unsorted array intptr_t hash; struct _jl_methtable_t *mt; + jl_array_t *partial; // incomplete instantiations of this type } jl_typename_t; typedef struct { diff --git a/src/julia_internal.h b/src/julia_internal.h index 39c5ad3dbbd86..226cca5bee065 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -1142,8 +1142,7 @@ extern jl_sym_t *new_sym; extern jl_sym_t *using_sym; extern jl_sym_t *splatnew_sym; extern jl_sym_t *pop_exception_sym; extern jl_sym_t *const_sym; extern jl_sym_t *thunk_sym; -extern jl_sym_t *abstracttype_sym; extern jl_sym_t *primtype_sym; -extern jl_sym_t *structtype_sym; extern jl_sym_t *foreigncall_sym; +extern jl_sym_t *foreigncall_sym; extern jl_sym_t *global_sym; extern jl_sym_t *list_sym; extern jl_sym_t *dot_sym; extern jl_sym_t *newvar_sym; extern jl_sym_t *boundscheck_sym; extern jl_sym_t *inbounds_sym; @@ -1169,8 +1168,6 @@ struct _jl_sysimg_fptrs_t; void jl_register_fptrs(uint64_t sysimage_base, const struct _jl_sysimg_fptrs_t *fptrs, jl_method_instance_t **linfos, size_t n); -extern arraylist_t partial_inst; - #if jl_has_builtin(__builtin_unreachable) || defined(_COMPILER_GCC_) || defined(_COMPILER_INTEL_) # define jl_unreachable() __builtin_unreachable() #else diff --git a/src/method.c b/src/method.c index 1fd2b43e7930b..75e1cca9383fa 100644 --- a/src/method.c +++ b/src/method.c @@ -129,8 +129,7 @@ static jl_value_t *resolve_globals(jl_value_t *expr, jl_module_t *module, jl_sve jl_exprargset(e, 0, resolve_globals(jl_exprarg(e, 0), module, sparam_vals, binding_effects, 1)); i++; } - if (e->head == method_sym || e->head == abstracttype_sym || e->head == structtype_sym || - e->head == primtype_sym || e->head == module_sym) { + if (e->head == method_sym || e->head == module_sym) { i++; } for (; i < nargs; i++) { diff --git a/src/staticdata.c b/src/staticdata.c index 93d0275bc7161..6765b706999a9 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -83,7 +83,7 @@ static void *const _tags[] = { &jl_builtin_getfield, &jl_builtin_setfield, &jl_builtin_fieldtype, &jl_builtin_arrayref, &jl_builtin_const_arrayref, &jl_builtin_arrayset, &jl_builtin_arraysize, &jl_builtin_apply_type, &jl_builtin_applicable, &jl_builtin_invoke, - &jl_builtin__expr, &jl_builtin_ifelse, + &jl_builtin__expr, &jl_builtin_ifelse, &jl_builtin__typebody, NULL }; static jl_value_t **const*const tags = (jl_value_t**const*const)_tags; @@ -119,7 +119,8 @@ static const jl_fptr_args_t id_to_fptrs[] = { &jl_f_getfield, &jl_f_setfield, &jl_f_fieldtype, &jl_f_nfields, &jl_f_arrayref, &jl_f_const_arrayref, &jl_f_arrayset, &jl_f_arraysize, &jl_f_apply_type, &jl_f_applicable, &jl_f_invoke, &jl_f_sizeof, &jl_f__expr, &jl_f__typevar, - &jl_f_ifelse, + &jl_f_ifelse, &jl_f__structtype, &jl_f__abstracttype, &jl_f__primitivetype, + &jl_f__typebody, &jl_f__setsuper, &jl_f__equiv_typedef, NULL }; typedef struct { diff --git a/src/toplevel.c b/src/toplevel.c index 636629e5bc9bd..6df7c7d7e35ea 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -312,8 +312,7 @@ static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs) *has_defs = 1; return; } - else if (head == method_sym || head == abstracttype_sym || head == primtype_sym || - head == structtype_sym || jl_is_toplevel_only_expr(v)) { + else if (head == method_sym || jl_is_toplevel_only_expr(v)) { *has_defs = 1; } else if (head == cfunction_sym) { @@ -339,10 +338,15 @@ static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs) else if (jl_is_quotenode(f)) { called = jl_quotenode_value(f); } - if (called && jl_is_intrinsic(called) && jl_unbox_int32(called) == (int)llvmcall) { - *has_intrinsics = 1; - return; + if (called) { + if (jl_is_intrinsic(called) && jl_unbox_int32(called) == (int)llvmcall) { + *has_intrinsics = 1; + } + if (called == jl_builtin__typebody) { + *has_defs = 1; + } } + return; } int i; for (i = 0; i < jl_array_len(e->args); i++) { diff --git a/test/core.jl b/test/core.jl index 5da6d7f33a8a1..d4401a02c79ff 100644 --- a/test/core.jl +++ b/test/core.jl @@ -7198,3 +7198,11 @@ struct NFANode34126 end @test repr(NFANode34126()) == "$NFANode34126(Tuple{Nothing,$NFANode34126}[])" + +# issue #35416 +struct Node35416{T,K,X} +end +struct AVL35416{K,V} + avl:: Union{Nothing,Node35416{AVL35416{K,V},<:K,<:V}} +end +@test AVL35416(Node35416{AVL35416{Integer,AbstractString},Int,String}()) isa AVL35416{Integer,AbstractString}