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

Introduce Semantics API #3222

Merged
merged 1 commit into from
Feb 26, 2020
Merged

Introduce Semantics API #3222

merged 1 commit into from
Feb 26, 2020

Conversation

let prev = cache.insert(root_node, file_id);
assert!(prev.is_none());
}
fn lookup(&self, root_node: &SyntaxNode) -> HirFileId {
Copy link
Contributor

@kjeremy kjeremy Feb 18, 2020

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.

@kjeremy
Copy link
Contributor

kjeremy commented Feb 18, 2020

Seems like an improvement to me!

@matklad matklad force-pushed the identity branch 4 times, most recently from 48ce3ad to ca119f4 Compare February 19, 2020 18:00
@matklad
Copy link
Member Author

matklad commented Feb 19, 2020

ported syntax highlighting to Semantics. It does look nicer!

@matklad matklad force-pushed the identity branch 7 times, most recently from ac91f9c to 3492bb5 Compare February 24, 2020 16:41

pub struct Semantics<'db, DB> {
pub db: &'db DB,
sb: RefCell<SourceBinder<'db, DB>>,
Copy link
Contributor

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...

Copy link
Member Author

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.

Copy link
Contributor

Choose a reason for hiding this comment

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

@matklad
Copy link
Member Author

matklad commented Feb 25, 2020 via email

@matklad
Copy link
Member Author

matklad commented Feb 25, 2020

Another interesting API i've discovered during the work: SemanticScope, which encapsulates scoping info at the given point of code. resolving ast::Path works with Semantics, resolving hir::Path needs a SemanticsScope.

@kiljacken
Copy link
Contributor

kiljacken commented Feb 25, 2020

@matklad SemanticScope seems like it would play nicely with local imports, so 👍 for that

@flodiebold
Copy link
Member

Another interesting API i've discovered during the work: SemanticScope, which encapsulates scoping info at the given point of code. resolving ast::Path works with Semantics, resolving hir::Path needs a SemanticsScope.

Yeah, that sounds like a good solution 🤔

pub(crate) struct AssistCtx<'a> {
// FIXME: Rc does not make much sense here
pub(crate) sema: Rc<Semantics<'a, RootDatabase>>,
Copy link
Contributor

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?

@matklad matklad force-pushed the identity branch 8 times, most recently from 957b2f3 to 1cbd839 Compare February 25, 2020 17:09
@matklad
Copy link
Member Author

matklad commented Feb 25, 2020

I think this is ready for review @flodiebold !

The public API looks good to me: we now have a single Semantics type, which handles all the things. We also don't really use HirFileId in public API anymore, except for HasSource trait.

The implementation is unfortunatelly still split between sa, sb and semantics :(

@matklad matklad changed the title Nth iteration of expression analysis API Introduce Semantics API Feb 25, 2020
Copy link
Member

@flodiebold flodiebold left a 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() {
Copy link
Member

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)

}

fn analyze2(&self, src: InFile<&SyntaxNode>, offset: Option<TextUnit>) -> SourceAnalyzer {
let _p = profile("SourceBinder::analyzer");
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
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\
Copy link
Member

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.

Copy link
Member Author

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?
Copy link
Member

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> {
Copy link
Member

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.
@matklad
Copy link
Member Author

matklad commented Feb 26, 2020

bors r+

@matklad matklad merged commit 5c64ad2 into rust-lang:master Feb 26, 2020
@matklad matklad deleted the identity branch February 26, 2020 12:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants