-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
De-Gc the AST #7929
Comments
There are several side-issues with making the AST map work "properly". For one, since it contains Much of the current code isn't designed to deal with these kinds of structures, happily copying around While unpalatable, a map based on unsafe pointers may help us, at least as a bridging solution until the rest of the code is brought up to a place where a safe-code map can be used instead. My idea is to integrate the map into a wrapper for the AST, to limit the potential for, uh, bad things to happen. A simple struct like this: struct ASTData {
crate: ast::crate,
priv map: ast_map::Map
} With methods like this: fn find<'a>(&'a self, node: node_id) -> Option<&'a node>; The only place (as far as I am aware) the AST undergoes structural changes is during folding. Thus, folding can maintain the AST map. There is very little code that absolutely requires The current AST map is The design above should be fairly safe as the pointers held in the map are "internal" pointers to the map's owner, meaning it's unlikely end up with dangling pointers. |
I actually don't know that |
@nikomatsakis as long as it can be semantically owned (so folding is memory efficient, it can be sent across task boundaries, etc) then I don't really care how it's implemented. Finishing the lifetime syntax would be very nice too 😄 |
Probably not enough code that uses it for it to be an issue yet ... but would you forsee a need for seperate compiler & tools AST structure/interfaces - similar to how clang provides a stable C interface and a more fully featured , but more rapidly changing internal representation. r.e. tools, are there any ideas on how incremental build might go - with C++ although the header situation is pretty dire, you can at least translate individual sources - wheras at present you must compile an entire crate. Perhaps a tools oriented AST could be more suited to incremental builds? (for ide support). (perhaps there are other issues more suitable for this question) |
@nikomatsakis given that said work seems to be being finished, is it time to reapproach this? Probably not a 1.0 priority, as it certainly has no bearing on the language itself, but it seems it will be necessary to get rustc memory usage reasonable. |
Well, PR #10153 has not yet landed (still under review) but yes it might be reasonable to experiment once it does. |
On Fri, Nov 08, 2013 at 12:18:45AM -0800, Corey Richardson wrote:
...though I'm not sure I agree with this particular statement. It Nonetheless, I don't think the AST is correctly structured today, just
Looking forward, I would (maybe) like to eventually convert from one That said, what I'd REALLY like to do is to desugar from the AST into |
cc me |
I would like to replace all uses of
|
@eddyb what is the motivation to make this change? The fact that some users want to take ownership of what they are passed seems like a good reason for keeping it the way it is. |
@nikomatsakis it's an extra cost (ref-counting right now) for all visitors and changing |
(The AST now has |
Replaces Gc<T> in the AST with a custom owned smart pointer, P<T>. Fixes #7929. ## Benefits * **Identity** (affinity?): sharing AST nodes is bad for the various analysis passes (e.g. one could bypass borrowck with a shared `ExprAddrOf` node taking a mutable borrow), the only reason we haven't hit any serious issues with it is because of inefficient folding passes which will always deduplicate any such shared nodes. Even if we were to switch to an arena, this would still hold, i.e. we wouldn't just use `&'a T` in the AST, but rather an wrapper (`P<'a, T>`?). * **Immutability**: `P<T>` disallows mutating its inner `T` (unless that contains an `Unsafe` interior, which won't happen in the AST), unlike `~T`. * **Efficiency**: folding can reuse allocation space for `P<T>` and `Vec<T>`, the latter even when the input and output types differ (as it would be the case with arenas or an AST with type parameters to toggle macro support). Also, various algorithms have been changed from copying `Gc<T>` to using `&T` and iterators. * **Maintainability**: there is another reason I didn't just replace `Gc<T>` with `~T`: `P<T>` provides a fixed interface (`Deref`, `and_then` and `map`) which can remain fully functional even if the implementation changes (using a special thread-local heap, for example). Moreover, switching to, e.g. `P<'a, T>` (for a contextual arena) is easy and mostly automated.
Rustup r? `@ghost` changelog: none
fix: make custom expr prefix completions to understand refs Possible fix of rust-lang#7929 While reviewing the postfix completion code I saw that while calling `add_custom_postfix_completions` we were doing it under the part where reference was not taken into consideration, but as we are only adding postfix completions with `Expr` scope ( [source](https://github.com/rust-lang/rust-analyzer/blob/ba28e19b7838e3ad4223ae82d074dc3950ef1548/crates/ide-completion/src/completions/postfix.rs#L272) ) I shifted the `add_custom_postfix_completions` call to part where references are considered I am not sure if this is the correct fix or I am understanding the problem exactly but this small move seemed to have fixed the issue :)
…hievink fix: breaking snippets on typed incomplete suggestions Possible fix for rust-lang#7929 Fix the case where if a user types `&&42.o`, snippet completion was still applying &&Ok(42). Note this was fixed previously on `&&42.` but this still remained a problem for this case Previous relevant PR: rust-lang#13517 ### Points to help in review: - The main problem why everything broke on adding an extra `o` was, earlier `dot_receiver` was `42.` which was a `LITERAL` but now `42.o` becomes a `FIELD_EXPR` - Till now `include_references` was just checking for parent of `LITERAL` and if it was a `REF_EXPR`, but now we consider `FIELD_EXPR` and traverse all of them, finally to reach `REF_EXPR`. If `REF_EXPR` is not found we just return the original `initial_element` - We are constructing a new node during `include_references` because if we rely on `dot_receiver` solely we would get `&&42.o` to be replaced with, but we want `&&42` to be replaced with ### Output Video: https://user-images.githubusercontent.com/49019259/205420166-efbdef78-5b3a-4aef-ab4b-d892dac056a0.mov Hope everything I wrote makes sense 😅 Also interestingly previous PR's number was `13517` and this PR's number is `13715`, nicee
It would be really nice to have an AST that was a tree with
~
. This would have countless advantages, like the ast-fold could consume the AST and only allocate if it is actually creating a new node, and we'd generally not have the problems associated withGc
(the GC might be able to land!).However, there are a few areas that are very tricky; mainly the AST map, which maps
node_id
to actual AST nodes of various types, the only safe way to do this with an~
tree is with&
references... which freezes the AST for the remainder of the program, so no transformations like constant evaluation, and no consuming of the AST by trans.The text was updated successfully, but these errors were encountered: