Auto merge of #105543 - matthiaskrgr:rollup-s9zj0pq, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #103146 (Cleanup timeouts in pthread condvar) - #105459 (Build rust-analyzer proc-macro server by default) - #105460 (Bump compiler-builtins to 0.1.85) - #105511 (Update rustix to 0.36.5) - #105530 (Clean up lifetimes in rustdoc syntax highlighting) - #105534 (Add Nilstrieb to compiler reviewers) - #105542 (Some method confirmation code nits) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
e1c91213ff
@ -809,9 +809,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.84"
|
||||
version = "0.1.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "989b2c1ca6e90ad06fdc69d1d1862fa28d27a977be6d92ae2fa762cf61fe0b10"
|
||||
checksum = "13e81c6cd7ab79f51a0c927d22858d61ad12bd0b3865f0b13ece02a4486aeabb"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"rustc-std-workspace-core",
|
||||
@ -4627,9 +4627,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.36.3"
|
||||
version = "0.36.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b1fbb4dfc4eb1d390c02df47760bb19a84bb80b301ecc947ab5406394d8223e"
|
||||
checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
|
@ -521,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
callee_expr,
|
||||
call_expr,
|
||||
callee_ty,
|
||||
pick,
|
||||
&pick,
|
||||
segment,
|
||||
);
|
||||
if pick.illegal_sized_bound.is_some() {
|
||||
|
@ -45,7 +45,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self_expr: &'tcx hir::Expr<'tcx>,
|
||||
call_expr: &'tcx hir::Expr<'tcx>,
|
||||
unadjusted_self_ty: Ty<'tcx>,
|
||||
pick: probe::Pick<'tcx>,
|
||||
pick: &probe::Pick<'tcx>,
|
||||
segment: &hir::PathSegment<'_>,
|
||||
) -> ConfirmResult<'tcx> {
|
||||
debug!(
|
||||
@ -71,7 +71,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
fn confirm(
|
||||
&mut self,
|
||||
unadjusted_self_ty: Ty<'tcx>,
|
||||
pick: probe::Pick<'tcx>,
|
||||
pick: &probe::Pick<'tcx>,
|
||||
segment: &hir::PathSegment<'_>,
|
||||
) -> ConfirmResult<'tcx> {
|
||||
// Adjust the self expression the user provided and obtain the adjusted type.
|
||||
|
@ -192,8 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
self.tcx.check_stability(pick.item.def_id, Some(call_expr.hir_id), span, None);
|
||||
|
||||
let result =
|
||||
self.confirm_method(span, self_expr, call_expr, self_ty, pick.clone(), segment);
|
||||
let result = self.confirm_method(span, self_expr, call_expr, self_ty, &pick, segment);
|
||||
debug!("result = {:?}", result);
|
||||
|
||||
if let Some(span) = result.illegal_sized_bound {
|
||||
|
@ -38,9 +38,9 @@ use rustc_trait_selection::traits::query::method_autoderef::{
|
||||
use rustc_trait_selection::traits::query::CanonicalTyGoal;
|
||||
use rustc_trait_selection::traits::NormalizeExt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCause};
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::max;
|
||||
use std::iter;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
@ -62,28 +62,29 @@ struct ProbeContext<'a, 'tcx> {
|
||||
|
||||
/// This is the OriginalQueryValues for the steps queries
|
||||
/// that are answered in steps.
|
||||
orig_steps_var_values: OriginalQueryValues<'tcx>,
|
||||
orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
|
||||
steps: &'tcx [CandidateStep<'tcx>],
|
||||
|
||||
inherent_candidates: Vec<Candidate<'tcx>>,
|
||||
extension_candidates: Vec<Candidate<'tcx>>,
|
||||
impl_dups: FxHashSet<DefId>,
|
||||
|
||||
/// Collects near misses when the candidate functions are missing a `self` keyword and is only
|
||||
/// used for error reporting
|
||||
static_candidates: Vec<CandidateSource>,
|
||||
|
||||
/// When probing for names, include names that are close to the
|
||||
/// requested name (by Levensthein distance)
|
||||
/// requested name (by Levenshtein distance)
|
||||
allow_similar_names: bool,
|
||||
|
||||
/// Some(candidate) if there is a private candidate
|
||||
private_candidate: Option<(DefKind, DefId)>,
|
||||
|
||||
/// Collects near misses when the candidate functions are missing a `self` keyword and is only
|
||||
/// used for error reporting
|
||||
static_candidates: RefCell<Vec<CandidateSource>>,
|
||||
|
||||
/// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
|
||||
/// for error reporting
|
||||
unsatisfied_predicates:
|
||||
unsatisfied_predicates: RefCell<
|
||||
Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>)>,
|
||||
>,
|
||||
|
||||
scope_expr_id: hir::HirId,
|
||||
}
|
||||
@ -334,7 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
op: OP,
|
||||
) -> Result<R, MethodError<'tcx>>
|
||||
where
|
||||
OP: FnOnce(ProbeContext<'a, 'tcx>) -> Result<R, MethodError<'tcx>>,
|
||||
OP: FnOnce(ProbeContext<'_, 'tcx>) -> Result<R, MethodError<'tcx>>,
|
||||
{
|
||||
let mut orig_values = OriginalQueryValues::default();
|
||||
let param_env_and_self_ty = self.canonicalize_query(
|
||||
@ -445,7 +446,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
mode,
|
||||
method_name,
|
||||
return_type,
|
||||
orig_values,
|
||||
&orig_values,
|
||||
steps.steps,
|
||||
scope_expr_id,
|
||||
);
|
||||
@ -539,7 +540,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
mode: Mode,
|
||||
method_name: Option<Ident>,
|
||||
return_type: Option<Ty<'tcx>>,
|
||||
orig_steps_var_values: OriginalQueryValues<'tcx>,
|
||||
orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
|
||||
steps: &'tcx [CandidateStep<'tcx>],
|
||||
scope_expr_id: hir::HirId,
|
||||
) -> ProbeContext<'a, 'tcx> {
|
||||
@ -554,10 +555,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
impl_dups: FxHashSet::default(),
|
||||
orig_steps_var_values,
|
||||
steps,
|
||||
static_candidates: Vec::new(),
|
||||
allow_similar_names: false,
|
||||
private_candidate: None,
|
||||
unsatisfied_predicates: Vec::new(),
|
||||
static_candidates: RefCell::new(Vec::new()),
|
||||
unsatisfied_predicates: RefCell::new(Vec::new()),
|
||||
scope_expr_id,
|
||||
}
|
||||
}
|
||||
@ -566,8 +567,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
self.inherent_candidates.clear();
|
||||
self.extension_candidates.clear();
|
||||
self.impl_dups.clear();
|
||||
self.static_candidates.clear();
|
||||
self.private_candidate = None;
|
||||
self.static_candidates.borrow_mut().clear();
|
||||
self.unsatisfied_predicates.borrow_mut().clear();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -1003,9 +1005,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
|
||||
debug!("pick: actual search failed, assemble diagnostics");
|
||||
|
||||
let static_candidates = mem::take(&mut self.static_candidates);
|
||||
let static_candidates = std::mem::take(self.static_candidates.get_mut());
|
||||
let private_candidate = self.private_candidate.take();
|
||||
let unsatisfied_predicates = mem::take(&mut self.unsatisfied_predicates);
|
||||
let unsatisfied_predicates = std::mem::take(self.unsatisfied_predicates.get_mut());
|
||||
|
||||
// things failed, so lets look at all traits, for diagnostic purposes now:
|
||||
self.reset();
|
||||
@ -1050,7 +1052,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
}))
|
||||
}
|
||||
|
||||
fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
|
||||
fn pick_core(&self) -> Option<PickResult<'tcx>> {
|
||||
let pick = self.pick_all_method(Some(&mut vec![]));
|
||||
|
||||
// In this case unstable picking is done by `pick_method`.
|
||||
@ -1065,11 +1067,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn pick_all_method(
|
||||
&mut self,
|
||||
&self,
|
||||
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
|
||||
) -> Option<PickResult<'tcx>> {
|
||||
let steps = self.steps.clone();
|
||||
steps
|
||||
self.steps
|
||||
.iter()
|
||||
.filter(|step| {
|
||||
debug!("pick_all_method: step={:?}", step);
|
||||
@ -1123,7 +1124,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
/// to transparently pass `&mut` pointers, in particular, without consuming
|
||||
/// them for their entire lifetime.
|
||||
fn pick_by_value_method(
|
||||
&mut self,
|
||||
&self,
|
||||
step: &CandidateStep<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
|
||||
@ -1151,7 +1152,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn pick_autorefd_method(
|
||||
&mut self,
|
||||
&self,
|
||||
step: &CandidateStep<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
mutbl: hir::Mutability,
|
||||
@ -1177,7 +1178,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
/// special case for this is because going from `*mut T` to `*const T` with autoderefs and
|
||||
/// autorefs would require dereferencing the pointer, which is not safe.
|
||||
fn pick_const_ptr_method(
|
||||
&mut self,
|
||||
&self,
|
||||
step: &CandidateStep<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
|
||||
@ -1202,7 +1203,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
fn pick_method_with_unstable(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
|
||||
fn pick_method_with_unstable(&self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
|
||||
debug!("pick_method_with_unstable(self_ty={})", self.ty_to_string(self_ty));
|
||||
|
||||
let mut possibly_unsatisfied_predicates = Vec::new();
|
||||
@ -1213,7 +1214,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
debug!("searching {} candidates", kind);
|
||||
let res = self.consider_candidates(
|
||||
self_ty,
|
||||
candidates.iter(),
|
||||
candidates,
|
||||
&mut possibly_unsatisfied_predicates,
|
||||
Some(&mut vec![]),
|
||||
);
|
||||
@ -1222,21 +1223,27 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
debug!("searching unstable candidates");
|
||||
for (kind, candidates) in
|
||||
&[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
|
||||
{
|
||||
debug!("searching unstable {kind} candidates");
|
||||
let res = self.consider_candidates(
|
||||
self_ty,
|
||||
self.inherent_candidates.iter().chain(&self.extension_candidates),
|
||||
candidates,
|
||||
&mut possibly_unsatisfied_predicates,
|
||||
None,
|
||||
);
|
||||
if res.is_none() {
|
||||
self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates);
|
||||
if res.is_some() {
|
||||
return res;
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates);
|
||||
None
|
||||
}
|
||||
|
||||
fn pick_method(
|
||||
&mut self,
|
||||
&self,
|
||||
self_ty: Ty<'tcx>,
|
||||
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
|
||||
) -> Option<PickResult<'tcx>> {
|
||||
@ -1254,7 +1261,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
debug!("searching {} candidates", kind);
|
||||
let res = self.consider_candidates(
|
||||
self_ty,
|
||||
candidates.iter(),
|
||||
candidates,
|
||||
&mut possibly_unsatisfied_predicates,
|
||||
unstable_candidates.as_deref_mut(),
|
||||
);
|
||||
@ -1266,28 +1273,24 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
// `pick_method` may be called twice for the same self_ty if no stable methods
|
||||
// match. Only extend once.
|
||||
if unstable_candidates.is_some() {
|
||||
self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates);
|
||||
self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn consider_candidates<'b, ProbesIter>(
|
||||
fn consider_candidates(
|
||||
&self,
|
||||
self_ty: Ty<'tcx>,
|
||||
probes: ProbesIter,
|
||||
candidates: &[Candidate<'tcx>],
|
||||
possibly_unsatisfied_predicates: &mut Vec<(
|
||||
ty::Predicate<'tcx>,
|
||||
Option<ty::Predicate<'tcx>>,
|
||||
Option<ObligationCause<'tcx>>,
|
||||
)>,
|
||||
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
|
||||
) -> Option<PickResult<'tcx>>
|
||||
where
|
||||
ProbesIter: Iterator<Item = &'b Candidate<'tcx>> + Clone,
|
||||
'tcx: 'b,
|
||||
{
|
||||
let mut applicable_candidates: Vec<_> = probes
|
||||
.clone()
|
||||
) -> Option<PickResult<'tcx>> {
|
||||
let mut applicable_candidates: Vec<_> = candidates
|
||||
.iter()
|
||||
.map(|probe| {
|
||||
(probe, self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates))
|
||||
})
|
||||
@ -1305,11 +1308,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
if let Some(uc) = &mut unstable_candidates {
|
||||
applicable_candidates.retain(|&(p, _)| {
|
||||
applicable_candidates.retain(|&(candidate, _)| {
|
||||
if let stability::EvalResult::Deny { feature, .. } =
|
||||
self.tcx.eval_stability(p.item.def_id, None, self.span, None)
|
||||
self.tcx.eval_stability(candidate.item.def_id, None, self.span, None)
|
||||
{
|
||||
uc.push((p.clone(), feature));
|
||||
uc.push((candidate.clone(), feature));
|
||||
return false;
|
||||
}
|
||||
true
|
||||
@ -1317,7 +1320,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
if applicable_candidates.len() > 1 {
|
||||
let sources = probes.map(|p| self.candidate_source(p, self_ty)).collect();
|
||||
let sources = candidates.iter().map(|p| self.candidate_source(p, self_ty)).collect();
|
||||
return Some(Err(MethodError::Ambiguity(sources)));
|
||||
}
|
||||
|
||||
@ -1701,7 +1704,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
self.mode,
|
||||
self.method_name,
|
||||
self.return_type,
|
||||
self.orig_steps_var_values.clone(),
|
||||
&self.orig_steps_var_values,
|
||||
steps,
|
||||
self.scope_expr_id,
|
||||
);
|
||||
@ -1763,8 +1766,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
// -- but this could be overcome.
|
||||
}
|
||||
|
||||
fn record_static_candidate(&mut self, source: CandidateSource) {
|
||||
self.static_candidates.push(source);
|
||||
fn record_static_candidate(&self, source: CandidateSource) {
|
||||
self.static_candidates.borrow_mut().push(source);
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
|
@ -16,7 +16,7 @@ panic_unwind = { path = "../panic_unwind", optional = true }
|
||||
panic_abort = { path = "../panic_abort" }
|
||||
core = { path = "../core" }
|
||||
libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] }
|
||||
compiler_builtins = { version = "0.1.82" }
|
||||
compiler_builtins = { version = "0.1.85" }
|
||||
profiler_builtins = { path = "../profiler_builtins", optional = true }
|
||||
unwind = { path = "../unwind" }
|
||||
hashbrown = { version = "0.12", default-features = false, features = ['rustc-dep-of-std'] }
|
||||
|
@ -2,6 +2,7 @@ use crate::cell::UnsafeCell;
|
||||
use crate::ptr;
|
||||
use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed};
|
||||
use crate::sys::locks::{pthread_mutex, Mutex};
|
||||
use crate::sys::time::TIMESPEC_MAX;
|
||||
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
|
||||
use crate::time::Duration;
|
||||
|
||||
@ -12,13 +13,6 @@ pub struct Condvar {
|
||||
mutex: AtomicPtr<libc::pthread_mutex_t>,
|
||||
}
|
||||
|
||||
const TIMESPEC_MAX: libc::timespec =
|
||||
libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
|
||||
|
||||
fn saturating_cast_to_time_t(value: u64) -> libc::time_t {
|
||||
if value > <libc::time_t>::MAX as u64 { <libc::time_t>::MAX } else { value as libc::time_t }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn raw(c: &Condvar) -> *mut libc::pthread_cond_t {
|
||||
c.inner.0.get()
|
||||
@ -133,26 +127,15 @@ impl Condvar {
|
||||
target_os = "horizon"
|
||||
)))]
|
||||
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
|
||||
use crate::mem;
|
||||
use crate::sys::time::Timespec;
|
||||
|
||||
let mutex = pthread_mutex::raw(mutex);
|
||||
self.verify(mutex);
|
||||
|
||||
let mut now: libc::timespec = mem::zeroed();
|
||||
let r = libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut now);
|
||||
assert_eq!(r, 0);
|
||||
|
||||
// Nanosecond calculations can't overflow because both values are below 1e9.
|
||||
let nsec = dur.subsec_nanos() + now.tv_nsec as u32;
|
||||
|
||||
let sec = saturating_cast_to_time_t(dur.as_secs())
|
||||
.checked_add((nsec / 1_000_000_000) as libc::time_t)
|
||||
.and_then(|s| s.checked_add(now.tv_sec));
|
||||
let nsec = nsec % 1_000_000_000;
|
||||
|
||||
let timeout =
|
||||
sec.map(|s| libc::timespec { tv_sec: s, tv_nsec: nsec as _ }).unwrap_or(TIMESPEC_MAX);
|
||||
|
||||
let timeout = Timespec::now(libc::CLOCK_MONOTONIC)
|
||||
.checked_add_duration(&dur)
|
||||
.and_then(|t| t.to_timespec())
|
||||
.unwrap_or(TIMESPEC_MAX);
|
||||
let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
|
||||
assert!(r == libc::ETIMEDOUT || r == 0);
|
||||
r == 0
|
||||
@ -169,20 +152,17 @@ impl Condvar {
|
||||
target_os = "espidf",
|
||||
target_os = "horizon"
|
||||
))]
|
||||
pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
|
||||
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
|
||||
use crate::sys::time::SystemTime;
|
||||
use crate::time::Instant;
|
||||
|
||||
let mutex = pthread_mutex::raw(mutex);
|
||||
self.verify(mutex);
|
||||
|
||||
// 1000 years
|
||||
let max_dur = Duration::from_secs(1000 * 365 * 86400);
|
||||
|
||||
if dur > max_dur {
|
||||
// OSX implementation of `pthread_cond_timedwait` is buggy
|
||||
// with super long durations. When duration is greater than
|
||||
// 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait`
|
||||
// in macOS Sierra return error 316.
|
||||
// in macOS Sierra returns error 316.
|
||||
//
|
||||
// This program demonstrates the issue:
|
||||
// https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c
|
||||
@ -190,36 +170,23 @@ impl Condvar {
|
||||
// To work around this issue, and possible bugs of other OSes, timeout
|
||||
// is clamped to 1000 years, which is allowable per the API of `wait_timeout`
|
||||
// because of spurious wakeups.
|
||||
let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400));
|
||||
|
||||
dur = max_dur;
|
||||
}
|
||||
// pthread_cond_timedwait uses system time, but we want to report timeout
|
||||
// based on stable time.
|
||||
let now = Instant::now();
|
||||
|
||||
// First, figure out what time it currently is, in both system and
|
||||
// stable time. pthread_cond_timedwait uses system time, but we want to
|
||||
// report timeout based on stable time.
|
||||
let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 };
|
||||
let stable_now = Instant::now();
|
||||
let r = libc::gettimeofday(&mut sys_now, ptr::null_mut());
|
||||
assert_eq!(r, 0, "unexpected error: {:?}", crate::io::Error::last_os_error());
|
||||
|
||||
let nsec = dur.subsec_nanos() as libc::c_long + (sys_now.tv_usec * 1000) as libc::c_long;
|
||||
let extra = (nsec / 1_000_000_000) as libc::time_t;
|
||||
let nsec = nsec % 1_000_000_000;
|
||||
let seconds = saturating_cast_to_time_t(dur.as_secs());
|
||||
|
||||
let timeout = sys_now
|
||||
.tv_sec
|
||||
.checked_add(extra)
|
||||
.and_then(|s| s.checked_add(seconds))
|
||||
.map(|s| libc::timespec { tv_sec: s, tv_nsec: nsec })
|
||||
let timeout = SystemTime::now()
|
||||
.t
|
||||
.checked_add_duration(&dur)
|
||||
.and_then(|t| t.to_timespec())
|
||||
.unwrap_or(TIMESPEC_MAX);
|
||||
|
||||
// And wait!
|
||||
let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
|
||||
debug_assert!(r == libc::ETIMEDOUT || r == 0);
|
||||
|
||||
// ETIMEDOUT is not a totally reliable method of determining timeout due
|
||||
// to clock shifts, so do the check ourselves
|
||||
stable_now.elapsed() < dur
|
||||
now.elapsed() < dur
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use crate::pin::Pin;
|
||||
use crate::ptr::addr_of_mut;
|
||||
use crate::sync::atomic::AtomicUsize;
|
||||
use crate::sync::atomic::Ordering::SeqCst;
|
||||
use crate::sys::time::TIMESPEC_MAX;
|
||||
use crate::time::Duration;
|
||||
|
||||
const EMPTY: usize = 0;
|
||||
@ -32,9 +33,6 @@ unsafe fn wait(cond: *mut libc::pthread_cond_t, lock: *mut libc::pthread_mutex_t
|
||||
debug_assert_eq!(r, 0);
|
||||
}
|
||||
|
||||
const TIMESPEC_MAX: libc::timespec =
|
||||
libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
|
||||
|
||||
unsafe fn wait_timeout(
|
||||
cond: *mut libc::pthread_cond_t,
|
||||
lock: *mut libc::pthread_mutex_t,
|
||||
|
@ -5,6 +5,9 @@ pub use self::inner::Instant;
|
||||
|
||||
const NSEC_PER_SEC: u64 = 1_000_000_000;
|
||||
pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
|
||||
#[allow(dead_code)] // Used for pthread condvar timeouts
|
||||
pub const TIMESPEC_MAX: libc::timespec =
|
||||
libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(transparent)]
|
||||
|
@ -747,19 +747,9 @@ impl Step for RustAnalyzerProcMacroSrv {
|
||||
const ONLY_HOSTS: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
||||
// Allow building `rust-analyzer-proc-macro-srv` both as part of the `rust-analyzer` and as a stand-alone tool.
|
||||
run.path("src/tools/rust-analyzer")
|
||||
.path("src/tools/rust-analyzer/crates/proc-macro-srv-cli")
|
||||
.default_condition(
|
||||
builder.config.extended
|
||||
&& builder.config.tools.as_ref().map_or(true, |tools| {
|
||||
tools.iter().any(|tool| {
|
||||
tool == "rust-analyzer" || tool == "rust-analyzer-proc-macro-srv"
|
||||
})
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
|
@ -21,15 +21,15 @@ use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||
use super::format::{self, Buffer};
|
||||
|
||||
/// This type is needed in case we want to render links on items to allow to go to their definition.
|
||||
pub(crate) struct HrefContext<'a, 'b, 'c> {
|
||||
pub(crate) context: &'a Context<'b>,
|
||||
pub(crate) struct HrefContext<'a, 'tcx> {
|
||||
pub(crate) context: &'a Context<'tcx>,
|
||||
/// This span contains the current file we're going through.
|
||||
pub(crate) file_span: Span,
|
||||
/// This field is used to know "how far" from the top of the directory we are to link to either
|
||||
/// documentation pages or other source pages.
|
||||
pub(crate) root_path: &'c str,
|
||||
pub(crate) root_path: &'a str,
|
||||
/// This field is used to calculate precise local URLs.
|
||||
pub(crate) current_href: &'c str,
|
||||
pub(crate) current_href: String,
|
||||
}
|
||||
|
||||
/// Decorations are represented as a map from CSS class to vector of character ranges.
|
||||
@ -70,7 +70,7 @@ pub(crate) fn render_source_with_highlighting(
|
||||
src: &str,
|
||||
out: &mut Buffer,
|
||||
line_numbers: Buffer,
|
||||
href_context: HrefContext<'_, '_, '_>,
|
||||
href_context: HrefContext<'_, '_>,
|
||||
decoration_info: DecorationInfo,
|
||||
extra: Option<&str>,
|
||||
) {
|
||||
@ -137,7 +137,7 @@ fn can_merge(class1: Option<Class>, class2: Option<Class>, text: &str) -> bool {
|
||||
|
||||
/// This type is used as a conveniency to prevent having to pass all its fields as arguments into
|
||||
/// the various functions (which became its methods).
|
||||
struct TokenHandler<'a, 'b, 'c, 'd, 'e> {
|
||||
struct TokenHandler<'a, 'tcx> {
|
||||
out: &'a mut Buffer,
|
||||
/// It contains the closing tag and the associated `Class`.
|
||||
closing_tags: Vec<(&'static str, Class)>,
|
||||
@ -149,11 +149,11 @@ struct TokenHandler<'a, 'b, 'c, 'd, 'e> {
|
||||
current_class: Option<Class>,
|
||||
/// We need to keep the `Class` for each element because it could contain a `Span` which is
|
||||
/// used to generate links.
|
||||
pending_elems: Vec<(&'b str, Option<Class>)>,
|
||||
href_context: Option<HrefContext<'c, 'd, 'e>>,
|
||||
pending_elems: Vec<(&'a str, Option<Class>)>,
|
||||
href_context: Option<HrefContext<'a, 'tcx>>,
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c, 'd, 'e> TokenHandler<'a, 'b, 'c, 'd, 'e> {
|
||||
impl<'a, 'tcx> TokenHandler<'a, 'tcx> {
|
||||
fn handle_exit_span(&mut self) {
|
||||
// We can't get the last `closing_tags` element using `pop()` because `closing_tags` is
|
||||
// being used in `write_pending_elems`.
|
||||
@ -205,7 +205,7 @@ impl<'a, 'b, 'c, 'd, 'e> TokenHandler<'a, 'b, 'c, 'd, 'e> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c, 'd, 'e> Drop for TokenHandler<'a, 'b, 'c, 'd, 'e> {
|
||||
impl<'a, 'tcx> Drop for TokenHandler<'a, 'tcx> {
|
||||
/// When leaving, we need to flush all pending data to not have missing content.
|
||||
fn drop(&mut self) {
|
||||
if self.pending_exit_span.is_some() {
|
||||
@ -230,7 +230,7 @@ impl<'a, 'b, 'c, 'd, 'e> Drop for TokenHandler<'a, 'b, 'c, 'd, 'e> {
|
||||
fn write_code(
|
||||
out: &mut Buffer,
|
||||
src: &str,
|
||||
href_context: Option<HrefContext<'_, '_, '_>>,
|
||||
href_context: Option<HrefContext<'_, '_>>,
|
||||
decoration_info: Option<DecorationInfo>,
|
||||
) {
|
||||
// This replace allows to fix how the code source with DOS backline characters is displayed.
|
||||
@ -514,18 +514,18 @@ impl Decorations {
|
||||
|
||||
/// Processes program tokens, classifying strings of text by highlighting
|
||||
/// category (`Class`).
|
||||
struct Classifier<'a> {
|
||||
tokens: PeekIter<'a>,
|
||||
struct Classifier<'src> {
|
||||
tokens: PeekIter<'src>,
|
||||
in_attribute: bool,
|
||||
in_macro: bool,
|
||||
in_macro_nonterminal: bool,
|
||||
byte_pos: u32,
|
||||
file_span: Span,
|
||||
src: &'a str,
|
||||
src: &'src str,
|
||||
decorations: Option<Decorations>,
|
||||
}
|
||||
|
||||
impl<'a> Classifier<'a> {
|
||||
impl<'src> Classifier<'src> {
|
||||
/// Takes as argument the source code to HTML-ify, the rust edition to use and the source code
|
||||
/// file span which will be used later on by the `span_correspondance_map`.
|
||||
fn new(src: &str, file_span: Span, decoration_info: Option<DecorationInfo>) -> Classifier<'_> {
|
||||
@ -603,7 +603,7 @@ impl<'a> Classifier<'a> {
|
||||
///
|
||||
/// It returns the token's kind, the token as a string and its byte position in the source
|
||||
/// string.
|
||||
fn next(&mut self) -> Option<(TokenKind, &'a str, u32)> {
|
||||
fn next(&mut self) -> Option<(TokenKind, &'src str, u32)> {
|
||||
if let Some((kind, text)) = self.tokens.next() {
|
||||
let before = self.byte_pos;
|
||||
self.byte_pos += text.len() as u32;
|
||||
@ -618,7 +618,7 @@ impl<'a> Classifier<'a> {
|
||||
/// The general structure for this method is to iterate over each token,
|
||||
/// possibly giving it an HTML span with a class specifying what flavor of
|
||||
/// token is used.
|
||||
fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'a>)) {
|
||||
fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'src>)) {
|
||||
loop {
|
||||
if let Some(decs) = self.decorations.as_mut() {
|
||||
let byte_pos = self.byte_pos;
|
||||
@ -666,8 +666,8 @@ impl<'a> Classifier<'a> {
|
||||
fn advance(
|
||||
&mut self,
|
||||
token: TokenKind,
|
||||
text: &'a str,
|
||||
sink: &mut dyn FnMut(Highlight<'a>),
|
||||
text: &'src str,
|
||||
sink: &mut dyn FnMut(Highlight<'src>),
|
||||
before: u32,
|
||||
) {
|
||||
let lookahead = self.peek();
|
||||
@ -881,7 +881,7 @@ impl<'a> Classifier<'a> {
|
||||
fn enter_span(
|
||||
out: &mut Buffer,
|
||||
klass: Class,
|
||||
href_context: &Option<HrefContext<'_, '_, '_>>,
|
||||
href_context: &Option<HrefContext<'_, '_>>,
|
||||
) -> &'static str {
|
||||
string_without_closing_tag(out, "", Some(klass), href_context, true).expect(
|
||||
"internal error: enter_span was called with Some(klass) but did not return a \
|
||||
@ -914,7 +914,7 @@ fn string<T: Display>(
|
||||
out: &mut Buffer,
|
||||
text: T,
|
||||
klass: Option<Class>,
|
||||
href_context: &Option<HrefContext<'_, '_, '_>>,
|
||||
href_context: &Option<HrefContext<'_, '_>>,
|
||||
open_tag: bool,
|
||||
) {
|
||||
if let Some(closing_tag) = string_without_closing_tag(out, text, klass, href_context, open_tag)
|
||||
@ -936,7 +936,7 @@ fn string_without_closing_tag<T: Display>(
|
||||
out: &mut Buffer,
|
||||
text: T,
|
||||
klass: Option<Class>,
|
||||
href_context: &Option<HrefContext<'_, '_, '_>>,
|
||||
href_context: &Option<HrefContext<'_, '_>>,
|
||||
open_tag: bool,
|
||||
) -> Option<&'static str> {
|
||||
let Some(klass) = klass
|
||||
@ -985,7 +985,7 @@ fn string_without_closing_tag<T: Display>(
|
||||
// https://github.com/rust-lang/rust/blob/60f1a2fc4b535ead9c85ce085fdce49b1b097531/src/librustdoc/html/render/context.rs#L315-L338
|
||||
match href {
|
||||
LinkFromSrc::Local(span) => {
|
||||
context.href_from_span_relative(*span, href_context.current_href)
|
||||
context.href_from_span_relative(*span, &href_context.current_href)
|
||||
}
|
||||
LinkFromSrc::External(def_id) => {
|
||||
format::href_with_root_path(*def_id, context, Some(href_context.root_path))
|
||||
|
@ -276,7 +276,7 @@ pub(crate) fn print_src(
|
||||
let mut line_numbers = Buffer::empty_from(buf);
|
||||
let extra;
|
||||
line_numbers.write_str("<pre class=\"src-line-numbers\">");
|
||||
let current_href = &context
|
||||
let current_href = context
|
||||
.href_from_span(clean::Span::new(file_span), false)
|
||||
.expect("only local crates should have sources emitted");
|
||||
match source_context {
|
||||
|
@ -469,6 +469,7 @@ compiler-team-contributors = [
|
||||
"@jackh726",
|
||||
"@fee1-dead",
|
||||
"@TaKO8Ki",
|
||||
"@Nilstrieb",
|
||||
]
|
||||
compiler = [
|
||||
"compiler-team",
|
||||
|
Loading…
x
Reference in New Issue
Block a user