1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use crate::enums::relation::Relation;
use crate::functions::relate_simplify::relate;
use crate::records::property_type::Property;
use crate::records::table_type::TableType;
use crate::type_aliases::simplifier_seen_set::SimplifierSeenSet;
/// @return The relationship between the single property on the right and its corresponding property
/// in the left table.
pub fn relate_table_to_prop(
left_table: &TableType,
prop_name: &str,
right_prop: &Property,
seen: &mut SimplifierSeenSet,
) -> Relation {
// If the left table does not have the property at all,
// assume an intersection.
let left_prop = match left_table.props.get(prop_name) {
Some(p) => p,
None => return Relation::Intersects,
};
if left_prop.is_shared() && right_prop.is_shared() {
match relate(
left_prop.read_ty.unwrap(),
right_prop.read_ty.unwrap(),
seen,
) {
// The two read properties are disjoint, so the tables are disjoint, e.g.:
//
// { y: string, x: number? } & { read x: string }
//
Relation::Disjoint => Relation::Disjoint,
Relation::Coincident => Relation::Coincident,
// For _all_ other cases, two shared properties indicate a non-empty intersection.
//
// Subset: { y: string, x: number } & { x: number? } (widened write type)
// Superset: { y: string, x: number? } & { x: number } (narrowed read type)
// Intersects: { y: string, x: number? } & { x: string? } (both)
Relation::Subset | Relation::Superset | Relation::Intersects => Relation::Intersects,
}
} else {
// Otherwise we want to hard match on the case of:
//
// { ..., x: T } & { read x: U }
//
// ... or ...
//
// { ..., read x: T } & { read x: U }
//
// We will use the relation between T and U here.
if left_prop.read_ty.is_none() || !right_prop.is_read_only() {
return Relation::Intersects;
}
match relate(
left_prop.read_ty.unwrap(),
right_prop.read_ty.unwrap(),
seen,
) {
// The two read properties are disjoint, so the tables are disjoint, e.g.:
//
// { y: string, x: number? } & { read x: string }
//
Relation::Disjoint => Relation::Disjoint,
// If the two read types are coincident, then the left property is a
// subset if it also has a write part.
Relation::Coincident => {
if left_prop.write_ty.is_some() {
Relation::Subset
} else {
Relation::Coincident
}
}
// If the left table's property is a subset of the right property, then
// the left table is a subset, as in:
//
// { y: string, x: number } & { read x: number? } => these tables intersect
Relation::Subset => Relation::Subset,
// If the left table's property is a superset of the right property, then
// the two tables intersect, as in:
//
// { y: string, x: number? } & { read x: number }
//
Relation::Superset => Relation::Intersects,
// If the left table's property intersects with the right property, then
// the two tables intersect, as in:
//
// { y: string, x: number? } & { read x: string? } => these tables intersect
Relation::Intersects => Relation::Intersects,
}
}
}