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 { CatchableError } from "../types";
import { CatchableError, ATTR_POSITIONS } from "../types";
import type { NixAttrs, NixBool, NixStrictValue, NixValue } from "../types";
import { forceList, forceAttrs, forceFunction, forceStringValue, forceString, forceStringNoCtx } from "../type-assert";
import * as context from "./context";
@@ -165,6 +165,14 @@ export const functionArgs = (f: NixValue): NixAttrs => {
for (const key of func.args!.optional) {
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 {};

View File

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

View File

@@ -424,14 +424,18 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Func {
}
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)));
})
"],["
joined(optional.iter(), ",", |ctx: &Ctx, buf, &sym| {
joined(optional.iter(), ",", |ctx: &Ctx, buf, &(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);
} else {

View File

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

View File

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