mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 21:34:57 +00:00
[ty] Keep track of type qualifiers in stub declarations without right-hand side (#19756)
Some checks are pending
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
Some checks are pending
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
## Summary closes https://github.com/astral-sh/ty/issues/937 ## Test Plan Regression test
This commit is contained in:
parent
2d2841e20d
commit
7df7be5c7d
2 changed files with 48 additions and 17 deletions
|
@ -38,6 +38,29 @@ c.d = 2
|
||||||
c.e = 2
|
c.e = 2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## From stubs
|
||||||
|
|
||||||
|
This is a regression test for a bug where we did not properly keep track of type qualifiers when
|
||||||
|
accessed from stub files.
|
||||||
|
|
||||||
|
`module.pyi`:
|
||||||
|
|
||||||
|
```pyi
|
||||||
|
from typing import ClassVar
|
||||||
|
|
||||||
|
class C:
|
||||||
|
a: ClassVar[int]
|
||||||
|
```
|
||||||
|
|
||||||
|
`main.py`:
|
||||||
|
|
||||||
|
```py
|
||||||
|
from module import C
|
||||||
|
|
||||||
|
c = C()
|
||||||
|
c.a = 2 # error: [invalid-attribute-access]
|
||||||
|
```
|
||||||
|
|
||||||
## Conflicting type qualifiers
|
## Conflicting type qualifiers
|
||||||
|
|
||||||
We currently ignore conflicting qualifiers and simply union them, which is more conservative than
|
We currently ignore conflicting qualifiers and simply union them, which is more conservative than
|
||||||
|
|
|
@ -694,7 +694,7 @@ enum IntersectionOn {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
enum DeclaredAndInferredType<'db> {
|
enum DeclaredAndInferredType<'db> {
|
||||||
/// We know that both the declared and inferred types are the same.
|
/// We know that both the declared and inferred types are the same.
|
||||||
AreTheSame(Type<'db>),
|
AreTheSame(TypeAndQualifiers<'db>),
|
||||||
/// Declared and inferred types might be different, we need to check assignability.
|
/// Declared and inferred types might be different, we need to check assignability.
|
||||||
MightBeDifferent {
|
MightBeDifferent {
|
||||||
declared_ty: TypeAndQualifiers<'db>,
|
declared_ty: TypeAndQualifiers<'db>,
|
||||||
|
@ -702,6 +702,12 @@ enum DeclaredAndInferredType<'db> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'db> DeclaredAndInferredType<'db> {
|
||||||
|
fn are_the_same_type(ty: Type<'db>) -> Self {
|
||||||
|
Self::AreTheSame(ty.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Builder to infer all types in a region.
|
/// Builder to infer all types in a region.
|
||||||
///
|
///
|
||||||
/// A builder is used by creating it with [`new()`](TypeInferenceBuilder::new), and then calling
|
/// A builder is used by creating it with [`new()`](TypeInferenceBuilder::new), and then calling
|
||||||
|
@ -2132,7 +2138,9 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let (declared_ty, inferred_ty) = match *declared_and_inferred_ty {
|
let (declared_ty, inferred_ty) = match *declared_and_inferred_ty {
|
||||||
DeclaredAndInferredType::AreTheSame(ty) => (ty.into(), ty),
|
DeclaredAndInferredType::AreTheSame(type_and_qualifiers) => {
|
||||||
|
(type_and_qualifiers, type_and_qualifiers.inner_type())
|
||||||
|
}
|
||||||
DeclaredAndInferredType::MightBeDifferent {
|
DeclaredAndInferredType::MightBeDifferent {
|
||||||
declared_ty,
|
declared_ty,
|
||||||
inferred_ty,
|
inferred_ty,
|
||||||
|
@ -2191,7 +2199,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
node,
|
node,
|
||||||
definition,
|
definition,
|
||||||
&DeclaredAndInferredType::AreTheSame(Type::unknown()),
|
&DeclaredAndInferredType::are_the_same_type(Type::unknown()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2658,7 +2666,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
function.into(),
|
function.into(),
|
||||||
definition,
|
definition,
|
||||||
&DeclaredAndInferredType::AreTheSame(inferred_ty),
|
&DeclaredAndInferredType::are_the_same_type(inferred_ty),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2818,7 +2826,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.is_some_and(|d| d.is_ellipsis_literal_expr())
|
.is_some_and(|d| d.is_ellipsis_literal_expr())
|
||||||
{
|
{
|
||||||
DeclaredAndInferredType::AreTheSame(declared_ty)
|
DeclaredAndInferredType::are_the_same_type(declared_ty)
|
||||||
} else {
|
} else {
|
||||||
if let Some(builder) = self
|
if let Some(builder) = self
|
||||||
.context
|
.context
|
||||||
|
@ -2831,10 +2839,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
declared_ty.display(self.db())
|
declared_ty.display(self.db())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
DeclaredAndInferredType::AreTheSame(declared_ty)
|
DeclaredAndInferredType::are_the_same_type(declared_ty)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DeclaredAndInferredType::AreTheSame(declared_ty)
|
DeclaredAndInferredType::are_the_same_type(declared_ty)
|
||||||
};
|
};
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
parameter.into(),
|
parameter.into(),
|
||||||
|
@ -2874,7 +2882,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
parameter.into(),
|
parameter.into(),
|
||||||
definition,
|
definition,
|
||||||
&DeclaredAndInferredType::AreTheSame(ty),
|
&DeclaredAndInferredType::are_the_same_type(ty),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
self.add_binding(
|
self.add_binding(
|
||||||
|
@ -2906,7 +2914,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
parameter.into(),
|
parameter.into(),
|
||||||
definition,
|
definition,
|
||||||
&DeclaredAndInferredType::AreTheSame(ty),
|
&DeclaredAndInferredType::are_the_same_type(ty),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
self.add_binding(
|
self.add_binding(
|
||||||
|
@ -3004,7 +3012,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
class_node.into(),
|
class_node.into(),
|
||||||
definition,
|
definition,
|
||||||
&DeclaredAndInferredType::AreTheSame(class_ty),
|
&DeclaredAndInferredType::are_the_same_type(class_ty),
|
||||||
);
|
);
|
||||||
|
|
||||||
// if there are type parameters, then the keywords and bases are within that scope
|
// if there are type parameters, then the keywords and bases are within that scope
|
||||||
|
@ -3078,7 +3086,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
type_alias.into(),
|
type_alias.into(),
|
||||||
definition,
|
definition,
|
||||||
&DeclaredAndInferredType::AreTheSame(type_alias_ty),
|
&DeclaredAndInferredType::are_the_same_type(type_alias_ty),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3433,7 +3441,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
node.into(),
|
node.into(),
|
||||||
definition,
|
definition,
|
||||||
&DeclaredAndInferredType::AreTheSame(ty),
|
&DeclaredAndInferredType::are_the_same_type(ty),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3453,7 +3461,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
node.into(),
|
node.into(),
|
||||||
definition,
|
definition,
|
||||||
&DeclaredAndInferredType::AreTheSame(pep_695_todo),
|
&DeclaredAndInferredType::are_the_same_type(pep_695_todo),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3473,7 +3481,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
node.into(),
|
node.into(),
|
||||||
definition,
|
definition,
|
||||||
&DeclaredAndInferredType::AreTheSame(pep_695_todo),
|
&DeclaredAndInferredType::are_the_same_type(pep_695_todo),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4558,7 +4566,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
target.into(),
|
target.into(),
|
||||||
definition,
|
definition,
|
||||||
&DeclaredAndInferredType::AreTheSame(declared.inner_type()),
|
&DeclaredAndInferredType::AreTheSame(declared),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
self.add_declaration(target.into(), definition, declared);
|
self.add_declaration(target.into(), definition, declared);
|
||||||
|
@ -4876,7 +4884,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
alias.into(),
|
alias.into(),
|
||||||
definition,
|
definition,
|
||||||
&DeclaredAndInferredType::AreTheSame(binding_ty),
|
&DeclaredAndInferredType::are_the_same_type(binding_ty),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5125,7 +5133,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
alias.into(),
|
alias.into(),
|
||||||
definition,
|
definition,
|
||||||
&DeclaredAndInferredType::AreTheSame(submodule_type),
|
&DeclaredAndInferredType::are_the_same_type(submodule_type),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue