repl: fix multi-line attribute set in variable binding (issue #16310) - #16521
Open
akashhg2007 wants to merge 1 commit into
Open
akashhg2007 wants to merge 1 commit into
akashhg2007 wants to merge 1 commit into
Conversation
…6310) When a user typed � = { followed by Enter in nix repl, the REPL produced a confusing error: error: syntax error, unexpected '=', expecting end of file at «string»:1:3: 1| a = { | ^ The root cause was in NixRepl::parseReplBindings: the first parse attempt (without semicolon) caught *all* ParseErrors silently. When the input was an incomplete attrset binding (e.g. � = {), the parse fails with 'unexpected end of file' — an incomplete-input signal. Because this was swallowed, the code fell through to the semicolon-retry, which produced a different syntax error (not 'unexpected end of file'), so the second catch returned ullptr. Back in processLine, ullptr caused the line to be evaluated as a Nix expression, which correctly rejected � = { as invalid expression syntax. Fix: mirror the isIncompleteInput check already present in the second catch block into the first catch block, throwing IncompleteReplExpr so the main loop prompts for continuation. This is analogous to the fix for multi-line strings in bindings (issue NixOS#15801, PR NixOS#15892). The single-line case � = { b = 1; } is unaffected — only incomplete inputs (missing closing }) trigger the continuation prompt. Add two characterisation tests: - multiline-attrset-binding: variable bound to a multi-line attrset - multiline-attrset-expr: multi-line attrset expression (regression guard)
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #16310.
When a user typed � = { followed by Enter in
ix repl, the REPL produced a confusing error:
error: syntax error, unexpected '=', expecting end of file at «string»:1:3: 1| a = { | ^This was already working for plain expressions (e.g. { without a binding), and was fixed for multi-line strings in bindings by PR #15892 (issue #15801). This PR fixes the same class of problem for multi-line attribute sets in bindings.
Root Cause
In NixRepl::parseReplBindings (src/libcmd/repl.cc), the first parse attempt catches all ParseErrors silently:
cpp // Before try { return state->parseReplBindings(s, basePath, staticEnv); } catch (ParseError &) { // ALL errors swallowed — including 'unexpected end of file'! }When the input was � = { (incomplete), the parse fails with unexpected end of file. Because this was swallowed without checking, the code fell through to the semicolon-retry, which produced a different error (not unexpected end of file), causing the second catch to return
ullptr. Back in processLine,
ullptr triggered expression evaluation of � = {, which correctly rejected it with the misleading unexpected '=' error.
Fix
Mirror the isIncompleteInput check already present in the second catch block into the first catch block. When the first parse attempt fails due to incomplete input, throw IncompleteReplExpr so the main loop prompts for continuation instead of falling through to expression evaluation:
cpp // After try { return state->parseReplBindings(s, basePath, staticEnv); } catch (ParseError & e) { if (isIncompleteInput(e)) throw IncompleteReplExpr(e.msg()); }Expected Behavior (After Fix)
`
nix-repl> a = {
> b = 1;
> }
nix-repl> a
{ b = 1; }
`
Tests
Two new characterisation tests are added in ests/functional/suites/repl/cases/: