-
Notifications
You must be signed in to change notification settings - Fork 305
fix Preserve arity for tuple literals with * #2861 #2888
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,7 @@ use crate::alt::answers::LookupAnswer; | |
| use crate::alt::answers_solver::AnswersSolver; | ||
| use crate::alt::call::CallStyle; | ||
| use crate::alt::callable::CallArg; | ||
| use crate::alt::expr::MAX_TUPLE_LENGTH; | ||
| use crate::alt::unwrap::HintRef; | ||
| use crate::binding::binding::KeyAnnotation; | ||
| use crate::config::error_kind::ErrorKind; | ||
|
|
@@ -315,6 +316,42 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> { | |
| } | ||
| } | ||
|
|
||
| fn try_tuple_repeat(&self, lhs: &Type, rhs: &Type) -> Option<Type> { | ||
| let repeat_count = |ty: &Type| match ty { | ||
| Type::Literal(box Literal { | ||
| value: Lit::Int(n), .. | ||
| }) => n.as_i64(), | ||
| _ => None, | ||
| }; | ||
| let (tuple, repeats) = match (lhs, rhs) { | ||
| (Type::Tuple(tuple), rhs) => (tuple, repeat_count(rhs)?), | ||
| (lhs, Type::Tuple(tuple)) => (tuple, repeat_count(lhs)?), | ||
| _ => return None, | ||
| }; | ||
| if repeats <= 0 { | ||
| return Some(self.heap.mk_concrete_tuple(Vec::new())); | ||
| } | ||
| if repeats == 1 { | ||
| return Some(self.heap.mk_tuple(tuple.clone())); | ||
| } | ||
| let repeats = usize::try_from(repeats).ok()?; | ||
| match tuple { | ||
| Tuple::Concrete(elements) => { | ||
| let total_len = elements.len().checked_mul(repeats)?; | ||
| if total_len > MAX_TUPLE_LENGTH { | ||
| return None; | ||
| } | ||
| let mut repeated = Vec::with_capacity(total_len); | ||
| for _ in 0..repeats { | ||
| repeated.extend(elements.iter().cloned()); | ||
| } | ||
| Some(self.heap.mk_concrete_tuple(repeated)) | ||
| } | ||
| Tuple::Unbounded(element) => Some(self.heap.mk_unbounded_tuple((**element).clone())), | ||
| Tuple::Unpacked(_) => None, | ||
| } | ||
| } | ||
|
|
||
| pub fn binop_infer( | ||
| &self, | ||
| x: &ExprBinOp, | ||
|
|
@@ -405,6 +442,10 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> { | |
| && let Type::Tuple(r) = rhs | ||
| { | ||
| self.tuple_concat(l, r) | ||
| } else if x.op == Operator::Mult | ||
| && let Some(result) = self.try_tuple_repeat(lhs, rhs) | ||
| { | ||
| result | ||
|
Comment on lines
444
to
+448
|
||
| } else if matches!( | ||
| x.op, | ||
| Operator::Add | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try_tuple_repeatonly recognizesLiteral[int]as the repeat count. In Python,boolis a subtype ofintandtuple * True/Falseis valid; right now those cases will fall through to the generic__mul__typing and won't preserve arity. Consider extracting the count viaLiteral.value.as_index_i64()(covers bothIntandBool) instead of matching onlyLit::Int.