fix: allow spread operator on positional constructors closes #677
This commit is contained in:
parent
d5820bb20a
commit
6ce30bd949
|
@ -981,6 +981,46 @@ fn list_pattern_6() {
|
||||||
assert!(check(parse(source_code)).is_ok())
|
assert!(check(parse(source_code)).is_ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn spread_with_positional_constr_args() {
|
||||||
|
let source_code = r#"
|
||||||
|
type Redeemer {
|
||||||
|
First(Int)
|
||||||
|
Second
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(redeemer: Redeemer) {
|
||||||
|
when redeemer is {
|
||||||
|
First(..) -> True
|
||||||
|
Second -> True
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
assert!(check(parse(source_code)).is_ok())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unnecessary_spread_with_positional_constr_args() {
|
||||||
|
let source_code = r#"
|
||||||
|
type Redeemer {
|
||||||
|
First(Int)
|
||||||
|
Second
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(redeemer: Redeemer) {
|
||||||
|
when redeemer is {
|
||||||
|
First(x, ..) -> True
|
||||||
|
Second -> True
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
check(parse(source_code)),
|
||||||
|
Err((_, Error::UnnecessarySpreadOperator { .. }))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn trace_strings() {
|
fn trace_strings() {
|
||||||
let source_code = r#"
|
let source_code = r#"
|
||||||
|
|
|
@ -314,6 +314,8 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
|
||||||
self.environment
|
self.environment
|
||||||
.get_value_constructor(module.as_ref(), &name, location)?;
|
.get_value_constructor(module.as_ref(), &name, location)?;
|
||||||
|
|
||||||
|
let has_no_fields = cons.field_map().is_none();
|
||||||
|
|
||||||
match cons.field_map() {
|
match cons.field_map() {
|
||||||
// The fun has a field map so labelled arguments may be present and need to be reordered.
|
// The fun has a field map so labelled arguments may be present and need to be reordered.
|
||||||
Some(field_map) => {
|
Some(field_map) => {
|
||||||
|
@ -399,8 +401,37 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
|
||||||
&mut HashMap::new(),
|
&mut HashMap::new(),
|
||||||
self.hydrator,
|
self.hydrator,
|
||||||
);
|
);
|
||||||
|
|
||||||
match instantiated_constructor_type.deref() {
|
match instantiated_constructor_type.deref() {
|
||||||
Type::Fn { args, ret } => {
|
Type::Fn { args, ret } => {
|
||||||
|
if with_spread && has_no_fields {
|
||||||
|
if pattern_args.len() == args.len() {
|
||||||
|
return Err(Error::UnnecessarySpreadOperator {
|
||||||
|
location: Span {
|
||||||
|
start: location.end - 3,
|
||||||
|
end: location.end - 1,
|
||||||
|
},
|
||||||
|
arity: args.len(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
while pattern_args.len() < args.len() {
|
||||||
|
let location = Span {
|
||||||
|
start: location.end - 3,
|
||||||
|
end: location.end - 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
pattern_args.push(CallArg {
|
||||||
|
value: Pattern::Discard {
|
||||||
|
name: "_".to_string(),
|
||||||
|
location,
|
||||||
|
},
|
||||||
|
location,
|
||||||
|
label: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if args.len() == pattern_args.len() {
|
if args.len() == pattern_args.len() {
|
||||||
let pattern_args = pattern_args
|
let pattern_args = pattern_args
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
Loading…
Reference in New Issue