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

Support multiple crate types and versions (and multiple passed directly in-memory) #106

Merged
merged 2 commits into from
Nov 3, 2017

Conversation

Xanewok
Copy link
Collaborator

@Xanewok Xanewok commented Oct 23, 2017

Fixes #93. (also includes and is based on #103, can rebase if needed)
Blocked by rust-lang/rust#45468 (emitting crate disambiguators in save-analysis in rustc) and rust-dev-tools/rls-data#11 (data definitions, this pulls my crate-source branch now).

Pushing this as a single squashed commit, since I did walk in circles a bit and had a lot of back and forth commits. This turned out to be bigger than intended, hope that's okay.

Most important change is that it tries to change the model from mapping Option<PathBuf> -> PerCrateAnalysis to CrateId -> PerCrateAnalysis.
To support passing multiple in-process analysis data, this effectively disconnects paths from loaded data. CrateId contains crate name and disambiguator, meaning it'll be unique for each crate target/version.

I tried to simplify some code and comment as I go, hope that's also okay.

Some quirks still to solve:

  • Changing dependencies for crates changes its crate id; This means that when working on a crate and reloading the new data directly, the old data will be orphaned. One idea is to forcibly reload the ones that are passed directly, e.g. every crate with a given name will be removed from database and new data (with new crate id) will be loaded
  • This possibly introduces small performance regressions, since timestamps are checked now after loading the data from files, not before (the blacklist is still respected before) here. This can be easily fixed by adding an additional PathBuf -> SystemTime cache (however I didn't want to change the architecture too much now).

To make it more consistent and to make external AnalysisLoader implementations more MT-safe, moved Mutex from inside the CargoAnalysisLoader to loader member itself. This works, but I'm not sure the MT code is safe and consistent in general, so it'd be good to take a look at that later, maybe.

r? @nrc

Copy link
Member

@nrc nrc left a comment

Choose a reason for hiding this comment

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

Overall approach looks great. A bunch of comments inline.

src/analysis.rs Outdated
@@ -36,7 +37,7 @@ pub struct PerCrateAnalysis {
pub globs: HashMap<Span, Glob>,
pub impls: HashMap<Id, Vec<Span>>,

pub name: String,
pub crate_id: CrateId,
Copy link
Member

Choose a reason for hiding this comment

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

I assume we always have a PerCrateAnalysis from Analysis, so do we need the CrateId here, when we'll always be looking up the Analysis using a CrateId? (Seems like duplication of the key).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yup, you're right - was used as a convenience in def_roots but it'd be good not to duplicate it

src/analysis.rs Outdated
self.per_crate
.iter()
.filter_map(|(s, pc)| s.as_ref().map(|s| (s.clone(), pc.timestamp)))
.map(|(id,c)| (id.clone(), c.timestamp.clone()))
Copy link
Member

Choose a reason for hiding this comment

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

nit: id, c

src/lib.rs Outdated
let raw_analysis = read_analysis_incremental(&self.loader, timestamps, blacklist);
let timestamps = self.analysis.lock()?.as_ref().unwrap().timestamps();
let loader = self.loader.lock()?;
let raw_analysis = read_analysis_from_files(&*loader, timestamps, blacklist);
Copy link
Member

Choose a reason for hiding this comment

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

Could we scope the lock on loader to just this call? (Probably me being paranoid, but I'd rather drop the lock as early as possible).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done! However, to be honest, right now it feels a bit too wild west wrt mutexes everywhere, so I think it'd be nice to make an assumption who can call what and come up with a more sane MT-safe interface

src/loader.rs Outdated
where
F: Fn(&Path) -> Vec<T>;
/// Returns every directory in which paths are to be considered.
/// TODO: Can it also return files?
Copy link
Member

Choose a reason for hiding this comment

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

It cannot

src/loader.rs Outdated
F: Fn(&Path) -> Vec<T>;
/// Returns every directory in which paths are to be considered.
/// TODO: Can it also return files?
fn paths(&self) -> Vec<PathBuf>;
Copy link
Member

Choose a reason for hiding this comment

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

Could paths be renamed search_directories or something a bit more descriptive?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, I wasn't sure before if it's designed to only return directories or can it also return paths, so that's the most neutral name I could come up with

src/lowering.rs Outdated
@@ -6,11 +6,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// For processing the raw save-analysis data from rustc into rustw's in-memory representation.
//! For processing the raw save-analysis data from rustc into rustw's
Copy link
Member

Choose a reason for hiding this comment

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

s/rustw/the rls

src/raw.rs Outdated
// TODO: Bring back path-based timestamps?
// This would speed up a bit reloading time, since non-blacklisted
// can be older than the ones loaded, so don't waste time
// reading the file and deserializing
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, it would be nice if we could avoid reading the file - reading and deserialising can be a significant overhead for large analysis files.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@nrc Can I add this after this PR lands?

Copy link
Member

Choose a reason for hiding this comment

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

Sure, that's fine.

@Xanewok
Copy link
Collaborator Author

Xanewok commented Oct 27, 2017

Rebased and pushed commit with addressed feedback, now this waits for rust-dev-tools/rls-data#11 to land

@Xanewok
Copy link
Collaborator Author

Xanewok commented Oct 29, 2017

Updated test data with changes to save-analysis from rust-lang/rust#45468

@Xanewok
Copy link
Collaborator Author

Xanewok commented Oct 30, 2017

Separated and rebased on top of #114, so it can land first for Rust CI

@Xanewok Xanewok force-pushed the multi-crates branch 3 times, most recently from 52b42fb to 1d6bf96 Compare November 1, 2017 00:08
@Xanewok
Copy link
Collaborator Author

Xanewok commented Nov 3, 2017

As of today nightly rustc emits the new analysis data, so I think we can proceed with this update.
Bumping version to 0.8, since it changes the public api, not to break other users, e.g. the new rustdoc.

@nrc nrc merged commit 1e640e9 into rust-dev-tools:master Nov 3, 2017
@nrc
Copy link
Member

nrc commented Nov 3, 2017

Thanks!

@Xanewok
Copy link
Collaborator Author

Xanewok commented Nov 3, 2017

Hopefully workspace support is more or less complete now! Now onto improvements 😄

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.

Support multiple crate types and versions (and multiple passed directly in-memory)
2 participants