Skip to content

Commit 91784bb

Browse files
committed
is this faster
1 parent 80136d8 commit 91784bb

File tree

3 files changed

+29
-30
lines changed

3 files changed

+29
-30
lines changed

crates/red_knot_python_semantic/resources/mdtest/exception/control_flow.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,9 @@ else:
455455
reveal_type(x) # revealed: slice
456456
finally:
457457
# TODO: should be `Literal[1] | str | bytes | bool | memoryview | float | range | slice`
458-
reveal_type(x) # revealed: bool | float | slice
458+
reveal_type(x) # revealed: bool | slice | float
459459

460-
reveal_type(x) # revealed: bool | float | slice
460+
reveal_type(x) # revealed: bool | slice | float
461461
```
462462

463463
## Nested `try`/`except` blocks
@@ -534,7 +534,7 @@ try:
534534
reveal_type(x) # revealed: slice
535535
finally:
536536
# TODO: should be `Literal[1] | str | bytes | bool | memoryview | float | range | slice`
537-
reveal_type(x) # revealed: bool | float | slice
537+
reveal_type(x) # revealed: bool | slice | float
538538
x = 2
539539
reveal_type(x) # revealed: Literal[2]
540540
reveal_type(x) # revealed: Literal[2]

crates/red_knot_python_semantic/resources/mdtest/narrow/truthiness.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,37 +11,37 @@ x = foo()
1111
if x:
1212
reveal_type(x) # revealed: Literal[-1, True, "foo", b"bar"]
1313
else:
14-
reveal_type(x) # revealed: Literal[0, False, "", b""] | None | tuple[()]
14+
reveal_type(x) # revealed: Literal[0, False, "", b""] | tuple[()] | None
1515

1616
if not x:
17-
reveal_type(x) # revealed: Literal[0, False, "", b""] | None | tuple[()]
17+
reveal_type(x) # revealed: Literal[0, False, "", b""] | tuple[()] | None
1818
else:
1919
reveal_type(x) # revealed: Literal[-1, True, "foo", b"bar"]
2020

2121
if x and not x:
2222
reveal_type(x) # revealed: Never
2323
else:
24-
reveal_type(x) # revealed: Literal[0, -1, "", "foo", b"", b"bar"] | bool | None | tuple[()]
24+
reveal_type(x) # revealed: Literal[0, -1, b"bar", "", "foo", b""] | bool | tuple[()] | None
2525

2626
if not (x and not x):
27-
reveal_type(x) # revealed: Literal[0, -1, "", "foo", b"", b"bar"] | bool | None | tuple[()]
27+
reveal_type(x) # revealed: Literal[0, -1, b"bar", "", "foo", b""] | bool | tuple[()] | None
2828
else:
2929
reveal_type(x) # revealed: Never
3030

3131
if x or not x:
32-
reveal_type(x) # revealed: Literal[0, -1, "", "foo", b"", b"bar"] | bool | None | tuple[()]
32+
reveal_type(x) # revealed: Literal[0, -1, b"bar", "", "foo", b""] | bool | tuple[()] | None
3333
else:
3434
reveal_type(x) # revealed: Never
3535

3636
if not (x or not x):
3737
reveal_type(x) # revealed: Never
3838
else:
39-
reveal_type(x) # revealed: Literal[0, -1, "", "foo", b"", b"bar"] | bool | None | tuple[()]
39+
reveal_type(x) # revealed: Literal[0, -1, b"bar", "", "foo", b""] | bool | tuple[()] | None
4040

4141
if (isinstance(x, int) or isinstance(x, str)) and x:
4242
reveal_type(x) # revealed: Literal[-1, True, "foo"]
4343
else:
44-
reveal_type(x) # revealed: Literal[b"", b"bar", 0, False, ""] | None | tuple[()]
44+
reveal_type(x) # revealed: tuple[()] | None | Literal[b"", b"bar", 0, False, ""]
4545
```
4646

4747
## Function Literals

crates/red_knot_python_semantic/src/types/builder.rs

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ use smallvec::SmallVec;
3333
pub(crate) struct UnionBuilder<'db> {
3434
elements: Vec<Type<'db>>,
3535
db: &'db dyn Db,
36+
contains_bool_literals: bool,
3637
}
3738

3839
impl<'db> UnionBuilder<'db> {
3940
pub(crate) fn new(db: &'db dyn Db) -> Self {
4041
Self {
4142
db,
4243
elements: vec![],
44+
contains_bool_literals: false,
4345
}
4446
}
4547

@@ -77,6 +79,7 @@ impl<'db> UnionBuilder<'db> {
7779
return self;
7880
}
7981
}
82+
self.contains_bool_literals |= ty.is_boolean_literal();
8083
match to_remove[..] {
8184
[] => self.elements.push(ty),
8285
[index] => self.elements[index] = ty,
@@ -103,34 +106,30 @@ impl<'db> UnionBuilder<'db> {
103106
}
104107

105108
pub(crate) fn build(self) -> Type<'db> {
106-
let UnionBuilder { elements, db } = self;
109+
let UnionBuilder {
110+
mut elements,
111+
db,
112+
contains_bool_literals,
113+
} = self;
107114

108115
match elements.len() {
109116
0 => Type::Never,
110117
1 => elements[0],
111118
_ => {
112-
let mut normalized_elements = Vec::with_capacity(elements.len());
113-
let mut first_bool_literal_pos = None;
114-
let mut seen_two_bool_literals = false;
115-
for (i, element) in elements.into_iter().enumerate() {
116-
if element.is_boolean_literal() {
117-
if first_bool_literal_pos.is_none() {
118-
first_bool_literal_pos = Some(i);
119-
} else {
120-
seen_two_bool_literals = true;
121-
continue;
119+
if contains_bool_literals {
120+
let mut element_iter = elements.iter();
121+
if let Some(first_pos) = element_iter.position(Type::is_boolean_literal) {
122+
if let Some(second_pos) = element_iter.position(Type::is_boolean_literal) {
123+
let bool_instance = KnownClass::Bool.to_instance(db);
124+
if elements.len() == 2 {
125+
return bool_instance;
126+
}
127+
elements.swap_remove(first_pos + second_pos + 1);
128+
elements[first_pos] = bool_instance;
122129
}
123130
}
124-
normalized_elements.push(element);
125-
}
126-
if let (Some(pos), true) = (first_bool_literal_pos, seen_two_bool_literals) {
127-
// If we have two boolean literals, we can merge them to `bool`.
128-
if normalized_elements.len() == 1 {
129-
return KnownClass::Bool.to_instance(db);
130-
}
131-
normalized_elements[pos] = KnownClass::Bool.to_instance(db);
132131
}
133-
Type::Union(UnionType::new(db, normalized_elements.into_boxed_slice()))
132+
Type::Union(UnionType::new(db, elements.into_boxed_slice()))
134133
}
135134
}
136135
}

0 commit comments

Comments
 (0)