mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 06:22:00 +00:00
Auto merge of #124330 - fmease:rollup-a98y7jf, r=fmease
Rollup of 6 pull requests Successful merges: - #123316 (Test `#[unix_sigpipe = "inherit"]` with both `SIG_DFL` and `SIG_IGN`) - #123794 (More DefineOpaqueTypes::Yes) - #123881 (Bump Fuchsia versions) - #124281 (fix weak memory bug in TLS on Windows) - #124282 (windows fill_utf16_buf: explain the expected return value) - #124308 (Add diagnostic item for `std::iter::Enumerate`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
ef8b9dcf23
@ -1139,7 +1139,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// are the same function and their parameters have a LUB.
|
||||
match self.commit_if_ok(|_| {
|
||||
self.at(cause, self.param_env).lub(
|
||||
DefineOpaqueTypes::No,
|
||||
DefineOpaqueTypes::Yes,
|
||||
prev_ty,
|
||||
new_ty,
|
||||
)
|
||||
|
@ -192,6 +192,7 @@ symbols! {
|
||||
Duration,
|
||||
Encodable,
|
||||
Encoder,
|
||||
Enumerate,
|
||||
Eq,
|
||||
Equal,
|
||||
Err,
|
||||
|
@ -15,6 +15,7 @@ use crate::ops::Try;
|
||||
#[derive(Clone, Debug)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "Enumerate")]
|
||||
pub struct Enumerate<I> {
|
||||
iter: I,
|
||||
count: usize,
|
||||
|
@ -201,14 +201,21 @@ pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> crate::io::Result<Vec<u16>> {
|
||||
// currently reside in the buffer. This function is an abstraction over these
|
||||
// functions by making them easier to call.
|
||||
//
|
||||
// The first callback, `f1`, is yielded a (pointer, len) pair which can be
|
||||
// The first callback, `f1`, is passed a (pointer, len) pair which can be
|
||||
// passed to a syscall. The `ptr` is valid for `len` items (u16 in this case).
|
||||
// The closure is expected to return what the syscall returns which will be
|
||||
// interpreted by this function to determine if the syscall needs to be invoked
|
||||
// again (with more buffer space).
|
||||
// The closure is expected to:
|
||||
// - On success, return the actual length of the written data *without* the null terminator.
|
||||
// This can be 0. In this case the last_error must be left unchanged.
|
||||
// - On insufficient buffer space,
|
||||
// - either return the required length *with* the null terminator,
|
||||
// - or set the last-error to ERROR_INSUFFICIENT_BUFFER and return `len`.
|
||||
// - On other failure, return 0 and set last_error.
|
||||
//
|
||||
// This is how most but not all syscalls indicate the required buffer space.
|
||||
// Other syscalls may need translation to match this protocol.
|
||||
//
|
||||
// Once the syscall has completed (errors bail out early) the second closure is
|
||||
// yielded the data which has been read from the syscall. The return value
|
||||
// passed the data which has been read from the syscall. The return value
|
||||
// from this closure is then the return value of the function.
|
||||
pub fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> crate::io::Result<T>
|
||||
where
|
||||
|
@ -326,6 +326,8 @@ fn home_dir_crt() -> Option<PathBuf> {
|
||||
|
||||
super::fill_utf16_buf(
|
||||
|buf, mut sz| {
|
||||
// GetUserProfileDirectoryW does not quite use the usual protocol for
|
||||
// negotiating the buffer size, so we have to translate.
|
||||
match c::GetUserProfileDirectoryW(
|
||||
ptr::without_provenance_mut(CURRENT_PROCESS_TOKEN),
|
||||
buf,
|
||||
|
@ -141,9 +141,15 @@ impl StaticKey {
|
||||
panic!("out of TLS indexes");
|
||||
}
|
||||
|
||||
self.key.store(key + 1, Release);
|
||||
register_dtor(self);
|
||||
|
||||
// Release-storing the key needs to be the last thing we do.
|
||||
// This is because in `fn key()`, other threads will do an acquire load of the key,
|
||||
// and if that sees this write then it will entirely bypass the `InitOnce`. We thus
|
||||
// need to establish synchronization through `key`. In particular that acquire load
|
||||
// must happen-after the register_dtor above, to ensure the dtor actually runs!
|
||||
self.key.store(key + 1, Release);
|
||||
|
||||
let r = c::InitOnceComplete(self.once.get(), 0, ptr::null_mut());
|
||||
debug_assert_eq!(r, c::TRUE);
|
||||
|
||||
@ -313,8 +319,22 @@ unsafe fn run_dtors() {
|
||||
// Use acquire ordering to observe key initialization.
|
||||
let mut cur = DTORS.load(Acquire);
|
||||
while !cur.is_null() {
|
||||
let key = (*cur).key.load(Relaxed) - 1;
|
||||
let pre_key = (*cur).key.load(Acquire);
|
||||
let dtor = (*cur).dtor.unwrap();
|
||||
cur = (*cur).next.load(Relaxed);
|
||||
|
||||
// In StaticKey::init, we register the dtor before setting `key`.
|
||||
// So if one thread's `run_dtors` races with another thread executing `init` on the same
|
||||
// `StaticKey`, we can encounter a key of 0 here. That means this key was never
|
||||
// initialized in this thread so we can safely skip it.
|
||||
if pre_key == 0 {
|
||||
continue;
|
||||
}
|
||||
// If this is non-zero, then via the `Acquire` load above we synchronized with
|
||||
// everything relevant for this key. (It's not clear that this is needed, since the
|
||||
// release-acquire pair on DTORS also establishes synchronization, but better safe than
|
||||
// sorry.)
|
||||
let key = pre_key - 1;
|
||||
|
||||
let ptr = c::TlsGetValue(key);
|
||||
if !ptr.is_null() {
|
||||
@ -322,8 +342,6 @@ unsafe fn run_dtors() {
|
||||
dtor(ptr as *mut _);
|
||||
any_run = true;
|
||||
}
|
||||
|
||||
cur = (*cur).next.load(Relaxed);
|
||||
}
|
||||
|
||||
if !any_run {
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
set -euf -o pipefail
|
||||
|
||||
INTEGRATION_SHA=56310bca298872ffb5ea02e665956d9b6dc41171
|
||||
INTEGRATION_SHA=1011e3298775ee7cdf6f6dc73e808d6a86e33bd6
|
||||
PICK_REFS=()
|
||||
|
||||
checkout=fuchsia
|
||||
|
@ -4,13 +4,13 @@ set -ex
|
||||
source shared.sh
|
||||
|
||||
FUCHSIA_SDK_URL=https://chrome-infra-packages.appspot.com/dl/fuchsia/sdk/core/linux-amd64
|
||||
FUCHSIA_SDK_ID=MrhQwtmP8CpZre-i_PNOREcThbUcrX3bA-45d6WQr-cC
|
||||
FUCHSIA_SDK_SHA256=32b850c2d98ff02a59adefa2fcf34e44471385b51cad7ddb03ee3977a590afe7
|
||||
FUCHSIA_SDK_ID=version:20.20240412.3.1
|
||||
FUCHSIA_SDK_SHA256=cc52f3497487dd813c89d9316e6967efcea89c7759edccf3e40fcf3662e53f19
|
||||
FUCHSIA_SDK_USR_DIR=/usr/local/core-linux-amd64-fuchsia-sdk
|
||||
CLANG_DOWNLOAD_URL=\
|
||||
https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/linux-amd64
|
||||
CLANG_DOWNLOAD_ID=Tpc85d1ZwSlZ6UKl2d96GRUBGNA5JKholOKe24sRDr0C
|
||||
CLANG_DOWNLOAD_SHA256=4e973ce5dd59c12959e942a5d9df7a19150118d03924a86894e29edb8b110ebd
|
||||
CLANG_DOWNLOAD_ID=git_revision:c777c011a709dffd4fa5e79cad7947b7c3405d02
|
||||
CLANG_DOWNLOAD_SHA256=779167422ad73c292f049dcea5569f84577af9292189ed2749518b966a4d0844
|
||||
|
||||
install_clang() {
|
||||
mkdir -p clang_download
|
||||
|
@ -280,7 +280,7 @@ class TestEnvironment:
|
||||
# Look up the product bundle transfer manifest.
|
||||
self.log_info("Looking up the product bundle transfer manifest...")
|
||||
product_name = "minimal." + self.triple_to_arch(self.target)
|
||||
fuchsia_version = "14.20230811.2.1"
|
||||
fuchsia_version = "20.20240412.3.1"
|
||||
|
||||
# FIXME: We should be able to replace this with the machine parsable
|
||||
# `ffx --machine json product lookup ...` once F15 is released.
|
||||
|
@ -0,0 +1,8 @@
|
||||
//@ aux-crate: sigpipe_utils=sigpipe-utils.rs
|
||||
|
||||
#![feature(unix_sigpipe)]
|
||||
|
||||
#[unix_sigpipe = "inherit"]
|
||||
fn main() {
|
||||
sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
//@ aux-crate: sigpipe_utils=sigpipe-utils.rs
|
||||
|
||||
#![feature(unix_sigpipe)]
|
||||
|
||||
#[unix_sigpipe = "inherit"]
|
||||
fn main() {
|
||||
sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
|
||||
}
|
@ -1,14 +1,29 @@
|
||||
//@ ignore-cross-compile because aux-bin does not yet support it
|
||||
//@ only-unix because SIGPIPE is a unix thing
|
||||
//@ aux-bin: assert-inherit-sig_dfl.rs
|
||||
//@ aux-bin: assert-inherit-sig_ign.rs
|
||||
//@ run-pass
|
||||
//@ aux-build:sigpipe-utils.rs
|
||||
|
||||
#![feature(unix_sigpipe)]
|
||||
#![feature(rustc_private, unix_sigpipe)]
|
||||
|
||||
#[unix_sigpipe = "inherit"]
|
||||
extern crate libc;
|
||||
|
||||
// By default the Rust runtime resets SIGPIPE to SIG_DFL before exec:ing child
|
||||
// processes so opt-out of that with `#[unix_sigpipe = "sig_dfl"]`. See
|
||||
// https://github.com/rust-lang/rust/blob/bf4de3a874753bbee3323081c8b0c133444fed2d/library/std/src/sys/pal/unix/process/process_unix.rs#L359-L384
|
||||
#[unix_sigpipe = "sig_dfl"]
|
||||
fn main() {
|
||||
extern crate sigpipe_utils;
|
||||
// First expect SIG_DFL in a child process with #[unix_sigpipe = "inherit"].
|
||||
assert_inherit_sigpipe_disposition("auxiliary/bin/assert-inherit-sig_dfl");
|
||||
|
||||
// #[unix_sigpipe = "inherit"] is active, so SIGPIPE shall NOT be ignored,
|
||||
// instead the default handler shall be installed. (We assume that the
|
||||
// process that runs these tests have the default handler.)
|
||||
sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
|
||||
// With SIG_IGN we expect #[unix_sigpipe = "inherit"] to also get SIG_IGN.
|
||||
unsafe {
|
||||
libc::signal(libc::SIGPIPE, libc::SIG_IGN);
|
||||
}
|
||||
assert_inherit_sigpipe_disposition("auxiliary/bin/assert-inherit-sig_ign");
|
||||
}
|
||||
|
||||
fn assert_inherit_sigpipe_disposition(aux_bin: &str) {
|
||||
let mut cmd = std::process::Command::new(aux_bin);
|
||||
assert!(cmd.status().unwrap().success());
|
||||
}
|
||||
|
58
tests/ui/fn/fn_def_coercion.rs
Normal file
58
tests/ui/fn/fn_def_coercion.rs
Normal file
@ -0,0 +1,58 @@
|
||||
//! Test that coercing between function items of the same function,
|
||||
//! but with different generic args succeeds in typeck, but then fails
|
||||
//! in borrowck when the lifetimes can't actually be merged.
|
||||
|
||||
fn foo<T>(t: T) -> T {
|
||||
t
|
||||
}
|
||||
|
||||
fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
let mut x = foo::<&'a ()>; //~ ERROR: lifetime may not live long enough
|
||||
x = foo::<&'b ()>; //~ ERROR: lifetime may not live long enough
|
||||
x = foo::<&'c ()>;
|
||||
x(a);
|
||||
x(b);
|
||||
x(c);
|
||||
}
|
||||
|
||||
fn g<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
let x = foo::<&'c ()>;
|
||||
let _: &'c () = x(a); //~ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn h<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
let x = foo::<&'a ()>;
|
||||
let _: &'a () = x(c);
|
||||
}
|
||||
|
||||
fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
let mut x = foo::<&'c ()>;
|
||||
x = foo::<&'b ()>; //~ ERROR lifetime may not live long enough
|
||||
x = foo::<&'a ()>; //~ ERROR lifetime may not live long enough
|
||||
x(a);
|
||||
x(b);
|
||||
x(c);
|
||||
}
|
||||
|
||||
fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
let x = match true {
|
||||
true => foo::<&'b ()>, //~ ERROR lifetime may not live long enough
|
||||
false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough
|
||||
};
|
||||
x(a);
|
||||
x(b);
|
||||
x(c);
|
||||
}
|
||||
|
||||
fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
let x = match true {
|
||||
true => foo::<&'c ()>,
|
||||
false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough
|
||||
};
|
||||
|
||||
x(a);
|
||||
x(b); //~ ERROR lifetime may not live long enough
|
||||
x(c);
|
||||
}
|
||||
|
||||
fn main() {}
|
154
tests/ui/fn/fn_def_coercion.stderr
Normal file
154
tests/ui/fn/fn_def_coercion.stderr
Normal file
@ -0,0 +1,154 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/fn_def_coercion.rs:10:17
|
||||
|
|
||||
LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | let mut x = foo::<&'a ()>;
|
||||
| ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
|
||||
|
|
||||
= help: consider adding the following bound: `'a: 'b`
|
||||
= note: requirement occurs because of a function pointer to `foo`
|
||||
= note: the function `foo` is invariant over the parameter `T`
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/fn_def_coercion.rs:11:5
|
||||
|
|
||||
LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | let mut x = foo::<&'a ()>;
|
||||
LL | x = foo::<&'b ()>;
|
||||
| ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
= note: requirement occurs because of a function pointer to `foo`
|
||||
= note: the function `foo` is invariant over the parameter `T`
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||
|
||||
help: `'a` and `'b` must be the same: replace one with the other
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/fn_def_coercion.rs:20:12
|
||||
|
|
||||
LL | fn g<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
| -- -- lifetime `'c` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | let x = foo::<&'c ()>;
|
||||
LL | let _: &'c () = x(a);
|
||||
| ^^^^^^ type annotation requires that `'a` must outlive `'c`
|
||||
|
|
||||
= help: consider adding the following bound: `'a: 'c`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/fn_def_coercion.rs:30:5
|
||||
|
|
||||
LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | let mut x = foo::<&'c ()>;
|
||||
LL | x = foo::<&'b ()>;
|
||||
| ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
= note: requirement occurs because of a function pointer to `foo`
|
||||
= note: the function `foo` is invariant over the parameter `T`
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/fn_def_coercion.rs:31:5
|
||||
|
|
||||
LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | x = foo::<&'a ()>;
|
||||
| ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
|
||||
|
|
||||
= help: consider adding the following bound: `'a: 'b`
|
||||
= note: requirement occurs because of a function pointer to `foo`
|
||||
= note: the function `foo` is invariant over the parameter `T`
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||
|
||||
help: `'a` and `'b` must be the same: replace one with the other
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/fn_def_coercion.rs:39:17
|
||||
|
|
||||
LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | let x = match true {
|
||||
LL | true => foo::<&'b ()>,
|
||||
| ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
= note: requirement occurs because of a function pointer to `foo`
|
||||
= note: the function `foo` is invariant over the parameter `T`
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/fn_def_coercion.rs:40:18
|
||||
|
|
||||
LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | false => foo::<&'a ()>,
|
||||
| ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
|
||||
|
|
||||
= help: consider adding the following bound: `'a: 'b`
|
||||
= note: requirement occurs because of a function pointer to `foo`
|
||||
= note: the function `foo` is invariant over the parameter `T`
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||
|
||||
help: `'a` and `'b` must be the same: replace one with the other
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/fn_def_coercion.rs:50:18
|
||||
|
|
||||
LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
| -- -- lifetime `'c` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | false => foo::<&'a ()>,
|
||||
| ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c`
|
||||
|
|
||||
= help: consider adding the following bound: `'a: 'c`
|
||||
= note: requirement occurs because of a function pointer to `foo`
|
||||
= note: the function `foo` is invariant over the parameter `T`
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/fn_def_coercion.rs:54:5
|
||||
|
|
||||
LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | x(b);
|
||||
| ^^^^ argument requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
|
||||
help: the following changes may resolve your lifetime errors
|
||||
|
|
||||
= help: add bound `'a: 'c`
|
||||
= help: add bound `'b: 'a`
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
69
tests/ui/fn/fn_def_opaque_coercion.rs
Normal file
69
tests/ui/fn/fn_def_opaque_coercion.rs
Normal file
@ -0,0 +1,69 @@
|
||||
//! Test that coercing between function items of the same function,
|
||||
//! but with different generic args works.
|
||||
|
||||
//@check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
fn foo<T>(t: T) -> T {
|
||||
t
|
||||
}
|
||||
|
||||
type F = impl Sized;
|
||||
|
||||
fn f(a: F) {
|
||||
let mut x = foo::<F>;
|
||||
x = foo::<()>;
|
||||
x(a);
|
||||
x(());
|
||||
}
|
||||
|
||||
type G = impl Sized;
|
||||
|
||||
fn g(a: G) {
|
||||
let x = foo::<()>;
|
||||
let _: () = x(a);
|
||||
}
|
||||
|
||||
type H = impl Sized;
|
||||
|
||||
fn h(a: H) {
|
||||
let x = foo::<H>;
|
||||
let _: H = x(());
|
||||
}
|
||||
|
||||
type I = impl Sized;
|
||||
|
||||
fn i(a: I) {
|
||||
let mut x = foo::<()>;
|
||||
x = foo::<I>;
|
||||
x(a);
|
||||
x(());
|
||||
}
|
||||
|
||||
type J = impl Sized;
|
||||
|
||||
fn j(a: J) {
|
||||
let x = match true {
|
||||
true => foo::<J>,
|
||||
false => foo::<()>,
|
||||
};
|
||||
x(a);
|
||||
x(());
|
||||
}
|
||||
|
||||
fn k() -> impl Sized {
|
||||
fn bind<T, F: FnOnce(T) -> T>(_: T, f: F) -> F {
|
||||
f
|
||||
}
|
||||
let x = match true {
|
||||
true => {
|
||||
let f = foo;
|
||||
bind(k(), f)
|
||||
}
|
||||
false => foo::<()>,
|
||||
};
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user