Skip to content

🐛 fix(mq-check): handle union overloads with consistent return types#1386

Merged
harehare merged 5 commits intomainfrom
fix/typechecker-union-overload
Mar 5, 2026
Merged

🐛 fix(mq-check): handle union overloads with consistent return types#1386
harehare merged 5 commits intomainfrom
fix/typechecker-union-overload

Conversation

@harehare
Copy link
Copy Markdown
Owner

@harehare harehare commented Mar 4, 2026

Fixes type inference for operators with union-typed arguments by checking if all union members yield the same return type. This prevents false-positive errors when unions are used with binary operators and improves Hindley-Milner inference robustness.

Fixes type inference for operators with union-typed arguments by checking if all union members yield the same return type. This prevents false-positive errors when unions are used with binary operators and improves Hindley-Milner inference robustness.
Copilot AI review requested due to automatic review settings March 4, 2026 14:54
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a false-positive type error in the mq-check type inference engine. Previously, using a union-typed value with a binary operator always triggered an error—even in cases where every member of the union would produce the same return type, making the operation safe. The fix adds a check (all_union_members_same_return) that tests each concrete member of the union against the operator's overloads; if all members resolve to the same return type, the operation is allowed.

Changes:

  • Introduces the all_union_members_same_return block (lines 470–503) that tests every concrete member of each union-typed operand against the operator's overloads to verify consistent return types.
  • Extends the condition at line 505 to also allow resolution when all union members yield the same return type, alongside the existing union_params_are_vars path.

Comment on lines +470 to +503
let all_union_members_same_return = {
let mut unique_ret: Option<types::Type> = None;
let mut all_match = true;
'outer: for (i, arg_ty) in resolved_operands.iter().enumerate() {
if let types::Type::Union(members) = arg_ty {
// Reject unions containing unresolved type variables
if members.iter().any(|m| m.is_var()) {
all_match = false;
break 'outer;
}
for member in members {
let mut test_args = resolved_operands.clone();
test_args[i] = member.clone();
if let Some(types::Type::Function(_, member_ret)) =
ctx.resolve_overload(&d.op_name, &test_args)
{
let resolved_ret = ctx.resolve_type(&member_ret);
match &unique_ret {
None => unique_ret = Some(resolved_ret),
Some(prev) if prev == &resolved_ret => {}
_ => {
all_match = false;
break 'outer;
}
}
} else {
all_match = false;
break 'outer;
}
}
}
}
all_match && unique_ret.is_some()
};
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new all_union_members_same_return logic introduces a distinct success path that is not covered by any new tests. The existing test suite has tests for the union_params_are_vars path (e.g., to_number on a union type) and tests that union + arithmetic should fail, but no test exercises the new path where all union members yield the same return type from a concrete (non-Var-parameter) overload.

A test case such as an operator call with a union argument where every member of that union maps to the same return type would validate this new code path. Without it, a regression in this path would not be caught.

This is required by the project's testing conventions (see crates/mq-check/tests/integration_test.rs where all similar paths have comprehensive test coverage).

Copilot generated this review using guidance from repository custom instructions.
@harehare
Copy link
Copy Markdown
Owner Author

harehare commented Mar 4, 2026

@copilot
Could you please refactor it to make the logic cleaner?

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 4, 2026

@harehare I've opened a new pull request, #1387, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 2 commits March 4, 2026 15:32
♻️ refactor(mq-check): extract union_members_consistent_return into standalone helper
@harehare
Copy link
Copy Markdown
Owner Author

harehare commented Mar 5, 2026

@copilot
Could you please optimize this PR for better performance?

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 5, 2026

@harehare I've opened a new pull request, #1390, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI review requested due to automatic review settings March 5, 2026 12:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

@harehare harehare merged commit 1ab12b4 into main Mar 5, 2026
8 checks passed
@harehare harehare deleted the fix/typechecker-union-overload branch March 5, 2026 12:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants