Skip to content

Commit 21ac2fa

Browse files
committed
Introduce and use LrcRef in ImplicitCtxt
1 parent cca14fa commit 21ac2fa

File tree

4 files changed

+51
-10
lines changed

4 files changed

+51
-10
lines changed

Diff for: src/librustc/ty/context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1878,7 +1878,7 @@ pub mod tls {
18781878
use ty::query;
18791879
use errors::{Diagnostic, TRACK_DIAGNOSTICS};
18801880
use rustc_data_structures::OnDrop;
1881-
use rustc_data_structures::sync::{self, Lrc, Lock};
1881+
use rustc_data_structures::sync::{self, Lock, LrcRef};
18821882
use dep_graph::OpenTask;
18831883

18841884
#[cfg(not(parallel_queries))]
@@ -1900,7 +1900,7 @@ pub mod tls {
19001900

19011901
/// The current query job, if any. This is updated by start_job in
19021902
/// ty::query::plumbing when executing a query
1903-
pub query: Option<Lrc<query::QueryJob<'gcx>>>,
1903+
pub query: Option<LrcRef<'a, query::QueryJob<'gcx>>>,
19041904

19051905
/// Used to prevent layout from recursing too deeply.
19061906
pub layout_depth: usize,

Diff for: src/librustc/ty/query/job.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
use std::mem;
1414
use rustc_data_structures::fx::FxHashSet;
15-
use rustc_data_structures::sync::{Lock, LockGuard, Lrc, Weak};
15+
use rustc_data_structures::sync::{Lock, LockGuard, Lrc, LrcRef, Weak};
1616
use rustc_data_structures::OnDrop;
1717
use syntax_pos::Span;
1818
use ty::tls;
@@ -118,7 +118,7 @@ impl<'tcx> QueryJob<'tcx> {
118118
) -> Result<(), Box<CycleError<'tcx>>> {
119119
tls::with_related_context(tcx, move |icx| {
120120
let mut waiter = Lrc::new(QueryWaiter {
121-
query: icx.query.clone(),
121+
query: icx.query.map(|q| LrcRef::into(q)),
122122
span,
123123
cycle: Lock::new(None),
124124
condvar: Condvar::new(),
@@ -139,7 +139,9 @@ impl<'tcx> QueryJob<'tcx> {
139139
span: Span,
140140
) -> CycleError<'tcx> {
141141
// Get the current executing query (waiter) and find the waitee amongst its parents
142-
let mut current_job = tls::with_related_context(tcx, |icx| icx.query.clone());
142+
let mut current_job = tls::with_related_context(tcx, |icx| {
143+
icx.query.map(|q| LrcRef::into(q))
144+
});
143145
let mut cycle = Vec::new();
144146

145147
while let Some(job) = current_job {
@@ -160,7 +162,7 @@ impl<'tcx> QueryJob<'tcx> {
160162
return CycleError { usage, cycle };
161163
}
162164

163-
current_job = job.parent.clone();
165+
current_job = job.parent.as_ref().map(|parent| parent.clone());
164166
}
165167

166168
panic!("did not find a cycle")

Diff for: src/librustc/ty/query/plumbing.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use ty::item_path;
2626
use util::common::{profq_msg, ProfileQueriesMsg, QueryMsg};
2727

2828
use rustc_data_structures::fx::{FxHashMap};
29-
use rustc_data_structures::sync::{Lrc, Lock};
29+
use rustc_data_structures::sync::{Lrc, LrcRef, Lock};
3030
use rustc_data_structures::by_move::{Move, MoveSlot};
3131
use std::hash::{Hash, Hasher, BuildHasher};
3232
use std::mem;
@@ -224,7 +224,8 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
224224
span,
225225
query: Q::query(key.clone()),
226226
};
227-
let job = Lrc::new(QueryJob::new(info, icx.query.clone()));
227+
let parent = icx.query.map(|q| LrcRef::into(q));
228+
let job = Lrc::new(QueryJob::new(info, parent));
228229
let owner = job_storage.init(JobOwner {
229230
cache,
230231
job: job.clone(),
@@ -296,7 +297,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
296297
// Update the ImplicitCtxt to point to our new query job
297298
let new_icx = tls::ImplicitCtxt {
298299
tcx,
299-
query: Some(self.job.clone()),
300+
query: Some(LrcRef::new(&self.job)),
300301
layout_depth: self.layout_depth,
301302
task,
302303
};
@@ -387,7 +388,7 @@ impl<'a, 'gcx> TyCtxt<'a, 'gcx, 'gcx> {
387388

388389
tls::with_context_opt(|icx| {
389390
if let Some(icx) = icx {
390-
let mut current_query = icx.query.clone();
391+
let mut current_query = icx.query.map(|q| LrcRef::into(q));
391392
let mut i = 0;
392393

393394
while let Some(query) = current_query {

Diff for: src/librustc_data_structures/sync.rs

+38
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use std::collections::HashMap;
3131
use std::hash::{Hash, BuildHasher};
3232
use std::marker::PhantomData;
3333
use std::ops::{Deref, DerefMut};
34+
use std::mem::ManuallyDrop;
3435
use owning_ref::{Erased, OwningRef};
3536

3637
pub fn serial_join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
@@ -669,3 +670,40 @@ impl<T> DerefMut for OneThread<T> {
669670
&mut self.inner
670671
}
671672
}
673+
674+
pub struct LrcRef<'a, T: ?Sized>(&'a T);
675+
676+
impl<'a, T: 'a + ?Sized> Clone for LrcRef<'a, T> {
677+
fn clone(&self) -> Self {
678+
LrcRef(self.0)
679+
}
680+
}
681+
impl<'a, T: 'a + ?Sized> Copy for LrcRef<'a, T> {}
682+
683+
impl<'a, T: 'a + ?Sized> LrcRef<'a, T> {
684+
#[inline]
685+
pub fn new(lrc: &Lrc<T>) -> LrcRef<'_, T> {
686+
LrcRef(&*lrc)
687+
}
688+
689+
#[inline]
690+
pub fn into(self) -> Lrc<T> {
691+
unsafe {
692+
// We know that we have a reference to an Lrc here.
693+
// Pretend to take ownership of the Lrc with from_raw
694+
// and the clone a new one.
695+
// We use ManuallyDrop to ensure the reference count
696+
// isn't decreased
697+
let lrc = ManuallyDrop::new(Lrc::from_raw(self.0));
698+
(*lrc).clone()
699+
}
700+
}
701+
}
702+
703+
impl<'a, T: ?Sized> Deref for LrcRef<'a, T> {
704+
type Target = T;
705+
706+
fn deref(&self) -> &T {
707+
self.0
708+
}
709+
}

0 commit comments

Comments
 (0)