mirror of
				https://github.com/astral-sh/ruff.git
				synced 2025-10-31 12:05:57 +00:00 
			
		
		
		
	[ruff] Recognize t-strings, generators, and lambdas in invalid-index-type (RUF016) (#20213)
				
					
				
			## Summary Fixes #20204 Recognize t-strings, generators, and lambdas in RUF016 - Accept boolean literals as valid index and slice bounds. - Add TString, Generator, and Lambda to `CheckableExprType`. - Expand RUF016.py fixture and update snapshots accordingly.
This commit is contained in:
		
							parent
							
								
									b6bd32d9dc
								
							
						
					
					
						commit
						ff677a96e4
					
				
					 3 changed files with 58 additions and 2 deletions
				
			
		|  | @ -113,3 +113,18 @@ var = bytearray(b"abc")["x"] | ||||||
| x = "x" | x = "x" | ||||||
| var = [1, 2, 3][0:x] | var = [1, 2, 3][0:x] | ||||||
| var = [1, 2, 3][x:1] | var = [1, 2, 3][x:1] | ||||||
|  | 
 | ||||||
|  | # https://github.com/astral-sh/ruff/issues/20204 | ||||||
|  | 
 | ||||||
|  | # Should not emit for boolean index and slice bounds | ||||||
|  | var = [1, 2, 3][False] | ||||||
|  | var = [1, 2, 3][False:True:True] | ||||||
|  | 
 | ||||||
|  | # Should emit for invalid access using t-string | ||||||
|  | var = [1, 2][t"x"] | ||||||
|  | 
 | ||||||
|  | # Should emit for invalid access using lambda | ||||||
|  | var = [1, 2, 3][lambda: 0] | ||||||
|  | 
 | ||||||
|  | # Should emit for invalid access using generator | ||||||
|  | var = [1, 2, 3][(x for x in ())] | ||||||
|  |  | ||||||
|  | @ -89,7 +89,9 @@ pub(crate) fn invalid_index_type(checker: &Checker, expr: &ExprSubscript) { | ||||||
| 
 | 
 | ||||||
|     if index_type.is_literal() { |     if index_type.is_literal() { | ||||||
|         // If the index is a literal, require an integer
 |         // If the index is a literal, require an integer
 | ||||||
|         if index_type != CheckableExprType::IntLiteral { |         if index_type != CheckableExprType::IntLiteral | ||||||
|  |             && index_type != CheckableExprType::BooleanLiteral | ||||||
|  |         { | ||||||
|             checker.report_diagnostic( |             checker.report_diagnostic( | ||||||
|                 InvalidIndexType { |                 InvalidIndexType { | ||||||
|                     value_type: value_type.to_string(), |                     value_type: value_type.to_string(), | ||||||
|  | @ -111,7 +113,9 @@ pub(crate) fn invalid_index_type(checker: &Checker, expr: &ExprSubscript) { | ||||||
|                 // If the index is a slice, require integer or null bounds
 |                 // If the index is a slice, require integer or null bounds
 | ||||||
|                 if !matches!( |                 if !matches!( | ||||||
|                     is_slice_type, |                     is_slice_type, | ||||||
|                     CheckableExprType::IntLiteral | CheckableExprType::NoneLiteral |                     CheckableExprType::IntLiteral | ||||||
|  |                         | CheckableExprType::NoneLiteral | ||||||
|  |                         | CheckableExprType::BooleanLiteral | ||||||
|                 ) { |                 ) { | ||||||
|                     checker.report_diagnostic( |                     checker.report_diagnostic( | ||||||
|                         InvalidIndexType { |                         InvalidIndexType { | ||||||
|  | @ -154,6 +158,7 @@ pub(crate) fn invalid_index_type(checker: &Checker, expr: &ExprSubscript) { | ||||||
| #[derive(Debug, Copy, Clone, PartialEq, Eq)] | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||||||
| enum CheckableExprType { | enum CheckableExprType { | ||||||
|     FString, |     FString, | ||||||
|  |     TString, | ||||||
|     StringLiteral, |     StringLiteral, | ||||||
|     BytesLiteral, |     BytesLiteral, | ||||||
|     IntLiteral, |     IntLiteral, | ||||||
|  | @ -170,12 +175,15 @@ enum CheckableExprType { | ||||||
|     Dict, |     Dict, | ||||||
|     Tuple, |     Tuple, | ||||||
|     Slice, |     Slice, | ||||||
|  |     Generator, | ||||||
|  |     Lambda, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl fmt::Display for CheckableExprType { | impl fmt::Display for CheckableExprType { | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||||
|         match self { |         match self { | ||||||
|             Self::FString => f.write_str("str"), |             Self::FString => f.write_str("str"), | ||||||
|  |             Self::TString => f.write_str("Template"), | ||||||
|             Self::StringLiteral => f.write_str("str"), |             Self::StringLiteral => f.write_str("str"), | ||||||
|             Self::BytesLiteral => f.write_str("bytes"), |             Self::BytesLiteral => f.write_str("bytes"), | ||||||
|             Self::IntLiteral => f.write_str("int"), |             Self::IntLiteral => f.write_str("int"), | ||||||
|  | @ -192,6 +200,8 @@ impl fmt::Display for CheckableExprType { | ||||||
|             Self::Slice => f.write_str("slice"), |             Self::Slice => f.write_str("slice"), | ||||||
|             Self::Dict => f.write_str("dict"), |             Self::Dict => f.write_str("dict"), | ||||||
|             Self::Tuple => f.write_str("tuple"), |             Self::Tuple => f.write_str("tuple"), | ||||||
|  |             Self::Generator => f.write_str("generator"), | ||||||
|  |             Self::Lambda => f.write_str("lambda"), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -209,6 +219,7 @@ impl CheckableExprType { | ||||||
|             Expr::BooleanLiteral(_) => Some(Self::BooleanLiteral), |             Expr::BooleanLiteral(_) => Some(Self::BooleanLiteral), | ||||||
|             Expr::NoneLiteral(_) => Some(Self::NoneLiteral), |             Expr::NoneLiteral(_) => Some(Self::NoneLiteral), | ||||||
|             Expr::EllipsisLiteral(_) => Some(Self::EllipsisLiteral), |             Expr::EllipsisLiteral(_) => Some(Self::EllipsisLiteral), | ||||||
|  |             Expr::TString(_) => Some(Self::TString), | ||||||
|             Expr::FString(_) => Some(Self::FString), |             Expr::FString(_) => Some(Self::FString), | ||||||
|             Expr::List(_) => Some(Self::List), |             Expr::List(_) => Some(Self::List), | ||||||
|             Expr::ListComp(_) => Some(Self::ListComp), |             Expr::ListComp(_) => Some(Self::ListComp), | ||||||
|  | @ -218,6 +229,8 @@ impl CheckableExprType { | ||||||
|             Expr::Dict(_) => Some(Self::Dict), |             Expr::Dict(_) => Some(Self::Dict), | ||||||
|             Expr::Tuple(_) => Some(Self::Tuple), |             Expr::Tuple(_) => Some(Self::Tuple), | ||||||
|             Expr::Slice(_) => Some(Self::Slice), |             Expr::Slice(_) => Some(Self::Slice), | ||||||
|  |             Expr::Generator(_) => Some(Self::Generator), | ||||||
|  |             Expr::Lambda(_) => Some(Self::Lambda), | ||||||
|             _ => None, |             _ => None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -415,3 +415,31 @@ RUF016 Indexed access to type `list` uses type `str` instead of an integer or sl | ||||||
| 95 | | 95 | | ||||||
| 96 | # Cannot emit on invalid access using variable in index | 96 | # Cannot emit on invalid access using variable in index | ||||||
|    | |    | | ||||||
|  | 
 | ||||||
|  | RUF016 Indexed access to type `list` uses type `Template` instead of an integer or slice | ||||||
|  |    --> RUF016.py:124:14 | ||||||
|  |     | | ||||||
|  | 123 | # Should emit for invalid access using t-string | ||||||
|  | 124 | var = [1, 2][t"x"] | ||||||
|  |     |              ^^^^ | ||||||
|  | 125 | | ||||||
|  | 126 | # Should emit for invalid access using lambda | ||||||
|  |     | | ||||||
|  | 
 | ||||||
|  | RUF016 Indexed access to type `list` uses type `lambda` instead of an integer or slice | ||||||
|  |    --> RUF016.py:127:17 | ||||||
|  |     | | ||||||
|  | 126 | # Should emit for invalid access using lambda | ||||||
|  | 127 | var = [1, 2, 3][lambda: 0] | ||||||
|  |     |                 ^^^^^^^^^ | ||||||
|  | 128 | | ||||||
|  | 129 | # Should emit for invalid access using generator | ||||||
|  |     | | ||||||
|  | 
 | ||||||
|  | RUF016 Indexed access to type `list` uses type `generator` instead of an integer or slice | ||||||
|  |    --> RUF016.py:130:17 | ||||||
|  |     | | ||||||
|  | 129 | # Should emit for invalid access using generator | ||||||
|  | 130 | var = [1, 2, 3][(x for x in ())] | ||||||
|  |     |                 ^^^^^^^^^^^^^^^ | ||||||
|  |     | | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Takayuki Maeda
						Takayuki Maeda