Skip to content

Commit 98b6f81

Browse files
committed
Wrap Package/Target in Rc.
This is intended to make it easier to deal with Unit lifetimes.
1 parent 8e8c62b commit 98b6f81

File tree

20 files changed

+138
-135
lines changed

20 files changed

+138
-135
lines changed

src/cargo/core/compiler/build_context/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub struct BuildContext<'a, 'cfg> {
3232
pub packages: &'a PackageSet<'cfg>,
3333

3434
/// Source of interning new units as they're created.
35-
pub units: &'a UnitInterner<'a>,
35+
pub units: &'a UnitInterner,
3636

3737
/// Information about rustc and the target platform.
3838
pub target_data: RustcTargetData,
@@ -45,7 +45,7 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
4545
config: &'cfg Config,
4646
build_config: &'a BuildConfig,
4747
profiles: Profiles,
48-
units: &'a UnitInterner<'a>,
48+
units: &'a UnitInterner,
4949
extra_compiler_args: HashMap<Unit<'a>, Vec<String>>,
5050
target_data: RustcTargetData,
5151
) -> CargoResult<BuildContext<'a, 'cfg>> {

src/cargo/core/compiler/compilation.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::collections::{BTreeSet, HashMap, HashSet};
22
use std::env;
33
use std::ffi::{OsStr, OsString};
44
use std::path::PathBuf;
5+
use std::rc::Rc;
56

67
use cargo_platform::CfgExpr;
78
use semver::Version;
@@ -14,9 +15,9 @@ use crate::util::{self, config, join_paths, process, CargoResult, Config, Proces
1415
/// Structure with enough information to run `rustdoc --test`.
1516
pub struct Doctest {
1617
/// The package being doc-tested.
17-
pub package: Package,
18+
pub package: Rc<Package>,
1819
/// The target being tested (currently always the package's lib).
19-
pub target: Target,
20+
pub target: Rc<Target>,
2021
/// Arguments needed to pass to rustdoc to run this test.
2122
pub args: Vec<OsString>,
2223
/// Whether or not -Zunstable-options is needed.
@@ -27,7 +28,7 @@ pub struct Doctest {
2728
pub struct Compilation<'cfg> {
2829
/// An array of all tests created during this compilation.
2930
/// `(package, target, path_to_test_exe)`
30-
pub tests: Vec<(Package, Target, PathBuf)>,
31+
pub tests: Vec<(Rc<Package>, Rc<Target>, PathBuf)>,
3132

3233
/// An array of all binaries created.
3334
pub binaries: Vec<PathBuf>,

src/cargo/core/compiler/context/compilation_files.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ fn compute_metadata<'a, 'cfg>(
631631

632632
hash_rustc_version(bcx, &mut hasher);
633633

634-
if cx.bcx.ws.is_member(unit.pkg) {
634+
if cx.bcx.ws.is_member(&unit.pkg) {
635635
// This is primarily here for clippy. This ensures that the clippy
636636
// artifacts are separate from the `check` ones.
637637
if let Some(path) = &cx.bcx.rustc().workspace_wrapper {

src/cargo/core/compiler/context/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![allow(deprecated)]
22
use std::collections::{BTreeSet, HashMap, HashSet};
33
use std::path::PathBuf;
4+
use std::rc::Rc;
45
use std::sync::{Arc, Mutex};
56

67
use filetime::FileTime;
@@ -179,8 +180,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
179180

180181
if unit.mode == CompileMode::Test {
181182
self.compilation.tests.push((
182-
unit.pkg.clone(),
183-
unit.target.clone(),
183+
Rc::clone(&unit.pkg),
184+
Rc::clone(&unit.target),
184185
output.path.clone(),
185186
));
186187
} else if unit.target.is_executable() {
@@ -212,8 +213,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
212213
let mut unstable_opts = false;
213214
let args = compiler::extern_args(&self, unit, &mut unstable_opts)?;
214215
self.compilation.to_doc_test.push(compilation::Doctest {
215-
package: unit.pkg.clone(),
216-
target: unit.target.clone(),
216+
package: Rc::clone(&unit.pkg),
217+
target: Rc::clone(&unit.target),
217218
args,
218219
unstable_opts,
219220
});

src/cargo/core/compiler/custom_build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
177177
// `Profiles::get_profile_run_custom_build` so that those flags get
178178
// carried over.
179179
let to_exec = to_exec.into_os_string();
180-
let mut cmd = cx.compilation.host_process(to_exec, unit.pkg)?;
180+
let mut cmd = cx.compilation.host_process(to_exec, &unit.pkg)?;
181181
let debug = unit.profile.debuginfo.unwrap_or(0) != 0;
182182
cmd.env("OUT_DIR", &script_out_dir)
183183
.env("CARGO_MANIFEST_DIR", unit.pkg.root())

src/cargo/core/compiler/fingerprint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1286,7 +1286,7 @@ fn calculate_run_custom_build<'a, 'cfg>(
12861286
// the whole crate.
12871287
let (gen_local, overridden) = build_script_local_fingerprints(cx, unit);
12881288
let deps = &cx.build_explicit_deps[unit];
1289-
let local = (gen_local)(deps, Some(&|| pkg_fingerprint(cx.bcx, unit.pkg)))?.unwrap();
1289+
let local = (gen_local)(deps, Some(&|| pkg_fingerprint(cx.bcx, &unit.pkg)))?.unwrap();
12901290
let output = deps.build_script_output.clone();
12911291

12921292
// Include any dependencies of our execution, which is typically just the

src/cargo/core/compiler/job_queue.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -932,15 +932,15 @@ impl<'a, 'cfg> DrainState<'a, 'cfg> {
932932
Dirty => {
933933
if unit.mode.is_doc() {
934934
self.documented.insert(unit.pkg.package_id());
935-
config.shell().status("Documenting", unit.pkg)?;
935+
config.shell().status("Documenting", &unit.pkg)?;
936936
} else if unit.mode.is_doc_test() {
937937
// Skip doc test.
938938
} else {
939939
self.compiled.insert(unit.pkg.package_id());
940940
if unit.mode.is_check() {
941-
config.shell().status("Checking", unit.pkg)?;
941+
config.shell().status("Checking", &unit.pkg)?;
942942
} else {
943-
config.shell().status("Compiling", unit.pkg)?;
943+
config.shell().status("Compiling", &unit.pkg)?;
944944
}
945945
}
946946
}
@@ -950,7 +950,7 @@ impl<'a, 'cfg> DrainState<'a, 'cfg> {
950950
&& !(unit.mode.is_doc_test() && self.compiled.contains(&unit.pkg.package_id()))
951951
{
952952
self.compiled.insert(unit.pkg.package_id());
953-
config.shell().verbose(|c| c.status("Fresh", unit.pkg))?;
953+
config.shell().verbose(|c| c.status("Fresh", &unit.pkg))?;
954954
}
955955
}
956956
}

src/cargo/core/compiler/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ fn compile<'a, 'cfg: 'a>(
139139
let work = if cx.bcx.show_warnings(unit.pkg.package_id()) {
140140
replay_output_cache(
141141
unit.pkg.package_id(),
142-
unit.target,
142+
&unit.target,
143143
cx.files().message_cache_path(unit),
144144
cx.bcx.build_config.message_format,
145145
cx.bcx.config.shell().supports_color(),
@@ -212,7 +212,7 @@ fn rustc<'a, 'cfg>(
212212
}
213213
let mut output_options = OutputOptions::new(cx, unit);
214214
let package_id = unit.pkg.package_id();
215-
let target = unit.target.clone();
215+
let target = Target::clone(&unit.target);
216216
let mode = unit.mode;
217217

218218
exec.init(cx, unit);
@@ -408,7 +408,7 @@ fn link_targets<'a, 'cfg>(
408408
let features = unit.features.iter().map(|s| s.to_string()).collect();
409409
let json_messages = bcx.build_config.emit_json();
410410
let executable = cx.get_executable(unit)?;
411-
let mut target = unit.target.clone();
411+
let mut target = Target::clone(&unit.target);
412412
if let TargetSourcePath::Metabuild = target.src_path() {
413413
// Give it something to serialize.
414414
let path = unit.pkg.manifest().metabuild_path(cx.bcx.ws.target_dir());
@@ -541,11 +541,11 @@ fn prepare_rustc<'a, 'cfg>(
541541
unit: &Unit<'a>,
542542
) -> CargoResult<ProcessBuilder> {
543543
let is_primary = cx.is_primary_package(unit);
544-
let is_workspace = cx.bcx.ws.is_member(unit.pkg);
544+
let is_workspace = cx.bcx.ws.is_member(&unit.pkg);
545545

546546
let mut base = cx
547547
.compilation
548-
.rustc_process(unit.pkg, is_primary, is_workspace)?;
548+
.rustc_process(&unit.pkg, is_primary, is_workspace)?;
549549
if cx.bcx.config.cli_unstable().jobserver_per_rustc {
550550
let client = cx.new_jobserver()?;
551551
base.inherit_jobserver(&client);
@@ -561,7 +561,7 @@ fn prepare_rustc<'a, 'cfg>(
561561

562562
fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult<Work> {
563563
let bcx = cx.bcx;
564-
let mut rustdoc = cx.compilation.rustdoc_process(unit.pkg, unit.target)?;
564+
let mut rustdoc = cx.compilation.rustdoc_process(&unit.pkg, &unit.target)?;
565565
rustdoc.inherit_jobserver(&cx.jobserver);
566566
rustdoc.arg("--crate-name").arg(&unit.target.crate_name());
567567
add_path_args(bcx, unit, &mut rustdoc);
@@ -599,7 +599,7 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult
599599
let name = unit.pkg.name().to_string();
600600
let build_script_outputs = Arc::clone(&cx.build_script_outputs);
601601
let package_id = unit.pkg.package_id();
602-
let target = unit.target.clone();
602+
let target = Target::clone(&unit.target);
603603
let mut output_options = OutputOptions::new(cx, unit);
604604
let pkg_id = unit.pkg.package_id();
605605
let script_metadata = cx.find_build_script_metadata(*unit);
@@ -786,7 +786,7 @@ fn build_base_args<'a, 'cfg>(
786786
}
787787

788788
let prefer_dynamic = (unit.target.for_host() && !unit.target.is_custom_build())
789-
|| (crate_types.contains(&"dylib") && bcx.ws.members().any(|p| p != unit.pkg));
789+
|| (crate_types.contains(&"dylib") && bcx.ws.members().any(|p| p != &*unit.pkg));
790790
if prefer_dynamic {
791791
cmd.arg("-C").arg("prefer-dynamic");
792792
}

src/cargo/core/compiler/timings.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ impl<'a, 'cfg> Timings<'a, 'cfg> {
225225
if self.report_json {
226226
let msg = machine_message::TimingInfo {
227227
package_id: unit_time.unit.pkg.package_id(),
228-
target: unit_time.unit.target,
228+
target: &unit_time.unit.target,
229229
mode: unit_time.unit.mode,
230230
duration: unit_time.duration,
231231
rmeta_time: unit_time.rmeta_time,

src/cargo/core/compiler/unit.rs

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
use crate::core::compiler::{CompileKind, CompileMode};
2-
use crate::core::{profiles::Profile, InternedString, Package, Target};
2+
use crate::core::manifest::{LibKind, Target, TargetKind};
3+
use crate::core::{profiles::Profile, InternedString, Package};
34
use crate::util::hex::short_hash;
45
use std::cell::RefCell;
56
use std::collections::HashSet;
67
use std::fmt;
78
use std::hash::{Hash, Hasher};
89
use std::ops::Deref;
10+
use std::rc::Rc;
911

1012
/// All information needed to define a unit.
1113
///
@@ -23,19 +25,19 @@ use std::ops::Deref;
2325
/// all that out.
2426
#[derive(Clone, Copy, PartialOrd, Ord)]
2527
pub struct Unit<'a> {
26-
inner: &'a UnitInner<'a>,
28+
inner: &'a UnitInner,
2729
}
2830

2931
/// Internal fields of `Unit` which `Unit` will dereference to.
3032
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
31-
pub struct UnitInner<'a> {
33+
pub struct UnitInner {
3234
/// Information about available targets, which files to include/exclude, etc. Basically stuff in
3335
/// `Cargo.toml`.
34-
pub pkg: &'a Package,
36+
pub pkg: Rc<Package>,
3537
/// Information about the specific target to build, out of the possible targets in `pkg`. Not
3638
/// to be confused with *target-triple* (or *target architecture* ...), the target arch for a
3739
/// build.
38-
pub target: &'a Target,
40+
pub target: Rc<Target>,
3941
/// The profile contains information about *how* the build should be run, including debug
4042
/// level, etc.
4143
pub profile: Profile,
@@ -55,7 +57,7 @@ pub struct UnitInner<'a> {
5557
pub is_std: bool,
5658
}
5759

58-
impl UnitInner<'_> {
60+
impl UnitInner {
5961
/// Returns whether compilation of this unit requires all upstream artifacts
6062
/// to be available.
6163
///
@@ -76,23 +78,23 @@ impl<'a> Unit<'a> {
7678
// Just hash the pointer for fast hashing
7779
impl<'a> Hash for Unit<'a> {
7880
fn hash<H: Hasher>(&self, hasher: &mut H) {
79-
(self.inner as *const UnitInner<'a>).hash(hasher)
81+
(self.inner as *const UnitInner).hash(hasher)
8082
}
8183
}
8284

8385
// Just equate the pointer since these are interned
8486
impl<'a> PartialEq for Unit<'a> {
8587
fn eq(&self, other: &Unit<'a>) -> bool {
86-
self.inner as *const UnitInner<'a> == other.inner as *const UnitInner<'a>
88+
self.inner as *const UnitInner == other.inner as *const UnitInner
8789
}
8890
}
8991

9092
impl<'a> Eq for Unit<'a> {}
9193

9294
impl<'a> Deref for Unit<'a> {
93-
type Target = UnitInner<'a>;
95+
type Target = UnitInner;
9496

95-
fn deref(&self) -> &UnitInner<'a> {
97+
fn deref(&self) -> &UnitInner {
9698
self.inner
9799
}
98100
}
@@ -117,17 +119,17 @@ impl<'a> fmt::Debug for Unit<'a> {
117119
/// efficient hash/equality implementation for `Unit`. All units are
118120
/// manufactured through an interner which guarantees that each equivalent value
119121
/// is only produced once.
120-
pub struct UnitInterner<'a> {
121-
state: RefCell<InternerState<'a>>,
122+
pub struct UnitInterner {
123+
state: RefCell<InternerState>,
122124
}
123125

124-
struct InternerState<'a> {
125-
cache: HashSet<Box<UnitInner<'a>>>,
126+
struct InternerState {
127+
cache: HashSet<Box<UnitInner>>,
126128
}
127129

128-
impl<'a> UnitInterner<'a> {
130+
impl UnitInterner {
129131
/// Creates a new blank interner
130-
pub fn new() -> UnitInterner<'a> {
132+
pub fn new() -> UnitInterner {
131133
UnitInterner {
132134
state: RefCell::new(InternerState {
133135
cache: HashSet::new(),
@@ -139,17 +141,38 @@ impl<'a> UnitInterner<'a> {
139141
/// will all be equivalent to the provided arguments, although they may not
140142
/// be the exact same instance.
141143
pub fn intern(
142-
&'a self,
143-
pkg: &'a Package,
144-
target: &'a Target,
144+
&self,
145+
pkg: &Rc<Package>,
146+
target: &Rc<Target>,
145147
profile: Profile,
146148
kind: CompileKind,
147149
mode: CompileMode,
148150
features: Vec<InternedString>,
149151
is_std: bool,
150-
) -> Unit<'a> {
152+
) -> Unit<'_> {
153+
let target = match (is_std, target.kind()) {
154+
// This is a horrible hack to support build-std. `libstd` declares
155+
// itself with both rlib and dylib. We don't want the dylib for a
156+
// few reasons:
157+
//
158+
// - dylibs don't have a hash in the filename. If you do something
159+
// (like switch rustc versions), it will stomp on the dylib
160+
// file, invalidating the entire cache (because std is a dep of
161+
// everything).
162+
// - We don't want to publicize the presence of dylib for the
163+
// standard library.
164+
//
165+
// At some point in the future, it would be nice to have a
166+
// first-class way of overriding or specifying crate-types.
167+
(true, TargetKind::Lib(crate_types)) if crate_types.contains(&LibKind::Dylib) => {
168+
let mut new_target = Target::clone(target);
169+
new_target.set_kind(TargetKind::Lib(vec![LibKind::Rlib]));
170+
Rc::new(new_target)
171+
}
172+
_ => Rc::clone(target),
173+
};
151174
let inner = self.intern_inner(&UnitInner {
152-
pkg,
175+
pkg: Rc::clone(pkg),
153176
target,
154177
profile,
155178
kind,
@@ -178,16 +201,16 @@ impl<'a> UnitInterner<'a> {
178201
// Ideally we'd use an off-the-shelf interner from crates.io which avoids a
179202
// small amount of unsafety here, but at the time this was written one
180203
// wasn't obviously available.
181-
fn intern_inner(&'a self, item: &UnitInner<'a>) -> &'a UnitInner<'a> {
204+
fn intern_inner(&self, item: &UnitInner) -> &UnitInner {
182205
let mut me = self.state.borrow_mut();
183206
if let Some(item) = me.cache.get(item) {
184-
// note that `item` has type `&Box<UnitInner<'a>`. Use `&**` to
185-
// convert that to `&UnitInner<'a>`, then do some trickery to extend
207+
// note that `item` has type `&Box<UnitInner>`. Use `&**` to
208+
// convert that to `&UnitInner`, then do some trickery to extend
186209
// the lifetime to the `'a` on the function here.
187-
return unsafe { &*(&**item as *const UnitInner<'a>) };
210+
return unsafe { &*(&**item as *const UnitInner) };
188211
}
189212
me.cache.insert(Box::new(item.clone()));
190213
let item = me.cache.get(item).unwrap();
191-
unsafe { &*(&**item as *const UnitInner<'a>) }
214+
unsafe { &*(&**item as *const UnitInner) }
192215
}
193216
}

0 commit comments

Comments
 (0)