Merge pull request #4616 from roc-lang/fix-pattern-equivalent

Fix missing cases in Pattern::equivalent
This commit is contained in:
Richard Feldman 2022-11-30 12:10:09 -05:00 committed by GitHub
commit a0bc105ca8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -773,69 +773,173 @@ impl<'a> Pattern<'a> {
pub fn equivalent(&self, other: &Self) -> bool { pub fn equivalent(&self, other: &Self) -> bool {
use Pattern::*; use Pattern::*;
match (self, other) { match other {
(Identifier(x), Identifier(y)) => x == y, SpaceBefore(y, _) | SpaceAfter(y, _) => {
(Tag(x), Tag(y)) => x == y, return self.equivalent(y);
(Apply(constructor_x, args_x), Apply(constructor_y, args_y)) => { }
let equivalent_args = args_x _ => {}
.iter() }
.zip(args_y.iter())
.all(|(p, q)| p.value.equivalent(&q.value));
constructor_x.value.equivalent(&constructor_y.value) && equivalent_args match self {
Tag(x) => {
if let Tag(y) = other {
x == y
} else {
false
}
} }
(RecordDestructure(fields_x), RecordDestructure(fields_y)) => fields_x Apply(constructor_x, args_x) => {
.iter() if let Apply(constructor_y, args_y) = other {
.zip(fields_y.iter()) let equivalent_args = args_x
.all(|(p, q)| p.value.equivalent(&q.value)), .iter()
(RequiredField(x, inner_x), RequiredField(y, inner_y)) => { .zip(args_y.iter())
x == y && inner_x.value.equivalent(&inner_y.value) .all(|(p, q)| p.value.equivalent(&q.value));
constructor_x.value.equivalent(&constructor_y.value) && equivalent_args
} else {
false
}
} }
(OptionalField(x, _), OptionalField(y, _)) RecordDestructure(fields_x) => {
| (OptionalField(x, _), Identifier(y)) if let RecordDestructure(fields_y) = other {
| (Identifier(x), OptionalField(y, _)) => { fields_x
// optional record fields can be annotated as: .iter()
// { x, y } : { x : Int, y ? Bool } .zip(fields_y.iter())
// { x, y ? False } = rec .all(|(p, q)| p.value.equivalent(&q.value))
x == y } else {
false
}
} }
// Literal RequiredField(x, inner_x) => {
(NumLiteral(x), NumLiteral(y)) => x == y, if let RequiredField(y, inner_y) = other {
( x == y && inner_x.value.equivalent(&inner_y.value)
NonBase10Literal { } else {
string: string_x, false
base: base_x, }
is_negative: is_negative_x, }
},
NonBase10Literal { // optional record fields can be annotated as:
// { x, y } : { x : Int, y ? Bool }
// { x, y ? False } = rec
OptionalField(x, _) => match other {
Identifier(y) | OptionalField(y, _) => x == y,
_ => false,
},
Identifier(x) => match other {
Identifier(y) | OptionalField(y, _) => x == y,
_ => false,
},
NumLiteral(x) => {
if let NumLiteral(y) = other {
x == y
} else {
false
}
}
NonBase10Literal {
string: string_x,
base: base_x,
is_negative: is_negative_x,
} => {
if let NonBase10Literal {
string: string_y, string: string_y,
base: base_y, base: base_y,
is_negative: is_negative_y, is_negative: is_negative_y,
}, } = other
) => string_x == string_y && base_x == base_y && is_negative_x == is_negative_y, {
(FloatLiteral(x), FloatLiteral(y)) => x == y, string_x == string_y && base_x == base_y && is_negative_x == is_negative_y
(StrLiteral(x), StrLiteral(y)) => x == y, } else {
(Underscore(x), Underscore(y)) => x == y, false
}
// Space }
(SpaceBefore(x, _), SpaceBefore(y, _)) => x.equivalent(y), FloatLiteral(x) => {
(SpaceAfter(x, _), SpaceAfter(y, _)) => x.equivalent(y), if let FloatLiteral(y) = other {
x == y
// Malformed } else {
(Malformed(x), Malformed(y)) => x == y, false
( }
QualifiedIdentifier { }
module_name: a, StrLiteral(x) => {
ident: x, if let StrLiteral(y) = other {
}, x == y
QualifiedIdentifier { } else {
false
}
}
Underscore(x) => {
if let Underscore(y) = other {
x == y
} else {
false
}
}
SpaceBefore(x, _) | SpaceAfter(x, _) => match other {
SpaceBefore(y, _) | SpaceAfter(y, _) => x.equivalent(y),
y => x.equivalent(y),
},
Malformed(x) => {
if let Malformed(y) = other {
x == y
} else {
false
}
}
QualifiedIdentifier {
module_name: a,
ident: x,
} => {
if let QualifiedIdentifier {
module_name: b, module_name: b,
ident: y, ident: y,
}, } = other
) => (a == b) && (x == y), {
a == b && x == y
// Different constructors } else {
_ => false, false
}
}
OpaqueRef(a) => {
if let OpaqueRef(b) = other {
a == b
} else {
false
}
}
SingleQuote(a) => {
if let SingleQuote(b) = other {
a == b
} else {
false
}
}
Tuple(items_x) => {
if let Tuple(items_y) = other {
items_x
.iter()
.zip(items_y.iter())
.all(|(p, q)| p.value.equivalent(&q.value))
} else {
false
}
}
List(items_x) => {
if let List(items_y) = other {
items_x
.iter()
.zip(items_y.iter())
.all(|(p, q)| p.value.equivalent(&q.value))
} else {
false
}
}
ListRest => matches!(other, ListRest),
MalformedIdent(str_x, _) => {
if let MalformedIdent(str_y, _) = other {
str_x == str_y
} else {
false
}
}
} }
} }
} }