Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[red-knot] flatten unions #11783

Merged
merged 3 commits into from
Jun 6, 2024
Merged

[red-knot] flatten unions #11783

merged 3 commits into from
Jun 6, 2024

Conversation

carljm
Copy link
Contributor

@carljm carljm commented Jun 6, 2024

Flatten union types. Fixes #11781

@carljm carljm requested a review from MichaReiser as a code owner June 6, 2024 21:00
@carljm carljm added the red-knot Multi-file analysis & type inference label Jun 6, 2024
@carljm carljm requested a review from AlexWaygood June 6, 2024 21:01
Copy link
Contributor

github-actions bot commented Jun 6, 2024

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

crates/red_knot/src/semantic/types/infer.rs Show resolved Hide resolved
crates/red_knot/src/semantic/types.rs Outdated Show resolved Hide resolved
crates/red_knot/src/semantic/types.rs Outdated Show resolved Hide resolved
@carljm carljm merged commit b2fc0df into main Jun 6, 2024
20 checks passed
@carljm carljm deleted the cjm/ifexpr branch June 6, 2024 22:13
@AlexWaygood
Copy link
Member

AlexWaygood commented Jun 7, 2024

I managed to get the elements() method working without any .collect() calls, if you're interested:

diff --git a/crates/red_knot/src/semantic/types.rs b/crates/red_knot/src/semantic/types.rs
index 360b157c5..ae866e00c 100644
--- a/crates/red_knot/src/semantic/types.rs
+++ b/crates/red_knot/src/semantic/types.rs
@@ -1,4 +1,6 @@
 #![allow(dead_code)]
+use std::iter::FusedIterator;
+
 use crate::ast_ids::NodeKey;
 use crate::db::{QueryResult, SemanticDb, SemanticJar};
 use crate::files::FileId;
@@ -531,12 +533,41 @@ pub struct UnionTypeId {
 }
 
 impl UnionTypeId {
-    pub fn elements(self, type_store: &TypeStore) -> Vec<Type> {
+    pub fn elements(self, type_store: &TypeStore) -> UnionElementsIterator {
         let union = type_store.get_union(self);
-        union.elements.iter().copied().collect()
+        UnionElementsIterator { union, index: 0 }
     }
 }
 
+pub struct UnionElementsIterator<'a> {
+    union: UnionTypeRef<'a>,
+    index: usize,
+}
+
+impl<'a> Iterator for UnionElementsIterator<'a> {
+    type Item = Type;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let item = self.union.elements.get_index(self.index).copied();
+        self.index += 1;
+        item
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let size = self.union.elements.len() - self.index;
+        (size, Some(size))
+    }
+
+    fn last(self) -> Option<Self::Item> {
+        self.union.elements.last().copied()
+    }
+}
+
+impl<'a> FusedIterator for UnionElementsIterator<'a> {}
+impl<'a> ExactSizeIterator for UnionElementsIterator<'a> {}

A bit more verbose, but maybe worth it if we'll be iterating over union elements a lot? WDYT?

@carljm
Copy link
Contributor Author

carljm commented Jun 7, 2024

Yeah, I think that's probably worth it! I knew this type of borrowing iterator was an option, but at the time I was being stubborn about trying to get it working with flat_map, which requires that the returned iterator own its items, meaning this type of iterator wouldn't work for that. But now that we aren't using flat_map to flatten anyway, this would work fine.

We should do the same for IntersectionPositiveIterator and IntersectionNegativeIterator as well.

I think this is something that can wait until post-Salsa, though; no need to introduce more PRs right now for Micha to port.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
red-knot Multi-file analysis & type inference
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[red-knot] flatten union types
2 participants