Skip to content

Commit 8ba4dfa

Browse files
committed
Auto merge of rust-lang#123667 - GuillaumeGomez:rollup-yylha9j, r=GuillaumeGomez
Rollup of 6 pull requests Successful merges: - rust-lang#123485 (macOS: Use `libc` definitions for copyfile) - rust-lang#123633 (Store all args in the unsupported Command implementation) - rust-lang#123638 (rustdoc: synthetic auto: filter out clauses from the implementor's ParamEnv) - rust-lang#123653 (Split `non_local_definitions` lint tests in separate test files) - rust-lang#123662 (Don't rely on upvars being assigned just because coroutine-closure kind is assigned) - rust-lang#123665 (Fix typo in `Future::poll()` docs) r? `@ghost` `@rustbot` modify labels: rollup
2 parents bb78dba + 06a481a commit 8ba4dfa

33 files changed

+1594
-1304
lines changed

compiler/rustc_middle/src/ty/sty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2231,7 +2231,7 @@ impl<'tcx> Ty<'tcx> {
22312231
pub fn tuple_fields(self) -> &'tcx List<Ty<'tcx>> {
22322232
match self.kind() {
22332233
Tuple(args) => args,
2234-
_ => bug!("tuple_fields called on non-tuple"),
2234+
_ => bug!("tuple_fields called on non-tuple: {self:?}"),
22352235
}
22362236
}
22372237

compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,9 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
292292
let kind_ty = args.kind_ty();
293293
let sig = args.coroutine_closure_sig().skip_binder();
294294

295-
let coroutine_ty = if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
295+
let coroutine_ty = if let Some(closure_kind) = kind_ty.to_opt_closure_kind()
296+
&& !args.tupled_upvars_ty().is_ty_var()
297+
{
296298
if !closure_kind.extends(goal_kind) {
297299
return Err(NoSolution);
298300
}
@@ -401,7 +403,9 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
401403
let kind_ty = args.kind_ty();
402404
let sig = args.coroutine_closure_sig().skip_binder();
403405
let mut nested = vec![];
404-
let coroutine_ty = if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
406+
let coroutine_ty = if let Some(closure_kind) = kind_ty.to_opt_closure_kind()
407+
&& !args.tupled_upvars_ty().is_ty_var()
408+
{
405409
if !closure_kind.extends(goal_kind) {
406410
return Err(NoSolution);
407411
}

compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
487487
bug!();
488488
};
489489

490+
// Bail if the upvars haven't been constrained.
491+
if tupled_upvars_ty.expect_ty().is_ty_var() {
492+
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
493+
}
494+
490495
let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
491496
// We don't need to worry about the self type being an infer var.
492497
return Err(NoSolution);

compiler/rustc_trait_selection/src/traits/project.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -1601,7 +1601,10 @@ fn confirm_closure_candidate<'cx, 'tcx>(
16011601
// If we know the kind and upvars, use that directly.
16021602
// Otherwise, defer to `AsyncFnKindHelper::Upvars` to delay
16031603
// the projection, like the `AsyncFn*` traits do.
1604-
let output_ty = if let Some(_) = kind_ty.to_opt_closure_kind() {
1604+
let output_ty = if let Some(_) = kind_ty.to_opt_closure_kind()
1605+
// Fall back to projection if upvars aren't constrained
1606+
&& !args.tupled_upvars_ty().is_ty_var()
1607+
{
16051608
sig.to_coroutine_given_kind_and_upvars(
16061609
tcx,
16071610
args.parent_args(),
@@ -1731,7 +1734,10 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
17311734

17321735
let term = match item_name {
17331736
sym::CallOnceFuture | sym::CallRefFuture => {
1734-
if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
1737+
if let Some(closure_kind) = kind_ty.to_opt_closure_kind()
1738+
// Fall back to projection if upvars aren't constrained
1739+
&& !args.tupled_upvars_ty().is_ty_var()
1740+
{
17351741
if !closure_kind.extends(goal_kind) {
17361742
bug!("we should not be confirming if the closure kind is not met");
17371743
}

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+28-31
Original file line numberDiff line numberDiff line change
@@ -400,39 +400,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
400400
}
401401
}
402402
ty::CoroutineClosure(def_id, args) => {
403+
let args = args.as_coroutine_closure();
403404
let is_const = self.tcx().is_const_fn_raw(def_id);
404-
match self.infcx.closure_kind(self_ty) {
405-
Some(closure_kind) => {
406-
let no_borrows = match self
407-
.infcx
408-
.shallow_resolve(args.as_coroutine_closure().tupled_upvars_ty())
409-
.kind()
410-
{
411-
ty::Tuple(tys) => tys.is_empty(),
412-
ty::Error(_) => false,
413-
_ => bug!("tuple_fields called on non-tuple"),
414-
};
415-
// A coroutine-closure implements `FnOnce` *always*, since it may
416-
// always be called once. It additionally implements `Fn`/`FnMut`
417-
// only if it has no upvars (therefore no borrows from the closure
418-
// that would need to be represented with a lifetime) and if the
419-
// closure kind permits it.
420-
// FIXME(async_closures): Actually, it could also implement `Fn`/`FnMut`
421-
// if it takes all of its upvars by copy, and none by ref. This would
422-
// require us to record a bit more information during upvar analysis.
423-
if no_borrows && closure_kind.extends(kind) {
424-
candidates.vec.push(ClosureCandidate { is_const });
425-
} else if kind == ty::ClosureKind::FnOnce {
426-
candidates.vec.push(ClosureCandidate { is_const });
427-
}
405+
if let Some(closure_kind) = self.infcx.closure_kind(self_ty)
406+
// Ambiguity if upvars haven't been constrained yet
407+
&& !args.tupled_upvars_ty().is_ty_var()
408+
{
409+
let no_borrows = match args.tupled_upvars_ty().kind() {
410+
ty::Tuple(tys) => tys.is_empty(),
411+
ty::Error(_) => false,
412+
_ => bug!("tuple_fields called on non-tuple"),
413+
};
414+
// A coroutine-closure implements `FnOnce` *always*, since it may
415+
// always be called once. It additionally implements `Fn`/`FnMut`
416+
// only if it has no upvars (therefore no borrows from the closure
417+
// that would need to be represented with a lifetime) and if the
418+
// closure kind permits it.
419+
// FIXME(async_closures): Actually, it could also implement `Fn`/`FnMut`
420+
// if it takes all of its upvars by copy, and none by ref. This would
421+
// require us to record a bit more information during upvar analysis.
422+
if no_borrows && closure_kind.extends(kind) {
423+
candidates.vec.push(ClosureCandidate { is_const });
424+
} else if kind == ty::ClosureKind::FnOnce {
425+
candidates.vec.push(ClosureCandidate { is_const });
428426
}
429-
None => {
430-
if kind == ty::ClosureKind::FnOnce {
431-
candidates.vec.push(ClosureCandidate { is_const });
432-
} else {
433-
// This stays ambiguous until kind+upvars are determined.
434-
candidates.ambiguous = true;
435-
}
427+
} else {
428+
if kind == ty::ClosureKind::FnOnce {
429+
candidates.vec.push(ClosureCandidate { is_const });
430+
} else {
431+
// This stays ambiguous until kind+upvars are determined.
432+
candidates.ambiguous = true;
436433
}
437434
}
438435
}

library/core/src/future/future.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ pub trait Future {
8181
/// An implementation of `poll` should strive to return quickly, and should
8282
/// not block. Returning quickly prevents unnecessarily clogging up
8383
/// threads or event loops. If it is known ahead of time that a call to
84-
/// `poll` may end up taking awhile, the work should be offloaded to a
84+
/// `poll` may end up taking a while, the work should be offloaded to a
8585
/// thread pool (or something similar) to ensure that `poll` can return
8686
/// quickly.
8787
///

library/std/src/sys/pal/unix/fs.rs

+10-39
Original file line numberDiff line numberDiff line change
@@ -1847,47 +1847,17 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
18471847
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
18481848
use crate::sync::atomic::{AtomicBool, Ordering};
18491849

1850-
const COPYFILE_ACL: u32 = 1 << 0;
1851-
const COPYFILE_STAT: u32 = 1 << 1;
1852-
const COPYFILE_XATTR: u32 = 1 << 2;
1853-
const COPYFILE_DATA: u32 = 1 << 3;
1854-
1855-
const COPYFILE_SECURITY: u32 = COPYFILE_STAT | COPYFILE_ACL;
1856-
const COPYFILE_METADATA: u32 = COPYFILE_SECURITY | COPYFILE_XATTR;
1857-
const COPYFILE_ALL: u32 = COPYFILE_METADATA | COPYFILE_DATA;
1858-
1859-
const COPYFILE_STATE_COPIED: u32 = 8;
1860-
1861-
#[allow(non_camel_case_types)]
1862-
type copyfile_state_t = *mut libc::c_void;
1863-
#[allow(non_camel_case_types)]
1864-
type copyfile_flags_t = u32;
1865-
1866-
extern "C" {
1867-
fn fcopyfile(
1868-
from: libc::c_int,
1869-
to: libc::c_int,
1870-
state: copyfile_state_t,
1871-
flags: copyfile_flags_t,
1872-
) -> libc::c_int;
1873-
fn copyfile_state_alloc() -> copyfile_state_t;
1874-
fn copyfile_state_free(state: copyfile_state_t) -> libc::c_int;
1875-
fn copyfile_state_get(
1876-
state: copyfile_state_t,
1877-
flag: u32,
1878-
dst: *mut libc::c_void,
1879-
) -> libc::c_int;
1880-
}
1881-
1882-
struct FreeOnDrop(copyfile_state_t);
1850+
const COPYFILE_ALL: libc::copyfile_flags_t = libc::COPYFILE_METADATA | libc::COPYFILE_DATA;
1851+
1852+
struct FreeOnDrop(libc::copyfile_state_t);
18831853
impl Drop for FreeOnDrop {
18841854
fn drop(&mut self) {
18851855
// The code below ensures that `FreeOnDrop` is never a null pointer
18861856
unsafe {
18871857
// `copyfile_state_free` returns -1 if the `to` or `from` files
18881858
// cannot be closed. However, this is not considered this an
18891859
// error.
1890-
copyfile_state_free(self.0);
1860+
libc::copyfile_state_free(self.0);
18911861
}
18921862
}
18931863
}
@@ -1896,6 +1866,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
18961866
// We store the availability in a global to avoid unnecessary syscalls
18971867
static HAS_FCLONEFILEAT: AtomicBool = AtomicBool::new(true);
18981868
syscall! {
1869+
// Mirrors `libc::fclonefileat`
18991870
fn fclonefileat(
19001871
srcfd: libc::c_int,
19011872
dst_dirfd: libc::c_int,
@@ -1932,22 +1903,22 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
19321903
// We ensure that `FreeOnDrop` never contains a null pointer so it is
19331904
// always safe to call `copyfile_state_free`
19341905
let state = unsafe {
1935-
let state = copyfile_state_alloc();
1906+
let state = libc::copyfile_state_alloc();
19361907
if state.is_null() {
19371908
return Err(crate::io::Error::last_os_error());
19381909
}
19391910
FreeOnDrop(state)
19401911
};
19411912

1942-
let flags = if writer_metadata.is_file() { COPYFILE_ALL } else { COPYFILE_DATA };
1913+
let flags = if writer_metadata.is_file() { COPYFILE_ALL } else { libc::COPYFILE_DATA };
19431914

1944-
cvt(unsafe { fcopyfile(reader.as_raw_fd(), writer.as_raw_fd(), state.0, flags) })?;
1915+
cvt(unsafe { libc::fcopyfile(reader.as_raw_fd(), writer.as_raw_fd(), state.0, flags) })?;
19451916

19461917
let mut bytes_copied: libc::off_t = 0;
19471918
cvt(unsafe {
1948-
copyfile_state_get(
1919+
libc::copyfile_state_get(
19491920
state.0,
1950-
COPYFILE_STATE_COPIED,
1921+
libc::COPYFILE_STATE_COPIED as u32,
19511922
core::ptr::addr_of_mut!(bytes_copied) as *mut libc::c_void,
19521923
)
19531924
})?;

0 commit comments

Comments
 (0)