diff --git a/ndc_analyser/src/analyser.rs b/ndc_analyser/src/analyser.rs index 212af7a9..87ecf2c1 100644 --- a/ndc_analyser/src/analyser.rs +++ b/ndc_analyser/src/analyser.rs @@ -517,9 +517,22 @@ impl Analyser { self.analyse(value)?; } Lvalue::Sequence(seq) => { - let sub_types = typ - .unpack() - .ok_or_else(|| AnalysisError::unable_to_unpack_type(&typ, span))?; + // If the type is a fixed-length Tuple whose arity doesn't match + // the number of lvalues, fall back to Any for each element. This + // can happen when a variable is declared with one type (e.g. ()) + // and later reassigned to a tuple of a different arity — the + // analyser doesn't track reassignment types. + let sub_types: Box> = + if let StaticType::Tuple(elems) = &typ { + if elems.len() != seq.len() { + Box::new(std::iter::repeat(&StaticType::Any)) + } else { + Box::new(elems.iter()) + } + } else { + typ.unpack() + .ok_or_else(|| AnalysisError::unable_to_unpack_type(&typ, span))? + }; for (sub_lvalue, sub_lvalue_type) in seq.iter_mut().zip(sub_types) { self.resolve_lvalue_declarative( diff --git a/ndc_bin/src/highlighter.rs b/ndc_bin/src/highlighter.rs index efdb33dc..3b7dbeae 100644 --- a/ndc_bin/src/highlighter.rs +++ b/ndc_bin/src/highlighter.rs @@ -1,7 +1,7 @@ +use ahash::AHashSet; use itertools::Itertools; use ndc_lexer::{Lexer, Token, TokenLocation}; use ndc_parser::{Expression, ExpressionLocation, ForBody, ForIteration}; -use ahash::AHashSet; use yansi::{Paint, Painted}; pub(crate) struct AndycppHighlighter; diff --git a/tests/programs/900_bugs/bug0015_unpack_mismatched_tuple_arity.ndc b/tests/programs/900_bugs/bug0015_unpack_mismatched_tuple_arity.ndc new file mode 100644 index 00000000..ba9120ff --- /dev/null +++ b/tests/programs/900_bugs/bug0015_unpack_mismatched_tuple_arity.ndc @@ -0,0 +1,13 @@ +// Destructuring let where the variable was declared as () but later +// reassigned to a 2-tuple should not cause a false "not declared" error. +// expect-output: 4 + +let pos = (); +pos = (1, 3); + +fn use_pos() { + let a, b = pos; + (a + b).print; +} + +use_pos();