diff --git a/releasenotes.md b/releasenotes.md index 113088822..daee07764 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -9,6 +9,8 @@ - Confusing error message when type has [] overloaded but not []= #2453 - $defined(x[0] = val) causes an error instead of returning false when a type does not have []= defined #2454 - Returning pointer to index of slice stored in a struct from method taking self incorrectly detected as returning pointer to local variable #2455. +- Inlining location when accessing #foo symbols. +- Improve inlined-at when checking generic code. ### Stdlib changes - Added generic `InterfaceList` to store a list of values that implement a specific interface diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index ce86c4d8a..685539656 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -1604,6 +1604,7 @@ Module *compiler_find_or_create_module(Path *module_name, const char **parameter // Set up the module. module = CALLOCS(Module); module->name = module_name; + module->inlined_at = (InliningSpan) { INVALID_SPAN, NULL }; size_t first = 0; for (size_t i = module_name->len; i > 0; i--) { diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 6973aa5cc..1d482179c 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -166,6 +166,25 @@ struct ConstInitializer_ }; }; +typedef union +{ + struct + { + FileId file_id; + unsigned char length; + unsigned char col; + uint32_t row; + }; + uint64_t a; +} SourceSpan; + +static_assert(sizeof(SourceSpan) == 8, "Expected 8 bytes"); + +typedef struct InliningSpan_ +{ + SourceSpan span; + struct InliningSpan_ *prev; +} InliningSpan; typedef struct { @@ -211,21 +230,8 @@ typedef struct const char *full_path; } File; -typedef union -{ - struct - { - FileId file_id; - unsigned char length; - unsigned char col; - uint32_t row; - }; - uint64_t a; -} SourceSpan; -static_assert(sizeof(SourceSpan) == 8, "Expected 8 bytes"); - typedef struct { const char *key; @@ -1607,6 +1613,7 @@ typedef struct Module_ Decl **tests; Decl **lambdas_to_evaluate; const char *generic_suffix; + InliningSpan inlined_at; } Module; @@ -1757,11 +1764,7 @@ typedef struct JumpTarget_ AstId defer; } JumpTarget; -typedef struct InliningSpan_ -{ - SourceSpan span; - struct InliningSpan_ *prev; -} InliningSpan; + struct SemaContext_ { @@ -2203,6 +2206,7 @@ Decl **copy_decl_list_macro(Decl **decl_list); Ast *copy_ast_macro(Ast *source_ast); Ast *copy_ast_defer(Ast *source_ast); TypeInfo *copy_type_info_single(TypeInfo *type_info); +InliningSpan *copy_inlining_span(InliningSpan *span); void init_asm(PlatformTarget *target); void print_asm_list(PlatformTarget *target); diff --git a/src/compiler/copying.c b/src/compiler/copying.c index d2a1472a3..6d68e2fce 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -1159,3 +1159,11 @@ Decl *copy_decl(CopyStruct *c, Decl *decl) return copy; } +InliningSpan *copy_inlining_span(InliningSpan *span) +{ + if (!span) return NULL; + InliningSpan *copy_span = MALLOCS(InliningSpan); + copy_span->span = span->span; + copy_span->prev = copy_inlining_span(span->prev); + return copy_span; +} \ No newline at end of file diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index c09d6ba44..26b42ab60 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -41,7 +41,7 @@ Expr *parse_integer(ParseContext *c, Expr *left, SourceSpan lhs_start); Expr *parse_decl_or_expr(ParseContext *c); void recover_top_level(ParseContext *c); Expr *parse_cond(ParseContext *c); -Ast* parse_compound_stmt(ParseContext *c); +Ast *parse_compound_stmt(ParseContext *c); Ast *parse_short_body(ParseContext *c, TypeInfoId return_type, bool is_regular_fn); bool parse_attribute(ParseContext *c, Attr **attribute_ref, bool expect_eos); diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index ae3b603c6..4f6631ea5 100755 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -48,7 +48,7 @@ static inline bool sema_analyse_distinct(SemaContext *context, Decl *decl, bool static CompilationUnit *unit_copy(Module *module, CompilationUnit *unit); -static Module *module_instantiate_generic(SemaContext *context, Module *module, Path *path, Expr **params); +static Module *module_instantiate_generic(SemaContext *context, Module *module, Path *path, Expr **params, SourceSpan from_span); static inline bool sema_analyse_enum_param(SemaContext *context, Decl *param); static inline bool sema_analyse_enum(SemaContext *context, Decl *decl, bool *erase_decl); @@ -4851,7 +4851,7 @@ static CompilationUnit *unit_copy(Module *module, CompilationUnit *unit) return copy; } -static Module *module_instantiate_generic(SemaContext *context, Module *module, Path *path, Expr **params) +static Module *module_instantiate_generic(SemaContext *context, Module *module, Path *path, Expr **params, SourceSpan from_span) { unsigned decls = 0; Decl* params_decls[MAX_PARAMS]; @@ -4902,6 +4902,7 @@ static Module *module_instantiate_generic(SemaContext *context, Module *module, new_module->contracts = astid(copy_ast_macro(astptr(module->contracts))); copy_end(); } + new_module->inlined_at = (InliningSpan) { .span = from_span, .prev = copy_inlining_span(context->inlined_at) }; return new_module; } @@ -5159,7 +5160,7 @@ Decl *sema_analyse_parameterized_identifier(SemaContext *c, Path *decl_path, con path->module = path_string; path->span = module->name->span; path->len = scratch_buffer.len; - instantiated_module = module_instantiate_generic(c, module, path, params); + instantiated_module = module_instantiate_generic(c, module, path, params, invocation_span); if (!instantiated_module) return poisoned_decl; if (!sema_generate_parameterized_name_to_scratch(c, module, params, false, NULL)) return poisoned_decl; instantiated_module->generic_suffix = scratch_buffer_copy(); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 17afbdaaa..5c9c887dd 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -216,19 +216,22 @@ static Type *defer_iptr_cast(Expr *maybe_pointer); typedef struct { bool in_no_eval; + InliningSpan *old_inlining; } ContextSwitchState; static inline ContextSwitchState context_switch_state_push(SemaContext *context, SemaContext *new_context) { - ContextSwitchState state = { .in_no_eval = new_context->call_env.in_no_eval, }; + ContextSwitchState state = { .in_no_eval = new_context->call_env.in_no_eval, .old_inlining = new_context->inlined_at }; new_context->call_env.in_no_eval = context->call_env.in_no_eval; + new_context->inlined_at = context->inlined_at; return state; } static inline void context_switch_stat_pop(SemaContext *swapped, ContextSwitchState state) { swapped->call_env.in_no_eval = state.in_no_eval; + swapped->inlined_at = state.old_inlining; } Expr *sema_enter_inline_member(Expr *parent, CanonicalType *type) diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index 9fdfedd76..75bea07ba 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -592,6 +592,17 @@ void sema_print_inline(SemaContext *context, SourceSpan original) } inlined_at = inlined_at->prev; } + InliningSpan span = context->compilation_unit->module->inlined_at; + if (span.span.a == INVALID_SPAN.a) return; + inlined_at = &span; + while (inlined_at) + { + if (inlined_at->span.a != original.a) + { + sema_note_prev_at(inlined_at->span, "Inlined from here."); + } + inlined_at = inlined_at->prev; + } } void sema_error_at(SemaContext *context, SourceSpan span, const char *message, ...)