improve subtyping (#9614)

# Description

the current subtyping rule needs you to define the record entries in the
same order as declared in the annotation. this pr improves that

now
```nushell
{ name: 'Him', age: 12 } 

# ,

{ age: 100, name: 'It' }

# and

{ name: 'Red', age: 69, height: "5-8" }

# will all match

record<name: string, age: int>

# previously only the first one would match
```

however, something like

```nushell
{ name: 'Her' } # will not


# and

{ name: 'Car', wheels: 5 }
```

EDIT: applied JT's suggestion
This commit is contained in:
mike
2023-07-06 11:25:39 +03:00
committed by GitHub
parent 6c8adac0d9
commit 544c46e0e4
3 changed files with 43 additions and 10 deletions

View File

@ -7,16 +7,18 @@ use nu_protocol::{
pub fn type_compatible(lhs: &Type, rhs: &Type) -> bool {
// Structural subtyping
let is_compatible = |expected: &[(String, Type)], found: &[(String, Type)]| {
// the expected type is `any`
if expected.is_empty() {
true
} else if expected.len() != found.len() {
} else if expected.len() > found.len() {
false
} else {
expected
.iter()
.zip(found.iter())
.all(|(lhs, rhs)| lhs.0 == rhs.0 && type_compatible(&lhs.1, &rhs.1))
expected.iter().all(|(col_x, ty_x)| {
if let Some((_, ty_y)) = found.iter().find(|(col_y, _)| col_x == col_y) {
type_compatible(ty_x, ty_y)
} else {
false
}
})
}
};