Skip to content
This repository was archived by the owner on Mar 1, 2019. It is now read-only.

Add structs for borrow and ownership information #71

Closed
wants to merge 4 commits into from

Conversation

Nashenas88
Copy link

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.

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"] }
Copy link
Author

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.

Copy link
Member

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?

Copy link
Author

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) {
Copy link
Author

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.

Copy link
Member

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.

Copy link
Author

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

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?

Copy link
Member

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|
Copy link
Author

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?

Copy link
Author

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?

Copy link
Member

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

Copy link
Member

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>,
Copy link
Author

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

Copy link
Member

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?

Copy link
Author

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

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::*;
Copy link
Member

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

use std::ops::Range;
use span;

pub type Span = span::Span<span::ZeroIndexed>;
Copy link
Member

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


pub type Span = span::Span<span::ZeroIndexed>;

#[derive(Debug)]
Copy link
Member

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?

| (&SpanKind::End, &SpanKind::Start) => self.0 == other.0,
_ => false,
}

Copy link
Member

Choose a reason for hiding this comment

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

nit: blank line


}
}
impl Eq for SearchSpan { }
Copy link
Member

Choose a reason for hiding this comment

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

Could derive this?

Copy link
Author

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.

}
}
}
impl PartialOrd<SearchSpan> for SearchSpan {
Copy link
Member

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

Copy link
Author

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

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

Choose a reason for hiding this comment

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

typo - "out\n out"

@Nashenas88
Copy link
Author

Nashenas88 commented Jun 24, 2017

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.

@nrc
Copy link
Member

nrc commented Jul 4, 2017

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

@Nashenas88
Copy link
Author

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 rls-data and the PR linked above, would you still want to push this through? Wouldn't it prevent other work from moving forward?

@nrc
Copy link
Member

nrc commented Jul 5, 2017

Ah, I hadn't seen that comment. Given the changes, lets close this for now.

@nrc nrc closed this Jul 5, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants