mirror of
				https://github.com/astral-sh/ruff.git
				synced 2025-11-03 21:24:29 +00:00 
			
		
		
		
	[ty] Remove special casing for tuple addition (#19636)
	
		
			
	
		
	
	
		
	
		
			Some checks are pending
		
		
	
	
		
			
				
	
				CI / Determine changes (push) Waiting to run
				
			
		
			
				
	
				CI / cargo fmt (push) Waiting to run
				
			
		
			
				
	
				CI / cargo clippy (push) Blocked by required conditions
				
			
		
			
				
	
				CI / cargo test (linux) (push) Blocked by required conditions
				
			
		
			
				
	
				CI / cargo test (linux, release) (push) Blocked by required conditions
				
			
		
			
				
	
				CI / cargo test (windows) (push) Blocked by required conditions
				
			
		
			
				
	
				CI / cargo test (wasm) (push) Blocked by required conditions
				
			
		
			
				
	
				CI / cargo build (release) (push) Waiting to run
				
			
		
			
				
	
				CI / cargo build (msrv) (push) Blocked by required conditions
				
			
		
			
				
	
				CI / cargo fuzz build (push) Blocked by required conditions
				
			
		
			
				
	
				CI / fuzz parser (push) Blocked by required conditions
				
			
		
			
				
	
				CI / test scripts (push) Blocked by required conditions
				
			
		
			
				
	
				CI / ecosystem (push) Blocked by required conditions
				
			
		
			
				
	
				CI / Fuzz for new ty panics (push) Blocked by required conditions
				
			
		
			
				
	
				CI / cargo shear (push) Blocked by required conditions
				
			
		
			
				
	
				CI / python package (push) Waiting to run
				
			
		
			
				
	
				CI / pre-commit (push) Waiting to run
				
			
		
			
				
	
				CI / mkdocs (push) Waiting to run
				
			
		
			
				
	
				CI / formatter instabilities and black similarity (push) Blocked by required conditions
				
			
		
			
				
	
				CI / test ruff-lsp (push) Blocked by required conditions
				
			
		
			
				
	
				CI / check playground (push) Blocked by required conditions
				
			
		
			
				
	
				CI / benchmarks-instrumented (push) Blocked by required conditions
				
			
		
			
				
	
				CI / benchmarks-walltime (push) Blocked by required conditions
				
			
		
			
				
	
				[ty Playground] Release / publish (push) Waiting to run
				
			
		
		
	
	
				
					
				
			
		
			Some checks are pending
		
		
	
	CI / Determine changes (push) Waiting to run
				
			CI / cargo fmt (push) Waiting to run
				
			CI / cargo clippy (push) Blocked by required conditions
				
			CI / cargo test (linux) (push) Blocked by required conditions
				
			CI / cargo test (linux, release) (push) Blocked by required conditions
				
			CI / cargo test (windows) (push) Blocked by required conditions
				
			CI / cargo test (wasm) (push) Blocked by required conditions
				
			CI / cargo build (release) (push) Waiting to run
				
			CI / cargo build (msrv) (push) Blocked by required conditions
				
			CI / cargo fuzz build (push) Blocked by required conditions
				
			CI / fuzz parser (push) Blocked by required conditions
				
			CI / test scripts (push) Blocked by required conditions
				
			CI / ecosystem (push) Blocked by required conditions
				
			CI / Fuzz for new ty panics (push) Blocked by required conditions
				
			CI / cargo shear (push) Blocked by required conditions
				
			CI / python package (push) Waiting to run
				
			CI / pre-commit (push) Waiting to run
				
			CI / mkdocs (push) Waiting to run
				
			CI / formatter instabilities and black similarity (push) Blocked by required conditions
				
			CI / test ruff-lsp (push) Blocked by required conditions
				
			CI / check playground (push) Blocked by required conditions
				
			CI / benchmarks-instrumented (push) Blocked by required conditions
				
			CI / benchmarks-walltime (push) Blocked by required conditions
				
			[ty Playground] Release / publish (push) Waiting to run
				
			This commit is contained in:
		
							parent
							
								
									38049aae12
								
							
						
					
					
						commit
						7b4103bcb6
					
				
					 6 changed files with 58 additions and 29 deletions
				
			
		| 
						 | 
					@ -351,6 +351,41 @@ fn benchmark_many_tuple_assignments(criterion: &mut Criterion) {
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn benchmark_tuple_implicit_instance_attributes(criterion: &mut Criterion) {
 | 
				
			||||||
 | 
					    setup_rayon();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    criterion.bench_function("ty_micro[many_tuple_assignments]", |b| {
 | 
				
			||||||
 | 
					        b.iter_batched_ref(
 | 
				
			||||||
 | 
					            || {
 | 
				
			||||||
 | 
					                // This is a regression benchmark for a case that used to hang:
 | 
				
			||||||
 | 
					                // https://github.com/astral-sh/ty/issues/765
 | 
				
			||||||
 | 
					                setup_micro_case(
 | 
				
			||||||
 | 
					                    r#"
 | 
				
			||||||
 | 
					                    from typing import Any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    class A:
 | 
				
			||||||
 | 
					                        foo: tuple[Any, ...]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    class B(A):
 | 
				
			||||||
 | 
					                        def __init__(self, parent: "C", x: tuple[Any]):
 | 
				
			||||||
 | 
					                            self.foo = parent.foo + x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    class C(A):
 | 
				
			||||||
 | 
					                        def __init__(self, parent: B, x: tuple[Any]):
 | 
				
			||||||
 | 
					                            self.foo = parent.foo + x
 | 
				
			||||||
 | 
					                    "#,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            |case| {
 | 
				
			||||||
 | 
					                let Case { db, .. } = case;
 | 
				
			||||||
 | 
					                let result = db.check();
 | 
				
			||||||
 | 
					                assert_eq!(result.len(), 0);
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            BatchSize::SmallInput,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn benchmark_complex_constrained_attributes_1(criterion: &mut Criterion) {
 | 
					fn benchmark_complex_constrained_attributes_1(criterion: &mut Criterion) {
 | 
				
			||||||
    setup_rayon();
 | 
					    setup_rayon();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -630,6 +665,7 @@ criterion_group!(
 | 
				
			||||||
    micro,
 | 
					    micro,
 | 
				
			||||||
    benchmark_many_string_assignments,
 | 
					    benchmark_many_string_assignments,
 | 
				
			||||||
    benchmark_many_tuple_assignments,
 | 
					    benchmark_many_tuple_assignments,
 | 
				
			||||||
 | 
					    benchmark_tuple_implicit_instance_attributes,
 | 
				
			||||||
    benchmark_complex_constrained_attributes_1,
 | 
					    benchmark_complex_constrained_attributes_1,
 | 
				
			||||||
    benchmark_complex_constrained_attributes_2,
 | 
					    benchmark_complex_constrained_attributes_2,
 | 
				
			||||||
    benchmark_many_enum_members,
 | 
					    benchmark_many_enum_members,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@ reveal_type(x)  # revealed: int | float
 | 
				
			||||||
 | 
					
 | 
				
			||||||
x = (1, 2)
 | 
					x = (1, 2)
 | 
				
			||||||
x += (3, 4)
 | 
					x += (3, 4)
 | 
				
			||||||
reveal_type(x)  # revealed: tuple[Literal[1], Literal[2], Literal[3], Literal[4]]
 | 
					reveal_type(x)  # revealed: tuple[Literal[1, 2, 3, 4], ...]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Dunder methods
 | 
					## Dunder methods
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,14 +3,14 @@
 | 
				
			||||||
## Concatenation for heterogeneous tuples
 | 
					## Concatenation for heterogeneous tuples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```py
 | 
					```py
 | 
				
			||||||
reveal_type((1, 2) + (3, 4))  # revealed: tuple[Literal[1], Literal[2], Literal[3], Literal[4]]
 | 
					reveal_type((1, 2) + (3, 4))  # revealed: tuple[Literal[1, 2, 3, 4], ...]
 | 
				
			||||||
reveal_type(() + (1, 2))  # revealed: tuple[Literal[1], Literal[2]]
 | 
					reveal_type(() + (1, 2))  # revealed: tuple[Literal[1, 2], ...]
 | 
				
			||||||
reveal_type((1, 2) + ())  # revealed: tuple[Literal[1], Literal[2]]
 | 
					reveal_type((1, 2) + ())  # revealed: tuple[Literal[1, 2], ...]
 | 
				
			||||||
reveal_type(() + ())  # revealed: tuple[()]
 | 
					reveal_type(() + ())  # revealed: tuple[()]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _(x: tuple[int, str], y: tuple[None, tuple[int]]):
 | 
					def _(x: tuple[int, str], y: tuple[None, tuple[int]]):
 | 
				
			||||||
    reveal_type(x + y)  # revealed: tuple[int, str, None, tuple[int]]
 | 
					    reveal_type(x + y)  # revealed: tuple[int | str | None | tuple[int], ...]
 | 
				
			||||||
    reveal_type(y + x)  # revealed: tuple[None, tuple[int], int, str]
 | 
					    reveal_type(y + x)  # revealed: tuple[None | tuple[int] | int | str, ...]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Concatenation for homogeneous tuples
 | 
					## Concatenation for homogeneous tuples
 | 
				
			||||||
| 
						 | 
					@ -19,10 +19,10 @@ def _(x: tuple[int, str], y: tuple[None, tuple[int]]):
 | 
				
			||||||
def _(x: tuple[int, ...], y: tuple[str, ...]):
 | 
					def _(x: tuple[int, ...], y: tuple[str, ...]):
 | 
				
			||||||
    reveal_type(x + x)  # revealed: tuple[int, ...]
 | 
					    reveal_type(x + x)  # revealed: tuple[int, ...]
 | 
				
			||||||
    reveal_type(x + y)  # revealed: tuple[int | str, ...]
 | 
					    reveal_type(x + y)  # revealed: tuple[int | str, ...]
 | 
				
			||||||
    reveal_type((1, 2) + x)  # revealed: tuple[Literal[1], Literal[2], *tuple[int, ...]]
 | 
					    reveal_type((1, 2) + x)  # revealed: tuple[int, ...]
 | 
				
			||||||
    reveal_type(x + (3, 4))  # revealed: tuple[*tuple[int, ...], Literal[3], Literal[4]]
 | 
					    reveal_type(x + (3, 4))  # revealed: tuple[int, ...]
 | 
				
			||||||
    reveal_type((1, 2) + x + (3, 4))  # revealed: tuple[Literal[1], Literal[2], *tuple[int, ...], Literal[3], Literal[4]]
 | 
					    reveal_type((1, 2) + x + (3, 4))  # revealed: tuple[int, ...]
 | 
				
			||||||
    reveal_type((1, 2) + y + (3, 4) + x)  # revealed: tuple[Literal[1], Literal[2], *tuple[int | str, ...]]
 | 
					    reveal_type((1, 2) + y + (3, 4) + x)  # revealed: tuple[int | str, ...]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
We get the same results even when we use a legacy type alias, even though this involves first
 | 
					We get the same results even when we use a legacy type alias, even though this involves first
 | 
				
			||||||
| 
						 | 
					@ -41,8 +41,8 @@ StrTuple = tuple[str, ...]
 | 
				
			||||||
def _(one_two: OneTwo, x: IntTuple, y: StrTuple, three_four: ThreeFour):
 | 
					def _(one_two: OneTwo, x: IntTuple, y: StrTuple, three_four: ThreeFour):
 | 
				
			||||||
    reveal_type(x + x)  # revealed: tuple[int, ...]
 | 
					    reveal_type(x + x)  # revealed: tuple[int, ...]
 | 
				
			||||||
    reveal_type(x + y)  # revealed: tuple[int | str, ...]
 | 
					    reveal_type(x + y)  # revealed: tuple[int | str, ...]
 | 
				
			||||||
    reveal_type(one_two + x)  # revealed: tuple[Literal[1], Literal[2], *tuple[int, ...]]
 | 
					    reveal_type(one_two + x)  # revealed: tuple[int, ...]
 | 
				
			||||||
    reveal_type(x + three_four)  # revealed: tuple[*tuple[int, ...], Literal[3], Literal[4]]
 | 
					    reveal_type(x + three_four)  # revealed: tuple[int, ...]
 | 
				
			||||||
    reveal_type(one_two + x + three_four)  # revealed: tuple[Literal[1], Literal[2], *tuple[int, ...], Literal[3], Literal[4]]
 | 
					    reveal_type(one_two + x + three_four)  # revealed: tuple[int, ...]
 | 
				
			||||||
    reveal_type(one_two + y + three_four + x)  # revealed: tuple[Literal[1], Literal[2], *tuple[int | str, ...]]
 | 
					    reveal_type(one_two + y + three_four + x)  # revealed: tuple[int | str, ...]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -122,15 +122,14 @@ class A:
 | 
				
			||||||
    __slots__ = ()
 | 
					    __slots__ = ()
 | 
				
			||||||
    __slots__ += ("a", "b")
 | 
					    __slots__ += ("a", "b")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
reveal_type(A.__slots__)  # revealed: tuple[Literal["a"], Literal["b"]]
 | 
					reveal_type(A.__slots__)  # revealed: tuple[Literal["a", "b"], ...]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class B:
 | 
					class B:
 | 
				
			||||||
    __slots__ = ("c", "d")
 | 
					    __slots__ = ("c", "d")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class C(  # error: [instance-layout-conflict]
 | 
					# TODO: ideally this would trigger `[instance-layout-conflict]`
 | 
				
			||||||
    A,
 | 
					# (but it's also not high-priority)
 | 
				
			||||||
    B,
 | 
					class C(A, B): ...
 | 
				
			||||||
): ...
 | 
					 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Explicitly annotated `__slots__`
 | 
					## Explicitly annotated `__slots__`
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -240,9 +240,7 @@ def homogeneous(t: tuple[str, ...]) -> None:
 | 
				
			||||||
    reveal_type(t[-3])  # revealed: str
 | 
					    reveal_type(t[-3])  # revealed: str
 | 
				
			||||||
    reveal_type(t[-4])  # revealed: str
 | 
					    reveal_type(t[-4])  # revealed: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def mixed(s: tuple[str, ...]) -> None:
 | 
					def mixed(t: tuple[Literal[1], Literal[2], Literal[3], *tuple[str, ...], Literal[8], Literal[9], Literal[10]]) -> None:
 | 
				
			||||||
    t = (1, 2, 3) + s + (8, 9, 10)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    reveal_type(t[0])  # revealed: Literal[1]
 | 
					    reveal_type(t[0])  # revealed: Literal[1]
 | 
				
			||||||
    reveal_type(t[1])  # revealed: Literal[2]
 | 
					    reveal_type(t[1])  # revealed: Literal[2]
 | 
				
			||||||
    reveal_type(t[2])  # revealed: Literal[3]
 | 
					    reveal_type(t[2])  # revealed: Literal[3]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7061,8 +7061,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
 | 
				
			||||||
            // the result would then become Any or Unknown, respectively).
 | 
					            // the result would then become Any or Unknown, respectively).
 | 
				
			||||||
            (any @ Type::Dynamic(DynamicType::Any), _, _)
 | 
					            (any @ Type::Dynamic(DynamicType::Any), _, _)
 | 
				
			||||||
            | (_, any @ Type::Dynamic(DynamicType::Any), _) => Some(any),
 | 
					            | (_, any @ Type::Dynamic(DynamicType::Any), _) => Some(any),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            (unknown @ Type::Dynamic(DynamicType::Unknown), _, _)
 | 
					            (unknown @ Type::Dynamic(DynamicType::Unknown), _, _)
 | 
				
			||||||
            | (_, unknown @ Type::Dynamic(DynamicType::Unknown), _) => Some(unknown),
 | 
					            | (_, unknown @ Type::Dynamic(DynamicType::Unknown), _) => Some(unknown),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            (
 | 
					            (
 | 
				
			||||||
                todo @ Type::Dynamic(
 | 
					                todo @ Type::Dynamic(
 | 
				
			||||||
                    DynamicType::Todo(_)
 | 
					                    DynamicType::Todo(_)
 | 
				
			||||||
| 
						 | 
					@ -7083,6 +7085,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                _,
 | 
					                _,
 | 
				
			||||||
            ) => Some(todo),
 | 
					            ) => Some(todo),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            (Type::Never, _, _) | (_, Type::Never, _) => Some(Type::Never),
 | 
					            (Type::Never, _, _) | (_, Type::Never, _) => Some(Type::Never),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            (Type::IntLiteral(n), Type::IntLiteral(m), ast::Operator::Add) => Some(
 | 
					            (Type::IntLiteral(n), Type::IntLiteral(m), ast::Operator::Add) => Some(
 | 
				
			||||||
| 
						 | 
					@ -7235,13 +7238,6 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
 | 
				
			||||||
                    op,
 | 
					                    op,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            (Type::Tuple(lhs), Type::Tuple(rhs), ast::Operator::Add) => {
 | 
					 | 
				
			||||||
                Some(Type::tuple(TupleType::new(
 | 
					 | 
				
			||||||
                    self.db(),
 | 
					 | 
				
			||||||
                    lhs.tuple(self.db()).concat(self.db(), rhs.tuple(self.db())),
 | 
					 | 
				
			||||||
                )))
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // We've handled all of the special cases that we support for literals, so we need to
 | 
					            // We've handled all of the special cases that we support for literals, so we need to
 | 
				
			||||||
            // fall back on looking for dunder methods on one of the operand types.
 | 
					            // fall back on looking for dunder methods on one of the operand types.
 | 
				
			||||||
            (
 | 
					            (
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue