@@ -2,7 +2,6 @@ use infer::nearest_enclosing_class;
22use itertools:: { Either , Itertools } ;
33use ruff_db:: parsed:: parsed_module;
44
5- use std:: borrow:: Cow ;
65use std:: slice:: Iter ;
76
87use bitflags:: bitflags;
@@ -687,7 +686,7 @@ impl<'db> Type<'db> {
687686 ///
688687 /// I.e., for the type `tuple[int, str]`, this will return the tuple spec `[int, str]`.
689688 /// For a subclass of `tuple[int, str]`, it will return the same tuple spec.
690- fn tuple_instance_spec ( & self , db : & ' db dyn Db ) -> Option < Cow < ' db , TupleSpec < ' db > > > {
689+ fn tuple_instance_spec ( & self , db : & ' db dyn Db ) -> Option < TupleSpec < ' db > > {
691690 self . into_nominal_instance ( )
692691 . and_then ( |instance| instance. tuple_spec ( db) )
693692 }
@@ -702,9 +701,9 @@ impl<'db> Type<'db> {
702701 ///
703702 /// I.e., for the type `tuple[int, str]`, this will return the tuple spec `[int, str]`.
704703 /// But for a subclass of `tuple[int, str]`, it will return `None`.
705- fn exact_tuple_instance_spec ( & self , db : & ' db dyn Db ) -> Option < Cow < ' db , TupleSpec < ' db > > > {
704+ fn exact_tuple_instance_spec ( & self ) -> Option < TupleSpec < ' db > > {
706705 self . into_nominal_instance ( )
707- . and_then ( |instance| instance. own_tuple_spec ( db ) )
706+ . and_then ( |instance| instance. own_tuple_spec ( ) )
708707 }
709708
710709 /// Returns the materialization of this type depending on the given `variance`.
@@ -4622,9 +4621,9 @@ impl<'db> Type<'db> {
46224621 ///
46234622 /// This method should only be used outside of type checking because it omits any errors.
46244623 /// For type checking, use [`try_iterate`](Self::try_iterate) instead.
4625- fn iterate ( self , db : & ' db dyn Db ) -> Cow < ' db , TupleSpec < ' db > > {
4624+ fn iterate ( self , db : & ' db dyn Db ) -> TupleSpec < ' db > {
46264625 self . try_iterate ( db)
4627- . unwrap_or_else ( |err| Cow :: Owned ( TupleSpec :: homogeneous ( err. fallback_element_type ( db) ) ) )
4626+ . unwrap_or_else ( |err| TupleSpec :: homogeneous ( db , err. fallback_element_type ( db) ) )
46284627 }
46294628
46304629 /// Given the type of an object that is iterated over in some way,
@@ -4635,15 +4634,15 @@ impl<'db> Type<'db> {
46354634 /// ```python
46364635 /// y(*x)
46374636 /// ```
4638- fn try_iterate ( self , db : & ' db dyn Db ) -> Result < Cow < ' db , TupleSpec < ' db > > , IterationError < ' db > > {
4637+ fn try_iterate ( self , db : & ' db dyn Db ) -> Result < TupleSpec < ' db > , IterationError < ' db > > {
46394638 self . try_iterate_with_mode ( db, EvaluationMode :: Sync )
46404639 }
46414640
46424641 fn try_iterate_with_mode (
46434642 self ,
46444643 db : & ' db dyn Db ,
46454644 mode : EvaluationMode ,
4646- ) -> Result < Cow < ' db , TupleSpec < ' db > > , IterationError < ' db > > {
4645+ ) -> Result < TupleSpec < ' db > , IterationError < ' db > > {
46474646 if mode. is_async ( ) {
46484647 let try_call_dunder_anext_on_iterator = |iterator : Type < ' db > | {
46494648 iterator
@@ -4657,7 +4656,7 @@ impl<'db> Type<'db> {
46574656 Ok ( dunder_aiter_bindings) => {
46584657 let iterator = dunder_aiter_bindings. return_type ( db) ;
46594658 match try_call_dunder_anext_on_iterator ( iterator) {
4660- Ok ( result) => Ok ( Cow :: Owned ( TupleSpec :: homogeneous ( result) ) ) ,
4659+ Ok ( result) => Ok ( TupleSpec :: homogeneous ( db , result) ) ,
46614660 Err ( dunder_anext_error) => {
46624661 Err ( IterationError :: IterReturnsInvalidIterator {
46634662 iterator,
@@ -4702,27 +4701,28 @@ impl<'db> Type<'db> {
47024701 }
47034702 }
47044703 Type :: GenericAlias ( alias) if alias. origin ( db) . is_tuple ( db) => {
4705- return Ok ( Cow :: Owned ( TupleSpec :: homogeneous ( todo_type ! (
4706- "*tuple[] annotations"
4707- ) ) ) ) ;
4704+ return Ok ( TupleSpec :: homogeneous (
4705+ db,
4706+ todo_type ! ( "*tuple[] annotations" ) ,
4707+ ) ) ;
47084708 }
47094709 Type :: StringLiteral ( string_literal_ty) => {
47104710 // We could go further and deconstruct to an array of `StringLiteral`
47114711 // with each individual character, instead of just an array of
47124712 // `LiteralString`, but there would be a cost and it's not clear that
47134713 // it's worth it.
4714- return Ok ( Cow :: Owned ( TupleSpec :: from_elements ( std :: iter :: repeat_n (
4715- Type :: LiteralString ,
4716- string_literal_ty. python_len ( db) ,
4717- ) ) ) ) ;
4714+ return Ok ( TupleSpec :: heterogeneous (
4715+ db ,
4716+ std :: iter :: repeat_n ( Type :: LiteralString , string_literal_ty. python_len ( db) ) ,
4717+ ) ) ;
47184718 }
47194719 Type :: Never => {
47204720 // The dunder logic below would have us return `tuple[Never, ...]`, which eagerly
47214721 // simplifies to `tuple[()]`. That will will cause us to emit false positives if we
47224722 // index into the tuple. Using `tuple[Unknown, ...]` avoids these false positives.
47234723 // TODO: Consider removing this special case, and instead hide the indexing
47244724 // diagnostic in unreachable code.
4725- return Ok ( Cow :: Owned ( TupleSpec :: homogeneous ( Type :: unknown ( ) ) ) ) ;
4725+ return Ok ( TupleSpec :: homogeneous ( db , Type :: unknown ( ) ) ) ;
47264726 }
47274727 _ => { }
47284728 }
@@ -4751,7 +4751,7 @@ impl<'db> Type<'db> {
47514751 // `__iter__` is definitely bound and calling it succeeds.
47524752 // See what calling `__next__` on the object returned by `__iter__` gives us...
47534753 try_call_dunder_next_on_iterator ( iterator)
4754- . map ( |ty| Cow :: Owned ( TupleSpec :: homogeneous ( ty ) ) )
4754+ . map ( |ty| TupleSpec :: homogeneous ( db , ty ) )
47554755 . map_err (
47564756 |dunder_next_error| IterationError :: IterReturnsInvalidIterator {
47574757 iterator,
@@ -4776,10 +4776,13 @@ impl<'db> Type<'db> {
47764776 // and the type returned by the `__getitem__` method.
47774777 //
47784778 // No diagnostic is emitted; iteration will always succeed!
4779- Cow :: Owned ( TupleSpec :: homogeneous ( UnionType :: from_elements (
4779+ TupleSpec :: homogeneous (
47804780 db,
4781- [ dunder_next_return, dunder_getitem_return_type] ,
4782- ) ) )
4781+ UnionType :: from_elements (
4782+ db,
4783+ [ dunder_next_return, dunder_getitem_return_type] ,
4784+ ) ,
4785+ )
47834786 } )
47844787 . map_err ( |dunder_getitem_error| {
47854788 IterationError :: PossiblyUnboundIterAndGetitemError {
@@ -4806,7 +4809,7 @@ impl<'db> Type<'db> {
48064809
48074810 // There's no `__iter__` method. Try `__getitem__` instead...
48084811 Err ( CallDunderError :: MethodNotAvailable ) => try_call_dunder_getitem ( )
4809- . map ( |ty| Cow :: Owned ( TupleSpec :: homogeneous ( ty ) ) )
4812+ . map ( |ty| TupleSpec :: homogeneous ( db , ty ) )
48104813 . map_err (
48114814 |dunder_getitem_error| IterationError :: UnboundIterAndGetitemError {
48124815 dunder_getitem_error,
0 commit comments