diff --git a/crates/erg_compiler/context/register.rs b/crates/erg_compiler/context/register.rs index fd67dbe6..c2f1687c 100644 --- a/crates/erg_compiler/context/register.rs +++ b/crates/erg_compiler/context/register.rs @@ -251,6 +251,7 @@ impl Context { Private }; let default = kind.default_info(); + let is_var_params = kind.is_var_params(); match &sig.pat { // Literal patterns will be desugared to discard patterns ast::ParamPattern::Lit(_) => unreachable!(), @@ -299,6 +300,11 @@ impl Context { Normal, kind, )?; + let spec_t = if is_var_params { + unknown_len_array_t(spec_t) + } else { + spec_t + }; if &name.inspect()[..] == "self" { if let Some(self_t) = self.rec_get_self_t() { self.sub_unify(&spec_t, &self_t, name.loc(), Some(name.inspect()))?; @@ -506,7 +512,7 @@ impl Context { }; let name = &sig.ident.name; // FIXME: constでない関数 - let t = self.get_current_scope_var(name).map(|v| &v.t).unwrap(); + let t = self.get_current_scope_var(name).map(|vi| &vi.t).unwrap(); let non_default_params = t.non_default_params().unwrap(); let var_args = t.var_params(); let default_params = t.default_params().unwrap(); diff --git a/crates/erg_compiler/hir.rs b/crates/erg_compiler/hir.rs index 5b70cdbb..ff52a064 100644 --- a/crates/erg_compiler/hir.rs +++ b/crates/erg_compiler/hir.rs @@ -176,7 +176,7 @@ impl NestedDisplay for Args { fmt_lines(self.pos_args.iter(), f, level)?; } if let Some(var_args) = &self.var_args { - writeln!(f, "...")?; + writeln!(f, "*")?; var_args.fmt_nest(f, level)?; } if !self.kw_args.is_empty() { @@ -1683,8 +1683,9 @@ impl Locational for Params { ) { (Some(l), _, Some(r)) => Location::concat(l, r), (Some(l), Some(r), None) => Location::concat(l, r.as_ref()), - (Some(l), None, None) => Location::concat(l, self.non_defaults.last().unwrap()), (None, Some(l), Some(r)) => Location::concat(l.as_ref(), r), + (Some(l), None, None) => Location::concat(l, self.non_defaults.last().unwrap()), + (None, Some(var), None) => var.loc(), (None, None, Some(r)) => Location::concat(self.defaults.first().unwrap(), r), _ => Location::Unknown, } diff --git a/crates/erg_parser/ast.rs b/crates/erg_parser/ast.rs index 2dae0537..10c3e012 100644 --- a/crates/erg_parser/ast.rs +++ b/crates/erg_parser/ast.rs @@ -3111,7 +3111,7 @@ impl fmt::Display for Params { f, "({}, {}, {})", fmt_vec(&self.non_defaults), - fmt_option!(pre "...", &self.var_params), + fmt_option!(pre "*", &self.var_params), fmt_vec(&self.defaults) ) } @@ -3132,8 +3132,9 @@ impl Locational for Params { ) { (Some(l), _, Some(r)) => Location::concat(l, r), (Some(l), Some(r), None) => Location::concat(l, r.as_ref()), - (Some(l), None, None) => Location::concat(l, self.non_defaults.last().unwrap()), (None, Some(l), Some(r)) => Location::concat(l.as_ref(), r), + (Some(l), None, None) => Location::concat(l, self.non_defaults.last().unwrap()), + (None, Some(var), None) => var.loc(), (None, None, Some(r)) => Location::concat(self.defaults.first().unwrap(), r), _ => Location::Unknown, } diff --git a/tests/should_err/var_args.er b/tests/should_err/var_args.er new file mode 100644 index 00000000..891f1172 --- /dev/null +++ b/tests/should_err/var_args.er @@ -0,0 +1,5 @@ +p! *x: Int = print! x +p! 1, 2, "a" # ERR + +first *x = x[0] +assert first(1, 2, 3) == "b" # ERR diff --git a/tests/should_ok/var_args.er b/tests/should_ok/var_args.er index 445592b6..c8fb122e 100644 --- a/tests/should_ok/var_args.er +++ b/tests/should_ok/var_args.er @@ -1,3 +1,5 @@ p! *x: Int = print! x - p! 1, 2, 3 + +first *x = x[0] +assert first(1, 2, 3) == 1 diff --git a/tests/test.rs b/tests/test.rs index 05e36b3f..941e5310 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -244,3 +244,8 @@ fn exec_quantified_err() -> Result<(), ()> { fn exec_var_args() -> Result<(), ()> { expect_success("tests/should_ok/var_args.er") } + +#[test] +fn exec_var_args_err() -> Result<(), ()> { + expect_failure("tests/should_err/var_args.er", 2) +}