Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Update to ruff 0.13.1
  • Loading branch information
coolreader18 committed Sep 29, 2025
commit de8c06de206ed373ad4cac468428212a54f9d877
251 changes: 169 additions & 82 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,10 @@ rustpython-sre_engine = { path = "vm/sre_engine", version = "0.4.0" }
rustpython-wtf8 = { path = "wtf8", version = "0.4.0" }
rustpython-doc = { git = "https://github.com/RustPython/__doc__", tag = "0.3.0", version = "0.3.0" }

ruff_python_parser = { git = "https://github.com/astral-sh/ruff.git", tag = "0.11.0" }
ruff_python_ast = { git = "https://github.com/astral-sh/ruff.git", tag = "0.11.0" }
ruff_text_size = { git = "https://github.com/astral-sh/ruff.git", tag = "0.11.0" }
ruff_source_file = { git = "https://github.com/astral-sh/ruff.git", tag = "0.11.0" }
ruff_python_parser = { git = "https://github.com/astral-sh/ruff.git", tag = "0.13.1" }
ruff_python_ast = { git = "https://github.com/astral-sh/ruff.git", tag = "0.13.1" }
ruff_text_size = { git = "https://github.com/astral-sh/ruff.git", tag = "0.13.1" }
ruff_source_file = { git = "https://github.com/astral-sh/ruff.git", tag = "0.13.1" }

ahash = "0.8.12"
ascii = "1.1"
Expand Down
179 changes: 109 additions & 70 deletions compiler/codegen/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ use ruff_python_ast::{
Alias, Arguments, BoolOp, CmpOp, Comprehension, ConversionFlag, DebugText, Decorator, DictItem,
ExceptHandler, ExceptHandlerExceptHandler, Expr, ExprAttribute, ExprBoolOp, ExprContext,
ExprFString, ExprList, ExprName, ExprSlice, ExprStarred, ExprSubscript, ExprTuple, ExprUnaryOp,
FString, FStringElement, FStringElements, FStringFlags, FStringPart, Identifier, Int, Keyword,
MatchCase, ModExpression, ModModule, Operator, Parameters, Pattern, PatternMatchAs,
PatternMatchClass, PatternMatchMapping, PatternMatchOr, PatternMatchSequence,
PatternMatchSingleton, PatternMatchStar, PatternMatchValue, Singleton, Stmt, StmtExpr,
TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple, TypeParams, UnaryOp,
WithItem,
FString, FStringFlags, FStringPart, Identifier, Int, InterpolatedElement,
InterpolatedStringElement, InterpolatedStringElements, Keyword, MatchCase, ModExpression,
ModModule, Operator, Parameters, Pattern, PatternMatchAs, PatternMatchClass,
PatternMatchMapping, PatternMatchOr, PatternMatchSequence, PatternMatchSingleton,
PatternMatchStar, PatternMatchValue, Singleton, Stmt, StmtExpr, TypeParam, TypeParamParamSpec,
TypeParamTypeVar, TypeParamTypeVarTuple, TypeParams, UnaryOp, WithItem,
};
use ruff_text_size::{Ranged, TextRange};
use rustpython_compiler_core::{
Mode, OneIndexed, SourceFile, SourceLocation,
Mode, OneIndexed, PositionEncoding, SourceFile, SourceLocation,
bytecode::{
self, Arg as OpArgMarker, BinaryOperator, CodeObject, ComparisonOperator, ConstantData,
Instruction, OpArg, OpArgType, UnpackExArgs,
Expand Down Expand Up @@ -240,18 +240,18 @@ fn eprint_location(zelf: &Compiler) {
let start = zelf
.source_file
.to_source_code()
.source_location(zelf.current_source_range.start());
.source_location(zelf.current_source_range.start(), PositionEncoding::Utf8);
let end = zelf
.source_file
.to_source_code()
.source_location(zelf.current_source_range.end());
.source_location(zelf.current_source_range.end(), PositionEncoding::Utf8);
eprintln!(
"LOCATION: {} from {}:{} to {}:{}",
zelf.source_file.name(),
start.row,
start.column,
end.row,
end.column
start.line,
start.character_offset,
end.line,
end.character_offset
);
}

Expand Down Expand Up @@ -531,7 +531,7 @@ impl Compiler {
let location = self
.source_file
.to_source_code()
.source_location(range.start());
.source_location(range.start(), PositionEncoding::Utf8);
CodegenError {
error,
location: Some(location),
Expand Down Expand Up @@ -631,8 +631,8 @@ impl Compiler {
) -> CompileResult<()> {
// Create location
let location = SourceLocation {
row: OneIndexed::new(lineno as usize).unwrap_or(OneIndexed::MIN),
column: OneIndexed::new(1).unwrap(),
line: OneIndexed::new(lineno as usize).unwrap_or(OneIndexed::MIN),
character_offset: OneIndexed::MIN,
};

// Allocate a new compiler unit
Expand Down Expand Up @@ -769,8 +769,8 @@ impl Compiler {
let _resume_loc = if scope_type == CompilerScope::Module {
// Module scope starts with lineno 0
SourceLocation {
row: OneIndexed::MIN,
column: OneIndexed::MIN,
line: OneIndexed::MIN,
character_offset: OneIndexed::MIN,
}
} else {
location
Expand Down Expand Up @@ -4872,6 +4872,7 @@ impl Compiler {
Expr::Named(ExprNamed {
target,
value,
node_index: _,
range: _,
}) => {
self.compile_expression(value)?;
Expand All @@ -4881,6 +4882,9 @@ impl Compiler {
Expr::FString(fstring) => {
self.compile_expr_fstring(fstring)?;
}
Expr::TString(_) => {
return Err(self.error(CodegenErrorType::NotImplementedYet));
}
Comment on lines +4905 to +4907
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

TString currently unimplemented in compiler

Compiler rejects Expr::TString with NotImplementedYet while unparser prints a placeholder. Align behavior (either both reject or both support) to avoid surprises.

  • For now, consider a targeted SyntaxError with a message like “t-strings not yet supported” to improve UX.
🤖 Prompt for AI Agents
In compiler/codegen/src/compile.rs around lines 4905–4907, the match arm for
Expr::TString returns a generic NotImplementedYet error while the unparser
prints a placeholder; change this to return a targeted SyntaxError with a clear
message like "t-strings not yet supported" (include the original span/location
info when constructing the error so diagnostics point to the t-string site).
Replace the NotImplementedYet Err with a call that creates/returns a SyntaxError
carrying that message and the expression span so the compiler reports a
user-friendly syntax-level message.

Expr::StringLiteral(string) => {
let value = string.value.to_str();
if value.contains(char::REPLACEMENT_CHARACTER) {
Expand Down Expand Up @@ -5334,7 +5338,7 @@ impl Compiler {
let location = self
.source_file
.to_source_code()
.source_location(range.start());
.source_location(range.start(), PositionEncoding::Utf8);
// TODO: insert source filename
self.current_block().instructions.push(ir::InstructionInfo {
instr,
Expand Down Expand Up @@ -5524,27 +5528,14 @@ impl Compiler {
Expr::Named(ExprNamed {
target,
value,
node_index: _,
range: _,
}) => Self::contains_await(target) || Self::contains_await(value),
Expr::FString(ExprFString { value, range: _ }) => {
fn expr_element_contains_await<F: Copy + Fn(&Expr) -> bool>(
expr_element: &FStringExpressionElement,
contains_await: F,
) -> bool {
contains_await(&expr_element.expression)
|| expr_element
.format_spec
.iter()
.flat_map(|spec| spec.elements.expressions())
.any(|element| expr_element_contains_await(element, contains_await))
}

value.elements().any(|element| match element {
FStringElement::Expression(expr_element) => {
expr_element_contains_await(expr_element, Self::contains_await)
}
FStringElement::Literal(_) => false,
})
Expr::FString(fstring) => {
Self::interpolated_string_contains_await(fstring.value.elements())
}
Expr::TString(tstring) => {
Self::interpolated_string_contains_await(tstring.value.elements())
}
Expr::StringLiteral(_)
| Expr::BytesLiteral(_)
Expand All @@ -5556,6 +5547,29 @@ impl Compiler {
}
}

fn interpolated_string_contains_await<'a>(
mut elements: impl Iterator<Item = &'a InterpolatedStringElement>,
) -> bool {
fn interpolated_element_contains_await<F: Copy + Fn(&Expr) -> bool>(
expr_element: &InterpolatedElement,
contains_await: F,
) -> bool {
contains_await(&expr_element.expression)
|| expr_element
.format_spec
.iter()
.flat_map(|spec| spec.elements.interpolations())
.any(|element| interpolated_element_contains_await(element, contains_await))
}

elements.any(|element| match element {
InterpolatedStringElement::Interpolation(expr_element) => {
interpolated_element_contains_await(expr_element, Self::contains_await)
}
InterpolatedStringElement::Literal(_) => false,
})
}

fn compile_expr_fstring(&mut self, fstring: &ExprFString) -> CompileResult<()> {
let fstring = &fstring.value;
for part in fstring {
Expand Down Expand Up @@ -5602,13 +5616,13 @@ impl Compiler {
fn compile_fstring_elements(
&mut self,
flags: FStringFlags,
fstring_elements: &FStringElements,
fstring_elements: &InterpolatedStringElements,
) -> CompileResult<()> {
let mut element_count = 0;
for element in fstring_elements {
element_count += 1;
match element {
FStringElement::Literal(string) => {
InterpolatedStringElement::Literal(string) => {
if string.value.contains(char::REPLACEMENT_CHARACTER) {
// might have a surrogate literal; should reparse to be sure
let source = self.source_file.slice(string.range);
Expand All @@ -5625,7 +5639,7 @@ impl Compiler {
});
}
}
FStringElement::Expression(fstring_expr) => {
InterpolatedStringElement::Interpolation(fstring_expr) => {
let mut conversion = fstring_expr.conversion;

if let Some(DebugText { leading, trailing }) = &fstring_expr.debug_text {
Expand Down Expand Up @@ -5858,21 +5872,27 @@ mod ruff_tests {

// f'{x}'
let expr_x = Expr::Name(ExprName {
node_index: AtomicNodeIndex::NONE,
range,
id: Name::new("x"),
ctx: ExprContext::Load,
});
let not_present = &Expr::FString(ExprFString {
node_index: AtomicNodeIndex::NONE,
range,
value: FStringValue::single(FString {
node_index: AtomicNodeIndex::NONE,
range,
elements: vec![FStringElement::Expression(FStringExpressionElement {
range,
expression: Box::new(expr_x),
debug_text: None,
conversion: ConversionFlag::None,
format_spec: None,
})]
elements: vec![InterpolatedStringElement::Interpolation(
InterpolatedElement {
node_index: AtomicNodeIndex::NONE,
range,
expression: Box::new(expr_x),
debug_text: None,
conversion: ConversionFlag::None,
format_spec: None,
},
)]
.into(),
flags,
}),
Expand All @@ -5881,24 +5901,31 @@ mod ruff_tests {

// f'{await x}'
let expr_await_x = Expr::Await(ExprAwait {
node_index: AtomicNodeIndex::NONE,
range,
value: Box::new(Expr::Name(ExprName {
node_index: AtomicNodeIndex::NONE,
range,
id: Name::new("x"),
ctx: ExprContext::Load,
})),
});
let present = &Expr::FString(ExprFString {
node_index: AtomicNodeIndex::NONE,
range,
value: FStringValue::single(FString {
node_index: AtomicNodeIndex::NONE,
range,
elements: vec![FStringElement::Expression(FStringExpressionElement {
range,
expression: Box::new(expr_await_x),
debug_text: None,
conversion: ConversionFlag::None,
format_spec: None,
})]
elements: vec![InterpolatedStringElement::Interpolation(
InterpolatedElement {
node_index: AtomicNodeIndex::NONE,
range,
expression: Box::new(expr_await_x),
debug_text: None,
conversion: ConversionFlag::None,
format_spec: None,
},
)]
.into(),
flags,
}),
Expand All @@ -5907,39 +5934,51 @@ mod ruff_tests {

// f'{x:{await y}}'
let expr_x = Expr::Name(ExprName {
node_index: AtomicNodeIndex::NONE,
range,
id: Name::new("x"),
ctx: ExprContext::Load,
});
let expr_await_y = Expr::Await(ExprAwait {
node_index: AtomicNodeIndex::NONE,
range,
value: Box::new(Expr::Name(ExprName {
node_index: AtomicNodeIndex::NONE,
range,
id: Name::new("y"),
ctx: ExprContext::Load,
})),
});
let present = &Expr::FString(ExprFString {
node_index: AtomicNodeIndex::NONE,
range,
value: FStringValue::single(FString {
node_index: AtomicNodeIndex::NONE,
range,
elements: vec![FStringElement::Expression(FStringExpressionElement {
range,
expression: Box::new(expr_x),
debug_text: None,
conversion: ConversionFlag::None,
format_spec: Some(Box::new(FStringFormatSpec {
elements: vec![InterpolatedStringElement::Interpolation(
InterpolatedElement {
node_index: AtomicNodeIndex::NONE,
range,
elements: vec![FStringElement::Expression(FStringExpressionElement {
expression: Box::new(expr_x),
debug_text: None,
conversion: ConversionFlag::None,
format_spec: Some(Box::new(InterpolatedStringFormatSpec {
node_index: AtomicNodeIndex::NONE,
range,
expression: Box::new(expr_await_y),
debug_text: None,
conversion: ConversionFlag::None,
format_spec: None,
})]
.into(),
})),
})]
elements: vec![InterpolatedStringElement::Interpolation(
InterpolatedElement {
node_index: AtomicNodeIndex::NONE,
range,
expression: Box::new(expr_await_y),
debug_text: None,
conversion: ConversionFlag::None,
format_spec: None,
},
)]
.into(),
})),
},
)]
.into(),
flags,
}),
Expand Down
6 changes: 3 additions & 3 deletions compiler/codegen/src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl CodeInfo {
*arg = new_arg;
}
let (extras, lo_arg) = arg.split();
locations.extend(std::iter::repeat_n(info.location.clone(), arg.instr_size()));
locations.extend(std::iter::repeat_n(info.location, arg.instr_size()));
instructions.extend(
extras
.map(|byte| CodeUnit::new(Instruction::ExtendedArg, byte))
Expand Down Expand Up @@ -422,8 +422,8 @@ fn generate_linetable(locations: &[SourceLocation], first_line: i32) -> Box<[u8]

// Get line and column information
// SourceLocation always has row and column (both are OneIndexed)
let line = loc.row.get() as i32;
let col = (loc.column.get() as i32) - 1; // Convert 1-based to 0-based
let line = loc.line.get() as i32;
let col = loc.character_offset.to_zero_indexed() as i32;

let line_delta = line - prev_line;

Expand Down
1 change: 1 addition & 0 deletions compiler/codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ impl ToPythonName for Expr {
Self::Starred { .. } => "starred",
Self::Slice { .. } => "slice",
Self::FString { .. } => "f-string expression",
Self::TString { .. } => "t-string expression",
Self::Name { .. } => "name",
Self::Lambda { .. } => "lambda",
Self::If { .. } => "conditional expression",
Expand Down
Loading
Loading