diff options
Diffstat (limited to 'crates/ra_project_model/src')
-rw-r--r-- | crates/ra_project_model/src/cargo_workspace.rs | 105 | ||||
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 135 |
2 files changed, 123 insertions, 117 deletions
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 291594e2a..b50cda06f 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs | |||
@@ -1,17 +1,18 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use std::{ | 3 | use std::{ |
4 | env, | ||
5 | ffi::OsStr, | ||
4 | ops, | 6 | ops, |
5 | path::{Path, PathBuf}, | 7 | path::{Path, PathBuf}, |
8 | process::Command, | ||
6 | }; | 9 | }; |
7 | 10 | ||
8 | use anyhow::{Context, Result}; | 11 | use anyhow::{Context, Result}; |
9 | use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId}; | 12 | use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId}; |
10 | use ra_arena::{Arena, Idx}; | 13 | use ra_arena::{Arena, Idx}; |
11 | use ra_cargo_watch::run_cargo; | ||
12 | use ra_db::Edition; | 14 | use ra_db::Edition; |
13 | use rustc_hash::FxHashMap; | 15 | use rustc_hash::FxHashMap; |
14 | use serde::Deserialize; | ||
15 | 16 | ||
16 | /// `CargoWorkspace` represents the logical structure of, well, a Cargo | 17 | /// `CargoWorkspace` represents the logical structure of, well, a Cargo |
17 | /// workspace. It pretty closely mirrors `cargo metadata` output. | 18 | /// workspace. It pretty closely mirrors `cargo metadata` output. |
@@ -41,9 +42,8 @@ impl ops::Index<Target> for CargoWorkspace { | |||
41 | } | 42 | } |
42 | } | 43 | } |
43 | 44 | ||
44 | #[derive(Deserialize, Clone, Debug, PartialEq, Eq)] | 45 | #[derive(Clone, Debug, PartialEq, Eq)] |
45 | #[serde(rename_all = "camelCase", default)] | 46 | pub struct CargoConfig { |
46 | pub struct CargoFeatures { | ||
47 | /// Do not activate the `default` feature. | 47 | /// Do not activate the `default` feature. |
48 | pub no_default_features: bool, | 48 | pub no_default_features: bool, |
49 | 49 | ||
@@ -58,9 +58,9 @@ pub struct CargoFeatures { | |||
58 | pub load_out_dirs_from_check: bool, | 58 | pub load_out_dirs_from_check: bool, |
59 | } | 59 | } |
60 | 60 | ||
61 | impl Default for CargoFeatures { | 61 | impl Default for CargoConfig { |
62 | fn default() -> Self { | 62 | fn default() -> Self { |
63 | CargoFeatures { | 63 | CargoConfig { |
64 | no_default_features: false, | 64 | no_default_features: false, |
65 | all_features: true, | 65 | all_features: true, |
66 | features: Vec::new(), | 66 | features: Vec::new(), |
@@ -75,6 +75,7 @@ pub type Target = Idx<TargetData>; | |||
75 | 75 | ||
76 | #[derive(Debug, Clone)] | 76 | #[derive(Debug, Clone)] |
77 | pub struct PackageData { | 77 | pub struct PackageData { |
78 | pub version: String, | ||
78 | pub name: String, | 79 | pub name: String, |
79 | pub manifest: PathBuf, | 80 | pub manifest: PathBuf, |
80 | pub targets: Vec<Target>, | 81 | pub targets: Vec<Target>, |
@@ -138,7 +139,7 @@ impl PackageData { | |||
138 | impl CargoWorkspace { | 139 | impl CargoWorkspace { |
139 | pub fn from_cargo_metadata( | 140 | pub fn from_cargo_metadata( |
140 | cargo_toml: &Path, | 141 | cargo_toml: &Path, |
141 | cargo_features: &CargoFeatures, | 142 | cargo_features: &CargoConfig, |
142 | ) -> Result<CargoWorkspace> { | 143 | ) -> Result<CargoWorkspace> { |
143 | let mut meta = MetadataCommand::new(); | 144 | let mut meta = MetadataCommand::new(); |
144 | meta.manifest_path(cargo_toml); | 145 | meta.manifest_path(cargo_toml); |
@@ -161,7 +162,7 @@ impl CargoWorkspace { | |||
161 | let mut out_dir_by_id = FxHashMap::default(); | 162 | let mut out_dir_by_id = FxHashMap::default(); |
162 | let mut proc_macro_dylib_paths = FxHashMap::default(); | 163 | let mut proc_macro_dylib_paths = FxHashMap::default(); |
163 | if cargo_features.load_out_dirs_from_check { | 164 | if cargo_features.load_out_dirs_from_check { |
164 | let resources = load_extern_resources(cargo_toml, cargo_features); | 165 | let resources = load_extern_resources(cargo_toml, cargo_features)?; |
165 | out_dir_by_id = resources.out_dirs; | 166 | out_dir_by_id = resources.out_dirs; |
166 | proc_macro_dylib_paths = resources.proc_dylib_paths; | 167 | proc_macro_dylib_paths = resources.proc_dylib_paths; |
167 | } | 168 | } |
@@ -173,13 +174,15 @@ impl CargoWorkspace { | |||
173 | let ws_members = &meta.workspace_members; | 174 | let ws_members = &meta.workspace_members; |
174 | 175 | ||
175 | for meta_pkg in meta.packages { | 176 | for meta_pkg in meta.packages { |
176 | let cargo_metadata::Package { id, edition, name, manifest_path, .. } = meta_pkg; | 177 | let cargo_metadata::Package { id, edition, name, manifest_path, version, .. } = |
178 | meta_pkg; | ||
177 | let is_member = ws_members.contains(&id); | 179 | let is_member = ws_members.contains(&id); |
178 | let edition = edition | 180 | let edition = edition |
179 | .parse::<Edition>() | 181 | .parse::<Edition>() |
180 | .with_context(|| format!("Failed to parse edition {}", edition))?; | 182 | .with_context(|| format!("Failed to parse edition {}", edition))?; |
181 | let pkg = packages.alloc(PackageData { | 183 | let pkg = packages.alloc(PackageData { |
182 | name, | 184 | name, |
185 | version: version.to_string(), | ||
183 | manifest: manifest_path, | 186 | manifest: manifest_path, |
184 | targets: Vec::new(), | 187 | targets: Vec::new(), |
185 | is_member, | 188 | is_member, |
@@ -249,6 +252,18 @@ impl CargoWorkspace { | |||
249 | pub fn workspace_root(&self) -> &Path { | 252 | pub fn workspace_root(&self) -> &Path { |
250 | &self.workspace_root | 253 | &self.workspace_root |
251 | } | 254 | } |
255 | |||
256 | pub fn package_flag(&self, package: &PackageData) -> String { | ||
257 | if self.is_unique(&*package.name) { | ||
258 | package.name.clone() | ||
259 | } else { | ||
260 | format!("{}:{}", package.name, package.version) | ||
261 | } | ||
262 | } | ||
263 | |||
264 | fn is_unique(&self, name: &str) -> bool { | ||
265 | self.packages.iter().filter(|(_, v)| v.name == name).count() == 1 | ||
266 | } | ||
252 | } | 267 | } |
253 | 268 | ||
254 | #[derive(Debug, Clone, Default)] | 269 | #[derive(Debug, Clone, Default)] |
@@ -257,48 +272,60 @@ pub struct ExternResources { | |||
257 | proc_dylib_paths: FxHashMap<PackageId, PathBuf>, | 272 | proc_dylib_paths: FxHashMap<PackageId, PathBuf>, |
258 | } | 273 | } |
259 | 274 | ||
260 | pub fn load_extern_resources(cargo_toml: &Path, cargo_features: &CargoFeatures) -> ExternResources { | 275 | pub fn load_extern_resources( |
261 | let mut args: Vec<String> = vec![ | 276 | cargo_toml: &Path, |
262 | "check".to_string(), | 277 | cargo_features: &CargoConfig, |
263 | "--message-format=json".to_string(), | 278 | ) -> Result<ExternResources> { |
264 | "--manifest-path".to_string(), | 279 | let mut cmd = Command::new(cargo_binary()); |
265 | cargo_toml.display().to_string(), | 280 | cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml); |
266 | ]; | ||
267 | |||
268 | if cargo_features.all_features { | 281 | if cargo_features.all_features { |
269 | args.push("--all-features".to_string()); | 282 | cmd.arg("--all-features"); |
270 | } else if cargo_features.no_default_features { | 283 | } else if cargo_features.no_default_features { |
271 | // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` | 284 | // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` |
272 | // https://github.com/oli-obk/cargo_metadata/issues/79 | 285 | // https://github.com/oli-obk/cargo_metadata/issues/79 |
273 | args.push("--no-default-features".to_string()); | 286 | cmd.arg("--no-default-features"); |
274 | } else { | 287 | } else { |
275 | args.extend(cargo_features.features.iter().cloned()); | 288 | cmd.args(&cargo_features.features); |
276 | } | 289 | } |
277 | 290 | ||
278 | let mut acc = ExternResources::default(); | 291 | let output = cmd.output()?; |
279 | let res = run_cargo(&args, cargo_toml.parent(), &mut |message| { | ||
280 | match message { | ||
281 | Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => { | ||
282 | acc.out_dirs.insert(package_id, out_dir); | ||
283 | } | ||
284 | 292 | ||
285 | Message::CompilerArtifact(message) => { | 293 | let mut res = ExternResources::default(); |
286 | if message.target.kind.contains(&"proc-macro".to_string()) { | 294 | |
287 | let package_id = message.package_id; | 295 | for message in cargo_metadata::parse_messages(output.stdout.as_slice()) { |
288 | if let Some(filename) = message.filenames.get(0) { | 296 | if let Ok(message) = message { |
289 | acc.proc_dylib_paths.insert(package_id, filename.clone()); | 297 | match message { |
298 | Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => { | ||
299 | res.out_dirs.insert(package_id, out_dir); | ||
300 | } | ||
301 | |||
302 | Message::CompilerArtifact(message) => { | ||
303 | if message.target.kind.contains(&"proc-macro".to_string()) { | ||
304 | let package_id = message.package_id; | ||
305 | // Skip rmeta file | ||
306 | if let Some(filename) = | ||
307 | message.filenames.iter().filter(|name| is_dylib(name)).next() | ||
308 | { | ||
309 | res.proc_dylib_paths.insert(package_id, filename.clone()); | ||
310 | } | ||
290 | } | 311 | } |
291 | } | 312 | } |
313 | Message::CompilerMessage(_) => (), | ||
314 | Message::Unknown => (), | ||
292 | } | 315 | } |
293 | Message::CompilerMessage(_) => (), | ||
294 | Message::Unknown => (), | ||
295 | } | 316 | } |
296 | true | 317 | } |
297 | }); | 318 | Ok(res) |
319 | } | ||
298 | 320 | ||
299 | if let Err(err) = res { | 321 | // FIXME: File a better way to know if it is a dylib |
300 | log::error!("Failed to load outdirs: {:?}", err); | 322 | fn is_dylib(path: &Path) -> bool { |
323 | match path.extension().and_then(OsStr::to_str).map(|it| it.to_string().to_lowercase()) { | ||
324 | None => false, | ||
325 | Some(ext) => matches!(ext.as_str(), "dll" | "dylib" | "so"), | ||
301 | } | 326 | } |
327 | } | ||
302 | 328 | ||
303 | acc | 329 | fn cargo_binary() -> String { |
330 | env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()) | ||
304 | } | 331 | } |
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 444d3bb3f..0ab64a1e0 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -19,7 +19,7 @@ use rustc_hash::FxHashMap; | |||
19 | use serde_json::from_reader; | 19 | use serde_json::from_reader; |
20 | 20 | ||
21 | pub use crate::{ | 21 | pub use crate::{ |
22 | cargo_workspace::{CargoFeatures, CargoWorkspace, Package, Target, TargetKind}, | 22 | cargo_workspace::{CargoConfig, CargoWorkspace, Package, Target, TargetKind}, |
23 | json_project::JsonProject, | 23 | json_project::JsonProject, |
24 | sysroot::Sysroot, | 24 | sysroot::Sysroot, |
25 | }; | 25 | }; |
@@ -62,30 +62,30 @@ pub struct PackageRoot { | |||
62 | /// Is a member of the current workspace | 62 | /// Is a member of the current workspace |
63 | is_member: bool, | 63 | is_member: bool, |
64 | } | 64 | } |
65 | |||
66 | impl PackageRoot { | 65 | impl PackageRoot { |
67 | pub fn new(path: PathBuf, is_member: bool) -> PackageRoot { | 66 | pub fn new_member(path: PathBuf) -> PackageRoot { |
68 | PackageRoot { path, is_member } | 67 | Self { path, is_member: true } |
69 | } | 68 | } |
70 | 69 | pub fn new_non_member(path: PathBuf) -> PackageRoot { | |
71 | pub fn path(&self) -> &PathBuf { | 70 | Self { path, is_member: false } |
71 | } | ||
72 | pub fn path(&self) -> &Path { | ||
72 | &self.path | 73 | &self.path |
73 | } | 74 | } |
74 | |||
75 | pub fn is_member(&self) -> bool { | 75 | pub fn is_member(&self) -> bool { |
76 | self.is_member | 76 | self.is_member |
77 | } | 77 | } |
78 | } | 78 | } |
79 | 79 | ||
80 | impl ProjectWorkspace { | 80 | impl ProjectWorkspace { |
81 | pub fn discover(path: &Path, cargo_features: &CargoFeatures) -> Result<ProjectWorkspace> { | 81 | pub fn discover(path: &Path, cargo_features: &CargoConfig) -> Result<ProjectWorkspace> { |
82 | ProjectWorkspace::discover_with_sysroot(path, true, cargo_features) | 82 | ProjectWorkspace::discover_with_sysroot(path, true, cargo_features) |
83 | } | 83 | } |
84 | 84 | ||
85 | pub fn discover_with_sysroot( | 85 | pub fn discover_with_sysroot( |
86 | path: &Path, | 86 | path: &Path, |
87 | with_sysroot: bool, | 87 | with_sysroot: bool, |
88 | cargo_features: &CargoFeatures, | 88 | cargo_features: &CargoConfig, |
89 | ) -> Result<ProjectWorkspace> { | 89 | ) -> Result<ProjectWorkspace> { |
90 | match find_rust_project_json(path) { | 90 | match find_rust_project_json(path) { |
91 | Some(json_path) => { | 91 | Some(json_path) => { |
@@ -130,70 +130,45 @@ impl ProjectWorkspace { | |||
130 | pub fn to_roots(&self) -> Vec<PackageRoot> { | 130 | pub fn to_roots(&self) -> Vec<PackageRoot> { |
131 | match self { | 131 | match self { |
132 | ProjectWorkspace::Json { project } => { | 132 | ProjectWorkspace::Json { project } => { |
133 | let mut roots = Vec::with_capacity(project.roots.len()); | 133 | project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect() |
134 | for root in &project.roots { | ||
135 | roots.push(PackageRoot::new(root.path.clone(), true)); | ||
136 | } | ||
137 | roots | ||
138 | } | ||
139 | ProjectWorkspace::Cargo { cargo, sysroot } => { | ||
140 | let mut roots = Vec::with_capacity(cargo.packages().len() + sysroot.crates().len()); | ||
141 | for pkg in cargo.packages() { | ||
142 | let root = cargo[pkg].root().to_path_buf(); | ||
143 | let member = cargo[pkg].is_member; | ||
144 | roots.push(PackageRoot::new(root, member)); | ||
145 | } | ||
146 | for krate in sysroot.crates() { | ||
147 | roots.push(PackageRoot::new(sysroot[krate].root_dir().to_path_buf(), false)) | ||
148 | } | ||
149 | roots | ||
150 | } | 134 | } |
135 | ProjectWorkspace::Cargo { cargo, sysroot } => cargo | ||
136 | .packages() | ||
137 | .map(|pkg| PackageRoot { | ||
138 | path: cargo[pkg].root().to_path_buf(), | ||
139 | is_member: cargo[pkg].is_member, | ||
140 | }) | ||
141 | .chain(sysroot.crates().map(|krate| { | ||
142 | PackageRoot::new_non_member(sysroot[krate].root_dir().to_path_buf()) | ||
143 | })) | ||
144 | .collect(), | ||
151 | } | 145 | } |
152 | } | 146 | } |
153 | 147 | ||
154 | pub fn out_dirs(&self) -> Vec<PathBuf> { | 148 | pub fn out_dirs(&self) -> Vec<PathBuf> { |
155 | match self { | 149 | match self { |
156 | ProjectWorkspace::Json { project } => { | 150 | ProjectWorkspace::Json { project } => { |
157 | let mut out_dirs = Vec::with_capacity(project.crates.len()); | 151 | project.crates.iter().filter_map(|krate| krate.out_dir.as_ref()).cloned().collect() |
158 | for krate in &project.crates { | ||
159 | if let Some(out_dir) = &krate.out_dir { | ||
160 | out_dirs.push(out_dir.to_path_buf()); | ||
161 | } | ||
162 | } | ||
163 | out_dirs | ||
164 | } | 152 | } |
165 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => { | 153 | ProjectWorkspace::Cargo { cargo, sysroot: _ } => { |
166 | let mut out_dirs = Vec::with_capacity(cargo.packages().len()); | 154 | cargo.packages().filter_map(|pkg| cargo[pkg].out_dir.as_ref()).cloned().collect() |
167 | for pkg in cargo.packages() { | ||
168 | if let Some(out_dir) = &cargo[pkg].out_dir { | ||
169 | out_dirs.push(out_dir.to_path_buf()); | ||
170 | } | ||
171 | } | ||
172 | out_dirs | ||
173 | } | 155 | } |
174 | } | 156 | } |
175 | } | 157 | } |
176 | 158 | ||
177 | pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> { | 159 | pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> { |
178 | match self { | 160 | match self { |
179 | ProjectWorkspace::Json { project } => { | 161 | ProjectWorkspace::Json { project } => project |
180 | let mut proc_macro_dylib_paths = Vec::with_capacity(project.crates.len()); | 162 | .crates |
181 | for krate in &project.crates { | 163 | .iter() |
182 | if let Some(out_dir) = &krate.proc_macro_dylib_path { | 164 | .filter_map(|krate| krate.proc_macro_dylib_path.as_ref()) |
183 | proc_macro_dylib_paths.push(out_dir.to_path_buf()); | 165 | .cloned() |
184 | } | 166 | .collect(), |
185 | } | 167 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => cargo |
186 | proc_macro_dylib_paths | 168 | .packages() |
187 | } | 169 | .filter_map(|pkg| cargo[pkg].proc_macro_dylib_path.as_ref()) |
188 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => { | 170 | .cloned() |
189 | let mut proc_macro_dylib_paths = Vec::with_capacity(cargo.packages().len()); | 171 | .collect(), |
190 | for pkg in cargo.packages() { | ||
191 | if let Some(dylib_path) = &cargo[pkg].proc_macro_dylib_path { | ||
192 | proc_macro_dylib_paths.push(dylib_path.to_path_buf()); | ||
193 | } | ||
194 | } | ||
195 | proc_macro_dylib_paths | ||
196 | } | ||
197 | } | 172 | } |
198 | } | 173 | } |
199 | 174 | ||
@@ -216,10 +191,12 @@ impl ProjectWorkspace { | |||
216 | let mut crate_graph = CrateGraph::default(); | 191 | let mut crate_graph = CrateGraph::default(); |
217 | match self { | 192 | match self { |
218 | ProjectWorkspace::Json { project } => { | 193 | ProjectWorkspace::Json { project } => { |
219 | let mut crates = FxHashMap::default(); | 194 | let crates: FxHashMap<_, _> = project |
220 | for (id, krate) in project.crates.iter().enumerate() { | 195 | .crates |
221 | let crate_id = json_project::CrateId(id); | 196 | .iter() |
222 | if let Some(file_id) = load(&krate.root_module) { | 197 | .enumerate() |
198 | .filter_map(|(seq_index, krate)| { | ||
199 | let file_id = load(&krate.root_module)?; | ||
223 | let edition = match krate.edition { | 200 | let edition = match krate.edition { |
224 | json_project::Edition::Edition2015 => Edition::Edition2015, | 201 | json_project::Edition::Edition2015 => Edition::Edition2015, |
225 | json_project::Edition::Edition2018 => Edition::Edition2018, | 202 | json_project::Edition::Edition2018 => Edition::Edition2018, |
@@ -249,8 +226,8 @@ impl ProjectWorkspace { | |||
249 | .clone() | 226 | .clone() |
250 | .map(|it| proc_macro_client.by_dylib_path(&it)); | 227 | .map(|it| proc_macro_client.by_dylib_path(&it)); |
251 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env | 228 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env |
252 | crates.insert( | 229 | Some(( |
253 | crate_id, | 230 | json_project::CrateId(seq_index), |
254 | crate_graph.add_crate_root( | 231 | crate_graph.add_crate_root( |
255 | file_id, | 232 | file_id, |
256 | edition, | 233 | edition, |
@@ -261,9 +238,9 @@ impl ProjectWorkspace { | |||
261 | extern_source, | 238 | extern_source, |
262 | proc_macro.unwrap_or_default(), | 239 | proc_macro.unwrap_or_default(), |
263 | ), | 240 | ), |
264 | ); | 241 | )) |
265 | } | 242 | }) |
266 | } | 243 | .collect(); |
267 | 244 | ||
268 | for (id, krate) in project.crates.iter().enumerate() { | 245 | for (id, krate) in project.crates.iter().enumerate() { |
269 | for dep in &krate.deps { | 246 | for dep in &krate.deps { |
@@ -287,9 +264,11 @@ impl ProjectWorkspace { | |||
287 | } | 264 | } |
288 | } | 265 | } |
289 | ProjectWorkspace::Cargo { cargo, sysroot } => { | 266 | ProjectWorkspace::Cargo { cargo, sysroot } => { |
290 | let mut sysroot_crates = FxHashMap::default(); | 267 | let sysroot_crates: FxHashMap<_, _> = sysroot |
291 | for krate in sysroot.crates() { | 268 | .crates() |
292 | if let Some(file_id) = load(&sysroot[krate].root) { | 269 | .filter_map(|krate| { |
270 | let file_id = load(&sysroot[krate].root)?; | ||
271 | |||
293 | // Crates from sysroot have `cfg(test)` disabled | 272 | // Crates from sysroot have `cfg(test)` disabled |
294 | let cfg_options = { | 273 | let cfg_options = { |
295 | let mut opts = default_cfg_options.clone(); | 274 | let mut opts = default_cfg_options.clone(); |
@@ -300,22 +279,22 @@ impl ProjectWorkspace { | |||
300 | let env = Env::default(); | 279 | let env = Env::default(); |
301 | let extern_source = ExternSource::default(); | 280 | let extern_source = ExternSource::default(); |
302 | let proc_macro = vec![]; | 281 | let proc_macro = vec![]; |
282 | let crate_name = CrateName::new(&sysroot[krate].name) | ||
283 | .expect("Sysroot crate names should not contain dashes"); | ||
303 | 284 | ||
304 | let crate_id = crate_graph.add_crate_root( | 285 | let crate_id = crate_graph.add_crate_root( |
305 | file_id, | 286 | file_id, |
306 | Edition::Edition2018, | 287 | Edition::Edition2018, |
307 | Some( | 288 | Some(crate_name), |
308 | CrateName::new(&sysroot[krate].name) | ||
309 | .expect("Sysroot crate names should not contain dashes"), | ||
310 | ), | ||
311 | cfg_options, | 289 | cfg_options, |
312 | env, | 290 | env, |
313 | extern_source, | 291 | extern_source, |
314 | proc_macro, | 292 | proc_macro, |
315 | ); | 293 | ); |
316 | sysroot_crates.insert(krate, crate_id); | 294 | Some((krate, crate_id)) |
317 | } | 295 | }) |
318 | } | 296 | .collect(); |
297 | |||
319 | for from in sysroot.crates() { | 298 | for from in sysroot.crates() { |
320 | for &to in sysroot[from].deps.iter() { | 299 | for &to in sysroot[from].deps.iter() { |
321 | let name = &sysroot[to].name; | 300 | let name = &sysroot[to].name; |