Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 0148a2b

Browse files
committedFeb 8, 2025
Auto merge of #136713 - matthiaskrgr:rollup-sy6py39, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #135179 (Make sure to use `Receiver` trait when extracting object method candidate) - #136554 (Add `opt_alias_variances` and use it in outlives code) - #136556 ([AIX] Update tests/ui/wait-forked-but-failed-child.rs to accomodate exiting and idle processes.) - #136589 (Enable "jump to def" feature on rustc docs) - #136615 (sys: net: Add UEFI stubs) - #136635 (Remove outdated `base_port` calculation in std net test) - #136682 (Move two windows process tests to tests/ui) r? `@ghost` `@rustbot` modify labels: rollup
2 parents e060723 + 0a33d7c commit 0148a2b

File tree

23 files changed

+722
-234
lines changed

23 files changed

+722
-234
lines changed
 

‎compiler/rustc_borrowck/src/type_check/opaque_types.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ where
284284
return;
285285
}
286286

287-
match ty.kind() {
287+
match *ty.kind() {
288288
ty::Closure(_, args) => {
289289
// Skip lifetime parameters of the enclosing item(s)
290290

@@ -316,10 +316,12 @@ where
316316
args.as_coroutine().resume_ty().visit_with(self);
317317
}
318318

319-
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
320-
// Skip lifetime parameters that are not captures.
321-
let variances = self.tcx.variances_of(*def_id);
322-
319+
ty::Alias(kind, ty::AliasTy { def_id, args, .. })
320+
if let Some(variances) = self.tcx.opt_alias_variances(kind, def_id) =>
321+
{
322+
// Skip lifetime parameters that are not captured, since they do
323+
// not need member constraints registered for them; we'll erase
324+
// them (and hopefully in the future replace them with placeholders).
323325
for (v, s) in std::iter::zip(variances, args.iter()) {
324326
if *v != ty::Bivariant {
325327
s.visit_with(self);

‎compiler/rustc_hir_typeck/src/method/confirm.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,17 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
347347
// yield an object-type (e.g., `&Object` or `Box<Object>`
348348
// etc).
349349

350-
// FIXME: this feels, like, super dubious
351-
self.fcx
352-
.autoderef(self.span, self_ty)
350+
let mut autoderef = self.fcx.autoderef(self.span, self_ty);
351+
352+
// We don't need to gate this behind arbitrary self types
353+
// per se, but it does make things a bit more gated.
354+
if self.tcx.features().arbitrary_self_types()
355+
|| self.tcx.features().arbitrary_self_types_pointers()
356+
{
357+
autoderef = autoderef.use_receiver_trait();
358+
}
359+
360+
autoderef
353361
.include_raw_pointers()
354362
.find_map(|(ty, _)| match ty.kind() {
355363
ty::Dynamic(data, ..) => Some(closure(

‎compiler/rustc_infer/src/infer/outlives/for_liveness.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ where
4848
return ty.super_visit_with(self);
4949
}
5050

51-
match ty.kind() {
51+
match *ty.kind() {
5252
// We can prove that an alias is live two ways:
5353
// 1. All the components are live.
5454
//
@@ -95,11 +95,9 @@ where
9595
assert!(r.type_flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS));
9696
r.visit_with(self);
9797
} else {
98-
// Skip lifetime parameters that are not captures.
99-
let variances = match kind {
100-
ty::Opaque => Some(self.tcx.variances_of(*def_id)),
101-
_ => None,
102-
};
98+
// Skip lifetime parameters that are not captured, since they do
99+
// not need to be live.
100+
let variances = tcx.opt_alias_variances(kind, def_id);
103101

104102
for (idx, s) in args.iter().enumerate() {
105103
if variances.map(|variances| variances[idx]) != Some(ty::Bivariant) {

‎compiler/rustc_infer/src/infer/outlives/obligations.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,13 +392,13 @@ where
392392
// the problem is to add `T: 'r`, which isn't true. So, if there are no
393393
// inference variables, we use a verify constraint instead of adding
394394
// edges, which winds up enforcing the same condition.
395-
let is_opaque = alias_ty.kind(self.tcx) == ty::Opaque;
395+
let kind = alias_ty.kind(self.tcx);
396396
if approx_env_bounds.is_empty()
397397
&& trait_bounds.is_empty()
398-
&& (alias_ty.has_infer_regions() || is_opaque)
398+
&& (alias_ty.has_infer_regions() || kind == ty::Opaque)
399399
{
400400
debug!("no declared bounds");
401-
let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id));
401+
let opt_variances = self.tcx.opt_alias_variances(kind, alias_ty.def_id);
402402
self.args_must_outlive(alias_ty.args, origin, region, opt_variances);
403403
return;
404404
}

‎compiler/rustc_infer/src/infer/outlives/verify.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,11 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
102102

103103
#[instrument(level = "debug", skip(self))]
104104
pub(crate) fn alias_bound(&self, alias_ty: ty::AliasTy<'tcx>) -> VerifyBound<'tcx> {
105-
let alias_ty_as_ty = alias_ty.to_ty(self.tcx);
106-
107105
// Search the env for where clauses like `P: 'a`.
108106
let env_bounds = self.approx_declared_bounds_from_env(alias_ty).into_iter().map(|binder| {
109107
if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars()
110-
&& ty == alias_ty_as_ty
108+
&& let ty::Alias(_, alias_ty_from_bound) = *ty.kind()
109+
&& alias_ty_from_bound == alias_ty
111110
{
112111
// Micro-optimize if this is an exact match (this
113112
// occurs often when there are no region variables
@@ -127,7 +126,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
127126
// see the extensive comment in projection_must_outlive
128127
let recursive_bound = {
129128
let mut components = smallvec![];
130-
compute_alias_components_recursive(self.tcx, alias_ty_as_ty, &mut components);
129+
let kind = alias_ty.kind(self.tcx);
130+
compute_alias_components_recursive(self.tcx, kind, alias_ty, &mut components);
131131
self.bound_from_components(&components)
132132
};
133133

‎compiler/rustc_interface/src/passes.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,9 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
827827
if tcx.sess.opts.unstable_opts.input_stats {
828828
rustc_passes::input_stats::print_hir_stats(tcx);
829829
}
830-
#[cfg(debug_assertions)]
830+
// When using rustdoc's "jump to def" feature, it enters this code and `check_crate`
831+
// is not defined. So we need to cfg it out.
832+
#[cfg(all(not(doc), debug_assertions))]
831833
rustc_passes::hir_id_validator::check_crate(tcx);
832834
let sess = tcx.sess;
833835
sess.time("misc_checking_1", || {

‎compiler/rustc_middle/src/ty/context.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
194194
self.variances_of(def_id)
195195
}
196196

197+
fn opt_alias_variances(
198+
self,
199+
kind: impl Into<ty::AliasTermKind>,
200+
def_id: DefId,
201+
) -> Option<&'tcx [ty::Variance]> {
202+
self.opt_alias_variances(kind, def_id)
203+
}
204+
197205
fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
198206
self.type_of(def_id)
199207
}

‎compiler/rustc_middle/src/ty/util.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,29 @@ impl<'tcx> TyCtxt<'tcx> {
948948

949949
ty
950950
}
951+
952+
// Computes the variances for an alias (opaque or RPITIT) that represent
953+
// its (un)captured regions.
954+
pub fn opt_alias_variances(
955+
self,
956+
kind: impl Into<ty::AliasTermKind>,
957+
def_id: DefId,
958+
) -> Option<&'tcx [ty::Variance]> {
959+
match kind.into() {
960+
ty::AliasTermKind::ProjectionTy => {
961+
if self.is_impl_trait_in_trait(def_id) {
962+
Some(self.variances_of(def_id))
963+
} else {
964+
None
965+
}
966+
}
967+
ty::AliasTermKind::OpaqueTy => Some(self.variances_of(def_id)),
968+
ty::AliasTermKind::InherentTy
969+
| ty::AliasTermKind::WeakTy
970+
| ty::AliasTermKind::UnevaluatedConst
971+
| ty::AliasTermKind::ProjectionConst => None,
972+
}
973+
}
951974
}
952975

953976
struct OpaqueTypeExpander<'tcx> {

‎compiler/rustc_type_ir/src/interner.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,12 @@ pub trait Interner:
141141
type VariancesOf: Copy + Debug + SliceLike<Item = ty::Variance>;
142142
fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf;
143143

144+
fn opt_alias_variances(
145+
self,
146+
kind: impl Into<ty::AliasTermKind>,
147+
def_id: Self::DefId,
148+
) -> Option<Self::VariancesOf>;
149+
144150
fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder<Self, Self::Ty>;
145151

146152
type AdtDef: AdtDef<Self>;

‎compiler/rustc_type_ir/src/outlives.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl<I: Interner> TypeVisitor<I> for OutlivesCollector<'_, I> {
148148
// trait-ref. Therefore, if we see any higher-ranked regions,
149149
// we simply fallback to the most restrictive rule, which
150150
// requires that `Pi: 'a` for all `i`.
151-
ty::Alias(_, alias_ty) => {
151+
ty::Alias(kind, alias_ty) => {
152152
if !alias_ty.has_escaping_bound_vars() {
153153
// best case: no escaping regions, so push the
154154
// projection and skip the subtree (thus generating no
@@ -162,7 +162,7 @@ impl<I: Interner> TypeVisitor<I> for OutlivesCollector<'_, I> {
162162
// OutlivesProjectionComponents. Continue walking
163163
// through and constrain Pi.
164164
let mut subcomponents = smallvec![];
165-
compute_alias_components_recursive(self.cx, ty, &mut subcomponents);
165+
compute_alias_components_recursive(self.cx, kind, alias_ty, &mut subcomponents);
166166
self.out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
167167
}
168168
}
@@ -217,21 +217,17 @@ impl<I: Interner> TypeVisitor<I> for OutlivesCollector<'_, I> {
217217
}
218218
}
219219

220-
/// Collect [Component]s for *all* the args of `parent`.
220+
/// Collect [Component]s for *all* the args of `alias_ty`.
221221
///
222-
/// This should not be used to get the components of `parent` itself.
222+
/// This should not be used to get the components of `alias_ty` itself.
223223
/// Use [push_outlives_components] instead.
224224
pub fn compute_alias_components_recursive<I: Interner>(
225225
cx: I,
226-
alias_ty: I::Ty,
226+
kind: ty::AliasTyKind,
227+
alias_ty: ty::AliasTy<I>,
227228
out: &mut SmallVec<[Component<I>; 4]>,
228229
) {
229-
let ty::Alias(kind, alias_ty) = alias_ty.kind() else {
230-
unreachable!("can only call `compute_alias_components_recursive` on an alias type")
231-
};
232-
233-
let opt_variances =
234-
if kind == ty::Opaque { Some(cx.variances_of(alias_ty.def_id)) } else { None };
230+
let opt_variances = cx.opt_alias_variances(kind, alias_ty.def_id);
235231

236232
let mut visitor = OutlivesCollector { cx, out, visited: Default::default() };
237233

‎compiler/rustc_type_ir/src/predicate.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,17 @@ impl AliasTermKind {
469469
}
470470
}
471471

472+
impl From<ty::AliasTyKind> for AliasTermKind {
473+
fn from(value: ty::AliasTyKind) -> Self {
474+
match value {
475+
ty::Projection => AliasTermKind::ProjectionTy,
476+
ty::Opaque => AliasTermKind::OpaqueTy,
477+
ty::Weak => AliasTermKind::WeakTy,
478+
ty::Inherent => AliasTermKind::InherentTy,
479+
}
480+
}
481+
}
482+
472483
/// Represents the unprojected term of a projection goal.
473484
///
474485
/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.

‎compiler/rustc_type_ir/src/relate.rs

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -236,28 +236,14 @@ impl<I: Interner> Relate<I> for ty::AliasTy<I> {
236236
ExpectedFound::new(a, b)
237237
}))
238238
} else {
239-
let args = match a.kind(relation.cx()) {
240-
ty::Opaque => relate_args_with_variances(
241-
relation,
242-
a.def_id,
243-
relation.cx().variances_of(a.def_id),
244-
a.args,
245-
b.args,
239+
let cx = relation.cx();
240+
let args = if let Some(variances) = cx.opt_alias_variances(a.kind(cx), a.def_id) {
241+
relate_args_with_variances(
242+
relation, a.def_id, variances, a.args, b.args,
246243
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
247-
)?,
248-
ty::Projection if relation.cx().is_impl_trait_in_trait(a.def_id) => {
249-
relate_args_with_variances(
250-
relation,
251-
a.def_id,
252-
relation.cx().variances_of(a.def_id),
253-
a.args,
254-
b.args,
255-
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
256-
)?
257-
}
258-
ty::Projection | ty::Weak | ty::Inherent => {
259-
relate_args_invariantly(relation, a.args, b.args)?
260-
}
244+
)?
245+
} else {
246+
relate_args_invariantly(relation, a.args, b.args)?
261247
};
262248
Ok(ty::AliasTy::new_from_args(relation.cx(), a.def_id, args))
263249
}

‎library/std/src/net/test.rs

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToS
55
use crate::sync::atomic::{AtomicUsize, Ordering};
66

77
static PORT: AtomicUsize = AtomicUsize::new(0);
8+
const BASE_PORT: u16 = 19600;
89

910
pub fn next_test_ip4() -> SocketAddr {
10-
let port = PORT.fetch_add(1, Ordering::Relaxed) as u16 + base_port();
11+
let port = PORT.fetch_add(1, Ordering::Relaxed) as u16 + BASE_PORT;
1112
SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port))
1213
}
1314

1415
pub fn next_test_ip6() -> SocketAddr {
15-
let port = PORT.fetch_add(1, Ordering::Relaxed) as u16 + base_port();
16+
let port = PORT.fetch_add(1, Ordering::Relaxed) as u16 + BASE_PORT;
1617
SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), port, 0, 0))
1718
}
1819

@@ -30,31 +31,3 @@ pub fn tsa<A: ToSocketAddrs>(a: A) -> Result<Vec<SocketAddr>, String> {
3031
Err(e) => Err(e.to_string()),
3132
}
3233
}
33-
34-
// The bots run multiple builds at the same time, and these builds
35-
// all want to use ports. This function figures out which workspace
36-
// it is running in and assigns a port range based on it.
37-
fn base_port() -> u16 {
38-
let cwd = if cfg!(target_env = "sgx") {
39-
String::from("sgx")
40-
} else {
41-
env::current_dir().unwrap().into_os_string().into_string().unwrap()
42-
};
43-
let dirs = [
44-
"32-opt",
45-
"32-nopt",
46-
"musl-64-opt",
47-
"cross-opt",
48-
"64-opt",
49-
"64-nopt",
50-
"64-opt-vg",
51-
"64-debug-opt",
52-
"all-opt",
53-
"snap3",
54-
"dist",
55-
"sgx",
56-
];
57-
dirs.iter().enumerate().find(|&(_, dir)| cwd.contains(dir)).map(|p| p.0).unwrap_or(0) as u16
58-
* 1000
59-
+ 19600
60-
}

‎library/std/src/process/tests.rs

Lines changed: 0 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -391,154 +391,6 @@ fn test_interior_nul_in_env_value_is_error() {
391391
}
392392
}
393393

394-
/// Tests that process creation flags work by debugging a process.
395-
/// Other creation flags make it hard or impossible to detect
396-
/// behavioral changes in the process.
397-
#[test]
398-
#[cfg(windows)]
399-
fn test_creation_flags() {
400-
use crate::os::windows::process::CommandExt;
401-
use crate::sys::c::{BOOL, INFINITE};
402-
#[repr(C)]
403-
struct DEBUG_EVENT {
404-
pub event_code: u32,
405-
pub process_id: u32,
406-
pub thread_id: u32,
407-
// This is a union in the real struct, but we don't
408-
// need this data for the purposes of this test.
409-
pub _junk: [u8; 164],
410-
}
411-
412-
extern "system" {
413-
fn WaitForDebugEvent(lpDebugEvent: *mut DEBUG_EVENT, dwMilliseconds: u32) -> BOOL;
414-
fn ContinueDebugEvent(dwProcessId: u32, dwThreadId: u32, dwContinueStatus: u32) -> BOOL;
415-
}
416-
417-
const DEBUG_PROCESS: u32 = 1;
418-
const EXIT_PROCESS_DEBUG_EVENT: u32 = 5;
419-
const DBG_EXCEPTION_NOT_HANDLED: u32 = 0x80010001;
420-
421-
let mut child = Command::new("cmd")
422-
.creation_flags(DEBUG_PROCESS)
423-
.stdin(Stdio::piped())
424-
.stdout(Stdio::null())
425-
.stderr(Stdio::null())
426-
.spawn()
427-
.unwrap();
428-
child.stdin.take().unwrap().write_all(b"exit\r\n").unwrap();
429-
let mut events = 0;
430-
let mut event = DEBUG_EVENT { event_code: 0, process_id: 0, thread_id: 0, _junk: [0; 164] };
431-
loop {
432-
if unsafe { WaitForDebugEvent(&mut event as *mut DEBUG_EVENT, INFINITE) } == 0 {
433-
panic!("WaitForDebugEvent failed!");
434-
}
435-
events += 1;
436-
437-
if event.event_code == EXIT_PROCESS_DEBUG_EVENT {
438-
break;
439-
}
440-
441-
if unsafe {
442-
ContinueDebugEvent(event.process_id, event.thread_id, DBG_EXCEPTION_NOT_HANDLED)
443-
} == 0
444-
{
445-
panic!("ContinueDebugEvent failed!");
446-
}
447-
}
448-
assert!(events > 0);
449-
}
450-
451-
/// Tests proc thread attributes by spawning a process with a custom parent process,
452-
/// then comparing the parent process ID with the expected parent process ID.
453-
#[test]
454-
#[cfg(windows)]
455-
fn test_proc_thread_attributes() {
456-
use crate::mem;
457-
use crate::os::windows::io::AsRawHandle;
458-
use crate::os::windows::process::{CommandExt, ProcThreadAttributeList};
459-
use crate::sys::c::{BOOL, CloseHandle, HANDLE};
460-
use crate::sys::cvt;
461-
462-
#[repr(C)]
463-
#[allow(non_snake_case)]
464-
struct PROCESSENTRY32W {
465-
dwSize: u32,
466-
cntUsage: u32,
467-
th32ProcessID: u32,
468-
th32DefaultHeapID: usize,
469-
th32ModuleID: u32,
470-
cntThreads: u32,
471-
th32ParentProcessID: u32,
472-
pcPriClassBase: i32,
473-
dwFlags: u32,
474-
szExeFile: [u16; 260],
475-
}
476-
477-
extern "system" {
478-
fn CreateToolhelp32Snapshot(dwflags: u32, th32processid: u32) -> HANDLE;
479-
fn Process32First(hsnapshot: HANDLE, lppe: *mut PROCESSENTRY32W) -> BOOL;
480-
fn Process32Next(hsnapshot: HANDLE, lppe: *mut PROCESSENTRY32W) -> BOOL;
481-
}
482-
483-
const PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: usize = 0x00020000;
484-
const TH32CS_SNAPPROCESS: u32 = 0x00000002;
485-
486-
struct ProcessDropGuard(crate::process::Child);
487-
488-
impl Drop for ProcessDropGuard {
489-
fn drop(&mut self) {
490-
let _ = self.0.kill();
491-
}
492-
}
493-
494-
let mut parent = Command::new("cmd");
495-
parent.stdout(Stdio::null()).stderr(Stdio::null());
496-
497-
let parent = ProcessDropGuard(parent.spawn().unwrap());
498-
499-
let mut child_cmd = Command::new("cmd");
500-
child_cmd.stdout(Stdio::null()).stderr(Stdio::null());
501-
502-
let parent_process_handle = parent.0.as_raw_handle();
503-
504-
let mut attribute_list = ProcThreadAttributeList::build()
505-
.attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &parent_process_handle)
506-
.finish()
507-
.unwrap();
508-
509-
let child = ProcessDropGuard(child_cmd.spawn_with_attributes(&mut attribute_list).unwrap());
510-
511-
let h_snapshot = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };
512-
513-
let mut process_entry = PROCESSENTRY32W {
514-
dwSize: mem::size_of::<PROCESSENTRY32W>() as u32,
515-
cntUsage: 0,
516-
th32ProcessID: 0,
517-
th32DefaultHeapID: 0,
518-
th32ModuleID: 0,
519-
cntThreads: 0,
520-
th32ParentProcessID: 0,
521-
pcPriClassBase: 0,
522-
dwFlags: 0,
523-
szExeFile: [0; 260],
524-
};
525-
526-
unsafe { cvt(Process32First(h_snapshot, &mut process_entry as *mut _)) }.unwrap();
527-
528-
loop {
529-
if child.0.id() == process_entry.th32ProcessID {
530-
break;
531-
}
532-
unsafe { cvt(Process32Next(h_snapshot, &mut process_entry as *mut _)) }.unwrap();
533-
}
534-
535-
unsafe { cvt(CloseHandle(h_snapshot)) }.unwrap();
536-
537-
assert_eq!(parent.0.id(), process_entry.th32ParentProcessID);
538-
539-
drop(child)
540-
}
541-
542394
#[test]
543395
fn test_command_implements_send_sync() {
544396
fn take_send_sync_type<T: Send + Sync>(_: T) {}
Lines changed: 369 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
1+
use crate::fmt;
2+
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
3+
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
4+
use crate::sys::unsupported;
5+
use crate::time::Duration;
6+
7+
pub struct TcpStream(!);
8+
9+
impl TcpStream {
10+
pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
11+
unsupported()
12+
}
13+
14+
pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
15+
unsupported()
16+
}
17+
18+
pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
19+
self.0
20+
}
21+
22+
pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
23+
self.0
24+
}
25+
26+
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
27+
self.0
28+
}
29+
30+
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
31+
self.0
32+
}
33+
34+
pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
35+
self.0
36+
}
37+
38+
pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
39+
self.0
40+
}
41+
42+
pub fn read_buf(&self, _buf: BorrowedCursor<'_>) -> io::Result<()> {
43+
self.0
44+
}
45+
46+
pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
47+
self.0
48+
}
49+
50+
pub fn is_read_vectored(&self) -> bool {
51+
self.0
52+
}
53+
54+
pub fn write(&self, _: &[u8]) -> io::Result<usize> {
55+
self.0
56+
}
57+
58+
pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
59+
self.0
60+
}
61+
62+
pub fn is_write_vectored(&self) -> bool {
63+
self.0
64+
}
65+
66+
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
67+
self.0
68+
}
69+
70+
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
71+
self.0
72+
}
73+
74+
pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
75+
self.0
76+
}
77+
78+
pub fn duplicate(&self) -> io::Result<TcpStream> {
79+
self.0
80+
}
81+
82+
pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
83+
self.0
84+
}
85+
86+
pub fn linger(&self) -> io::Result<Option<Duration>> {
87+
self.0
88+
}
89+
90+
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
91+
self.0
92+
}
93+
94+
pub fn nodelay(&self) -> io::Result<bool> {
95+
self.0
96+
}
97+
98+
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
99+
self.0
100+
}
101+
102+
pub fn ttl(&self) -> io::Result<u32> {
103+
self.0
104+
}
105+
106+
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
107+
self.0
108+
}
109+
110+
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
111+
self.0
112+
}
113+
}
114+
115+
impl fmt::Debug for TcpStream {
116+
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
117+
self.0
118+
}
119+
}
120+
121+
pub struct TcpListener(!);
122+
123+
impl TcpListener {
124+
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
125+
unsupported()
126+
}
127+
128+
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
129+
self.0
130+
}
131+
132+
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
133+
self.0
134+
}
135+
136+
pub fn duplicate(&self) -> io::Result<TcpListener> {
137+
self.0
138+
}
139+
140+
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
141+
self.0
142+
}
143+
144+
pub fn ttl(&self) -> io::Result<u32> {
145+
self.0
146+
}
147+
148+
pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
149+
self.0
150+
}
151+
152+
pub fn only_v6(&self) -> io::Result<bool> {
153+
self.0
154+
}
155+
156+
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
157+
self.0
158+
}
159+
160+
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
161+
self.0
162+
}
163+
}
164+
165+
impl fmt::Debug for TcpListener {
166+
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
167+
self.0
168+
}
169+
}
170+
171+
pub struct UdpSocket(!);
172+
173+
impl UdpSocket {
174+
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
175+
unsupported()
176+
}
177+
178+
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
179+
self.0
180+
}
181+
182+
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
183+
self.0
184+
}
185+
186+
pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
187+
self.0
188+
}
189+
190+
pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
191+
self.0
192+
}
193+
194+
pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
195+
self.0
196+
}
197+
198+
pub fn duplicate(&self) -> io::Result<UdpSocket> {
199+
self.0
200+
}
201+
202+
pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
203+
self.0
204+
}
205+
206+
pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
207+
self.0
208+
}
209+
210+
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
211+
self.0
212+
}
213+
214+
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
215+
self.0
216+
}
217+
218+
pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
219+
self.0
220+
}
221+
222+
pub fn broadcast(&self) -> io::Result<bool> {
223+
self.0
224+
}
225+
226+
pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
227+
self.0
228+
}
229+
230+
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
231+
self.0
232+
}
233+
234+
pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
235+
self.0
236+
}
237+
238+
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
239+
self.0
240+
}
241+
242+
pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
243+
self.0
244+
}
245+
246+
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
247+
self.0
248+
}
249+
250+
pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
251+
self.0
252+
}
253+
254+
pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
255+
self.0
256+
}
257+
258+
pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
259+
self.0
260+
}
261+
262+
pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
263+
self.0
264+
}
265+
266+
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
267+
self.0
268+
}
269+
270+
pub fn ttl(&self) -> io::Result<u32> {
271+
self.0
272+
}
273+
274+
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
275+
self.0
276+
}
277+
278+
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
279+
self.0
280+
}
281+
282+
pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
283+
self.0
284+
}
285+
286+
pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
287+
self.0
288+
}
289+
290+
pub fn send(&self, _: &[u8]) -> io::Result<usize> {
291+
self.0
292+
}
293+
294+
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
295+
self.0
296+
}
297+
}
298+
299+
impl fmt::Debug for UdpSocket {
300+
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
301+
self.0
302+
}
303+
}
304+
305+
pub struct LookupHost(!);
306+
307+
impl LookupHost {
308+
pub fn port(&self) -> u16 {
309+
self.0
310+
}
311+
}
312+
313+
impl Iterator for LookupHost {
314+
type Item = SocketAddr;
315+
fn next(&mut self) -> Option<SocketAddr> {
316+
self.0
317+
}
318+
}
319+
320+
impl TryFrom<&str> for LookupHost {
321+
type Error = io::Error;
322+
323+
fn try_from(_v: &str) -> io::Result<LookupHost> {
324+
unsupported()
325+
}
326+
}
327+
328+
impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
329+
type Error = io::Error;
330+
331+
fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
332+
unsupported()
333+
}
334+
}
335+
336+
#[allow(nonstandard_style)]
337+
pub mod netc {
338+
pub const AF_INET: u8 = 0;
339+
pub const AF_INET6: u8 = 1;
340+
pub type sa_family_t = u8;
341+
342+
#[derive(Copy, Clone)]
343+
pub struct in_addr {
344+
pub s_addr: u32,
345+
}
346+
347+
#[derive(Copy, Clone)]
348+
pub struct sockaddr_in {
349+
#[allow(dead_code)]
350+
pub sin_family: sa_family_t,
351+
pub sin_port: u16,
352+
pub sin_addr: in_addr,
353+
}
354+
355+
#[derive(Copy, Clone)]
356+
pub struct in6_addr {
357+
pub s6_addr: [u8; 16],
358+
}
359+
360+
#[derive(Copy, Clone)]
361+
pub struct sockaddr_in6 {
362+
#[allow(dead_code)]
363+
pub sin6_family: sa_family_t,
364+
pub sin6_port: u16,
365+
pub sin6_addr: in6_addr,
366+
pub sin6_flowinfo: u32,
367+
pub sin6_scope_id: u32,
368+
}
369+
}

‎library/std/src/sys/net/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ cfg_if::cfg_if! {
2525
mod xous;
2626
pub use xous::*;
2727
}
28+
} else if #[cfg(target_os = "uefi")] {
29+
mod connection {
30+
mod uefi;
31+
pub use uefi::*;
32+
}
2833
} else {
2934
mod connection {
3035
mod unsupported;

‎src/bootstrap/src/core/build_steps/doc.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,8 @@ impl Step for Rustc {
830830
cargo.rustdocflag("--show-type-layout");
831831
// FIXME: `--generate-link-to-definition` tries to resolve cfged out code
832832
// see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222
833-
// cargo.rustdocflag("--generate-link-to-definition");
833+
// If there is any bug, please comment out the next line.
834+
cargo.rustdocflag("--generate-link-to-definition");
834835

835836
compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
836837
cargo.arg("-Zskip-rustdoc-fingerprint");
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ check-pass
2+
3+
// Ensure that we skip uncaptured args from RPITITs when comptuing outlives.
4+
5+
#![feature(precise_capturing_in_traits)]
6+
7+
struct Invariant<T>(*mut T);
8+
9+
trait Foo {
10+
fn hello<'s: 's>(&'s self) -> Invariant<impl Sized + use<Self>>;
11+
}
12+
13+
fn outlives_static(_: impl Sized + 'static) {}
14+
15+
fn hello<'s, T: Foo + 'static>(x: &'s T) {
16+
outlives_static(x.hello());
17+
}
18+
19+
fn main() {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//@ check-pass
2+
3+
// Ensure that we skip uncaptured args from RPITITs when collecting the regions
4+
// to enforce member constraints in opaque type inference.
5+
6+
#![feature(precise_capturing_in_traits)]
7+
8+
struct Invariant<T>(*mut T);
9+
10+
trait Foo {
11+
fn hello<'s: 's>(&'s self) -> Invariant<impl Sized + use<Self>>;
12+
}
13+
14+
fn hello<'s, T: Foo>(x: &'s T) -> Invariant<impl Sized> {
15+
x.hello()
16+
}
17+
18+
fn main() {}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Test that windows `creation_flags` extension to `Command` works.
2+
3+
//@ run-pass
4+
//@ only-windows
5+
//@ needs-subprocess
6+
7+
use std::env;
8+
use std::os::windows::process::CommandExt;
9+
use std::process::{Command, exit};
10+
11+
fn main() {
12+
if env::args().skip(1).any(|s| s == "--child") {
13+
child();
14+
} else {
15+
parent();
16+
}
17+
}
18+
19+
fn parent() {
20+
let exe = env::current_exe().unwrap();
21+
22+
// Use the DETACH_PROCESS to create a subprocess that isn't attached to the console.
23+
// The subprocess's exit status will be 0 if it's detached.
24+
let status = Command::new(&exe)
25+
.arg("--child")
26+
.creation_flags(DETACH_PROCESS)
27+
.spawn()
28+
.unwrap()
29+
.wait()
30+
.unwrap();
31+
assert_eq!(status.code(), Some(0));
32+
33+
// Try without DETACH_PROCESS to ensure this test works.
34+
let status = Command::new(&exe).arg("--child").spawn().unwrap().wait().unwrap();
35+
assert_eq!(status.code(), Some(1));
36+
}
37+
38+
// exits with 1 if the console is attached or 0 otherwise
39+
fn child() {
40+
// Get the attached console's code page.
41+
// This will fail (return 0) if no console is attached.
42+
let has_console = GetConsoleCP() != 0;
43+
exit(has_console as i32);
44+
}
45+
46+
// Windows API definitions.
47+
const DETACH_PROCESS: u32 = 0x00000008;
48+
#[link(name = "kernel32")]
49+
unsafe extern "system" {
50+
safe fn GetConsoleCP() -> u32;
51+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// Tests proc thread attributes by spawning a process with a custom parent process,
2+
// then comparing the parent process ID with the expected parent process ID.
3+
4+
//@ run-pass
5+
//@ only-windows
6+
//@ needs-subprocess
7+
//@ edition: 2021
8+
9+
#![feature(windows_process_extensions_raw_attribute)]
10+
11+
use std::os::windows::io::AsRawHandle;
12+
use std::os::windows::process::{CommandExt, ProcThreadAttributeList};
13+
use std::process::{Child, Command};
14+
use std::{env, mem, ptr, thread, time};
15+
16+
// Make a best effort to ensure child processes always exit.
17+
struct ProcessDropGuard(Child);
18+
impl Drop for ProcessDropGuard {
19+
fn drop(&mut self) {
20+
let _ = self.0.kill();
21+
}
22+
}
23+
24+
fn main() {
25+
if env::args().skip(1).any(|s| s == "--child") {
26+
child();
27+
} else {
28+
parent();
29+
}
30+
}
31+
32+
fn parent() {
33+
let exe = env::current_exe().unwrap();
34+
35+
let (fake_parent_id, child_parent_id) = {
36+
// Create a process to be our fake parent process.
37+
let fake_parent = Command::new(&exe).arg("--child").spawn().unwrap();
38+
let fake_parent = ProcessDropGuard(fake_parent);
39+
let parent_handle = fake_parent.0.as_raw_handle();
40+
41+
// Create another process with the parent process set to the fake.
42+
let mut attribute_list = ProcThreadAttributeList::build()
43+
.attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &parent_handle)
44+
.finish()
45+
.unwrap();
46+
let child =
47+
Command::new(&exe).arg("--child").spawn_with_attributes(&mut attribute_list).unwrap();
48+
let child = ProcessDropGuard(child);
49+
50+
// Return the fake's process id and the child's parent's id.
51+
(process_info(&fake_parent.0).process_id(), process_info(&child.0).parent_id())
52+
};
53+
54+
assert_eq!(fake_parent_id, child_parent_id);
55+
}
56+
57+
// A process that stays running until killed.
58+
fn child() {
59+
// Don't wait forever if something goes wrong.
60+
thread::sleep(time::Duration::from_secs(60));
61+
}
62+
63+
fn process_info(child: &Child) -> PROCESS_BASIC_INFORMATION {
64+
unsafe {
65+
let mut info: PROCESS_BASIC_INFORMATION = mem::zeroed();
66+
let result = NtQueryInformationProcess(
67+
child.as_raw_handle(),
68+
ProcessBasicInformation,
69+
ptr::from_mut(&mut info).cast(),
70+
mem::size_of_val(&info).try_into().unwrap(),
71+
ptr::null_mut(),
72+
);
73+
assert_eq!(result, 0);
74+
info
75+
}
76+
}
77+
78+
// Windows API
79+
mod winapi {
80+
#![allow(nonstandard_style)]
81+
use std::ffi::c_void;
82+
83+
pub type HANDLE = *mut c_void;
84+
type NTSTATUS = i32;
85+
type PROCESSINFOCLASS = i32;
86+
87+
pub const ProcessBasicInformation: i32 = 0;
88+
pub const PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: usize = 0x00020000;
89+
#[repr(C)]
90+
pub struct PROCESS_BASIC_INFORMATION {
91+
pub ExitStatus: NTSTATUS,
92+
pub PebBaseAddress: *mut (),
93+
pub AffinityMask: usize,
94+
pub BasePriority: i32,
95+
pub UniqueProcessId: usize,
96+
pub InheritedFromUniqueProcessId: usize,
97+
}
98+
impl PROCESS_BASIC_INFORMATION {
99+
pub fn parent_id(&self) -> usize {
100+
self.InheritedFromUniqueProcessId
101+
}
102+
pub fn process_id(&self) -> usize {
103+
self.UniqueProcessId
104+
}
105+
}
106+
107+
#[link(name = "ntdll")]
108+
extern "system" {
109+
pub fn NtQueryInformationProcess(
110+
ProcessHandle: HANDLE,
111+
ProcessInformationClass: PROCESSINFOCLASS,
112+
ProcessInformation: *mut c_void,
113+
ProcessInformationLength: u32,
114+
ReturnLength: *mut u32,
115+
) -> NTSTATUS;
116+
}
117+
}
118+
use winapi::*;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//@ check-pass
2+
3+
#![feature(derive_coerce_pointee)]
4+
#![feature(arbitrary_self_types)]
5+
6+
use std::marker::CoercePointee;
7+
use std::ops::Receiver;
8+
9+
// `CoercePointee` isn't needed here, it's just a simpler
10+
// (and more conceptual) way of deriving `DispatchFromDyn`.
11+
// You could think of `MyDispatcher` as a smart pointer
12+
// that just doesn't deref to its target type.
13+
#[derive(CoercePointee)]
14+
#[repr(transparent)]
15+
struct MyDispatcher<T: ?Sized>(*const T);
16+
17+
impl<T: ?Sized> Receiver for MyDispatcher<T> {
18+
type Target = T;
19+
}
20+
struct Test;
21+
22+
trait Trait {
23+
fn test(self: MyDispatcher<Self>);
24+
}
25+
26+
impl Trait for Test {
27+
fn test(self: MyDispatcher<Self>) {
28+
todo!()
29+
}
30+
}
31+
fn main() {
32+
MyDispatcher::<dyn Trait>(core::ptr::null_mut::<Test>()).test();
33+
}

‎tests/ui/wait-forked-but-failed-child.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,17 @@ fn find_zombies() {
3131
// https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html
3232
let ps_cmd_output = Command::new("ps").args(&["-A", "-o", "pid,ppid,args"]).output().unwrap();
3333
let ps_output = String::from_utf8_lossy(&ps_cmd_output.stdout);
34+
// On AIX, the PPID is not always present, such as when a process is blocked
35+
// (marked as <exiting>), or if a process is idle. In these situations,
36+
// the PPID column contains a "-" for the respective process.
37+
// Filter out any lines that have a "-" as the PPID as the PPID is
38+
// expected to be an integer.
39+
let filtered_ps: Vec<_> = ps_output
40+
.lines()
41+
.filter(|line| line.split_whitespace().nth(1) != Some("-"))
42+
.collect();
3443

35-
for (line_no, line) in ps_output.split('\n').enumerate() {
44+
for (line_no, line) in filtered_ps.into_iter().enumerate() {
3645
if 0 < line_no && 0 < line.len() &&
3746
my_pid == line.split(' ').filter(|w| 0 < w.len()).nth(1)
3847
.expect("1st column should be PPID")

0 commit comments

Comments
 (0)
Please sign in to comment.