Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upAdd structs for borrow and ownership information #71
Conversation
Nashenas88
reviewed
Jun 18, 2017
| @@ -10,6 +10,6 @@ categories = ["development-tools"] | |||
| [dependencies] | |||
| rustc-serialize = "0.3" | |||
| log = "0.3" | |||
| rls-data = "= 0.4.1" | |||
| rls-data = { path = "../rls-data", default-features = true, features = ["borrows"] } | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
nrc
Jun 18, 2017
Member
v0.7 is now published, but I think we need to upgrade rustc to use that version before we can make rls-analysis use that version.
Is it necessary to specify default-features = true?
This comment has been minimized.
This comment has been minimized.
Nashenas88
Jun 20, 2017
Author
I misread the docs the first time. I thought it was necessary when overriding the features list, but it seems to not be the case. And yes, this is dependent on both rustc and rls-data. Did I mention that incorrectly in the rust-lang/rust PR?
| for (_, b) in c.per_fn_borrows.iter() { | ||
| // If we find a `BorrowData` where there's a matching scope, then filter out | ||
| // out matching items. | ||
| if b.scopes.iter().any(|a| a.ref_id == id) { |
This comment has been minimized.
This comment has been minimized.
Nashenas88
Jun 18, 2017
Author
I built BorrowData around the idea that I could quickly figure out the fn item wrapping a span. I couldn't figure out how to do that just yet. Any ideas? If it's not something that's going to be supported, I'll change per_fn_borrows to be a Vec rather than a HashMap.
This comment has been minimized.
This comment has been minimized.
nrc
Jun 18, 2017
Member
Hmm, that is not something that is easy to do (at the moment), I think. We could save a 'map' of spans to function ids, then do some kind of sub-span check to get the function id. I think that should be relatively easy if the 'map' is the correct data structure (maybe just an ordered Vec is fine, but building it would be easier if it were some kind of tree) and I think the memory overhead wouldn't be too high.
This comment has been minimized.
This comment has been minimized.
Nashenas88
Jun 21, 2017
Author
I think I have a working implementation with BTreeMap. I'll clean it up and update the PR for review after work (~10 hours from now). The implementation is ... interesting? I'll add a lot of comments to explain what's going on.
| @@ -610,6 +635,39 @@ pub struct Glob { | |||
| pub value: String, | |||
| } | |||
|
|
|||
| #[derive(Debug, Clone)] | |||
| pub struct BorrowData { | |||
This comment has been minimized.
This comment has been minimized.
Nashenas88
Jun 18, 2017
Author
Should I toggle all of this behind a feature flag like I did in rls-data?
This comment has been minimized.
This comment has been minimized.
| } | ||
| }; | ||
|
|
||
| let scopes = b.scopes.into_iter().filter_map(|a| |
This comment has been minimized.
This comment has been minimized.
Nashenas88
Jun 18, 2017
Author
This section seems a bit repetitive. Is there a simple way to clean this up, or do you think we need to worry about logging here?
This comment has been minimized.
This comment has been minimized.
Nashenas88
Jun 18, 2017
Author
Also, I was using into_iter here to avoid cloneing everything. Is that a bad idea?
This comment has been minimized.
This comment has been minimized.
nrc
Jun 18, 2017
Member
Also, I was using into_iter here to avoid cloneing everything. Is that a bad idea?
No, that is a good thing to do
This comment has been minimized.
This comment has been minimized.
nrc
Jun 18, 2017
Member
An easy refactoring would be to factor out lower functions to map rls-data structs to rls-analysis ones. A better, but trickier one would be to make a Lower trait and then use macros 1.1 to derive that for each of the data types.
Nashenas88
referenced this pull request
Jun 18, 2017
Closed
Support borrow, scope and move visualization through RLS #42733
Nashenas88
reviewed
Jun 22, 2017
| @@ -569,6 +613,8 @@ pub struct PerCrateAnalysis { | |||
| ref_spans: HashMap<Id, Vec<Span>>, | |||
| globs: HashMap<Span, Glob>, | |||
| impls: HashMap<Id, Vec<Span>>, | |||
| per_fn_borrows: HashMap<Id, BorrowData>, | |||
| fn_span_lookup_tree: BTreeMap<SearchSpan, Id>, | |||
This comment has been minimized.
This comment has been minimized.
Nashenas88
Jun 22, 2017
Author
I had an alternative design where rather than storing SearchSpan here, I stored a type called InTreeSearchSpan, which was just a wrapper around SearchSpan(some_span, SpanKind::InTree). Though in that case, I had to implement Borrow<SearchSpan> as well as all the Eq and Ord traits. It's safer type-wise since one wouldn't be able to accidentally store the SpanKind's Start and End values like you can now. However, I wasn't sure if it's worth the extra maintenance cost since the usage is so simple and easy to verify for correctness. Let me know if you'd like me to add it back in (assuming this SearchSpan and BTreeMap combination is something you're ok with).
This comment has been minimized.
This comment has been minimized.
nrc
Jun 22, 2017
Member
It's safer type-wise since one wouldn't be able to accidentally store the SpanKind's Start and End values like you can now
Is this invariant enforced dynamically in the current system?
This comment has been minimized.
This comment has been minimized.
Nashenas88
Jun 24, 2017
Author
It's not really enforced at all. The only reason it's working is because I only insert SearchSpans of kind InTreeinto the BTreeMap. I'll add it back in since that will prevent any errors in the future when someone else tries to modify the code.
nrc
reviewed
Jun 22, 2017
| @@ -26,12 +26,17 @@ mod test; | |||
|
|
|||
| pub use self::raw::{Target, name_space_for_def_kind, read_analyis_incremental}; | |||
|
|
|||
| mod search_span; | |||
| use search_span::*; | |||
This comment has been minimized.
This comment has been minimized.
| use std::ops::Range; | ||
| use span; | ||
|
|
||
| pub type Span = span::Span<span::ZeroIndexed>; |
This comment has been minimized.
This comment has been minimized.
|
|
||
| pub type Span = span::Span<span::ZeroIndexed>; | ||
|
|
||
| #[derive(Debug)] |
This comment has been minimized.
This comment has been minimized.
| | (&SpanKind::End, &SpanKind::Start) => self.0 == other.0, | ||
| _ => false, | ||
| } | ||
|
|
This comment has been minimized.
This comment has been minimized.
|
|
||
| } | ||
| } | ||
| impl Eq for SearchSpan { } |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Nashenas88
Jun 24, 2017
Author
No because that would also require deriving PartialEq and Eq for SpanKind, and I think that would imply the SpanKind value would be used to implement the derived Eq? See my response to the Ord derive.
| } | ||
| } | ||
| } | ||
| impl PartialOrd<SearchSpan> for SearchSpan { |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Nashenas88
Jun 24, 2017
Author
This requires implementing PartialOrd and Ord on SpanKind, which I don't think makes sense. This would mean the SpanKind would be used to break up the ordering when the spans are equal, but I don't want that to happen.
| @@ -569,6 +613,8 @@ pub struct PerCrateAnalysis { | |||
| ref_spans: HashMap<Id, Vec<Span>>, | |||
| globs: HashMap<Span, Glob>, | |||
| impls: HashMap<Id, Vec<Span>>, | |||
| per_fn_borrows: HashMap<Id, BorrowData>, | |||
| fn_span_lookup_tree: BTreeMap<SearchSpan, Id>, | |||
This comment has been minimized.
This comment has been minimized.
nrc
Jun 22, 2017
Member
It's safer type-wise since one wouldn't be able to accidentally store the SpanKind's Start and End values like you can now
Is this invariant enforced dynamically in the current system?
|
|
||
| if borrow_data.scopes.iter().any(|a| a.ref_id == id) { | ||
| // If we find a `BorrowData` where there's a matching scope, then filter out | ||
| // out matching items. |
This comment has been minimized.
This comment has been minimized.
Nashenas88
added some commits
Jun 18, 2017
Nashenas88
force-pushed the
Nashenas88:master
branch
from
3bf3f2e
to
7c8f808
Jun 24, 2017
This comment has been minimized.
This comment has been minimized.
|
Argh, I forgot rebasing messes up the comment history. I'm sorry about that. Note that the last few commits are now dependent on rust-dev-tools/rls-data#6. I believe I addressed all of your current concerns either with the commits or in the comments. |
Nashenas88
referenced this pull request
Jun 30, 2017
Closed
Support visualization of scopes, borrows and moves #387
This comment has been minimized.
This comment has been minimized.
|
Thanks for the fixes and updates! I think this is ready to land now right? (I merged the rls-data change, and it looks like the Cargo files take that into account). Could you confirm and also rebase please? (Sorry for the slow review here, I was travelling last week). |
This comment has been minimized.
This comment has been minimized.
|
I commented on rust#42733 that I don't think using Id's for the Scopes, Moves and Loans is going to work. I was originally testing with a crate that had no external dependencies and all types were defined in the same file. Once I was able to test on more complex examples, I noticed a serious flaw where all of those ref_ids get transformed into a NULL Id (the local variables don't have a def_id) when the type was outside of the local crate. I'm a little confused as to how it was tracking the loans and moves uniquely within the file. Given that this would require changes to |
This comment has been minimized.
This comment has been minimized.
|
Ah, I hadn't seen that comment. Given the changes, lets close this for now. |
Nashenas88 commentedJun 18, 2017
Note: This can't be merged until the latest changes to rls-data are pushed to crates.io and this PR's Cargo.toml is updated.