Skip to content

Commit 81a6c54

Browse files
yangdanny97meta-codesync[bot]
authored andcommitted
add unannotated-attribute error kind
Summary: closes #1779 Reviewed By: stroxler Differential Revision: D88562236 fbshipit-source-id: b6a89b1a615cf7e81ff5fc3daf5799c16be1f195
1 parent 5701322 commit 81a6c54

File tree

5 files changed

+31
-2
lines changed

5 files changed

+31
-2
lines changed

crates/pyrefly_config/src/error_kind.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ pub enum ErrorKind {
232232
RedundantCondition,
233233
/// Raised by a call to reveal_type().
234234
RevealType,
235+
/// An attribute is missing a type annotation and is initialized with the `None` literal.
236+
UnannotatedAttribute,
235237
/// A function parameter is missing a type annotation.
236238
UnannotatedParameter,
237239
/// A function is missing a return type annotation.
@@ -304,6 +306,7 @@ impl ErrorKind {
304306
ErrorKind::ImplicitAny => Severity::Ignore,
305307
ErrorKind::UnannotatedParameter => Severity::Ignore,
306308
ErrorKind::UnannotatedReturn => Severity::Ignore,
309+
ErrorKind::UnannotatedAttribute => Severity::Ignore,
307310
ErrorKind::MissingSource => Severity::Ignore,
308311
ErrorKind::OpenUnpacking => Severity::Ignore,
309312
_ => Severity::Error,

pyrefly/lib/alt/class/class_field.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1737,7 +1737,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
17371737
}
17381738
// We interpret `self.foo = None` to mean the type of foo is None or some unknown type.
17391739
(None, Expr::NoneLiteral(_)) => {
1740-
self.error(errors, x.range(), ErrorInfo::Kind(ErrorKind::ImplicitAny), "This expression is implicitly inferred to be `Any | None`. Please provide an explicit type annotation.".to_owned());
1740+
self.error(errors, x.range(), ErrorInfo::Kind(ErrorKind::UnannotatedAttribute), "This expression is implicitly inferred to be `Any | None`. Please provide an explicit type annotation.".to_owned());
17411741
self.union(Type::None, Type::any_implicit())
17421742
}
17431743
(None, _) => self.expr_infer(x, errors),

pyrefly/lib/test/inference.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ x2 = {}
9797

9898
testcase!(
9999
test_warn_on_implicit_any_in_attribute,
100-
TestEnv::new().enable_implicit_any_error(),
100+
TestEnv::new().enable_unannotated_attribute_error(),
101101
r#"
102102
from typing import Any
103103
class A:

pyrefly/lib/test/util.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ pub struct TestEnv {
108108
implicit_any_error: bool,
109109
unannotated_return_error: bool,
110110
unannotated_parameter_error: bool,
111+
unannotated_attribute_error: bool,
111112
implicit_abstract_class_error: bool,
112113
open_unpacking_error: bool,
113114
default_require_level: Require,
@@ -127,6 +128,7 @@ impl TestEnv {
127128
implicit_any_error: false,
128129
unannotated_return_error: false,
129130
unannotated_parameter_error: false,
131+
unannotated_attribute_error: false,
130132
implicit_abstract_class_error: false,
131133
open_unpacking_error: false,
132134
default_require_level: Require::Exports,
@@ -167,6 +169,11 @@ impl TestEnv {
167169
self
168170
}
169171

172+
pub fn enable_unannotated_attribute_error(mut self) -> Self {
173+
self.unannotated_attribute_error = true;
174+
self
175+
}
176+
170177
pub fn enable_unannotated_return_error(mut self) -> Self {
171178
self.unannotated_return_error = true;
172179
self
@@ -268,6 +275,9 @@ impl TestEnv {
268275
if self.implicit_any_error {
269276
errors.set_error_severity(ErrorKind::ImplicitAny, Severity::Error);
270277
}
278+
if self.unannotated_attribute_error {
279+
errors.set_error_severity(ErrorKind::UnannotatedAttribute, Severity::Error);
280+
}
271281
if self.unannotated_return_error {
272282
errors.set_error_severity(ErrorKind::UnannotatedReturn, Severity::Error);
273283
}

website/docs/error-kinds.mdx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,22 @@ if "abc":
975975

976976
Pyrefly uses this error to communicate the output of the [`reveal_type`](https://typing.python.org/en/latest/spec/directives.html#reveal-type) function.
977977

978+
## unannotated-attribute
979+
980+
This error is raised when a class attribute is missing a type annotation and is initialized with the `None` literal. Without an explicit annotation, Pyrefly infers the type as `Any | None`, which reduces type safety.
981+
982+
This error is off by default. To fix it, add an explicit type annotation to the attribute.
983+
984+
```python
985+
class MyClass:
986+
# error: This expression is implicitly inferred to be `Any | None`. Please provide an explicit type annotation.
987+
value = None
988+
989+
# Fixed version:
990+
class MyClass:
991+
value: int | None = None
992+
```
993+
978994
## unannotated-parameter
979995

980996
This error is raised when a function parameter is missing a type annotation. This helps enforce fully-typed codebases by ensuring all parameters have explicit types.

0 commit comments

Comments
 (0)