From f08ae95b9d8be5165f9c8cac4c755d0510c3a18a Mon Sep 17 00:00:00 2001 From: Laurenz Date: Wed, 19 Apr 2023 17:51:33 +0200 Subject: [PATCH] Fix argument sinks Fixes #886. --- .github/workflows/ci.yml | 3 +++ library/src/compute/calc.rs | 2 +- src/eval/args.rs | 21 +++++++++++++++------ src/eval/scope.rs | 8 ++++---- src/syntax/parser.rs | 2 +- tests/ref/bugs/args-sink.png | Bin 0 -> 1001 bytes tests/typ/bugs/args-sink.typ | 5 +++++ 7 files changed, 29 insertions(+), 12 deletions(-) create mode 100644 tests/ref/bugs/args-sink.png create mode 100644 tests/typ/bugs/args-sink.typ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0eb493ec8..a0158ad8a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,9 @@ name: Continuous integration on: [push, pull_request] +env: + RUSTFLAGS: "-Dwarnings" + jobs: ci: runs-on: ubuntu-latest diff --git a/library/src/compute/calc.rs b/library/src/compute/calc.rs index 62c529deb..3875e3c3c 100644 --- a/library/src/compute/calc.rs +++ b/library/src/compute/calc.rs @@ -541,7 +541,7 @@ pub fn gcd( /// The second integer. b: i64, ) -> Value { - Value::Int(calculate_gcd(a, b).into()) + Value::Int(calculate_gcd(a, b)) } /// Calculates the greatest common divisor of two integers diff --git a/src/eval/args.rs b/src/eval/args.rs index 8617bd93a..bea2baa1c 100644 --- a/src/eval/args.rs +++ b/src/eval/args.rs @@ -62,14 +62,23 @@ impl Args { } /// Consume n positional arguments if possible. - pub fn consume(&mut self, n: usize) -> SourceResult> { - if n > self.items.len() { + pub fn consume(&mut self, n: usize) -> SourceResult> { + let mut list = vec![]; + + let mut i = 0; + while i < self.items.len() && list.len() < n { + if self.items[i].name.is_none() { + list.push(self.items.remove(i)); + } else { + i += 1; + } + } + + if list.len() < n { bail!(self.span, "not enough arguments"); } - let vec = self.items.to_vec(); - let (left, right) = vec.split_at(n); - self.items = right.into(); - Ok(left.into()) + + Ok(list) } /// Consume and cast the first positional argument. diff --git a/src/eval/scope.rs b/src/eval/scope.rs index f2207188a..76633bf28 100644 --- a/src/eval/scope.rs +++ b/src/eval/scope.rs @@ -38,20 +38,20 @@ impl<'a> Scopes<'a> { /// Try to access a variable immutably. pub fn get(&self, var: &str) -> StrResult<&Value> { - Ok(std::iter::once(&self.top) + std::iter::once(&self.top) .chain(self.scopes.iter().rev()) .chain(self.base.map(|base| base.global.scope())) .find_map(|scope| scope.get(var)) - .ok_or(eco_format!("unknown variable: {}", var))?) + .ok_or_else(|| eco_format!("unknown variable: {}", var)) } /// Try to access a variable immutably in math. pub fn get_in_math(&self, var: &str) -> StrResult<&Value> { - Ok(std::iter::once(&self.top) + std::iter::once(&self.top) .chain(self.scopes.iter().rev()) .chain(self.base.map(|base| base.math.scope())) .find_map(|scope| scope.get(var)) - .ok_or(eco_format!("unknown variable: {}", var))?) + .ok_or_else(|| eco_format!("unknown variable: {}", var)) } /// Try to access a variable mutably. diff --git a/src/syntax/parser.rs b/src/syntax/parser.rs index 4bc25a30d..801fdfc8c 100644 --- a/src/syntax/parser.rs +++ b/src/syntax/parser.rs @@ -1047,7 +1047,7 @@ fn validate_dict(p: &mut Parser, m: Marker) { }; if !used.insert(key.clone()) { - first.convert_to_error(eco_format!("duplicate key: {}", key)); + first.convert_to_error(eco_format!("duplicate key: {key}")); child.make_erroneous(); } } diff --git a/tests/ref/bugs/args-sink.png b/tests/ref/bugs/args-sink.png new file mode 100644 index 0000000000000000000000000000000000000000..35f5021adc8c9c0eb809035191571049a3d65510 GIT binary patch literal 1001 zcmVuDqs@wnj0$a0D$JJ(`hj)ajC4#QHE(uzj!mxeDBT(K_E9e-yd`D`R3j?@BMgl&Uue95{X12kw_#G z=?{hfOay@-5Cnoi5C{T6AP5A3AP@wCKoAH5K_CbOfgm&jgbPWHbXJ>+goSX^ulDbL ztlEY5)78TKVda8C_}2BceLTCEyR_&)f1g7d>-Owm{j5^{0O>6>;rmX#yuCb*bBj#j zaR3g?6cj>8Fo2rVeI@%#w0K9JjA=H;%5(*_^k6CM9qyJ(N^TY0dy zN)-}9QIli<-xEJ{n5OZobX$R1_wg!gK@flm!?pWsXV3J|7^jRbK>M1NLktoU!v5Aa z$7FyO0%Gz3tNTQiQ(grWdPZrNMIVmPLWqiT&b%IZ$}E|^5)s0%A#e>rRwg^BHL?dq zXj5L!bZ`)ii?^(Zx2l~=uZ7j09Mg9!Mnnj0{Tqf*J8_IQ^Bddf{2pkEz?cFa!j{m4 zNYDOem2;7eT<+I8Qm#Q(DNsNNRZ>X95O$3)^HxsJ7Oz#|?pW{;WL;vLRM9q84(w$K zcIKl6gitJnHwYnSe5Lb-bJFhmAh$4TiUBn#|Z*Lu($;@ z1R-v$1#s%49<$B$!8?D0!O-2!5W%l%=c@|VNk0I1%lE*~CW}PO3ErcWN&l(ZFH*aI z0WilY)3fuOMg`~LIF5r<)E{+*emWUA2rTg-5 zYzA{%mJY09`;n}K z9LO@2HA(u7C;FX{XX|^5**5#Fkw0H$=jA^C2p}=kVVkq_OeRxK8DN=T*XvegT>s!` zGwUH(p1sI@{sl-0`kiYpXIkX(N7&gq%X}ln(MNZV6BEKyy}AzCmZtFwN+&rLiCar~ zr)J$%-ui0z%v;xdYXp6ij$NS&b~-)bRIDuIt-CvIP6xTdJ2si2*SSxfkYyaNF)-8L~@~D X?XrV45RH(j00000NkvXXu0mjfJ)p`$ literal 0 HcmV?d00001 diff --git a/tests/typ/bugs/args-sink.typ b/tests/typ/bugs/args-sink.typ new file mode 100644 index 000000000..4f7492ac4 --- /dev/null +++ b/tests/typ/bugs/args-sink.typ @@ -0,0 +1,5 @@ +// Test bugs with argument sinks. + +--- +#let foo(..body) = repr(body.pos()) +#foo(a: "1", b: "2", 1, 2, 3, 4, 5, 6)