mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 10:23:11 +00:00
[red-knot] Fix panic on cyclic *
imports (#16958)
## Summary Further work towards https://github.com/astral-sh/ruff/issues/14169. We currently panic on encountering cyclic `*` imports. This is easily fixed using fixpoint iteration. ## Test Plan Added a test that panics on `main`, but passes with this PR
This commit is contained in:
parent
dd5b02aaa2
commit
4975c2f027
2 changed files with 47 additions and 1 deletions
|
@ -834,6 +834,35 @@ reveal_type(g) # revealed: Unknown
|
|||
reveal_type(h) # revealed: Unknown
|
||||
```
|
||||
|
||||
## Cyclic star imports
|
||||
|
||||
Believe it or not, this code does _not_ raise an exception at runtime!
|
||||
|
||||
`a.py`:
|
||||
|
||||
```py
|
||||
from b import *
|
||||
|
||||
A: bool = True
|
||||
```
|
||||
|
||||
`b.py`:
|
||||
|
||||
```py
|
||||
from a import *
|
||||
|
||||
B: bool = True
|
||||
```
|
||||
|
||||
`c.py`:
|
||||
|
||||
```py
|
||||
from a import *
|
||||
|
||||
reveal_type(A) # revealed: bool
|
||||
reveal_type(B) # revealed: bool
|
||||
```
|
||||
|
||||
## Integration test: `collections.abc`
|
||||
|
||||
The `collections.abc` standard-library module provides a good integration test, as all its symbols
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
//! separate query, we would need to complete semantic indexing on `bar` in order to
|
||||
//! complete analysis of the global namespace of `foo`. Since semantic indexing is somewhat
|
||||
//! expensive, this would be undesirable. A separate query allows us to avoid this issue.
|
||||
//!
|
||||
//! An additional concern is that the recursive nature of this query means that it must be able
|
||||
//! to handle cycles. We do this using fixpoint iteration; adding fixpoint iteration to the
|
||||
//! whole [`super::semantic_index()`] query would probably be prohibitively expensive.
|
||||
|
||||
use ruff_db::{files::File, parsed::parsed_module};
|
||||
use ruff_python_ast::{
|
||||
|
@ -26,7 +30,20 @@ use rustc_hash::FxHashSet;
|
|||
|
||||
use crate::{module_name::ModuleName, resolve_module, Db};
|
||||
|
||||
#[salsa::tracked(return_ref)]
|
||||
fn exports_cycle_recover(
|
||||
_db: &dyn Db,
|
||||
_value: &FxHashSet<Name>,
|
||||
_count: u32,
|
||||
_file: File,
|
||||
) -> salsa::CycleRecoveryAction<FxHashSet<Name>> {
|
||||
salsa::CycleRecoveryAction::Iterate
|
||||
}
|
||||
|
||||
fn exports_cycle_initial(_db: &dyn Db, _file: File) -> FxHashSet<Name> {
|
||||
FxHashSet::default()
|
||||
}
|
||||
|
||||
#[salsa::tracked(return_ref, cycle_fn=exports_cycle_recover, cycle_initial=exports_cycle_initial)]
|
||||
pub(super) fn exported_names(db: &dyn Db, file: File) -> FxHashSet<Name> {
|
||||
let module = parsed_module(db.upcast(), file);
|
||||
let mut finder = ExportFinder::new(db, file);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue