Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[red-knot] implement eval_symbol for from-import and class-def #11157

Merged
merged 4 commits into from
Apr 26, 2024

Conversation

carljm
Copy link
Contributor

@carljm carljm commented Apr 26, 2024

This PR demonstrates resolving an import from one module to a class type from another module!

Copy link
Contributor

github-actions bot commented Apr 26, 2024

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Comment on lines 17 to 23
if let Some(ty) = db
.jar()
.type_store
.get_cached_symbol_type(file_id, symbol_id)
{
return ty;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is allowing multiple threads to race resolution intentional if we don't have a cache hit? Or how does the locking work here between: No cache entry found and writing a new cache entry.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great question. Currently of course it's "not an issue" because I was lazy and just took a mutable reference to the entire db, but as you pointed out above, that's a much bigger problem :) I will have to think more about the right strategy here. Ideally we do want to lock here to avoid multiple threads racing to resolve the same symbol, but ideally we want it to be somewhat fine-grained. But keeping a lock for every symbol might be too much.

crates/red_knot/src/types/eval.rs Outdated Show resolved Hide resolved
Comment on lines 51 to 67
if let Some(ty) = db.jar().type_store.get_cached_node_type(file_id, node_key) {
ty
} else {
let parsed = db.parse(file_id);
let ast = parsed.ast();
let node = StmtClassDef::cast_ref(
node_key
.resolve(ast.as_any_node_ref())
.expect("node key should resolve"),
)
.expect("node key should cast");

let store = &mut db.jar_mut().type_store;
let ty = store.add_class(file_id, &node.name.id);
store.cache_node_type(file_id, *node_key, ty);
ty
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit

Suggested change
if let Some(ty) = db.jar().type_store.get_cached_node_type(file_id, node_key) {
ty
} else {
let parsed = db.parse(file_id);
let ast = parsed.ast();
let node = StmtClassDef::cast_ref(
node_key
.resolve(ast.as_any_node_ref())
.expect("node key should resolve"),
)
.expect("node key should cast");
let store = &mut db.jar_mut().type_store;
let ty = store.add_class(file_id, &node.name.id);
store.cache_node_type(file_id, *node_key, ty);
ty
}
let Some(ty) = db.jar().type_store.get_cached_node_type(file_id, node_key) else {
let parsed = db.parse(file_id);
let ast = parsed.ast();
let node = StmtClassDef::cast_ref(
node_key
.resolve(ast.as_any_node_ref())
.expect("node key should resolve"),
)
.expect("node key should cast");
let store = &mut db.jar_mut().type_store;
let ty = store.add_class(file_id, &node.name.id);
store.cache_node_type(file_id, *node_key, ty);
ty
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suggested change here doesn't work as-is, because this arm of the match needs to actually evaluate to a Type (ty). From what I can tell, it seems like let-else is for cases where the else diverges, but doesn't evaluate to an expression. I could restructure this to use a mutable ty I guess, but that doesn't seem like an improvement over the if-let-else I have now.

Let me know if I'm missing a way for this suggestion to work out better than the if-let-else!

Comment on lines 37 to 38

fn eval_symbol(&mut self, file_id: FileId, symbol_id: SymbolId) -> Type;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a query and not a mutation

  • Move up to other queries
  • Change self to take a readonly reference.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes agreed, I'll make this update, and use internal mutability on the type store for the caching instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to do this in a follow up

Copy link
Member

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can follow up on proper synchronization if we add a FIXME

Base automatically changed from cjm/red-knot/type-arenas to red-knot April 26, 2024 18:54
@carljm carljm force-pushed the cjm/red-knot/type-eval branch from 7134d44 to 8898486 Compare April 26, 2024 18:59
@carljm carljm added the internal An internal refactor or improvement label Apr 26, 2024
@carljm carljm merged commit 1ec66d9 into red-knot Apr 26, 2024
18 checks passed
@carljm carljm deleted the cjm/red-knot/type-eval branch April 26, 2024 20:05
MichaReiser pushed a commit that referenced this pull request Apr 27, 2024
This PR demonstrates resolving an import from one module to a class type
from another module!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
internal An internal refactor or improvement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants