warning diagnostics for unused locals
This commit is contained in:
+175
-68
@@ -80,6 +80,9 @@ Build_Ctx :: struct {
|
||||
local_types: []types.Type,
|
||||
locals: ^[dynamic]Build_Local,
|
||||
hir_locals: ^[dynamic]hir.Local,
|
||||
local_spans: ^[dynamic]source.Span,
|
||||
local_used: ^[dynamic]bool,
|
||||
local_warnable: ^[dynamic]bool,
|
||||
global_reads: ^[dynamic]hir.Global_Id,
|
||||
calls: ^[dynamic]hir.Function_Id,
|
||||
problematic: ^bool,
|
||||
@@ -170,6 +173,94 @@ symbol_text :: proc(checker: ^Checker, id: symbol.Id) -> string {
|
||||
return symbol.resolve(checker.symbols, id)
|
||||
}
|
||||
|
||||
append_tracked_local :: proc(
|
||||
locals: ^[dynamic]hir.Local,
|
||||
spans: ^[dynamic]source.Span,
|
||||
used: ^[dynamic]bool,
|
||||
warnable: ^[dynamic]bool,
|
||||
local: hir.Local,
|
||||
span: source.Span,
|
||||
) -> hir.Local_Id {
|
||||
id := hir.local_id(len(locals^))
|
||||
append(locals, local)
|
||||
append(spans, span)
|
||||
append(used, false)
|
||||
append(warnable, true)
|
||||
return id
|
||||
}
|
||||
|
||||
append_build_local :: proc(
|
||||
ctx: ^Build_Ctx,
|
||||
name: symbol.Id,
|
||||
type: types.Type,
|
||||
mutable: bool,
|
||||
span: source.Span,
|
||||
) -> hir.Local_Id {
|
||||
id := append_tracked_local(
|
||||
ctx.hir_locals,
|
||||
ctx.local_spans,
|
||||
ctx.local_used,
|
||||
ctx.local_warnable,
|
||||
hir.Local{name=name, type=type, mutable=mutable},
|
||||
span,
|
||||
)
|
||||
append(ctx.locals, Build_Local{name=name, type=type, mutable=mutable, id=id})
|
||||
return id
|
||||
}
|
||||
|
||||
ignore_tracked_locals :: proc(ctx: ^Build_Ctx, start: int) {
|
||||
for i := start; i < len(ctx.local_warnable^); i += 1 {
|
||||
ctx.local_warnable^[i] = false
|
||||
}
|
||||
}
|
||||
|
||||
mark_local_used :: proc(checker: ^Checker, id: hir.Local_Id) {
|
||||
ctx := checker.current_build_ctx
|
||||
if ctx == nil || id == hir.INVALID_LOCAL {
|
||||
return
|
||||
}
|
||||
index := int(id)
|
||||
if index >= 0 && index < len(ctx.local_used^) {
|
||||
ctx.local_used^[index] = true
|
||||
}
|
||||
}
|
||||
|
||||
build_local_expr :: proc(checker: ^Checker, local: Build_Local, span: source.Span) -> hir.Expr_Id {
|
||||
mark_local_used(checker, local.id)
|
||||
return add_hir_expr(checker, hir.Expr{
|
||||
kind=.Local, span=span, type=local.type, target=hir.local_ref(local.id),
|
||||
left=hir.INVALID_EXPR, right=hir.INVALID_EXPR, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
}
|
||||
|
||||
record_unused_locals :: proc(
|
||||
checker: ^Checker,
|
||||
locals: []hir.Local,
|
||||
spans: []source.Span,
|
||||
used: []bool,
|
||||
warnable: []bool,
|
||||
) {
|
||||
for local, index in locals {
|
||||
if local.name == checker.sink_symbol ||
|
||||
!symbol.is_valid(local.name) ||
|
||||
index >= len(warnable) ||
|
||||
!warnable[index] ||
|
||||
index >= len(used) ||
|
||||
used[index] {
|
||||
continue
|
||||
}
|
||||
span := source.Span{}
|
||||
if index < len(spans) {
|
||||
span = spans[index]
|
||||
}
|
||||
if local.parameter {
|
||||
source.addf_warning(checker.diagnostics, span, "unused parameter '%s'", symbol_text(checker, local.name))
|
||||
} else {
|
||||
source.addf_warning(checker.diagnostics, span, "unused local '%s'", symbol_text(checker, local.name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// type_label renders a type for a diagnostic, resolving a named type (enum/union/struct/
|
||||
// distinct) to its declared source name; primitives and unnamed types fall back to
|
||||
// `types.name` (which prints `<type N>` for anonymous nodes).
|
||||
@@ -3698,10 +3789,7 @@ build_qualified_value_field :: proc(
|
||||
return hir.INVALID_EXPR, false, false
|
||||
}
|
||||
if local, ok := find_build_local(locals, expr.qualifier); ok {
|
||||
base := add_hir_expr(checker, hir.Expr{
|
||||
kind=.Local, span=expr.span, type=local.type, target=hir.local_ref(local.id),
|
||||
left=hir.INVALID_EXPR, right=hir.INVALID_EXPR, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
base := build_local_expr(checker, local, expr.span)
|
||||
value, ok := build_field_from_value(checker, expr, base, local.type)
|
||||
return value, true, ok
|
||||
}
|
||||
@@ -4285,9 +4373,7 @@ build_compound_expr :: proc(
|
||||
capture_start := len(ctx.locals^)
|
||||
error_type := types.fallible_error(channel_type, store)
|
||||
if symbol.is_valid(expr.name) && expr.name != checker.sink_symbol {
|
||||
capture = hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{name=expr.name, type=error_type, mutable=false})
|
||||
append(ctx.locals, Build_Local{name=expr.name, type=error_type, mutable=false, id=capture})
|
||||
capture = append_build_local(ctx, expr.name, error_type, false, expr.span)
|
||||
}
|
||||
handler: [dynamic]hir.Stmt_Id
|
||||
handler.allocator = checker.allocator
|
||||
@@ -4652,16 +4738,10 @@ build_expr :: proc(
|
||||
last = hir.INVALID_EXPR
|
||||
if !symbol.is_valid(expr.qualifier) {
|
||||
if local, ok := find_build_local(locals, expr.name); ok {
|
||||
last = add_hir_expr(checker, hir.Expr{
|
||||
kind=.Local, span=expr.span, type=local.type, target=hir.local_ref(local.id),
|
||||
left = hir.INVALID_EXPR, right = hir.INVALID_EXPR, diagnostic = source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
last = build_local_expr(checker, local, expr.span)
|
||||
}
|
||||
} else if local, ok := find_build_local(locals, expr.qualifier); ok {
|
||||
base := add_hir_expr(checker, hir.Expr{
|
||||
kind=.Local, span=expr.span, type=local.type, target=hir.local_ref(local.id),
|
||||
left=hir.INVALID_EXPR, right=hir.INVALID_EXPR, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
base := build_local_expr(checker, local, expr.span)
|
||||
base_type := local.type
|
||||
item, has_item := types.container(base_type, &checker.module.types)
|
||||
field_name := symbol_text(checker, expr.name)
|
||||
@@ -4851,10 +4931,7 @@ build_expr :: proc(
|
||||
if !symbol.is_valid(expr.qualifier) {
|
||||
if local, ok := find_build_local(locals, expr.name); ok {
|
||||
if _, _, _, callable := types.function_pointer(local.type, &checker.module.types); callable {
|
||||
callee = add_hir_expr(checker, hir.Expr{
|
||||
kind=.Local, span=expr.span, type=local.type, target=hir.local_ref(local.id),
|
||||
left=hir.INVALID_EXPR, right=hir.INVALID_EXPR, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
callee = build_local_expr(checker, local, expr.span)
|
||||
} else {
|
||||
non_callable = true
|
||||
}
|
||||
@@ -5409,13 +5486,7 @@ build_block :: proc(
|
||||
ctx.problematic^ = true
|
||||
continue
|
||||
}
|
||||
local_id := hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{
|
||||
name = statement.name, type = value_type, mutable = !statement.immutable,
|
||||
})
|
||||
append(ctx.locals, Build_Local{
|
||||
name = statement.name, type = value_type, mutable = !statement.immutable, id = local_id,
|
||||
})
|
||||
local_id := append_build_local(ctx, statement.name, value_type, !statement.immutable, statement.span)
|
||||
append(&body, hir.stmt_id(len(checker.module.statements)))
|
||||
append(&checker.module.statements, hir.Stmt{
|
||||
kind = .Declaration, span = statement.span, local = local_id, expr = value,
|
||||
@@ -5536,13 +5607,7 @@ build_block :: proc(
|
||||
ctx.problematic^ = true
|
||||
continue
|
||||
}
|
||||
local_id := hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{
|
||||
name = statement.name, type = value_type, mutable = !statement.immutable,
|
||||
})
|
||||
append(ctx.locals, Build_Local{
|
||||
name = statement.name, type = value_type, mutable = !statement.immutable, id = local_id,
|
||||
})
|
||||
local_id := append_build_local(ctx, statement.name, value_type, !statement.immutable, statement.span)
|
||||
append(&body, hir.stmt_id(len(checker.module.statements)))
|
||||
append(&checker.module.statements, hir.Stmt{
|
||||
kind = .Declaration, span = statement.span, local = local_id, expr = value,
|
||||
@@ -5861,8 +5926,14 @@ build_block :: proc(
|
||||
// runs defers.
|
||||
if len(ctx.defers^) > 0 {
|
||||
if checker.module.exprs[value].kind != .Invalid {
|
||||
tmp := hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{name = checker.sink_symbol, type = ctx.result, mutable = false})
|
||||
tmp := append_tracked_local(
|
||||
ctx.hir_locals,
|
||||
ctx.local_spans,
|
||||
ctx.local_used,
|
||||
ctx.local_warnable,
|
||||
hir.Local{name = checker.sink_symbol, type = ctx.result, mutable = false},
|
||||
source.Span{},
|
||||
)
|
||||
append(&body, hir.stmt_id(len(checker.module.statements)))
|
||||
append(&checker.module.statements, hir.Stmt{
|
||||
kind = .Declaration, span = statement.span, local = tmp, expr = value,
|
||||
@@ -5965,9 +6036,7 @@ build_block :: proc(
|
||||
diagnostic = id
|
||||
valid_unwrap = false
|
||||
}
|
||||
local = hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{name=capture, type=child, mutable=false})
|
||||
append(ctx.locals, Build_Local{name=capture, type=child, mutable=false, id=local})
|
||||
local = append_build_local(ctx, capture, child, false, statement.span)
|
||||
}
|
||||
if index < len(values) {
|
||||
append(&unwraps, hir.Conditional_Unwrap{expr=values[index], local=local})
|
||||
@@ -6169,9 +6238,7 @@ build_block :: proc(
|
||||
valid_loop = false
|
||||
}
|
||||
}
|
||||
item_local := hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{name=statement.name, type=capture_type, mutable=false})
|
||||
append(ctx.locals, Build_Local{name=statement.name, type=capture_type, mutable=false, id=item_local})
|
||||
item_local := append_build_local(ctx, statement.name, capture_type, false, statement.span)
|
||||
index_local := hir.INVALID_LOCAL
|
||||
if symbol.is_valid(statement.index_name) {
|
||||
if statement.index_name == statement.name {
|
||||
@@ -6184,9 +6251,7 @@ build_block :: proc(
|
||||
diagnostic = id
|
||||
valid_loop = false
|
||||
} else {
|
||||
index_local = hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{name=statement.index_name, type=types.USIZE, mutable=false})
|
||||
append(ctx.locals, Build_Local{name=statement.index_name, type=types.USIZE, mutable=false, id=index_local})
|
||||
index_local = append_build_local(ctx, statement.index_name, types.USIZE, false, statement.span)
|
||||
}
|
||||
}
|
||||
if id := add_label_shadow_diagnostic(ctx, statement.span, statement.label);
|
||||
@@ -6512,8 +6577,14 @@ build_value_block :: proc(
|
||||
// rule as `return`.
|
||||
if len(ctx.defers^) > defer_start {
|
||||
if checker.module.exprs[value].kind != .Invalid {
|
||||
tmp := hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{name = checker.sink_symbol, type = value_type, mutable = false})
|
||||
tmp := append_tracked_local(
|
||||
ctx.hir_locals,
|
||||
ctx.local_spans,
|
||||
ctx.local_used,
|
||||
ctx.local_warnable,
|
||||
hir.Local{name = checker.sink_symbol, type = value_type, mutable = false},
|
||||
source.Span{},
|
||||
)
|
||||
append(body, hir.stmt_id(len(checker.module.statements)))
|
||||
append(&checker.module.statements, hir.Stmt{
|
||||
kind = .Declaration, span = yield_stmt.span, local = tmp, expr = value,
|
||||
@@ -6568,9 +6639,14 @@ build_value_source :: proc(
|
||||
// new_value_slot allocates a fresh, un-nameable mutable local to hold a value-if/loop
|
||||
// result. Branches/iterations assign it; the construct's value is a read of it.
|
||||
new_value_slot :: proc(ctx: ^Build_Ctx, slot_type: types.Type) -> hir.Local_Id {
|
||||
slot := hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{name = ctx.checker.sink_symbol, type = slot_type, mutable = true})
|
||||
return slot
|
||||
return append_tracked_local(
|
||||
ctx.hir_locals,
|
||||
ctx.local_spans,
|
||||
ctx.local_used,
|
||||
ctx.local_warnable,
|
||||
hir.Local{name = ctx.checker.sink_symbol, type = slot_type, mutable = true},
|
||||
source.Span{},
|
||||
)
|
||||
}
|
||||
|
||||
// slot_read builds a `.Local` read of a result slot.
|
||||
@@ -6730,9 +6806,7 @@ emit_value_if :: proc(
|
||||
) != source.INVALID_DIAGNOSTIC {
|
||||
ok = false
|
||||
}
|
||||
local = hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{name=capture, type=child, mutable=false})
|
||||
append(ctx.locals, Build_Local{name=capture, type=child, mutable=false, id=local})
|
||||
local = append_build_local(ctx, capture, child, false, if_stmt.span)
|
||||
}
|
||||
if index < len(values) {
|
||||
append(&unwrap_list, hir.Conditional_Unwrap{expr=values[index], local=local})
|
||||
@@ -6964,8 +7038,14 @@ emit_match :: proc(
|
||||
target = hir.INVALID_REF, right = hir.INVALID_EXPR, diagnostic = source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
}
|
||||
subj_local := hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{name = checker.sink_symbol, type = spill_type, mutable = false})
|
||||
subj_local := append_tracked_local(
|
||||
ctx.hir_locals,
|
||||
ctx.local_spans,
|
||||
ctx.local_used,
|
||||
ctx.local_warnable,
|
||||
hir.Local{name = checker.sink_symbol, type = spill_type, mutable = false},
|
||||
source.Span{},
|
||||
)
|
||||
append(out, hir.stmt_id(len(checker.module.statements)))
|
||||
append(&checker.module.statements, hir.Stmt{
|
||||
kind = .Declaration, span = span, local = subj_local, expr = spill_value,
|
||||
@@ -6984,8 +7064,14 @@ emit_match :: proc(
|
||||
left = match_subject_location(checker, subj_local, subj_is_pointer, subject_type, ptr_type, span),
|
||||
target = hir.INVALID_REF, right = hir.INVALID_EXPR, diagnostic = source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
tag_local := hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{name = checker.sink_symbol, type = tag_enum, mutable = false})
|
||||
tag_local := append_tracked_local(
|
||||
ctx.hir_locals,
|
||||
ctx.local_spans,
|
||||
ctx.local_used,
|
||||
ctx.local_warnable,
|
||||
hir.Local{name = checker.sink_symbol, type = tag_enum, mutable = false},
|
||||
source.Span{},
|
||||
)
|
||||
append(out, hir.stmt_id(len(checker.module.statements)))
|
||||
append(&checker.module.statements, hir.Stmt{
|
||||
kind = .Declaration, span = span, local = tag_local, expr = tag_read,
|
||||
@@ -7295,9 +7381,7 @@ build_match_arm_body :: proc(
|
||||
target = hir.INVALID_REF, right = hir.INVALID_EXPR, diagnostic = source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
}
|
||||
cap_local := hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{name = capture, type = cap_type, mutable = false})
|
||||
append(ctx.locals, Build_Local{name = capture, type = cap_type, mutable = false, id = cap_local})
|
||||
cap_local := append_build_local(ctx, capture, cap_type, false, span)
|
||||
append(&result, hir.stmt_id(len(checker.module.statements)))
|
||||
append(&checker.module.statements, hir.Stmt{
|
||||
kind = .Declaration, span = span, local = cap_local, expr = cap_value,
|
||||
@@ -7473,6 +7557,7 @@ value_loop_element_type :: proc(ctx: ^Build_Ctx, loop_stmt: ast.Stmt) -> types.T
|
||||
return types.INVALID
|
||||
}
|
||||
capture_start := len(ctx.locals^)
|
||||
local_start := len(ctx.hir_locals^)
|
||||
if loop_stmt.kind == .For {
|
||||
// Mirror the `.For` arm's capture-type computation just enough to type the probe.
|
||||
iterable := build_expr(checker, loop_stmt.expr, ctx.locals^[:], ctx.global_reads, ctx.calls, types.INVALID, ctx.pkg, ctx.file)
|
||||
@@ -7487,19 +7572,16 @@ value_loop_element_type :: proc(ctx: ^Build_Ctx, loop_stmt: ast.Stmt) -> types.T
|
||||
}
|
||||
}
|
||||
if symbol.is_valid(loop_stmt.name) {
|
||||
id := hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{name=loop_stmt.name, type=capture_type, mutable=false})
|
||||
append(ctx.locals, Build_Local{name=loop_stmt.name, type=capture_type, mutable=false, id=id})
|
||||
append_build_local(ctx, loop_stmt.name, capture_type, false, loop_stmt.span)
|
||||
}
|
||||
if symbol.is_valid(loop_stmt.index_name) {
|
||||
id := hir.local_id(len(ctx.hir_locals^))
|
||||
append(ctx.hir_locals, hir.Local{name=loop_stmt.index_name, type=types.USIZE, mutable=false})
|
||||
append(ctx.locals, Build_Local{name=loop_stmt.index_name, type=types.USIZE, mutable=false, id=id})
|
||||
append_build_local(ctx, loop_stmt.index_name, types.USIZE, false, loop_stmt.span)
|
||||
}
|
||||
}
|
||||
probe := build_expr(checker, yield_expr, ctx.locals^[:], ctx.global_reads, ctx.calls, types.INVALID, ctx.pkg, ctx.file)
|
||||
result := checker.module.exprs[probe].type if checker.module.exprs[probe].kind != .Invalid else types.INVALID
|
||||
resize(ctx.locals, capture_start)
|
||||
ignore_tracked_locals(ctx, local_start)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -7545,6 +7627,7 @@ block_element_type :: proc(ctx: ^Build_Ctx, block_stmts: []ast.Stmt_Id) -> types
|
||||
}
|
||||
}
|
||||
scope_start := len(ctx.locals^)
|
||||
local_start := len(ctx.hir_locals^)
|
||||
defer_start := len(ctx.defers^)
|
||||
lead := build_block(ctx, block_stmts[:lead_end], close = false)
|
||||
delete(lead, checker.allocator)
|
||||
@@ -7556,6 +7639,7 @@ block_element_type :: proc(ctx: ^Build_Ctx, block_stmts: []ast.Stmt_Id) -> types
|
||||
}
|
||||
resize(ctx.defers, defer_start)
|
||||
resize(ctx.locals, scope_start)
|
||||
ignore_tracked_locals(ctx, local_start)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -7848,6 +7932,12 @@ build_function :: proc(checker: ^Checker, id: Spec_Id) {
|
||||
locals.allocator = checker.allocator
|
||||
hir_locals: [dynamic]hir.Local
|
||||
hir_locals.allocator = checker.allocator
|
||||
local_spans: [dynamic]source.Span
|
||||
local_spans.allocator = checker.allocator
|
||||
local_used: [dynamic]bool
|
||||
local_used.allocator = checker.allocator
|
||||
local_warnable: [dynamic]bool
|
||||
local_warnable.allocator = checker.allocator
|
||||
params: [dynamic]hir.Local_Id
|
||||
params.allocator = checker.allocator
|
||||
body: [dynamic]hir.Stmt_Id
|
||||
@@ -7869,12 +7959,18 @@ build_function :: proc(checker: ^Checker, id: Spec_Id) {
|
||||
if param.comptime_value {
|
||||
continue
|
||||
}
|
||||
local_id := hir.local_id(len(hir_locals))
|
||||
param_type := types.INVALID
|
||||
if runtime_index < len(spec.args) {
|
||||
param_type = spec.args[runtime_index]
|
||||
}
|
||||
append(&hir_locals, hir.Local{name = param.name, type = param_type, parameter = true})
|
||||
local_id := append_tracked_local(
|
||||
&hir_locals,
|
||||
&local_spans,
|
||||
&local_used,
|
||||
&local_warnable,
|
||||
hir.Local{name = param.name, type = param_type, parameter = true},
|
||||
param.span,
|
||||
)
|
||||
append(&locals, Build_Local{name = param.name, type = param_type, id = local_id})
|
||||
append(¶ms, local_id)
|
||||
runtime_index += 1
|
||||
@@ -7905,6 +8001,9 @@ build_function :: proc(checker: ^Checker, id: Spec_Id) {
|
||||
},
|
||||
)
|
||||
delete(locals)
|
||||
delete(local_spans)
|
||||
delete(local_used)
|
||||
delete(local_warnable)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -7939,6 +8038,9 @@ build_function :: proc(checker: ^Checker, id: Spec_Id) {
|
||||
local_types = local_types,
|
||||
locals = &locals,
|
||||
hir_locals = &hir_locals,
|
||||
local_spans = &local_spans,
|
||||
local_used = &local_used,
|
||||
local_warnable = &local_warnable,
|
||||
global_reads = &global_reads,
|
||||
calls = &calls,
|
||||
problematic = &problematic,
|
||||
@@ -7976,6 +8078,8 @@ build_function :: proc(checker: ^Checker, id: Spec_Id) {
|
||||
problematic = true
|
||||
}
|
||||
|
||||
record_unused_locals(checker, hir_locals[:], local_spans[:], local_used[:], local_warnable[:])
|
||||
|
||||
assert(spec.hir_id == hir.function_id(len(checker.module.functions)))
|
||||
append(
|
||||
&checker.module.functions,
|
||||
@@ -8006,6 +8110,9 @@ build_function :: proc(checker: ^Checker, id: Spec_Id) {
|
||||
delete(loop_is_loop)
|
||||
delete(yield_targets)
|
||||
delete(locals)
|
||||
delete(local_spans)
|
||||
delete(local_used)
|
||||
delete(local_warnable)
|
||||
}
|
||||
|
||||
expr_problematic :: proc(checker: ^Checker, expr_id: hir.Expr_Id) -> bool {
|
||||
@@ -8576,7 +8683,7 @@ check :: proc(
|
||||
propagate_problems(&checker)
|
||||
for import_item in ast_module.imports {
|
||||
if import_item.valid && !import_item.used {
|
||||
source.addf(diagnostics, import_item.span, "unused import '%s'", symbol_text(&checker, import_item.alias))
|
||||
source.addf_warning(diagnostics, import_item.span, "unused import '%s'", symbol_text(&checker, import_item.alias))
|
||||
}
|
||||
}
|
||||
return checker.module
|
||||
|
||||
Reference in New Issue
Block a user