You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
replace <pattern> with <text> in <text> is a silent no-op: returns the input unchanged, exit 0, no diagnostic (and literal string replace is unreachable) #698
replace <pattern> with <text> in <text> silently returns the input unchanged — it parses, type-checks, runs, exits 0, and produces a wrong answer with no diagnostic.
Reproduction
create pattern w:
"world"
end pattern
store s as "hello world world"
display "[" with (replace w with "there" in s) with "]"
Command:
wfl d1_pattern_replace_noop.wfl
Expected
[hello there there].
replace is documented as the pattern-replacement keyword in Docs/reference/keyword-reference.md:155 (| replace | Pattern replacement | ✗ |),
and the expression form is a first-class production in the parser
(src/parser/expr/primary.rs:1218-1238 and src/parser/expr/binary.rs:648-665),
the analyzer, the type checker, and the interpreter
(src/interpreter/mod.rs:14628).
Actual
[hello world world]
Exit code: 0. No warning, no error, no diagnostic on stderr.
Root cause: native_pattern_replace validates all three arguments and then discards them.
// src/stdlib/pattern.rs:214-262pubfnnative_pattern_replace(args:Vec<Value>,line:usize,column:usize) -> Result<Value,RuntimeError>{
...
let _pattern = ...;// validated, then unusedlet _replacement = ...;// validated, then unused// TODO: Update to use new pattern system for replacementOk(Value::Text(Arc::from(text)))}
Passing a Text where the Pattern is expected does fail loudly
(Second argument must be a pattern), so the failure is specific to the
supported, documented form.
Compounding problem — the literal string replace is unreachable from WFL source.
A working 3-argument literal replace exists and is unit-tested
(native_replace, src/stdlib/text.rs:435, tests at :456-472), but replace
lexes as Token::KeywordReplace and the parser only accepts the <pattern> with <x> in <y> shape:
display replace of s and "world" and "there"
=> error[ERROR]: Unexpected token in expression: KeywordOf (exit 2)
The repository already documents this dead end in a test comment:
// TestPrograms/stdlib_comprehensive.wfl:95-96
// Note: string replace() is a native function but 'replace' keyword is reserved
// for pattern replacement. String replace is tested in Rust unit tests.
So today WFL has no reachable string-replacement operation at all: the pattern
form silently no-ops, and the literal form cannot be called. The documented
workaround shape is join of (split <text> by <needle>) and <replacement>.
Environment
wfl --version: WebFirst Language (WFL) version 26.8.4
binary: system install C:\Program Files\wfl\bin\wfl.exe
Also reproduces identically on the repo build G:\repos\wfl\target\release\wfl.exe
(version 26.8.2), so this is not a regression — it is long-standing.
No .wflcfg in scope for the repro.
Context
Found while porting G:/repos/JShrink/src/JShrink/Minifier.php (a 738-line PHP
JavaScript minifier) to WFL. JShrink's unlock() step is a literal str_replace
and its lock() step is a preg_replace with backreferences.
This one was encountered, not blocking: the port uses join of (split src by needle) and replacement for the literal replace and a pattern_find_all + rebuild loop for the backreference case, so no stub was left.
It is filed because of how it fails, not because it blocked us — a program that
reaches for the documented keyword gets a silently wrong result and a zero exit
status, which is the worst failure mode in the set. Separately, replacement with
capture-group backreferences ($1/$2) has no form at all; that is a distinct
enhancement, not part of this bug.
Activity
test: red tests for the review follow-ups on #698-#700
fix: stop the program everywhere, and only reject steps that matter