Repository: astral-sh/ruff
File: crates/ty_python_semantic/src/types/builder.rs (Rust)

Code before:
            }
        }
    }

    fn push_type(&mut self, ty: Type<'db>, seen_aliases: &mut Vec<Type<'db>>) {
        let bool_pair = if let Type::BooleanLiteral(b) = ty {
            Some(Type::BooleanLiteral(!b))
        } else {
            None
        };

        // If an alias gets here, it means we aren't unpacking aliases, and we also
        // shouldn't try to simplify aliases out of the union, because that will require
        // unpacking them.
        let should_simplify_full = !matches!(ty, Type::TypeAlias(_)) && !self.cycle_recovery;

        let mut ty_negated: Option<Type> = None;

        let mut i = 0;
        let mut insertion_point: Option<usize> = None;

        let mut remove_or_replace = |i: usize, elements: &mut Vec<UnionElement<'db>>| {
            if insertion_point.is_none() {
                insertion_point = Some(i);
            } else {
                elements.swap_remove(i);
            }
        };

        while i < self.elements.len() {
            let element = &mut self.elements[i];

            let element_type = match element.try_reduce(self.db, ty) {
                ReduceResult::KeepIf(keep) => {
                    if !keep {
                        remove_or_replace(i, &mut self.elements);
                    }
                    i += 1;
                    continue;
                }
                ReduceResult::Type(ty) => ty,
                ReduceResult::CollapseToObject => {
                    self.collapse_to_object();
                    return;
                }
                ReduceResult::Ignore => {
                    return;
                }
            };

            if ty == element_type {

Review comment (suggestion):
Unlike before, the new implementation removes redundant elements before we decided if we want to add `ty`. 

I think this might be okay because we only early-exit if the type is redundant with any existing type and, if that's the case, then the element that would be removed here must have been redundant too? But not feeling a 100% sure about this

Code after:
                {
                    self.push_type(Type::EnumLiteral(enum_member_to_add), seen_aliases);
                }
            }
            // Adding `object` to a union results in `object`.
            ty if ty.is_object() => {
                self.collapse_to_object();
            }
            _ => {
                self.push_type(ty, seen_aliases);
            }
        }
    }

    fn push_type(&mut self, ty: Type<'db>, seen_aliases: &mut Vec<Type<'db>>) {
        let bool_pair = if let Type::BooleanLiteral(b) = ty {
            Some(Type::BooleanLiteral(!b))
        } else {
            None
        };

        // If an alias gets here, it means we aren't unpacking aliases, and we also
        // shouldn't try to simplify aliases out of the union, because that will require
        // unpacking them.
        let should_simplify_full = !matches!(ty, Type::TypeAlias(_)) && !self.cycle_recovery;

        let mut ty_negated: Option<Type> = None;
        let mut to_remove = SmallVec::<[usize; 2]>::new();

        for (i, element) in self.elements.iter_mut().enumerate() {
            let element_type = match element.try_reduce(self.db, ty) {
                ReduceResult::KeepIf(keep) => {
                    if !keep {
                        to_remove.push(i);
                    }
                    continue;
                }
                ReduceResult::Type(ty) => ty,
                ReduceResult::CollapseToObject => {
                    self.collapse_to_object();
                    return;
                }
                ReduceResult::Ignore => {
                    return;
                }
            };

            if ty == element_type {
                return;
            }