-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Introduce Semantics API #3222
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
Introduce Semantics API #3222
Conversation
crates/ra_hir/src/semantics.rs
Outdated
let prev = cache.insert(root_node, file_id); | ||
assert!(prev.is_none()); | ||
} | ||
fn lookup(&self, root_node: &SyntaxNode) -> HirFileId { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this name should be more specific.
Seems like an improvement to me! |
48ce3ad
to
ca119f4
Compare
ported syntax highlighting to |
ac91f9c
to
3492bb5
Compare
crates/ra_hir/src/semantics.rs
Outdated
|
||
pub struct Semantics<'db, DB> { | ||
pub db: &'db DB, | ||
sb: RefCell<SourceBinder<'db, DB>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wish we could avoid RefCell
for SourceBinder
here...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the perfect use-case for RefCell actually. Or, rather, it was an API mistake to not use RefCell
in the SourceBinder
in the first place.
This type is not thread safe (as it stores syntax nodes) and in general is transient in nature. Additionally, what RefCell
guards here are essentially caches. From the consumers pov, this looks like an immutable data structure. And &T
APIs are much more convenient to use than &mut T
APIs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So should we use RefCell<FxHashMap<...>>
here inside of SourceBinder
instead?https://github.com/rust-analyzer/rust-analyzer/blob/1fe48a0115c24240f5a3e1b329e642f18e2715d6/crates/ra_hir/src/source_binder.rs#L23-L26
Yeah, both sa and sb should just go away as a result of this refactoring .
…On Tuesday, 25 February 2020, Veetaha ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In crates/ra_hir/src/semantics.rs
<#3222 (comment)>
:
> +use std::{cell::RefCell, fmt, iter::successors};
+
+use ra_db::{FileId, FileRange};
+use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange};
+use rustc_hash::{FxHashMap, FxHashSet};
+
+use crate::{
+ db::HirDatabase, source_analyzer::ReferenceDescriptor, source_binder::ToDef, Function,
+ HirFileId, InFile, MacroDef, Module, Name, Origin, PathResolution, ScopeDef, SourceAnalyzer,
+ SourceBinder, StructField, Type, VariantDef,
+};
+use hir_def::TraitId;
+
+pub struct Semantics<'db, DB> {
+ pub db: &'db DB,
+ sb: RefCell<SourceBinder<'db, DB>>,
So should we use RefCell<FxHashMap<...>> here inside of SourceBinder
instead?https://github.com/rust-analyzer/rust-analyzer/blob/
1fe48a0/crates/ra_hir/src/
source_binder.rs#L23-L26
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#3222>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AANB3MZMPFFVNMLFQEXOVKDRETV2VANCNFSM4KXJFIGQ>
.
|
Another interesting API i've discovered during the work: |
@matklad |
Yeah, that sounds like a good solution 🤔 |
crates/ra_assists/src/assist_ctx.rs
Outdated
pub(crate) struct AssistCtx<'a> { | ||
// FIXME: Rc does not make much sense here | ||
pub(crate) sema: Rc<Semantics<'a, RootDatabase>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It made sense when you put it here or what did you want to say?
957b2f3
to
1cbd839
Compare
I think this is ready for review @flodiebold ! The public API looks good to me: we now have a single The implementation is unfortunatelly still split between sa, sb and semantics :( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks really nice! Much more straightforward than before.
|
||
let result = expr_ty.autoderef(db).find_map(|ty| match ty.as_adt() { | ||
fn resolve_enum_def(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<hir::Enum> { | ||
sema.type_of_expr(&expr)?.autoderef(sema.db).find_map(|ty| match ty.as_adt() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(btw, I think the use of autoderef
isn't quite correct here -- since this is about match
, we should have something that just strips references. We don't want to apply the Deref trait, for example)
crates/ra_hir/src/semantics.rs
Outdated
} | ||
|
||
fn analyze2(&self, src: InFile<&SyntaxNode>, offset: Option<TextUnit>) -> SourceAnalyzer { | ||
let _p = profile("SourceBinder::analyzer"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let _p = profile("SourceBinder::analyzer"); | |
let _p = profile("Semantics::analyze2"); |
?
let file_id = self.lookup(&root_node).unwrap_or_else(|| { | ||
panic!( | ||
"\n\nFailed to lookup {:?} in this Semantics.\n\ | ||
Make sure to use only query nodes, derived from this instance of Semantics.\n\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this requirement is the only thing that worries me. I guess we'll see how problematic it is in practice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah... A path forward is to add that u32
to rowan, as we originally planned, and add an interned query for TreeProvenance
or some such.
} | ||
|
||
/// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type | ||
// FIXME: rename to visible_traits to not repeat scope? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems a better name, yeah
@@ -56,6 +56,11 @@ pub fn find_covering_element(root: &SyntaxNode, range: TextRange) -> SyntaxEleme | |||
root.covering_element(range) | |||
} | |||
|
|||
pub fn least_common_ancestor(u: &SyntaxNode, v: &SyntaxNode) -> Option<SyntaxNode> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat !
This introduces the new type -- Semantics. Semantics maps SyntaxNodes to various semantic info, such as type, name resolution or macro expansions. To do so, Semantics maintains a HashMap which maps every node it saw to the file from which the node originated. This is enough to get all the necessary hir bits just from syntax.
bors r+ |
Based on ideas in https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0/topic/Design.20question.3A.20identity.20in.20syntax.20trees