mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 10:48:32 +00:00
[ty] Fix attribute writes to unions/intersections including modules (#18313)
## Summary Fix a bug that involved writes to attributes on union/intersection types that included modules as elements. This is a prerequisite to avoid some ecosystem false positives in https://github.com/astral-sh/ruff/pull/18312 ## Test Plan Added regression test
This commit is contained in:
parent
fbaf826a9d
commit
7eca6f96e3
2 changed files with 53 additions and 16 deletions
|
@ -1698,6 +1698,36 @@ reveal_type(outer.nested.inner.Outer.Nested.Inner.attr) # revealed: int
|
|||
outer.nested.inner.Outer.Nested.Inner.attr = "a"
|
||||
```
|
||||
|
||||
### Unions of module attributes
|
||||
|
||||
`mod1.py`:
|
||||
|
||||
```py
|
||||
global_symbol: str = "a"
|
||||
```
|
||||
|
||||
`mod2.py`:
|
||||
|
||||
```py
|
||||
global_symbol: str = "a"
|
||||
```
|
||||
|
||||
```py
|
||||
import mod1
|
||||
import mod2
|
||||
|
||||
def _(flag: bool):
|
||||
if flag:
|
||||
mod = mod1
|
||||
else:
|
||||
mod = mod2
|
||||
|
||||
mod.global_symbol = "b"
|
||||
|
||||
# error: [invalid-assignment] "Object of type `Literal[1]` is not assignable to attribute `global_symbol` on type `<module 'mod1'> | <module 'mod2'>`"
|
||||
mod.global_symbol = 1
|
||||
```
|
||||
|
||||
## Literal types
|
||||
|
||||
### Function-literal attributes
|
||||
|
|
|
@ -3406,24 +3406,31 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
Type::ModuleLiteral(module) => {
|
||||
if let Symbol::Type(attr_ty, _) = module.static_member(db, attribute) {
|
||||
let assignable = value_ty.is_assignable_to(db, attr_ty);
|
||||
if !assignable {
|
||||
report_invalid_attribute_assignment(
|
||||
&self.context,
|
||||
target.into(),
|
||||
attr_ty,
|
||||
value_ty,
|
||||
attribute,
|
||||
);
|
||||
if assignable {
|
||||
true
|
||||
} else {
|
||||
if emit_diagnostics {
|
||||
report_invalid_attribute_assignment(
|
||||
&self.context,
|
||||
target.into(),
|
||||
attr_ty,
|
||||
value_ty,
|
||||
attribute,
|
||||
);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
false
|
||||
} else {
|
||||
if let Some(builder) = self.context.report_lint(&UNRESOLVED_ATTRIBUTE, target) {
|
||||
builder.into_diagnostic(format_args!(
|
||||
"Unresolved attribute `{}` on type `{}`.",
|
||||
attribute,
|
||||
object_ty.display(db)
|
||||
));
|
||||
if emit_diagnostics {
|
||||
if let Some(builder) =
|
||||
self.context.report_lint(&UNRESOLVED_ATTRIBUTE, target)
|
||||
{
|
||||
builder.into_diagnostic(format_args!(
|
||||
"Unresolved attribute `{}` on type `{}`.",
|
||||
attribute,
|
||||
object_ty.display(db)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue