From 2e48ba3e177a45d1ae02c179f7556ef13159de76 Mon Sep 17 00:00:00 2001 From: snowapril Date: Wed, 27 Oct 2021 15:25:01 +0900 Subject: [PATCH] fix `make_parameters` in `GenericAlias` make_parameters must not push duplicated parameters as cpython implementation. See `tuple_add` function of `genericaliasobject.c` in cpython code https://github.com/python/cpython/blob/main/Objects/genericaliasobject.c#L191 Signed-off-by: snowapril --- vm/src/builtins/genericalias.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/vm/src/builtins/genericalias.rs b/vm/src/builtins/genericalias.rs index f96ca9d55..b91e41a97 100644 --- a/vm/src/builtins/genericalias.rs +++ b/vm/src/builtins/genericalias.rs @@ -175,20 +175,25 @@ fn is_typevar(obj: &PyObjectRef) -> bool { } fn make_parameters(args: &PyTupleRef, vm: &VirtualMachine) -> PyTupleRef { - let mut parameters: Vec = vec![]; + let mut parameters: Vec = Vec::with_capacity(args.len()); for arg in args.as_slice() { if is_typevar(arg) { - parameters.push(arg.clone()); - } else if let Ok(tuple) = arg + if !parameters.iter().any(|param| param.is(arg)) { + parameters.push(arg.clone()); + } + } else if let Ok(subparams) = arg .clone() .get_attr("__parameters__", vm) .and_then(|obj| PyTupleRef::try_from_object(vm, obj)) { - for subparam in tuple.as_slice() { - parameters.push(subparam.clone()); + for subparam in subparams.as_slice() { + if !parameters.iter().any(|param| param.is(subparam)) { + parameters.push(subparam.clone()); + } } } } + parameters.shrink_to_fit(); PyTuple::new_ref(parameters, &vm.ctx) }