mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-09 21:28:04 +00:00
[ty] Detect illegal non-enum attribute accesses in Literal annotation
This commit is contained in:
parent
897889d1ce
commit
cbc8c08016
3 changed files with 28 additions and 8 deletions
|
@ -51,6 +51,13 @@ invalid4: Literal[
|
||||||
hello, # error: [invalid-type-form]
|
hello, # error: [invalid-type-form]
|
||||||
(1, 2, 3), # error: [invalid-type-form]
|
(1, 2, 3), # error: [invalid-type-form]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
class NotAnEnum:
|
||||||
|
x: int = 1
|
||||||
|
|
||||||
|
# error: [invalid-type-form]
|
||||||
|
def _(invalid: Literal[NotAnEnum.x]) -> None:
|
||||||
|
reveal_type(invalid) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
## Shortening unions of literals
|
## Shortening unions of literals
|
||||||
|
|
|
@ -240,3 +240,10 @@ pub(crate) fn enum_member_literals<'a, 'db: 'a>(
|
||||||
pub(crate) fn is_single_member_enum<'db>(db: &'db dyn Db, class: ClassLiteral<'db>) -> bool {
|
pub(crate) fn is_single_member_enum<'db>(db: &'db dyn Db, class: ClassLiteral<'db>) -> bool {
|
||||||
enum_metadata(db, class).is_some_and(|metadata| metadata.members.len() == 1)
|
enum_metadata(db, class).is_some_and(|metadata| metadata.members.len() == 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_enum_class<'db>(db: &'db dyn Db, ty: Type<'db>) -> bool {
|
||||||
|
match ty {
|
||||||
|
Type::ClassLiteral(class_literal) => enum_metadata(db, class_literal).is_some(),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -102,6 +102,7 @@ use crate::types::diagnostic::{
|
||||||
report_invalid_generator_function_return_type, report_invalid_return_type,
|
report_invalid_generator_function_return_type, report_invalid_return_type,
|
||||||
report_possibly_unbound_attribute,
|
report_possibly_unbound_attribute,
|
||||||
};
|
};
|
||||||
|
use crate::types::enums::{enum_metadata, is_enum_class};
|
||||||
use crate::types::function::{
|
use crate::types::function::{
|
||||||
FunctionDecorators, FunctionLiteral, FunctionType, KnownFunction, OverloadLiteral,
|
FunctionDecorators, FunctionLiteral, FunctionType, KnownFunction, OverloadLiteral,
|
||||||
};
|
};
|
||||||
|
@ -10033,7 +10034,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
|
||||||
// For enum values
|
// For enum values
|
||||||
ast::Expr::Attribute(ast::ExprAttribute { value, attr, .. }) => {
|
ast::Expr::Attribute(ast::ExprAttribute { value, attr, .. }) => {
|
||||||
let value_ty = self.infer_expression(value);
|
let value_ty = self.infer_expression(value);
|
||||||
// TODO: Check that value type is enum otherwise return None
|
|
||||||
|
if is_enum_class(self.db(), value_ty) {
|
||||||
let ty = value_ty
|
let ty = value_ty
|
||||||
.member(self.db(), &attr.id)
|
.member(self.db(), &attr.id)
|
||||||
.place
|
.place
|
||||||
|
@ -10041,6 +10043,10 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
|
||||||
.unwrap_or(Type::unknown());
|
.unwrap_or(Type::unknown());
|
||||||
self.store_expression_type(parameters, ty);
|
self.store_expression_type(parameters, ty);
|
||||||
ty
|
ty
|
||||||
|
} else {
|
||||||
|
self.store_expression_type(parameters, Type::unknown());
|
||||||
|
return Err(vec![parameters]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// for negative and positive numbers
|
// for negative and positive numbers
|
||||||
ast::Expr::UnaryOp(u)
|
ast::Expr::UnaryOp(u)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue