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

@ -1568,8 +1568,8 @@ impl<'a> Visitor<'a> for Checker<'a> {
// Step 1: Binding
match type_param {
ast::TypeParam::TypeVar(ast::TypeParamTypeVar { name, range, .. })
| ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { name, range })
| ast::TypeParam::ParamSpec(ast::TypeParamParamSpec { name, range }) => {
| ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { name, range, .. })
| ast::TypeParam::ParamSpec(ast::TypeParamParamSpec { name, range, .. }) => {
self.add_binding(
name.as_str(),
*range,
@ -1579,13 +1579,46 @@ impl<'a> Visitor<'a> for Checker<'a> {
}
}
// Step 2: Traversal
if let ast::TypeParam::TypeVar(ast::TypeParamTypeVar {
bound: Some(bound), ..
}) = type_param
{
self.visit
.type_param_definitions
.push((bound, self.semantic.snapshot()));
match type_param {
ast::TypeParam::TypeVar(ast::TypeParamTypeVar {
bound,
default,
name: _,
range: _,
}) => {
if let Some(expr) = bound {
self.visit
.type_param_definitions
.push((expr, self.semantic.snapshot()));
}
if let Some(expr) = default {
self.visit
.type_param_definitions
.push((expr, self.semantic.snapshot()));
}
}
ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple {
default,
name: _,
range: _,
}) => {
if let Some(expr) = default {
self.visit
.type_param_definitions
.push((expr, self.semantic.snapshot()));
}
}
ast::TypeParam::ParamSpec(ast::TypeParamParamSpec {
default,
name: _,
range: _,
}) => {
if let Some(expr) = default {
self.visit
.type_param_definitions
.push((expr, self.semantic.snapshot()));
}
}
}
}

View file

@ -134,7 +134,7 @@ F821_17.py:77:15: F821 Undefined name `DoesNotExist1`
77 | class Foo[T: (DoesNotExist1, DoesNotExist2)](list[T]): ... # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
| ^^^^^^^^^^^^^ F821
78 |
79 | # Type parameters in nested classes
79 | # Same in defaults
|
F821_17.py:77:30: F821 Undefined name `DoesNotExist2`
@ -144,35 +144,117 @@ F821_17.py:77:30: F821 Undefined name `DoesNotExist2`
77 | class Foo[T: (DoesNotExist1, DoesNotExist2)](list[T]): ... # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
| ^^^^^^^^^^^^^ F821
78 |
79 | # Type parameters in nested classes
79 | # Same in defaults
|
F821_17.py:92:52: F821 Undefined name `t`
F821_17.py:81:14: F821 Undefined name `DoesNotExist`
|
90 | return x
91 |
92 | def cannot_access_parent_variable(self, x: t) -> t: # F821: Undefined name `T`
| ^ F821
93 | t # F821: Undefined name `t`
94 | return x
79 | # Same in defaults
80 |
81 | type Foo[T = DoesNotExist] = T # F821: Undefined name `DoesNotExist`
| ^^^^^^^^^^^^ F821
82 | def foo[T = DoesNotExist](t: T) -> T: return t # F821: Undefined name `DoesNotExist`
83 | class Foo[T = DoesNotExist](list[T]): ... # F821: Undefined name `DoesNotExist`
|
F821_17.py:92:58: F821 Undefined name `t`
F821_17.py:82:13: F821 Undefined name `DoesNotExist`
|
90 | return x
91 |
92 | def cannot_access_parent_variable(self, x: t) -> t: # F821: Undefined name `T`
| ^ F821
93 | t # F821: Undefined name `t`
94 | return x
81 | type Foo[T = DoesNotExist] = T # F821: Undefined name `DoesNotExist`
82 | def foo[T = DoesNotExist](t: T) -> T: return t # F821: Undefined name `DoesNotExist`
| ^^^^^^^^^^^^ F821
83 | class Foo[T = DoesNotExist](list[T]): ... # F821: Undefined name `DoesNotExist`
|
F821_17.py:93:17: F821 Undefined name `t`
F821_17.py:83:15: F821 Undefined name `DoesNotExist`
|
92 | def cannot_access_parent_variable(self, x: t) -> t: # F821: Undefined name `T`
93 | t # F821: Undefined name `t`
| ^ F821
94 | return x
81 | type Foo[T = DoesNotExist] = T # F821: Undefined name `DoesNotExist`
82 | def foo[T = DoesNotExist](t: T) -> T: return t # F821: Undefined name `DoesNotExist`
83 | class Foo[T = DoesNotExist](list[T]): ... # F821: Undefined name `DoesNotExist`
| ^^^^^^^^^^^^ F821
84 |
85 | type Foo[T = (DoesNotExist1, DoesNotExist2)] = T # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
|
F821_17.py:85:15: F821 Undefined name `DoesNotExist1`
|
83 | class Foo[T = DoesNotExist](list[T]): ... # F821: Undefined name `DoesNotExist`
84 |
85 | type Foo[T = (DoesNotExist1, DoesNotExist2)] = T # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
| ^^^^^^^^^^^^^ F821
86 | def foo[T = (DoesNotExist1, DoesNotExist2)](t: T) -> T: return t # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
87 | class Foo[T = (DoesNotExist1, DoesNotExist2)](list[T]): ... # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
|
F821_17.py:85:30: F821 Undefined name `DoesNotExist2`
|
83 | class Foo[T = DoesNotExist](list[T]): ... # F821: Undefined name `DoesNotExist`
84 |
85 | type Foo[T = (DoesNotExist1, DoesNotExist2)] = T # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
| ^^^^^^^^^^^^^ F821
86 | def foo[T = (DoesNotExist1, DoesNotExist2)](t: T) -> T: return t # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
87 | class Foo[T = (DoesNotExist1, DoesNotExist2)](list[T]): ... # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
|
F821_17.py:86:14: F821 Undefined name `DoesNotExist1`
|
85 | type Foo[T = (DoesNotExist1, DoesNotExist2)] = T # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
86 | def foo[T = (DoesNotExist1, DoesNotExist2)](t: T) -> T: return t # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
| ^^^^^^^^^^^^^ F821
87 | class Foo[T = (DoesNotExist1, DoesNotExist2)](list[T]): ... # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
|
F821_17.py:86:29: F821 Undefined name `DoesNotExist2`
|
85 | type Foo[T = (DoesNotExist1, DoesNotExist2)] = T # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
86 | def foo[T = (DoesNotExist1, DoesNotExist2)](t: T) -> T: return t # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
| ^^^^^^^^^^^^^ F821
87 | class Foo[T = (DoesNotExist1, DoesNotExist2)](list[T]): ... # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
|
F821_17.py:87:16: F821 Undefined name `DoesNotExist1`
|
85 | type Foo[T = (DoesNotExist1, DoesNotExist2)] = T # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
86 | def foo[T = (DoesNotExist1, DoesNotExist2)](t: T) -> T: return t # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
87 | class Foo[T = (DoesNotExist1, DoesNotExist2)](list[T]): ... # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
| ^^^^^^^^^^^^^ F821
88 |
89 | # Type parameters in nested classes
|
F821_17.py:87:31: F821 Undefined name `DoesNotExist2`
|
85 | type Foo[T = (DoesNotExist1, DoesNotExist2)] = T # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
86 | def foo[T = (DoesNotExist1, DoesNotExist2)](t: T) -> T: return t # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
87 | class Foo[T = (DoesNotExist1, DoesNotExist2)](list[T]): ... # F821: Undefined name `DoesNotExist1`, Undefined name `DoesNotExist2`
| ^^^^^^^^^^^^^ F821
88 |
89 | # Type parameters in nested classes
|
F821_17.py:102:52: F821 Undefined name `t`
|
100 | return x
101 |
102 | def cannot_access_parent_variable(self, x: t) -> t: # F821: Undefined name `T`
| ^ F821
103 | t # F821: Undefined name `t`
104 | return x
|
F821_17.py:102:58: F821 Undefined name `t`
|
100 | return x
101 |
102 | def cannot_access_parent_variable(self, x: t) -> t: # F821: Undefined name `T`
| ^ F821
103 | t # F821: Undefined name `t`
104 | return x
|
F821_17.py:103:17: F821 Undefined name `t`
|
102 | def cannot_access_parent_variable(self, x: t) -> t: # F821: Undefined name `T`
103 | t # F821: Undefined name `t`
| ^ F821
104 | return x
|

View file

@ -132,6 +132,9 @@ pub(crate) fn non_pep695_type_alias(checker: &mut Checker, stmt: &StmtAnnAssign)
}
None => None,
},
// We don't handle defaults here yet. Should perhaps be a different rule since
// defaults are only valid in 3.13+.
default: None,
})
})
.collect(),