fluffos/testsuite/std
Yucong Sun 8822499822
compiler: coerce return <expr>; to the function's declared return type (#1334)
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>
2026-07-27 22:29:15 -07:00
..
fonts update stdlib, add bitmap_font 2020-03-10 08:57:53 -07:00
tui lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
all_environment.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
base64.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
bitmap_font.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
break_string.h update break_string sefun 2020-03-11 21:53:17 -07:00
break_string.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
database.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
decimal.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
element_of_weighted.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
ffi_util.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
highest.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
http.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
json.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
lowest.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
number_string.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
percent.lpc compiler: coerce return <expr>; to the function's declared return type (#1334) 2026-07-27 22:29:15 -07:00
present_clone.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
range.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
reduce.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
sum.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00
telnet.lpc lpc-syntax: source-following LPC formatter with printWidth wrapping and full testsuite reformat (#1270) 2026-07-17 11:55:21 -07:00