fix: unsafeGetAttrPos call on functionArgs

This commit is contained in:
2026-01-31 16:46:14 +08:00
parent cb539c52c3
commit 6838f9a0cf
5 changed files with 35 additions and 18 deletions

View File

@@ -3,7 +3,7 @@
*/ */
import { force } from "../thunk"; import { force } from "../thunk";
import { CatchableError } from "../types"; import { CatchableError, ATTR_POSITIONS } from "../types";
import type { NixAttrs, NixBool, NixStrictValue, NixValue } from "../types"; import type { NixAttrs, NixBool, NixStrictValue, NixValue } from "../types";
import { forceList, forceAttrs, forceFunction, forceStringValue, forceString, forceStringNoCtx } from "../type-assert"; import { forceList, forceAttrs, forceFunction, forceStringValue, forceString, forceStringNoCtx } from "../type-assert";
import * as context from "./context"; import * as context from "./context";
@@ -165,6 +165,14 @@ export const functionArgs = (f: NixValue): NixAttrs => {
for (const key of func.args!.optional) { for (const key of func.args!.optional) {
ret[key] = true; ret[key] = true;
} }
const positions = func.args!.positions;
if (positions && Object.keys(positions).length > 0) {
Object.defineProperty(ret, ATTR_POSITIONS, {
value: positions,
enumerable: false,
writable: false,
});
}
return ret; return ret;
} }
return {}; return {};

View File

@@ -39,9 +39,11 @@ export class NixArgs {
optional: string[]; optional: string[];
allowed: Set<string>; allowed: Set<string>;
ellipsis: boolean; ellipsis: boolean;
constructor(required: string[], optional: string[], ellipsis: boolean) { positions: Record<string, string>;
constructor(required: string[], optional: string[], positions: Record<string, string>, ellipsis: boolean) {
this.required = required; this.required = required;
this.optional = optional; this.optional = optional;
this.positions = positions;
this.ellipsis = ellipsis; this.ellipsis = ellipsis;
this.allowed = new Set(required.concat(optional)); this.allowed = new Set(required.concat(optional));
} }
@@ -67,10 +69,11 @@ export const mkFunction = (
f: (arg: NixValue) => NixValue, f: (arg: NixValue) => NixValue,
required: string[], required: string[],
optional: string[], optional: string[],
positions: Record<string, string>,
ellipsis: boolean, ellipsis: boolean,
): NixFunction => { ): NixFunction => {
const func = f as NixFunction; const func = f as NixFunction;
func.args = new NixArgs(required, optional, ellipsis); func.args = new NixArgs(required, optional, positions, ellipsis);
return func; return func;
}; };

View File

@@ -424,14 +424,18 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Func {
} }
code!(buf, ctx; code!(buf, ctx;
",[" ",["
joined(required.iter(), ",", |ctx: &Ctx, buf, &sym| { joined(required.iter(), ",", |ctx: &Ctx, buf, &(sym, _)| {
code!(buf, ctx; quoted(ctx.get_sym(sym))); code!(buf, ctx; quoted(ctx.get_sym(sym)));
}) })
"],[" "],["
joined(optional.iter(), ",", |ctx: &Ctx, buf, &sym| { joined(optional.iter(), ",", |ctx: &Ctx, buf, &(sym, _)| {
code!(buf, ctx; quoted(ctx.get_sym(sym))); code!(buf, ctx; quoted(ctx.get_sym(sym)));
}) })
"]," "],{"
joined(required.iter().chain(optional.iter()), ",", |ctx: &Ctx, buf, &(sym, span)| {
code!(buf, ctx; quoted(ctx.get_sym(sym)), ":", span);
})
"},"
); );
code!(buf, "{})", ellipsis); code!(buf, "{})", ellipsis);
} else { } else {

View File

@@ -173,7 +173,7 @@ impl From<ast::UnaryOpKind> for UnOpKind {
/// Describes the parameters of a function. /// Describes the parameters of a function.
#[derive(Debug)] #[derive(Debug)]
pub struct Param { pub struct Param {
pub required: Vec<SymId>, pub required: Vec<(SymId, TextRange)>,
pub optional: Vec<SymId>, pub optional: Vec<(SymId, TextRange)>,
pub ellipsis: bool, pub ellipsis: bool,
} }

View File

@@ -474,8 +474,8 @@ pub fn downgrade_attrpath(
pub struct PatternBindings { pub struct PatternBindings {
pub body: ExprId, pub body: ExprId,
pub required: Vec<SymId>, pub required: Vec<(SymId, TextRange)>,
pub optional: Vec<SymId>, pub optional: Vec<(SymId, TextRange)>,
} }
/// Helper function for Lambda pattern parameters. /// Helper function for Lambda pattern parameters.
@@ -529,14 +529,16 @@ where
binding_keys.push(alias_sym); binding_keys.push(alias_sym);
} }
let (required, optional) = params.iter().partition_map(|Param { sym, default, .. }| { let (required, optional) = params
use itertools::Either::*; .iter()
if default.is_none() { .partition_map(|Param { sym, sym_span, default, .. }| {
Left(sym) use itertools::Either::*;
} else { if default.is_none() {
Right(sym) Left((*sym, *sym_span))
} } else {
}); Right((*sym, *sym_span))
}
});
let slots: Vec<_> = ctx.reserve_slots(binding_keys.len()).collect(); let slots: Vec<_> = ctx.reserve_slots(binding_keys.len()).collect();
let let_bindings: HashMap<_, _> = binding_keys let let_bindings: HashMap<_, _> = binding_keys