mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 21:05:08 +00:00
[ty] Add cycle handling for unpacking targets (#18078)
Some checks are pending
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 / 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 / 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 (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
Some checks are pending
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 / 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 / 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 (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
## Summary This PR adds cycle handling for `infer_unpack_types` based on the analysis in astral-sh/ty#364. Fixes: astral-sh/ty#364 ## Test Plan Add a cycle handling test for unpacking in `cycle.md`
This commit is contained in:
parent
65e48cb439
commit
8cbd433a31
3 changed files with 60 additions and 3 deletions
|
@ -307,7 +307,7 @@ fn single_expression_cycle_initial<'db>(
|
|||
/// involved in an unpacking operation. It returns a result-like object that can be used to get the
|
||||
/// type of the variables involved in this unpacking along with any violations that are detected
|
||||
/// during this unpacking.
|
||||
#[salsa::tracked(returns(ref))]
|
||||
#[salsa::tracked(returns(ref), cycle_fn=unpack_cycle_recover, cycle_initial=unpack_cycle_initial)]
|
||||
pub(super) fn infer_unpack_types<'db>(db: &'db dyn Db, unpack: Unpack<'db>) -> UnpackResult<'db> {
|
||||
let file = unpack.file(db);
|
||||
let _span =
|
||||
|
@ -318,6 +318,19 @@ pub(super) fn infer_unpack_types<'db>(db: &'db dyn Db, unpack: Unpack<'db>) -> U
|
|||
unpacker.finish()
|
||||
}
|
||||
|
||||
fn unpack_cycle_recover<'db>(
|
||||
_db: &'db dyn Db,
|
||||
_value: &UnpackResult<'db>,
|
||||
_count: u32,
|
||||
_unpack: Unpack<'db>,
|
||||
) -> salsa::CycleRecoveryAction<UnpackResult<'db>> {
|
||||
salsa::CycleRecoveryAction::Iterate
|
||||
}
|
||||
|
||||
fn unpack_cycle_initial<'db>(_db: &'db dyn Db, _unpack: Unpack<'db>) -> UnpackResult<'db> {
|
||||
UnpackResult::cycle_fallback(Type::Never)
|
||||
}
|
||||
|
||||
/// Returns the type of the nearest enclosing class for the given scope.
|
||||
///
|
||||
/// This function walks up the ancestor scopes starting from the given scope,
|
||||
|
|
|
@ -287,6 +287,7 @@ impl<'db> Unpacker<'db> {
|
|||
UnpackResult {
|
||||
diagnostics: self.context.finish(),
|
||||
targets: self.targets,
|
||||
cycle_fallback_type: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -295,21 +296,46 @@ impl<'db> Unpacker<'db> {
|
|||
pub(crate) struct UnpackResult<'db> {
|
||||
targets: FxHashMap<ScopedExpressionId, Type<'db>>,
|
||||
diagnostics: TypeCheckDiagnostics,
|
||||
|
||||
/// The fallback type for missing expressions.
|
||||
///
|
||||
/// This is used only when constructing a cycle-recovery `UnpackResult`.
|
||||
cycle_fallback_type: Option<Type<'db>>,
|
||||
}
|
||||
|
||||
impl<'db> UnpackResult<'db> {
|
||||
/// Returns the inferred type for a given sub-expression of the left-hand side target
|
||||
/// of an unpacking assignment.
|
||||
///
|
||||
/// Panics if a scoped expression ID is passed in that does not correspond to a sub-
|
||||
/// # Panics
|
||||
///
|
||||
/// May panic if a scoped expression ID is passed in that does not correspond to a sub-
|
||||
/// expression of the target.
|
||||
#[track_caller]
|
||||
pub(crate) fn expression_type(&self, expr_id: ScopedExpressionId) -> Type<'db> {
|
||||
self.targets[&expr_id]
|
||||
self.try_expression_type(expr_id).expect(
|
||||
"expression should belong to this `UnpackResult` and \
|
||||
`Unpacker` should have inferred a type for it",
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn try_expression_type(&self, expr_id: ScopedExpressionId) -> Option<Type<'db>> {
|
||||
self.targets
|
||||
.get(&expr_id)
|
||||
.copied()
|
||||
.or(self.cycle_fallback_type)
|
||||
}
|
||||
|
||||
/// Returns the diagnostics in this unpacking assignment.
|
||||
pub(crate) fn diagnostics(&self) -> &TypeCheckDiagnostics {
|
||||
&self.diagnostics
|
||||
}
|
||||
|
||||
pub(crate) fn cycle_fallback(cycle_fallback_type: Type<'db>) -> Self {
|
||||
Self {
|
||||
targets: FxHashMap::default(),
|
||||
diagnostics: TypeCheckDiagnostics::default(),
|
||||
cycle_fallback_type: Some(cycle_fallback_type),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue