mirror of https://github.com/astral-sh/ruff
use `infer_annotation_expression` for `TypedDict` fields
This commit is contained in:
parent
6fdd4c3334
commit
6981500d93
|
|
@ -5656,7 +5656,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let field_ty = self.infer_typed_dict_field_type_expression(&item.value);
|
// TODO: The only qualifiers supported on `TypedDict` are `Required`, `NotRequired`,
|
||||||
|
// and `ReadOnly`. We may want to error if others are used.
|
||||||
|
let field_ty =
|
||||||
|
self.infer_annotation_expression(&item.value, DeferredExpressionState::None);
|
||||||
|
|
||||||
let is_required = if field_ty.qualifiers.contains(TypeQualifiers::REQUIRED) {
|
let is_required = if field_ty.qualifiers.contains(TypeQualifiers::REQUIRED) {
|
||||||
// Explicit Required[T] annotation - always required
|
// Explicit Required[T] annotation - always required
|
||||||
|
|
@ -5689,85 +5692,6 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer_typed_dict_field_type_expression(
|
|
||||||
&mut self,
|
|
||||||
expr: &ast::Expr,
|
|
||||||
) -> TypeAndQualifiers<'db> {
|
|
||||||
let ty = match expr {
|
|
||||||
ast::Expr::Subscript(subscript @ ast::ExprSubscript { value, slice, .. }) => {
|
|
||||||
let value_ty = self.infer_expression(value, TypeContext::default());
|
|
||||||
let slice = &**slice;
|
|
||||||
|
|
||||||
// Unlike other type-form expressions, `TypedDict` constructor literals support
|
|
||||||
// the `Required`, `NotRequired`, and `ReadOnly` qualifiers.
|
|
||||||
match value_ty {
|
|
||||||
Type::SpecialForm(
|
|
||||||
type_qualifier @ (SpecialFormType::Required
|
|
||||||
| SpecialFormType::NotRequired
|
|
||||||
| SpecialFormType::ReadOnly),
|
|
||||||
) => {
|
|
||||||
let arguments = if let ast::Expr::Tuple(tuple) = slice {
|
|
||||||
&*tuple.elts
|
|
||||||
} else {
|
|
||||||
std::slice::from_ref(slice)
|
|
||||||
};
|
|
||||||
|
|
||||||
let num_arguments = arguments.len();
|
|
||||||
let type_and_qualifiers = if num_arguments == 1 {
|
|
||||||
let mut type_and_qualifiers =
|
|
||||||
self.infer_typed_dict_field_type_expression(slice);
|
|
||||||
|
|
||||||
match type_qualifier {
|
|
||||||
SpecialFormType::Required => {
|
|
||||||
type_and_qualifiers.add_qualifier(TypeQualifiers::REQUIRED);
|
|
||||||
}
|
|
||||||
SpecialFormType::NotRequired => {
|
|
||||||
type_and_qualifiers.add_qualifier(TypeQualifiers::NOT_REQUIRED);
|
|
||||||
}
|
|
||||||
SpecialFormType::ReadOnly => {
|
|
||||||
type_and_qualifiers.add_qualifier(TypeQualifiers::READ_ONLY);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
|
|
||||||
type_and_qualifiers
|
|
||||||
} else {
|
|
||||||
for element in arguments {
|
|
||||||
self.infer_typed_dict_field_type_expression(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(builder) =
|
|
||||||
self.context.report_lint(&INVALID_TYPE_FORM, subscript)
|
|
||||||
{
|
|
||||||
builder.into_diagnostic(format_args!(
|
|
||||||
"Type qualifier `{type_qualifier}` expected exactly 1 argument, \
|
|
||||||
got {num_arguments}",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Type::unknown().into()
|
|
||||||
};
|
|
||||||
|
|
||||||
if slice.is_tuple_expr() {
|
|
||||||
self.store_expression_type(slice, type_and_qualifiers.inner_type());
|
|
||||||
}
|
|
||||||
|
|
||||||
type_and_qualifiers
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => self
|
|
||||||
.infer_subscript_type_expression_no_store(subscript, slice, value_ty)
|
|
||||||
.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type_expr => self.infer_type_expression_no_store(type_expr).into(),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.store_expression_type(expr, ty.inner_type());
|
|
||||||
ty
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Infer the type of the `iter` expression of the first comprehension.
|
/// Infer the type of the `iter` expression of the first comprehension.
|
||||||
fn infer_first_comprehension_iter(&mut self, comprehensions: &[ast::Comprehension]) {
|
fn infer_first_comprehension_iter(&mut self, comprehensions: &[ast::Comprehension]) {
|
||||||
let mut comprehensions_iter = comprehensions.iter();
|
let mut comprehensions_iter = comprehensions.iter();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue