aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2025-06-15 21:16:24 +0200
committerDanielGavin <danielgavin5@hotmail.com>2025-06-15 21:16:24 +0200
commit1f56bbb7e4f350e618942d7f4cb329511f2ece1f (patch)
tree0e372258cb1f09529068bb92d3ce1ed447545326 /src/server
parent9cba63205b8c93f10b99a548769ee01536fd40cd (diff)
parent5e55397d6b64e7c6da29c2db384cf240008927c4 (diff)
Merge branch 'BradLewis-fix/further-overload-resolution-improvements'
Diffstat (limited to 'src/server')
-rw-r--r--src/server/analysis.odin62
1 files changed, 43 insertions, 19 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index b2ab4f2..9daf67a 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -330,45 +330,54 @@ resolve_type_comp_literal :: proc(
return current_symbol, current_comp_lit, true
}
-
-is_symbol_same_typed :: proc(ast_context: ^AstContext, a, b: Symbol, flags: ast.Field_Flags = {}) -> bool {
- //relying on the fact that a is the call argument to avoid checking both sides for untyped.
+// NOTE: This function is not commutative
+are_symbol_untyped_basic_same_typed :: proc(a, b: Symbol) -> (bool, bool) {
if untyped, ok := a.value.(SymbolUntypedValue); ok {
if basic, ok := b.value.(SymbolBasicValue); ok {
switch untyped.type {
case .Integer:
switch basic.ident.name {
case "int", "uint", "u32", "i32", "u8", "i8", "u64", "u16", "i16":
- return true
+ return true, true
case:
- return false
+ return false, true
}
case .Bool:
switch basic.ident.name {
case "bool", "b32", "b64":
- return true
+ return true, true
case:
- return false
+ return false, true
}
case .String:
switch basic.ident.name {
case "string", "cstring":
- return true
+ return true, true
case:
- return false
+ return false, true
}
case .Float:
switch basic.ident.name {
case "f32", "f64":
- return true
+ return true, true
case:
- return false
+ return false, true
}
}
} else if untyped_b, ok := b.value.(SymbolUntypedValue); ok {
- return untyped.type == untyped_b.type
+ return untyped.type == untyped_b.type, true
}
}
+ return false, false
+}
+
+is_symbol_same_typed :: proc(ast_context: ^AstContext, a, b: Symbol, flags: ast.Field_Flags = {}) -> bool {
+ // In order to correctly equate the symbols for overloaded functions, we need to check both directions
+ if same, ok := are_symbol_untyped_basic_same_typed(a, b); ok {
+ return same
+ } else if same, ok := are_symbol_untyped_basic_same_typed(b, a); ok {
+ return same
+ }
a_id := reflect.union_variant_typeid(a.value)
b_id := reflect.union_variant_typeid(b.value)
@@ -657,7 +666,7 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou
//named parameter
if field, is_field := call_arg.derived.(^ast.Field_Value); is_field {
named = true
- call_symbol, ok = resolve_type_expression(ast_context, field.value)
+ call_symbol, ok = resolve_call_arg_type_expression(ast_context, field.value)
if !ok {
break next_fn
}
@@ -675,7 +684,7 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou
log.error("Expected name parameter after starting named parmeter phase")
return {}, false
}
- call_symbol, ok = resolve_type_expression(ast_context, call_arg)
+ call_symbol, ok = resolve_call_arg_type_expression(ast_context, call_arg)
}
if !ok {
@@ -686,7 +695,7 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou
if len(p.return_types) != 1 {
break next_fn
}
- if s, ok := resolve_type_expression(ast_context, p.return_types[0].type); ok {
+ if s, ok := resolve_call_arg_type_expression(ast_context, p.return_types[0].type); ok {
call_symbol = s
}
}
@@ -737,6 +746,16 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou
return Symbol{}, false
}
+resolve_call_arg_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (Symbol, bool) {
+ old_current_package := ast_context.current_package
+ ast_context.current_package = ast_context.document_package
+ defer {
+ ast_context.current_package = old_current_package
+ }
+
+ return resolve_type_expression(ast_context, node)
+}
+
resolve_basic_lit :: proc(ast_context: ^AstContext, basic_lit: ast.Basic_Lit) -> (Symbol, bool) {
symbol := Symbol {
type = .Constant,
@@ -1154,12 +1173,18 @@ get_local :: proc(ast_context: AstContext, ident: ast.Ident) -> (DocumentLocal,
local_stack := locals[ident.name] or_continue
#reverse for local in local_stack {
+ // Ensure that if the identifier has a file, the local is also part of the same file
+ // and the context is in the correct package
+ correct_file := ident.pos.file == "" || local.lhs.pos.file == ident.pos.file
+ correct_package := ast_context.current_package == ast_context.document_package
+ if !correct_file || !correct_package {
+ continue
+ }
+
if local.local_global {
return local, true
}
- // Ensure that if the identifier has a file, the local is also part of the same file
- correct_file := ident.pos.file == "" || local.lhs.pos.file == ident.pos.file
- if correct_file && (local.offset <= ident.pos.offset || local.lhs.pos.offset == ident.pos.offset) {
+ if local.offset <= ident.pos.offset || local.lhs.pos.offset == ident.pos.offset {
// checking equal offsets is a hack to allow matching lhs ident in var decls
// because otherwise minimal offset begins after the decl
return local, true
@@ -2800,7 +2825,6 @@ get_generic_assignment :: proc(
//We have to resolve early and can't rely on lazy evalutation because it can have multiple returns.
if symbol, ok := resolve_type_expression(ast_context, v.expr); ok {
-
#partial switch symbol_value in symbol.value {
case SymbolProcedureValue:
for ret in symbol_value.return_types {