Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions ndc_analyser/src/analyser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<dyn Iterator<Item = &StaticType>> =
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(
Expand Down
2 changes: 1 addition & 1 deletion ndc_bin/src/highlighter.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
13 changes: 13 additions & 0 deletions tests/programs/900_bugs/bug0015_unpack_mismatched_tuple_arity.ndc
Original file line number Diff line number Diff line change
@@ -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();
Loading