mirror of
https://github.com/fluffos/fluffos
synced 2026-08-12 18:26:06 -04:00
Issue #1331: a function declared `int` whose return expression actually evaluates to a float (e.g. `return sqrt(x);`) genuinely handed back a T_REAL svalue at runtime. compatible_types() intentionally treats int and float as compatible (so no compile error), and until now nothing enforced the declared type at the return statement itself -- unlike '='/op= assignment, which rule_expr_assign() already coerces to a declared-type lvalue (#1303). A caller doing `int_var += that_call()` then hit F_ADD_EQ's untyped-lvalue promotion path meant only for mixed/mapping slots, silently promoting a genuinely int-declared variable to float -- exactly the reporter's own example (`int heat_close(...) { return (range - sqrt(dist_sq)) * ...; }` then `int_var += heat_close(...)`), cascading into switch()/array-index/% errors mudlib-wide. rule_return_expr() (grammar_rules_loops.cc) now applies the same int<->float promotion rule_expr_assign() already applies to an assignment RHS, scoped to scalar int/float only (exact-equality checks, matching the op= precedent, correctly exclude array return types like `int *`) and never touching untyped (mixed) returns. One nuance the compound-assignment precedent doesn't have to deal with: CREATE_NUMBER() gives a literal `0` node type TYPE_ANY, not TYPE_NUMBER (0 doubles as LPC's untyped "nil" across every type), so `float f() { return 0; }` needs the same `|| kind == NODE_NUMBER` fallback do_promotions() already uses (compiler.cc) -- otherwise it falls through unpromoted to the F_RETURN_ZERO fast path, which always returns an int-typed 0 regardless of the function's declared type. testsuite/std/percent.lpc's percent()/percent_of() were declared `int` but are genuinely polymorphic by design (float args in, float result out; int args in, truncated int result out) -- an intentional escape from their declared type that this fix would otherwise silently truncate. Redeclared `mixed` to accurately reflect that contract; this changes nothing for any caller; the compiler applies no coercion at all to a mixed-declared function's return in the first place, and this already-passing testsuite file is proof such a pattern needs to be called out by an honest `mixed` return type, not "int" while quietly depending on the driver not really enforcing it. New regression test testsuite/single/tests/operators/return_type_coercion.lpc, verified to fail (9 checks) on the unfixed binary via a worktree with just this commit reverted, and pass on the fix. Full LPC suite x3 (randomized order) + 373 GTests clean on RelWithDebInfo; full suite + GTests clean on Debug+ASan (one unrelated pre-existing leak surfaced in RcTest, in read_config()/rc.cc, unconnected to this change -- see PR description). Co-authored-by: Claude <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| fonts | ||
| tui | ||
| all_environment.lpc | ||
| base64.lpc | ||
| bitmap_font.lpc | ||
| break_string.h | ||
| break_string.lpc | ||
| database.lpc | ||
| decimal.lpc | ||
| element_of_weighted.lpc | ||
| ffi_util.lpc | ||
| highest.lpc | ||
| http.lpc | ||
| json.lpc | ||
| lowest.lpc | ||
| number_string.lpc | ||
| percent.lpc | ||
| present_clone.lpc | ||
| range.lpc | ||
| reduce.lpc | ||
| sum.lpc | ||
| telnet.lpc | ||