mirror of
https://github.com/odin-lang/Odin.git
synced 2026-10-09 06:12:05 -04:00
parapoly: Fix bug on error reporting when none of the parameters match in a parapoly procedure
This commit is contained in:
1 parent
96dd7d22ec
commit
f65f3cd4da
1 file changed
+42
-21
+42
-21
@@ -8136,8 +8136,36 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c,
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
// NOTE)(bill): resolved container base of a candidate's first parameter, through a pointer and a `$T/...`
|
||||
// constraint, e.g. `^$T/[dynamic]$E` -> the `[dynamic]$E` base type
|
||||
auto first_param_container_base = [](Entity *proc) -> Type * {
|
||||
if (proc == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
Type *t = base_type(proc->type);
|
||||
if (t == nullptr || t->kind != Type_Proc || t->Proc.param_count == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
Type *p0 = base_type(t->Proc.params->Tuple.variables[0]->type);
|
||||
if (p0->kind == Type_Pointer) {
|
||||
p0 = base_type(p0->Pointer.elem);
|
||||
} else if (p0->kind == Type_MultiPointer) {
|
||||
p0 = base_type(p0->MultiPointer.elem);
|
||||
}
|
||||
while (p0->kind == Type_Generic && p0->Generic.specialized != nullptr) {
|
||||
p0 = base_type(p0->Generic.specialized);
|
||||
}
|
||||
return p0;
|
||||
};
|
||||
|
||||
// NOTE(bill): Check for a confident diagnosis
|
||||
if (procs.count == 0) {
|
||||
procs = proc_group_entities_cloned(c, *operand);
|
||||
}
|
||||
|
||||
// NOTE(bill): Confident diagnosis:
|
||||
// A container-first call (e.g. `append`) where the container matches some overload but a later argument does not match the container's element type.
|
||||
// Only fire when an overload actually accepts this container kind, so an unrelated group (nothing close) still gets the generic message.
|
||||
// The relevant overloads are still listed below.
|
||||
Ast *diag_expr = nullptr;
|
||||
isize diag_index = -1;
|
||||
Type *diag_elem = nullptr;
|
||||
@@ -8146,7 +8174,17 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c,
|
||||
if (positional_operands.count >= 2 && positional_operands[0].type != nullptr) {
|
||||
Type *cont = base_type(type_deref(positional_operands[0].type));
|
||||
Type *elem = container_elem(cont);
|
||||
bool container_matched = false;
|
||||
if (elem != nullptr && !is_type_polymorphic(elem)) {
|
||||
for (Entity *proc : procs) {
|
||||
Type *p0 = first_param_container_base(proc);
|
||||
if (p0 != nullptr && p0->kind == cont->kind) {
|
||||
container_matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (container_matched) {
|
||||
for (isize i = 1; i < positional_operands.count; i++) {
|
||||
Operand src = positional_operands[i];
|
||||
if (src.deferred_untyped_arg || src.mode == Addressing_Invalid || src.type == nullptr) {
|
||||
@@ -8183,10 +8221,6 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c,
|
||||
}
|
||||
}
|
||||
|
||||
if (procs.count == 0) {
|
||||
procs = proc_group_entities_cloned(c, *operand);
|
||||
}
|
||||
|
||||
// Try to reduce the list further for `$T: typeid` like parameters
|
||||
bool *possibly_ignore = temporary_alloc_array<bool>(procs.count);
|
||||
isize possibly_ignore_set = 0;
|
||||
@@ -8252,22 +8286,9 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c,
|
||||
if (possibly_ignore[i]) {
|
||||
continue;
|
||||
}
|
||||
Entity *proc = procs[i];
|
||||
Type *t = base_type(proc->type);
|
||||
if (t == nullptr || t->kind != Type_Proc || t->Proc.param_count == 0) {
|
||||
continue;
|
||||
}
|
||||
Type *p0 = base_type(t->Proc.params->Tuple.variables[0]->type);
|
||||
if (p0->kind == Type_Pointer) {
|
||||
p0 = base_type(p0->Pointer.elem);
|
||||
} else if (p0->kind == Type_MultiPointer) {
|
||||
p0 = base_type(p0->MultiPointer.elem);
|
||||
}
|
||||
while (p0->kind == Type_Generic && p0->Generic.specialized != nullptr) {
|
||||
p0 = base_type(p0->Generic.specialized);
|
||||
}
|
||||
if (p0->kind == Type_Generic) {
|
||||
continue; // unconstrained `$T`: cannot tell, keep it
|
||||
Type *p0 = first_param_container_base(procs[i]);
|
||||
if (p0 == nullptr || p0->kind == Type_Generic) {
|
||||
continue; // unconstrained `$T` or no first parameter: cannot tell, keep it
|
||||
}
|
||||
bool incompatible = false;
|
||||
if (p0->kind != arg0->kind) {
|
||||
|
||||
Reference in new issue
Block a user