FutureFeature enum (#8185)

This commit is contained in:
Shahar Naveh authored and GitHub committed 2026-06-30 23:39:13 +09:00
1 parent e831e24865
commit eae567ff33
2 files changed
+140 -35

No files matched your search

+108 -17
View File
@@ -201,6 +201,90 @@ enum DoneWithFuture {
Yes,
}
/// A Python `__future__` feature flag imported via `from __future__ import <feature>`.
///
/// # See Also
///
/// - [Python documentation on `__future__`](https://docs.python.org/3.14/library/__future__.html)
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum FutureFeature {
/// ```py
/// from __future__ import absolute_import
/// ```
AbsoluteImport,
/// ```py
/// from __future__ import annotations
/// ```
Annotations,
/// ```py
/// from __future__ import barry_as_FLUFL
/// ```
BarryAsFLUFL,
/// ```py
/// from __future__ import braces
/// ```
Braces,
/// ```py
/// from __future__ import division
/// ```
Division,
/// ```py
/// from __future__ import generator_stop
/// ```
GeneratorStop,
/// ```py
/// from __future__ import generators
/// ```
Generators,
/// ```py
/// from __future__ import nested_scopes
/// ```
NestedScopes,
/// ```py
/// from __future__ import print_function
/// ```
PrintFunction,
/// ```py
/// from __future__ import unicode_literals
/// ```
UnicodeLiterals,
/// ```py
/// from __future__ import with_statement
/// ```
WithStatement,
}
impl TryFrom<&str> for FutureFeature {
type Error = String;
fn try_from(name: &str) -> Result<Self, Self::Error> {
Ok(match name {
"absolute_import" => Self::AbsoluteImport,
"annotations" => Self::Annotations,
"barry_as_FLUFL" => Self::BarryAsFLUFL,
"braces" => Self::Braces,
"division" => Self::Division,
"generator_stop" => Self::GeneratorStop,
"generators" => Self::Generators,
"nested_scopes" => Self::NestedScopes,
"print_function" => Self::PrintFunction,
"unicode_literals" => Self::UnicodeLiterals,
"with_statement" => Self::WithStatement,
_ => return Err(name.into()),
})
}
}
#[derive(Clone, Copy)]
enum ComprehensionSymbolSource {
Child,
@@ -11144,16 +11228,21 @@ impl<'warnings> Compiler<'warnings> {
if let DoneWithFuture::Yes = self.done_with_future_stmts {
return Err(self.error(CodegenErrorType::InvalidFuturePlacement));
}
self.done_with_future_stmts = DoneWithFuture::DoneWithDoc;
for feature in features {
match feature.name.as_str() {
// Python 3 features; we've already implemented them by default
"nested_scopes" | "generators" | "division" | "absolute_import"
| "with_statement" | "print_function" | "unicode_literals" | "generator_stop" => {}
// Accept the future feature name, but do not implement
// Barry-as-BDFL parser mode.
"barry_as_FLUFL" => {}
"annotations" => {
let future_feature = feature.name.as_str().try_into().map_err(|name| {
self.error_ranged(CodegenErrorType::InvalidFutureFeature(name), feature.range)
})?;
match future_feature {
FutureFeature::Braces => {
return Err(
self.error_ranged(CodegenErrorType::InvalidFutureBraces, feature.range)
);
}
FutureFeature::Annotations => {
self.future_annotations = true;
self.future_features
.insert(bytecode::CodeFlags::FUTURE_ANNOTATIONS);
@@ -11161,16 +11250,18 @@ impl<'warnings> Compiler<'warnings> {
.flags
.insert(bytecode::CodeFlags::FUTURE_ANNOTATIONS);
}
"braces" => {
return Err(
self.error_ranged(CodegenErrorType::InvalidFutureBraces, feature.range)
);
FutureFeature::BarryAsFLUFL => {
// We do not support Barry-as-BDFL parser mode yet. This is a nop for now.
}
other => {
return Err(self.error_ranged(
CodegenErrorType::InvalidFutureFeature(other.to_owned()),
feature.range,
));
FutureFeature::AbsoluteImport
| FutureFeature::Division
| FutureFeature::GeneratorStop
| FutureFeature::Generators
| FutureFeature::NestedScopes
| FutureFeature::PrintFunction
| FutureFeature::UnicodeLiterals
| FutureFeature::WithStatement => {
// Python 3 features. They are already implemented by default.
}
}
}
+32 -18
View File
@@ -8,6 +8,8 @@ use ruff_python_ast::{
visitor::transformer::{self, Transformer},
};
use ruff_text_size::{Ranged, TextRange};
use crate::compile::FutureFeature;
use rustpython_compiler_core::bytecode;
const MAXDIGITS: usize = 3;
@@ -232,29 +234,40 @@ pub fn checked_future_features_in_body(
..
}) if *level == 0 && module.as_ref().map(|id| id.as_str()) == Some("__future__") => {
for alias in names {
match alias.name.as_str() {
"nested_scopes" | "generators" | "division" | "absolute_import"
| "with_statement" | "print_function" | "unicode_literals"
| "generator_stop" => {}
"annotations" => {
future_features.insert(bytecode::CodeFlags::FUTURE_ANNOTATIONS);
}
// Accept the future feature name, but leave it
// as a RustPython no-op.
"barry_as_FLUFL" => {}
"braces" => {
let future_feature =
alias
.name
.as_str()
.try_into()
.map_err(|name| FutureFeatureError {
features: future_features,
range: alias.range,
kind: FutureFeatureErrorKind::InvalidFeature(name),
})?;
match future_feature {
FutureFeature::Braces => {
return Err(FutureFeatureError {
features: future_features,
range: alias.range,
kind: FutureFeatureErrorKind::InvalidBraces,
});
}
other => {
return Err(FutureFeatureError {
features: future_features,
range: alias.range,
kind: FutureFeatureErrorKind::InvalidFeature(other.to_owned()),
});
FutureFeature::Annotations => {
future_features.insert(bytecode::CodeFlags::FUTURE_ANNOTATIONS)
}
FutureFeature::BarryAsFLUFL => {
// We do not support Barry-as-BDFL parser mode yet. This is a nop for now.
}
FutureFeature::AbsoluteImport
| FutureFeature::Division
| FutureFeature::GeneratorStop
| FutureFeature::Generators
| FutureFeature::NestedScopes
| FutureFeature::PrintFunction
| FutureFeature::UnicodeLiterals
| FutureFeature::WithStatement => {
// Python 3 features. They are already implemented by default.
}
}
}
@@ -298,6 +311,7 @@ pub fn preprocess_mod(
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct AstPreprocessor {
optimize: u8,
future_annotations: bool,
@@ -305,7 +319,7 @@ struct AstPreprocessor {
}
impl AstPreprocessor {
fn visit_astfold_body(&self, body: &mut ast::Suite) {
fn visit_astfold_body(self, body: &mut ast::Suite) {
let mut docstring = body_starts_with_docstring(body);
if docstring && self.optimize >= 2 {
remove_docstring_from_body(body);