aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/manual/rl-next/inherit-error-positions.md6
-rw-r--r--src/libexpr/parser.y25
-rw-r--r--tests/functional/lang/eval-fail-dupAttr-inherit.err.exp2
-rw-r--r--tests/functional/lang/eval-okay-inherit-attr-pos.exp1
-rw-r--r--tests/functional/lang/eval-okay-inherit-attr-pos.nix12
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-2.err.exp4
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-3.err.exp4
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-7.err.exp6
-rw-r--r--tests/functional/lang/parse-fail-regression-20060610.err.exp6
9 files changed, 43 insertions, 23 deletions
diff --git a/doc/manual/rl-next/inherit-error-positions.md b/doc/manual/rl-next/inherit-error-positions.md
new file mode 100644
index 000000000..643080e9e
--- /dev/null
+++ b/doc/manual/rl-next/inherit-error-positions.md
@@ -0,0 +1,6 @@
+---
+synopsis: fix duplicate attribute error positions for `inherit`
+prs: 9874
+---
+
+When an inherit caused a duplicate attribute error the position of the error was not reported correctly, placing the error with the inherit itself or at the start of the bindings block instead of the offending attribute name.
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index ee44a6d7a..476403c4c 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -85,6 +85,7 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParserState * state, const char *
nix::StringToken uri;
nix::StringToken str;
std::vector<nix::AttrName> * attrNames;
+ std::vector<std::pair<nix::AttrName, nix::PosIdx>> * inheritAttrs;
std::vector<std::pair<nix::PosIdx, nix::Expr *>> * string_parts;
std::vector<std::pair<nix::PosIdx, std::variant<nix::Expr *, nix::StringToken>>> * ind_string_parts;
}
@@ -95,7 +96,8 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParserState * state, const char *
%type <attrs> binds
%type <formals> formals
%type <formal> formal
-%type <attrNames> attrs attrpath
+%type <attrNames> attrpath
+%type <inheritAttrs> attrs
%type <string_parts> string_parts_interpolated
%type <ind_string_parts> ind_string_parts
%type <e> path_start string_parts string_attr
@@ -307,13 +309,12 @@ binds
: binds attrpath '=' expr ';' { $$ = $1; state->addAttr($$, std::move(*$2), $4, state->at(@2)); delete $2; }
| binds INHERIT attrs ';'
{ $$ = $1;
- for (auto & i : *$3) {
+ for (auto & [i, iPos] : *$3) {
if ($$->attrs.find(i.symbol) != $$->attrs.end())
- state->dupAttr(i.symbol, state->at(@3), $$->attrs[i.symbol].pos);
- auto pos = state->at(@3);
+ state->dupAttr(i.symbol, iPos, $$->attrs[i.symbol].pos);
$$->attrs.emplace(
i.symbol,
- ExprAttrs::AttrDef(new ExprVar(CUR_POS, i.symbol), pos, ExprAttrs::AttrDef::Kind::Inherited));
+ ExprAttrs::AttrDef(new ExprVar(iPos, i.symbol), iPos, ExprAttrs::AttrDef::Kind::Inherited));
}
delete $3;
}
@@ -323,14 +324,14 @@ binds
$$->inheritFromExprs = std::make_unique<std::vector<Expr *>>();
$$->inheritFromExprs->push_back($4);
auto from = new nix::ExprInheritFrom(state->at(@4), $$->inheritFromExprs->size() - 1);
- for (auto & i : *$6) {
+ for (auto & [i, iPos] : *$6) {
if ($$->attrs.find(i.symbol) != $$->attrs.end())
- state->dupAttr(i.symbol, state->at(@6), $$->attrs[i.symbol].pos);
+ state->dupAttr(i.symbol, iPos, $$->attrs[i.symbol].pos);
$$->attrs.emplace(
i.symbol,
ExprAttrs::AttrDef(
- new ExprSelect(CUR_POS, from, i.symbol),
- state->at(@6),
+ new ExprSelect(iPos, from, i.symbol),
+ iPos,
ExprAttrs::AttrDef::Kind::InheritedFrom));
}
delete $6;
@@ -339,12 +340,12 @@ binds
;
attrs
- : attrs attr { $$ = $1; $1->push_back(AttrName(state->symbols.create($2))); }
+ : attrs attr { $$ = $1; $1->emplace_back(AttrName(state->symbols.create($2)), state->at(@2)); }
| attrs string_attr
{ $$ = $1;
ExprString * str = dynamic_cast<ExprString *>($2);
if (str) {
- $$->push_back(AttrName(state->symbols.create(str->s)));
+ $$->emplace_back(AttrName(state->symbols.create(str->s)), state->at(@2));
delete str;
} else
throw ParseError({
@@ -352,7 +353,7 @@ attrs
.pos = state->positions[state->at(@2)]
});
}
- | { $$ = new AttrPath; }
+ | { $$ = new std::vector<std::pair<AttrName, PosIdx>>; }
;
attrpath
diff --git a/tests/functional/lang/eval-fail-dupAttr-inherit.err.exp b/tests/functional/lang/eval-fail-dupAttr-inherit.err.exp
index 7744b838f..3e6475a1c 100644
--- a/tests/functional/lang/eval-fail-dupAttr-inherit.err.exp
+++ b/tests/functional/lang/eval-fail-dupAttr-inherit.err.exp
@@ -1,4 +1,4 @@
-error: attribute 'a' already defined at /pwd/lang/eval-fail-dupAttr-inherit.nix:1:15
+error: attribute 'a' already defined at /pwd/lang/eval-fail-dupAttr-inherit.nix:1:16
at /pwd/lang/eval-fail-dupAttr-inherit.nix:1:19:
1| { inherit ({}) a; a.b = 1; }
| ^
diff --git a/tests/functional/lang/eval-okay-inherit-attr-pos.exp b/tests/functional/lang/eval-okay-inherit-attr-pos.exp
new file mode 100644
index 000000000..e87d037c6
--- /dev/null
+++ b/tests/functional/lang/eval-okay-inherit-attr-pos.exp
@@ -0,0 +1 @@
+[ { column = 17; file = "/pwd/lang/eval-okay-inherit-attr-pos.nix"; line = 4; } { column = 19; file = "/pwd/lang/eval-okay-inherit-attr-pos.nix"; line = 4; } { column = 21; file = "/pwd/lang/eval-okay-inherit-attr-pos.nix"; line = 5; } { column = 23; file = "/pwd/lang/eval-okay-inherit-attr-pos.nix"; line = 5; } ]
diff --git a/tests/functional/lang/eval-okay-inherit-attr-pos.nix b/tests/functional/lang/eval-okay-inherit-attr-pos.nix
new file mode 100644
index 000000000..017ab1d36
--- /dev/null
+++ b/tests/functional/lang/eval-okay-inherit-attr-pos.nix
@@ -0,0 +1,12 @@
+let
+ d = 0;
+ x = 1;
+ y = { inherit d x; };
+ z = { inherit (y) d x; };
+in
+ [
+ (builtins.unsafeGetAttrPos "d" y)
+ (builtins.unsafeGetAttrPos "x" y)
+ (builtins.unsafeGetAttrPos "d" z)
+ (builtins.unsafeGetAttrPos "x" z)
+ ]
diff --git a/tests/functional/lang/parse-fail-dup-attrs-2.err.exp b/tests/functional/lang/parse-fail-dup-attrs-2.err.exp
index 4607a5d59..3105e60de 100644
--- a/tests/functional/lang/parse-fail-dup-attrs-2.err.exp
+++ b/tests/functional/lang/parse-fail-dup-attrs-2.err.exp
@@ -1,6 +1,6 @@
error: attribute 'x' already defined at «stdin»:9:5
- at «stdin»:10:17:
+ at «stdin»:10:18:
9| x = 789;
10| inherit (as) x;
- | ^
+ | ^
11| };
diff --git a/tests/functional/lang/parse-fail-dup-attrs-3.err.exp b/tests/functional/lang/parse-fail-dup-attrs-3.err.exp
index 4607a5d59..3105e60de 100644
--- a/tests/functional/lang/parse-fail-dup-attrs-3.err.exp
+++ b/tests/functional/lang/parse-fail-dup-attrs-3.err.exp
@@ -1,6 +1,6 @@
error: attribute 'x' already defined at «stdin»:9:5
- at «stdin»:10:17:
+ at «stdin»:10:18:
9| x = 789;
10| inherit (as) x;
- | ^
+ | ^
11| };
diff --git a/tests/functional/lang/parse-fail-dup-attrs-7.err.exp b/tests/functional/lang/parse-fail-dup-attrs-7.err.exp
index 2daddf380..4e0a48eff 100644
--- a/tests/functional/lang/parse-fail-dup-attrs-7.err.exp
+++ b/tests/functional/lang/parse-fail-dup-attrs-7.err.exp
@@ -1,6 +1,6 @@
-error: attribute 'x' already defined at «stdin»:6:12
- at «stdin»:7:12:
+error: attribute 'x' already defined at «stdin»:6:13
+ at «stdin»:7:13:
6| inherit x;
7| inherit x;
- | ^
+ | ^
8| };
diff --git a/tests/functional/lang/parse-fail-regression-20060610.err.exp b/tests/functional/lang/parse-fail-regression-20060610.err.exp
index d8875a6a5..6ae7c01bf 100644
--- a/tests/functional/lang/parse-fail-regression-20060610.err.exp
+++ b/tests/functional/lang/parse-fail-regression-20060610.err.exp
@@ -1,6 +1,6 @@
error: undefined variable 'gcc'
- at «stdin»:8:12:
- 7|
+ at «stdin»:9:13:
8| body = ({
- | ^
9| inherit gcc;
+ | ^
+ 10| }).gcc;