-
Notifications
You must be signed in to change notification settings - Fork 26
Add structs for borrow and ownership information #71
Conversation
Cargo.toml
Outdated
@@ -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"] } |
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 needs to be updated once rls-data
is updated in crates.io.
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.
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
?
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 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?
src/lib.rs
Outdated
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) { |
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 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
.
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.
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.
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 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 { |
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.
Should I toggle all of this behind a feature flag like I did in rls-data
?
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.
no, I don't think it is necessary
src/lowering.rs
Outdated
} | ||
}; | ||
|
||
let scopes = b.scopes.into_iter().filter_map(|a| |
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 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?
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.
Also, I was using into_iter
here to avoid clone
ing everything. Is that a bad idea?
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.
Also, I was using into_iter here to avoid cloneing everything. Is that a bad idea?
No, that is a good thing to do
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.
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.
src/lib.rs
Outdated
@@ -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>, |
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 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).
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'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?
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's not really enforced at all. The only reason it's working is because I only insert SearchSpan
s of kind InTree
into 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.
src/lib.rs
Outdated
@@ -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::*; |
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.
could you use explicit imports instead of a glob please
src/search_span.rs
Outdated
use std::ops::Range; | ||
use span; | ||
|
||
pub type Span = span::Span<span::ZeroIndexed>; |
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 would put this at the top level
src/search_span.rs
Outdated
|
||
pub type Span = span::Span<span::ZeroIndexed>; | ||
|
||
#[derive(Debug)] |
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.
Could you add a module comment explaining how to use this module?
src/search_span.rs
Outdated
| (&SpanKind::End, &SpanKind::Start) => self.0 == other.0, | ||
_ => false, | ||
} | ||
|
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.
nit: blank line
src/search_span.rs
Outdated
|
||
} | ||
} | ||
impl Eq for SearchSpan { } |
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.
Could derive this?
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.
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.
src/search_span.rs
Outdated
} | ||
} | ||
} | ||
impl PartialOrd<SearchSpan> for SearchSpan { |
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 you could move the Ord implementation here, and then derive Ord
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 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.
src/lib.rs
Outdated
@@ -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>, |
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'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?
src/lib.rs
Outdated
|
||
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. |
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.
typo - "out\n out"
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. |
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). |
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 |
Ah, I hadn't seen that comment. Given the changes, lets close this for now. |
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.