Add support for PEP 696 syntax (#11120)

This commit is contained in:
Jelle Zijlstra 2024-04-26 00:47:29 -07:00 committed by GitHub
parent 45725d3275
commit cd3e319538
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 4338 additions and 669 deletions

View file

@ -1173,21 +1173,29 @@ impl<'a> From<&'a ast::TypeParam> for ComparableTypeParam<'a> {
ast::TypeParam::TypeVar(ast::TypeParamTypeVar {
name,
bound,
default,
range: _,
}) => Self::TypeVar(TypeParamTypeVar {
name: name.as_str(),
bound: bound.as_ref().map(Into::into),
default: default.as_ref().map(Into::into),
}),
ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple {
name,
default,
range: _,
}) => Self::TypeVarTuple(TypeParamTypeVarTuple {
name: name.as_str(),
default: default.as_ref().map(Into::into),
}),
ast::TypeParam::ParamSpec(ast::TypeParamParamSpec {
name,
default,
range: _,
}) => Self::ParamSpec(TypeParamParamSpec {
name: name.as_str(),
default: default.as_ref().map(Into::into),
}),
ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { name, range: _ }) => {
Self::TypeVarTuple(TypeParamTypeVarTuple {
name: name.as_str(),
})
}
ast::TypeParam::ParamSpec(ast::TypeParamParamSpec { name, range: _ }) => {
Self::ParamSpec(TypeParamParamSpec {
name: name.as_str(),
})
}
}
}
}
@ -1196,16 +1204,19 @@ impl<'a> From<&'a ast::TypeParam> for ComparableTypeParam<'a> {
pub struct TypeParamTypeVar<'a> {
pub name: &'a str,
pub bound: Option<Box<ComparableExpr<'a>>>,
pub default: Option<Box<ComparableExpr<'a>>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TypeParamParamSpec<'a> {
pub name: &'a str,
pub default: Option<Box<ComparableExpr<'a>>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TypeParamTypeVarTuple<'a> {
pub name: &'a str,
pub default: Option<Box<ComparableExpr<'a>>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]

View file

@ -264,11 +264,20 @@ pub fn any_over_expr(expr: &Expr, func: &dyn Fn(&Expr) -> bool) -> bool {
pub fn any_over_type_param(type_param: &TypeParam, func: &dyn Fn(&Expr) -> bool) -> bool {
match type_param {
TypeParam::TypeVar(ast::TypeParamTypeVar { bound, .. }) => bound
TypeParam::TypeVar(ast::TypeParamTypeVar { bound, default, .. }) => {
bound
.as_ref()
.is_some_and(|value| any_over_expr(value, func))
|| default
.as_ref()
.is_some_and(|value| any_over_expr(value, func))
}
TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { default, .. }) => default
.as_ref()
.is_some_and(|value| any_over_expr(value, func)),
TypeParam::ParamSpec(ast::TypeParamParamSpec { default, .. }) => default
.as_ref()
.is_some_and(|value| any_over_expr(value, func)),
TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { .. }) => false,
TypeParam::ParamSpec(ast::TypeParamParamSpec { .. }) => false,
}
}
@ -1619,11 +1628,13 @@ mod tests {
let type_var_one = TypeParam::TypeVar(TypeParamTypeVar {
range: TextRange::default(),
bound: Some(Box::new(constant_one.clone())),
default: None,
name: Identifier::new("x", TextRange::default()),
});
let type_var_two = TypeParam::TypeVar(TypeParamTypeVar {
range: TextRange::default(),
bound: Some(Box::new(constant_two.clone())),
bound: None,
default: Some(Box::new(constant_two.clone())),
name: Identifier::new("x", TextRange::default()),
});
let type_alias = Stmt::TypeAlias(StmtTypeAlias {
@ -1650,30 +1661,49 @@ mod tests {
let type_var_no_bound = TypeParam::TypeVar(TypeParamTypeVar {
range: TextRange::default(),
bound: None,
default: None,
name: Identifier::new("x", TextRange::default()),
});
assert!(!any_over_type_param(&type_var_no_bound, &|_expr| true));
let bound = Expr::NumberLiteral(ExprNumberLiteral {
let constant = Expr::NumberLiteral(ExprNumberLiteral {
value: Number::Int(Int::ONE),
range: TextRange::default(),
});
let type_var_with_bound = TypeParam::TypeVar(TypeParamTypeVar {
range: TextRange::default(),
bound: Some(Box::new(bound.clone())),
bound: Some(Box::new(constant.clone())),
default: None,
name: Identifier::new("x", TextRange::default()),
});
assert!(
any_over_type_param(&type_var_with_bound, &|expr| {
assert_eq!(
*expr, bound,
*expr, constant,
"the received expression should be the unwrapped bound"
);
true
}),
"if true is returned from `func` it should be respected"
);
let type_var_with_default = TypeParam::TypeVar(TypeParamTypeVar {
range: TextRange::default(),
default: Some(Box::new(constant.clone())),
bound: None,
name: Identifier::new("x", TextRange::default()),
});
assert!(
any_over_type_param(&type_var_with_default, &|expr| {
assert_eq!(
*expr, constant,
"the received expression should be the unwrapped default"
);
true
}),
"if true is returned from `func` it should be respected"
);
}
#[test]
@ -1681,10 +1711,32 @@ mod tests {
let type_var_tuple = TypeParam::TypeVarTuple(TypeParamTypeVarTuple {
range: TextRange::default(),
name: Identifier::new("x", TextRange::default()),
default: None,
});
assert!(
!any_over_type_param(&type_var_tuple, &|_expr| true),
"type var tuples have no expressions to visit"
"this TypeVarTuple has no expressions to visit"
);
let constant = Expr::NumberLiteral(ExprNumberLiteral {
value: Number::Int(Int::ONE),
range: TextRange::default(),
});
let type_var_tuple_with_default = TypeParam::TypeVarTuple(TypeParamTypeVarTuple {
range: TextRange::default(),
default: Some(Box::new(constant.clone())),
name: Identifier::new("x", TextRange::default()),
});
assert!(
any_over_type_param(&type_var_tuple_with_default, &|expr| {
assert_eq!(
*expr, constant,
"the received expression should be the unwrapped default"
);
true
}),
"if true is returned from `func` it should be respected"
);
}
@ -1693,10 +1745,32 @@ mod tests {
let type_param_spec = TypeParam::ParamSpec(TypeParamParamSpec {
range: TextRange::default(),
name: Identifier::new("x", TextRange::default()),
default: None,
});
assert!(
!any_over_type_param(&type_param_spec, &|_expr| true),
"param specs have no expressions to visit"
"this ParamSpec has no expressions to visit"
);
let constant = Expr::NumberLiteral(ExprNumberLiteral {
value: Number::Int(Int::ONE),
range: TextRange::default(),
});
let param_spec_with_default = TypeParam::TypeVarTuple(TypeParamTypeVarTuple {
range: TextRange::default(),
default: Some(Box::new(constant.clone())),
name: Identifier::new("x", TextRange::default()),
});
assert!(
any_over_type_param(&param_spec_with_default, &|expr| {
assert_eq!(
*expr, constant,
"the received expression should be the unwrapped default"
);
true
}),
"if true is returned from `func` it should be respected"
);
}
}

View file

@ -4317,6 +4317,7 @@ impl AstNode for ast::TypeParamTypeVar {
{
let ast::TypeParamTypeVar {
bound,
default,
name: _,
range: _,
} = self;
@ -4324,6 +4325,9 @@ impl AstNode for ast::TypeParamTypeVar {
if let Some(expr) = bound {
visitor.visit_expr(expr);
}
if let Some(expr) = default {
visitor.visit_expr(expr);
}
}
}
impl AstNode for ast::TypeParamTypeVarTuple {
@ -4355,11 +4359,18 @@ impl AstNode for ast::TypeParamTypeVarTuple {
}
#[inline]
fn visit_preorder<'a, V>(&'a self, _visitor: &mut V)
fn visit_preorder<'a, V>(&'a self, visitor: &mut V)
where
V: PreorderVisitor<'a> + ?Sized,
{
let ast::TypeParamTypeVarTuple { range: _, name: _ } = self;
let ast::TypeParamTypeVarTuple {
range: _,
name: _,
default,
} = self;
if let Some(expr) = default {
visitor.visit_expr(expr);
}
}
}
impl AstNode for ast::TypeParamParamSpec {
@ -4391,11 +4402,18 @@ impl AstNode for ast::TypeParamParamSpec {
}
#[inline]
fn visit_preorder<'a, V>(&'a self, _visitor: &mut V)
fn visit_preorder<'a, V>(&'a self, visitor: &mut V)
where
V: PreorderVisitor<'a> + ?Sized,
{
let ast::TypeParamParamSpec { range: _, name: _ } = self;
let ast::TypeParamParamSpec {
range: _,
name: _,
default,
} = self;
if let Some(expr) = default {
visitor.visit_expr(expr);
}
}
}
impl AstNode for ast::FString {

View file

@ -3132,6 +3132,7 @@ pub struct TypeParamTypeVar {
pub range: TextRange,
pub name: Identifier,
pub bound: Option<Box<Expr>>,
pub default: Option<Box<Expr>>,
}
impl From<TypeParamTypeVar> for TypeParam {
@ -3145,6 +3146,7 @@ impl From<TypeParamTypeVar> for TypeParam {
pub struct TypeParamParamSpec {
pub range: TextRange,
pub name: Identifier,
pub default: Option<Box<Expr>>,
}
impl From<TypeParamParamSpec> for TypeParam {
@ -3158,6 +3160,7 @@ impl From<TypeParamParamSpec> for TypeParam {
pub struct TypeParamTypeVarTuple {
pub range: TextRange,
pub name: Identifier,
pub default: Option<Box<Expr>>,
}
impl From<TypeParamTypeVarTuple> for TypeParam {

View file

@ -7,7 +7,8 @@ use crate::{
self as ast, Alias, Arguments, BoolOp, BytesLiteral, CmpOp, Comprehension, Decorator,
ElifElseClause, ExceptHandler, Expr, ExprContext, FString, FStringElement, FStringPart,
Keyword, MatchCase, Operator, Parameter, Parameters, Pattern, PatternArguments, PatternKeyword,
Stmt, StringLiteral, TypeParam, TypeParamTypeVar, TypeParams, UnaryOp, WithItem,
Stmt, StringLiteral, TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple,
TypeParams, UnaryOp, WithItem,
};
/// A trait for AST visitors. Visits all nodes in the AST recursively in evaluation-order.
@ -666,14 +667,35 @@ pub fn walk_type_param<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, type_param:
match type_param {
TypeParam::TypeVar(TypeParamTypeVar {
bound,
default,
name: _,
range: _,
}) => {
if let Some(expr) = bound {
visitor.visit_expr(expr);
}
if let Some(expr) = default {
visitor.visit_expr(expr);
}
}
TypeParam::TypeVarTuple(TypeParamTypeVarTuple {
default,
name: _,
range: _,
}) => {
if let Some(expr) = default {
visitor.visit_expr(expr);
}
}
TypeParam::ParamSpec(TypeParamParamSpec {
default,
name: _,
range: _,
}) => {
if let Some(expr) = default {
visitor.visit_expr(expr);
}
}
TypeParam::TypeVarTuple(_) | TypeParam::ParamSpec(_) => {}
}
}

View file

@ -2,7 +2,8 @@ use crate::{
self as ast, Alias, Arguments, BoolOp, BytesLiteral, CmpOp, Comprehension, Decorator,
ElifElseClause, ExceptHandler, Expr, ExprContext, FString, FStringElement, Keyword, MatchCase,
Operator, Parameter, Parameters, Pattern, PatternArguments, PatternKeyword, Stmt,
StringLiteral, TypeParam, TypeParamTypeVar, TypeParams, UnaryOp, WithItem,
StringLiteral, TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple,
TypeParams, UnaryOp, WithItem,
};
/// A trait for transforming ASTs. Visits all nodes in the AST recursively in evaluation-order.
@ -652,14 +653,35 @@ pub fn walk_type_param<V: Transformer + ?Sized>(visitor: &V, type_param: &mut Ty
match type_param {
TypeParam::TypeVar(TypeParamTypeVar {
bound,
default,
name: _,
range: _,
}) => {
if let Some(expr) = bound {
visitor.visit_expr(expr);
}
if let Some(expr) = default {
visitor.visit_expr(expr);
}
}
TypeParam::TypeVarTuple(TypeParamTypeVarTuple {
default,
name: _,
range: _,
}) => {
if let Some(expr) = default {
visitor.visit_expr(expr);
}
}
TypeParam::ParamSpec(TypeParamParamSpec {
default,
name: _,
range: _,
}) => {
if let Some(expr) = default {
visitor.visit_expr(expr);
}
}
TypeParam::TypeVarTuple(_) | TypeParam::ParamSpec(_) => {}
}
}