From 328f81713cc80861fb79c629e4887de1a8b7bf05 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 12 Oct 2022 12:57:16 +0200 Subject: [PATCH 01/20] Make `CStr::from_ptr` `const`. --- library/core/src/ffi/c_str.rs | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 55e58c4e0baa5..ae15be793414e 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -240,7 +240,9 @@ impl CStr { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { + #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")] + #[rustc_allow_const_fn_unstable(const_eval_select)] + pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { // SAFETY: The caller has provided a pointer that points to a valid C // string with a NUL terminator of size less than `isize::MAX`, whose // content remain valid and doesn't change for the lifetime of the @@ -252,13 +254,29 @@ impl CStr { // // The cast from c_char to u8 is ok because a c_char is always one byte. unsafe { - extern "C" { - /// Provided by libc or compiler_builtins. - fn strlen(s: *const c_char) -> usize; + const fn strlen_ct(s: *const c_char) -> usize { + let mut len = 0; + + // SAFETY: Outer caller has provided a pointer to a valid C string. + while unsafe { *s.add(len) } != 0 { + len += 1; + } + + len } - let len = strlen(ptr); - let ptr = ptr as *const u8; - CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) + + fn strlen_rt(s: *const c_char) -> usize { + extern "C" { + /// Provided by libc or compiler_builtins. + fn strlen(s: *const c_char) -> usize; + } + + // SAFETY: Outer caller has provided a pointer to a valid C string. + unsafe { strlen(s) } + } + + let len = intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt); + Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr.cast(), len + 1)) } } From 36dbb07dafe59c4d1491c2fbff6971d653f2ff77 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 12 Oct 2022 13:12:27 +0200 Subject: [PATCH 02/20] Update docs for `CStr::from_ptr`. --- library/core/src/ffi/c_str.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index ae15be793414e..9f7c960d88feb 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -221,9 +221,7 @@ impl CStr { /// # Examples /// /// ```ignore (extern-declaration) - /// # fn main() { - /// use std::ffi::CStr; - /// use std::os::raw::c_char; + /// use std::ffi::{c_char, CStr}; /// /// extern "C" { /// fn my_string() -> *const c_char; @@ -233,7 +231,18 @@ impl CStr { /// let slice = CStr::from_ptr(my_string()); /// println!("string returned: {}", slice.to_str().unwrap()); /// } - /// # } + /// ``` + /// + /// ``` + /// #![feature(const_cstr_methods)] + /// + /// use std::ffi::{c_char, CStr}; + /// + /// const HELLO_PTR: *const c_char = { + /// const BYTES: &[u8] = b"Hello, world!\0"; + /// BYTES.as_ptr().cast() + /// }; + /// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) }; /// ``` /// /// [valid]: core::ptr#safety From 4accf838f6d847c0c93f4c25540446dad0309519 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 22 Oct 2022 03:09:49 +0000 Subject: [PATCH 03/20] Note scope of TAIT more accurately --- .../rustc_error_messages/locales/en-US/hir_analysis.ftl | 2 +- compiler/rustc_hir_analysis/src/collect/type_of.rs | 6 ++++++ compiler/rustc_hir_analysis/src/errors.rs | 1 + src/test/ui/generic-associated-types/issue-87258_a.stderr | 2 +- src/test/ui/lint/inline-trait-and-foreign-items.stderr | 2 +- src/test/ui/lint/no-coverage.stderr | 2 +- src/test/ui/save-analysis/issue-68621.stderr | 2 +- 7 files changed, 12 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 357c6900a70e5..a5bbd1f7fc24b 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -93,7 +93,7 @@ hir_analysis_expected_default_return_type = expected `()` because of default ret hir_analysis_expected_return_type = expected `{$expected}` because of return type hir_analysis_unconstrained_opaque_type = unconstrained opaque type - .note = `{$name}` must be used in combination with a concrete type within the same module + .note = `{$name}` must be used in combination with a concrete type within the same {$what} hir_analysis_missing_type_params = the type {$parameterCount -> diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 32f359a815819..05ada7879224a 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -693,6 +693,12 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T tcx.sess.emit_err(UnconstrainedOpaqueType { span: tcx.def_span(def_id), name: tcx.item_name(tcx.local_parent(def_id).to_def_id()), + what: match tcx.hir().get(scope) { + _ if scope == hir::CRATE_HIR_ID => "module", + Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module", + Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl", + _ => "item", + }, }); return tcx.ty_error(); }; diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index aaebbe6398a13..5b41a64dcd8e7 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -143,6 +143,7 @@ pub struct UnconstrainedOpaqueType { #[primary_span] pub span: Span, pub name: Symbol, + pub what: &'static str, } pub struct MissingTypeParams { diff --git a/src/test/ui/generic-associated-types/issue-87258_a.stderr b/src/test/ui/generic-associated-types/issue-87258_a.stderr index fa0748a280b60..eae9bd9b16f2d 100644 --- a/src/test/ui/generic-associated-types/issue-87258_a.stderr +++ b/src/test/ui/generic-associated-types/issue-87258_a.stderr @@ -4,7 +4,7 @@ error: unconstrained opaque type LL | type FooFuture<'a> = impl Trait1; | ^^^^^^^^^^^ | - = note: `FooFuture` must be used in combination with a concrete type within the same module + = note: `FooFuture` must be used in combination with a concrete type within the same impl error: aborting due to previous error diff --git a/src/test/ui/lint/inline-trait-and-foreign-items.stderr b/src/test/ui/lint/inline-trait-and-foreign-items.stderr index 27399746bed6f..2f1fb4c46c08b 100644 --- a/src/test/ui/lint/inline-trait-and-foreign-items.stderr +++ b/src/test/ui/lint/inline-trait-and-foreign-items.stderr @@ -67,7 +67,7 @@ error: unconstrained opaque type LL | type U = impl Trait; | ^^^^^^^^^^ | - = note: `U` must be used in combination with a concrete type within the same module + = note: `U` must be used in combination with a concrete type within the same impl error: aborting due to 6 previous errors; 2 warnings emitted diff --git a/src/test/ui/lint/no-coverage.stderr b/src/test/ui/lint/no-coverage.stderr index 8452ccc7a03cb..404efbeac1e13 100644 --- a/src/test/ui/lint/no-coverage.stderr +++ b/src/test/ui/lint/no-coverage.stderr @@ -94,7 +94,7 @@ error: unconstrained opaque type LL | type U = impl Trait; | ^^^^^^^^^^ | - = note: `U` must be used in combination with a concrete type within the same module + = note: `U` must be used in combination with a concrete type within the same impl error: aborting due to 7 previous errors; 6 warnings emitted diff --git a/src/test/ui/save-analysis/issue-68621.stderr b/src/test/ui/save-analysis/issue-68621.stderr index 4a4bf9a6996bc..4452ee7915baa 100644 --- a/src/test/ui/save-analysis/issue-68621.stderr +++ b/src/test/ui/save-analysis/issue-68621.stderr @@ -4,7 +4,7 @@ error: unconstrained opaque type LL | type Future = impl Trait; | ^^^^^^^^^^ | - = note: `Future` must be used in combination with a concrete type within the same module + = note: `Future` must be used in combination with a concrete type within the same impl error: aborting due to previous error From 8b984e5c2487d9d4029b35cf9a0b079b66f3b7c6 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Thu, 11 Aug 2022 15:40:23 +0300 Subject: [PATCH 04/20] fake capture if min_captures empty --- compiler/rustc_hir_typeck/src/upvar.rs | 7 ++++++- src/test/ui/closures/issue-93242.rs | 11 +++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/closures/issue-93242.rs diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 4dea40829f622..3aa8c56138de6 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -231,7 +231,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We now fake capture information for all variables that are mentioned within the closure // We do this after handling migrations so that min_captures computes before - if !enable_precise_capture(self.tcx, span) { + if !enable_precise_capture(self.tcx, span) + // (ouz-a) #93242 - ICE happens because closure_min_captures is empty with + // 2021 edition, because it sets `enable_precise_capture` to true, which won't allow us + // fake capture information this check sidesteps that and avoids the ICE. + || (infer_kind == None && self.typeck_results.borrow().closure_min_captures.is_empty()) + { let mut capture_information: InferredCaptureInformation<'tcx> = Default::default(); if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) { diff --git a/src/test/ui/closures/issue-93242.rs b/src/test/ui/closures/issue-93242.rs new file mode 100644 index 0000000000000..56f8b0a477935 --- /dev/null +++ b/src/test/ui/closures/issue-93242.rs @@ -0,0 +1,11 @@ +// check-pass +// edition:2021 + +pub fn something(path: &[usize]) -> impl Fn() -> usize + '_ { + move || match path { + [] => 0, + _ => 1, + } +} + +fn main(){} From e521a8d46b4437f94ba1bb85826bb7d00ba13436 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 5 Oct 2022 19:59:45 +0100 Subject: [PATCH 05/20] Prevent foreign Rust exceptions from being caught --- library/panic_unwind/src/gcc.rs | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 261404e8795fc..777ae41fab124 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -38,12 +38,23 @@ use alloc::boxed::Box; use core::any::Any; +use core::ptr; use unwind as uw; +// In case where multiple copies of std is compiled into a single binary, +// we use address of this static variable to distinguish an exception raised by +// this copy and some other copy (which needs to be treated as foreign exception). +static CANARY: u8 = 0; + +// NOTE(nbdd0121) +// Once `c_unwind` feature is stabilized, there will be ABI stability requirement +// on this struct. The first two field must be `_Unwind_Exception` and `canary`, +// as it may be accessed by a different version of the std with a different compiler. #[repr(C)] struct Exception { _uwe: uw::_Unwind_Exception, + canary: *const u8, cause: Box, } @@ -54,6 +65,7 @@ pub unsafe fn panic(data: Box) -> u32 { exception_cleanup, private: [0; uw::unwinder_private_data_size], }, + canary: &CANARY, cause: data, }); let exception_param = Box::into_raw(exception) as *mut uw::_Unwind_Exception; @@ -75,10 +87,22 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box { if (*exception).exception_class != rust_exception_class() { uw::_Unwind_DeleteException(exception); super::__rust_foreign_exception(); - } else { - let exception = Box::from_raw(exception as *mut Exception); - exception.cause } + + let exception = exception.cast::(); + // Just access the canary field, avoid accessing the entire `Exception` as + // it can be a foreign Rust exception. + let canary = ptr::addr_of!((*exception).canary).read(); + if !ptr::eq(canary, &CANARY) { + // A foreign Rust exception, treat it slightly differently from other + // foreign exceptions, because call into `_Unwind_DeleteException` will + // call into `__rust_drop_panic` which produces a confusing + // "Rust panic must be rethrown" message. + super::__rust_foreign_exception(); + } + + let exception = Box::from_raw(exception as *mut Exception); + exception.cause } // Rust's exception class identifier. This is used by personality routines to From 86c65d2c1ce5aba2c1c74298c3e42696cff1d41a Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 5 Oct 2022 22:40:07 +0100 Subject: [PATCH 06/20] Implement Rust foreign exception protection for EMCC and SEH --- library/panic_unwind/src/emcc.rs | 37 +++++++++++++++++++++++--------- library/panic_unwind/src/seh.rs | 20 ++++++++++++----- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index 7c233c7c3a1cb..57e817ce6ad54 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -47,7 +47,12 @@ static EXCEPTION_TYPE_INFO: TypeInfo = TypeInfo { name: b"rust_panic\0".as_ptr(), }; +// NOTE(nbdd0121): The `canary` field will be part of stable ABI after `c_unwind` stabilization. +#[repr(C)] struct Exception { + // See `gcc.rs` on why this is present. We already have a static here so just use it. + canary: *const TypeInfo, + // This is necessary because C++ code can capture our exception with // std::exception_ptr and rethrow it multiple times, possibly even in // another thread. @@ -70,16 +75,21 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box { let catch_data = &*(ptr as *mut CatchData); let adjusted_ptr = __cxa_begin_catch(catch_data.ptr as *mut libc::c_void) as *mut Exception; - let out = if catch_data.is_rust_panic { - let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::SeqCst); - if was_caught { - // Since cleanup() isn't allowed to panic, we just abort instead. - intrinsics::abort(); - } - (*adjusted_ptr).data.take().unwrap() - } else { + if !catch_data.is_rust_panic { super::__rust_foreign_exception(); - }; + } + + let canary = ptr::addr_of!((*adjusted_ptr).canary).read(); + if !ptr::eq(canary, &EXCEPTION_TYPE_INFO) { + super::__rust_foreign_exception(); + } + + let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::SeqCst); + if was_caught { + // Since cleanup() isn't allowed to panic, we just abort instead. + intrinsics::abort(); + } + let out = (*adjusted_ptr).data.take().unwrap(); __cxa_end_catch(); out } @@ -90,7 +100,14 @@ pub unsafe fn panic(data: Box) -> u32 { if exception.is_null() { return uw::_URC_FATAL_PHASE1_ERROR as u32; } - ptr::write(exception, Exception { caught: AtomicBool::new(false), data: Some(data) }); + ptr::write( + exception, + Exception { + canary: &EXCEPTION_TYPE_INFO, + caught: AtomicBool::new(false), + data: Some(data), + }, + ); __cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, exception_cleanup); } diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index 6b8d065686113..651115a8248ac 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -49,9 +49,15 @@ use alloc::boxed::Box; use core::any::Any; use core::mem::{self, ManuallyDrop}; +use core::ptr; use libc::{c_int, c_uint, c_void}; +// NOTE(nbdd0121): The `canary` field will be part of stable ABI after `c_unwind` stabilization. +#[repr(C)] struct Exception { + // See `gcc.rs` on why this is present. We already have a static here so just use it. + canary: *const _TypeDescriptor, + // This needs to be an Option because we catch the exception by reference // and its destructor is executed by the C++ runtime. When we take the Box // out of the exception, we need to leave the exception in a valid state @@ -235,7 +241,7 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { macro_rules! define_cleanup { ($abi:tt $abi2:tt) => { unsafe extern $abi fn exception_cleanup(e: *mut Exception) { - if let Exception { data: Some(b) } = e.read() { + if let Exception { data: Some(b), .. } = e.read() { drop(b); super::__rust_drop_panic(); } @@ -265,7 +271,7 @@ pub unsafe fn panic(data: Box) -> u32 { // The ManuallyDrop is needed here since we don't want Exception to be // dropped when unwinding. Instead it will be dropped by exception_cleanup // which is invoked by the C++ runtime. - let mut exception = ManuallyDrop::new(Exception { data: Some(data) }); + let mut exception = ManuallyDrop::new(Exception { canary: &TYPE_DESCRIPTOR, data: Some(data) }); let throw_ptr = &mut exception as *mut _ as *mut _; // This... may seems surprising, and justifiably so. On 32-bit MSVC the @@ -321,8 +327,12 @@ pub unsafe fn cleanup(payload: *mut u8) -> Box { // __rust_try. This happens when a non-Rust foreign exception is caught. if payload.is_null() { super::__rust_foreign_exception(); - } else { - let exception = &mut *(payload as *mut Exception); - exception.data.take().unwrap() } + let exception = payload as *mut Exception; + let canary = ptr::addr_of!((*exception).canary).read(); + if !ptr::eq(canary, &TYPE_DESCRIPTOR) { + // A foreign Rust exception. + super::__rust_foreign_exception(); + } + (*exception).data.take().unwrap() } From daf3063056d6c3dbd402d5b940f0b28aac0e1dff Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 5 Oct 2022 23:58:35 +0100 Subject: [PATCH 07/20] Add test case for foreign Rust exceptions --- .../foreign-rust-exceptions/Makefile | 6 ++++++ .../run-make-fulldeps/foreign-rust-exceptions/bar.rs | 7 +++++++ .../run-make-fulldeps/foreign-rust-exceptions/foo.rs | 12 ++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile create mode 100644 src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs create mode 100644 src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile b/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile new file mode 100644 index 0000000000000..24d9742aef0b0 --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile @@ -0,0 +1,6 @@ +include ../tools.mk + +all: + $(RUSTC) bar.rs --crate-type=cdylib + $(RUSTC) foo.rs + $(call RUN,foo) 2>&1 | $(CGREP) "Rust cannot catch foreign exceptions" diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs b/src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs new file mode 100644 index 0000000000000..5f9efe323609b --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs @@ -0,0 +1,7 @@ +#![crate_type = "cdylib"] +#![feature(c_unwind)] + +#[no_mangle] +extern "C-unwind" fn panic() { + panic!(); +} diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs new file mode 100644 index 0000000000000..d6a6d94a19497 --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs @@ -0,0 +1,12 @@ +#![feature(c_unwind)] + +#[link(name = "bar")] +extern "C-unwind" { + fn panic(); +} + +fn main() { + let _ = std::panic::catch_unwind(|| { + unsafe { panic() }; + }); +} From 979d1a2c78a3fd45807eb28ccff5aeea37128e0f Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 11 Oct 2022 18:02:07 +0100 Subject: [PATCH 08/20] Apply suggestion Co-authored-by: Amanieu d'Antras --- library/panic_unwind/src/gcc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 777ae41fab124..0b7a873a691cc 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -42,7 +42,7 @@ use core::ptr; use unwind as uw; -// In case where multiple copies of std is compiled into a single binary, +// In case where multiple copies of std exist in a single process, // we use address of this static variable to distinguish an exception raised by // this copy and some other copy (which needs to be treated as foreign exception). static CANARY: u8 = 0; From 4e6d60c837e178950b844bd1235c67ebbb6a5899 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 12 Oct 2022 12:24:59 +0100 Subject: [PATCH 09/20] Fix alloc size --- library/panic_unwind/src/emcc.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index 57e817ce6ad54..c6d42308596cb 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -95,8 +95,7 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box { } pub unsafe fn panic(data: Box) -> u32 { - let sz = mem::size_of_val(&data); - let exception = __cxa_allocate_exception(sz) as *mut Exception; + let exception = __cxa_allocate_exception(mem::size_of::()) as *mut Exception; if exception.is_null() { return uw::_URC_FATAL_PHASE1_ERROR as u32; } From c9cca33e85352c6ffd0c29a22c7302ca5f761ba3 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sun, 23 Oct 2022 21:30:37 +0100 Subject: [PATCH 10/20] Fix windows compilation --- src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs index d6a6d94a19497..266987c5b6d63 100644 --- a/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs +++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs @@ -1,6 +1,7 @@ #![feature(c_unwind)] -#[link(name = "bar")] +#[cfg_attr(not(windows), link(name = "bar"))] +#[cfg_attr(windows, link(name = "bar.dll"))] extern "C-unwind" { fn panic(); } From 8b494f427cb06896996fb02ac8c3ff745fde4d15 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 2 Feb 2022 15:09:44 +0300 Subject: [PATCH 11/20] Allow `impl Fn() -> impl Trait` in return position This allows writing the following function signatures: ```rust fn f0() -> impl Fn() -> impl Trait; fn f3() -> &'static dyn Fn() -> impl Trait; ``` These signatures were already allowed for common traits and associated types, there is no reason why `Fn*` traits should be special in this regard. --- compiler/rustc_ast_lowering/src/path.rs | 13 ++- .../ui/impl-trait/impl_fn_associativity.rs | 16 ++++ src/test/ui/impl-trait/nested_impl_trait.rs | 3 +- .../ui/impl-trait/nested_impl_trait.stderr | 8 +- src/test/ui/impl-trait/where-allowed.rs | 6 +- src/test/ui/impl-trait/where-allowed.stderr | 94 ++++++++----------- 6 files changed, 73 insertions(+), 67 deletions(-) create mode 100644 src/test/ui/impl-trait/impl_fn_associativity.rs diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 888776cccac2d..4b7ef960d4b61 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -191,7 +191,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) } GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args { - ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data), + ParenthesizedGenericArgs::Ok => { + self.lower_parenthesized_parameter_data(data, itctx) + } ParenthesizedGenericArgs::Err => { // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait` let sub = if !data.inputs.is_empty() { @@ -344,6 +346,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_parenthesized_parameter_data( &mut self, data: &ParenthesizedArgs, + itctx: ImplTraitContext, ) -> (GenericArgsCtor<'hir>, bool) { // Switch to `PassThrough` mode for anonymous lifetimes; this // means that we permit things like `&Ref`, where `Ref` has @@ -355,6 +358,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_ty_direct(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) })); let output_ty = match output { + // Only allow `impl Trait` in return position. i.e.: + // ```rust + // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug + // // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^ + // ``` + FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => { + self.lower_ty(&ty, itctx) + } FnRetTy::Ty(ty) => { self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) } diff --git a/src/test/ui/impl-trait/impl_fn_associativity.rs b/src/test/ui/impl-trait/impl_fn_associativity.rs new file mode 100644 index 0000000000000..f5f1909cf58b0 --- /dev/null +++ b/src/test/ui/impl-trait/impl_fn_associativity.rs @@ -0,0 +1,16 @@ +// run-pass +use std::fmt::Debug; + +fn f_debug() -> impl Fn() -> impl Debug { + || () +} + +fn ff_debug() -> impl Fn() -> impl Fn() -> impl Debug { + || f_debug() +} + +fn main() { + // Check that `ff_debug` is `() -> (() -> Debug)` and not `(() -> ()) -> Debug` + let debug = ff_debug()()(); + assert_eq!(format!("{:?}", debug), "()"); +} diff --git a/src/test/ui/impl-trait/nested_impl_trait.rs b/src/test/ui/impl-trait/nested_impl_trait.rs index 85c6f8c462cbb..9b0dbacaded8d 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.rs +++ b/src/test/ui/impl-trait/nested_impl_trait.rs @@ -25,8 +25,7 @@ fn allowed_in_assoc_type() -> impl Iterator { } fn allowed_in_ret_type() -> impl Fn() -> impl Into { -//~^ `impl Trait` only allowed in function and inherent method return types - || 5 + || 5u8 } fn main() {} diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr index 3291cad6882e1..e2ce7d15a0697 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.stderr +++ b/src/test/ui/impl-trait/nested_impl_trait.stderr @@ -40,12 +40,6 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ^^^^^^^^^^^^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/nested_impl_trait.rs:27:42 - | -LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into { - | ^^^^^^^^^^^^^^ - error[E0277]: the trait bound `impl Debug: From>` is not satisfied --> $DIR/nested_impl_trait.rs:5:46 | @@ -64,7 +58,7 @@ LL | fn bad(x: impl Into) -> impl Into { x } = help: the trait `Into` is implemented for `T` = note: required for `impl Into` to implement `Into` -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0277, E0562, E0666. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/where-allowed.rs b/src/test/ui/impl-trait/where-allowed.rs index c1dd46c7ff7fd..d337ab422d746 100644 --- a/src/test/ui/impl-trait/where-allowed.rs +++ b/src/test/ui/impl-trait/where-allowed.rs @@ -39,9 +39,8 @@ fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } //~^ ERROR `impl Trait` only allowed in function and inherent method return types -// Disallowed +// Allowed fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types // Disallowed fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } @@ -57,9 +56,8 @@ fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } //~^ ERROR `impl Trait` only allowed in function and inherent method return types //~| ERROR nested `impl Trait` is not allowed -// Disallowed +// Allowed fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types // Disallowed fn in_Fn_parameter_in_generics (_: F) { panic!() } diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr index 2e7c7ca40ddb3..1b704d0d92465 100644 --- a/src/test/ui/impl-trait/where-allowed.stderr +++ b/src/test/ui/impl-trait/where-allowed.stderr @@ -1,5 +1,5 @@ error[E0666]: nested `impl Trait` is not allowed - --> $DIR/where-allowed.rs:47:51 + --> $DIR/where-allowed.rs:46:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | --------^^^^^^^^^^- @@ -8,7 +8,7 @@ LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/where-allowed.rs:56:57 + --> $DIR/where-allowed.rs:55:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | --------^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic | outer `impl Trait` error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:119:16 + --> $DIR/where-allowed.rs:117:16 | LL | type Out = impl Debug; | ^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | type Out = impl Debug; = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:154:23 + --> $DIR/where-allowed.rs:152:23 | LL | type InTypeAlias = impl Debug; | ^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | type InTypeAlias = impl Debug; = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:157:39 + --> $DIR/where-allowed.rs:155:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ @@ -85,80 +85,68 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:43:57 - | -LL | fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } - | ^^^^^^^^^^ - error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:47:51 + --> $DIR/where-allowed.rs:46:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:52:53 + --> $DIR/where-allowed.rs:51:53 | LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:56:57 + --> $DIR/where-allowed.rs:55:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:61:59 - | -LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() } - | ^^^^^^^^^^ - error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:65:38 + --> $DIR/where-allowed.rs:63:38 | LL | fn in_Fn_parameter_in_generics (_: F) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:69:40 + --> $DIR/where-allowed.rs:67:40 | LL | fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:82:32 + --> $DIR/where-allowed.rs:80:32 | LL | struct InBraceStructField { x: impl Debug } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in path - --> $DIR/where-allowed.rs:86:41 + --> $DIR/where-allowed.rs:84:41 | LL | struct InAdtInBraceStructField { x: Vec } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:90:27 + --> $DIR/where-allowed.rs:88:27 | LL | struct InTupleStructField(impl Debug); | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:95:25 + --> $DIR/where-allowed.rs:93:25 | LL | InBraceVariant { x: impl Debug }, | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:97:20 + --> $DIR/where-allowed.rs:95:20 | LL | InTupleVariant(impl Debug), | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return - --> $DIR/where-allowed.rs:108:23 + --> $DIR/where-allowed.rs:106:23 | LL | fn in_return() -> impl Debug; | ^^^^^^^^^^ @@ -167,7 +155,7 @@ LL | fn in_return() -> impl Debug; = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return - --> $DIR/where-allowed.rs:125:34 + --> $DIR/where-allowed.rs:123:34 | LL | fn in_trait_impl_return() -> impl Debug { () } | ^^^^^^^^^^ @@ -176,127 +164,127 @@ LL | fn in_trait_impl_return() -> impl Debug { () } = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` param - --> $DIR/where-allowed.rs:138:33 + --> $DIR/where-allowed.rs:136:33 | LL | fn in_foreign_parameters(_: impl Debug); | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` return - --> $DIR/where-allowed.rs:141:31 + --> $DIR/where-allowed.rs:139:31 | LL | fn in_foreign_return() -> impl Debug; | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return - --> $DIR/where-allowed.rs:157:39 + --> $DIR/where-allowed.rs:155:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait - --> $DIR/where-allowed.rs:162:16 + --> $DIR/where-allowed.rs:160:16 | LL | impl PartialEq for () { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:167:24 + --> $DIR/where-allowed.rs:165:24 | LL | impl PartialEq<()> for impl Debug { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:172:6 + --> $DIR/where-allowed.rs:170:6 | LL | impl impl Debug { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:178:24 + --> $DIR/where-allowed.rs:176:24 | LL | impl InInherentImplAdt { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:184:11 + --> $DIR/where-allowed.rs:182:11 | LL | where impl Debug: Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:191:15 + --> $DIR/where-allowed.rs:189:15 | LL | where Vec: Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bound - --> $DIR/where-allowed.rs:198:24 + --> $DIR/where-allowed.rs:196:24 | LL | where T: PartialEq | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:205:17 + --> $DIR/where-allowed.rs:203:17 | LL | where T: Fn(impl Debug) | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:212:22 + --> $DIR/where-allowed.rs:210:22 | LL | where T: Fn() -> impl Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:218:40 + --> $DIR/where-allowed.rs:216:40 | LL | struct InStructGenericParamDefault(T); | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:222:36 + --> $DIR/where-allowed.rs:220:36 | LL | enum InEnumGenericParamDefault { Variant(T) } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:226:38 + --> $DIR/where-allowed.rs:224:38 | LL | trait InTraitGenericParamDefault {} | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:230:41 + --> $DIR/where-allowed.rs:228:41 | LL | type InTypeAliasGenericParamDefault = T; | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:234:11 + --> $DIR/where-allowed.rs:232:11 | LL | impl T {} | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:241:40 + --> $DIR/where-allowed.rs:239:40 | LL | fn in_method_generic_param_default(_: T) {} | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding - --> $DIR/where-allowed.rs:247:29 + --> $DIR/where-allowed.rs:245:29 | LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in closure return - --> $DIR/where-allowed.rs:249:46 + --> $DIR/where-allowed.rs:247:46 | LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; | ^^^^^^^^^ error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:234:7 + --> $DIR/where-allowed.rs:232:7 | LL | impl T {} | ^^^^^^^^^^^^^^ @@ -306,7 +294,7 @@ LL | impl T {} = note: `#[deny(invalid_type_param_default)]` on by default error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:241:36 + --> $DIR/where-allowed.rs:239:36 | LL | fn in_method_generic_param_default(_: T) {} | ^^^^^^^^^^^^^^ @@ -315,14 +303,14 @@ LL | fn in_method_generic_param_default(_: T) {} = note: for more information, see issue #36887 error[E0118]: no nominal type found for inherent implementation - --> $DIR/where-allowed.rs:234:23 + --> $DIR/where-allowed.rs:232:23 | LL | impl T {} | ^ impl requires a nominal type | = note: either implement a trait on it or create a newtype to wrap it instead -error: aborting due to 49 previous errors +error: aborting due to 47 previous errors Some errors have detailed explanations: E0118, E0562, E0658, E0666. For more information about an error, try `rustc --explain E0118`. From 7a4ba2ffdee0e63fe62f7543589faec9ad29fb9c Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 23 Jun 2022 19:00:03 +0400 Subject: [PATCH 12/20] Add more tests for `impl Fn() -> impl Trait` --- .../ui/impl-trait/impl-fn-hrtb-bounds-2.rs | 7 +++++ .../impl-trait/impl-fn-hrtb-bounds-2.stderr | 11 ++++++++ src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs | 13 ++++++++++ .../ui/impl-trait/impl-fn-hrtb-bounds.stderr | 26 +++++++++++++++++++ .../impl-trait/impl-fn-parsing-ambiguities.rs | 14 ++++++++++ .../impl-fn-parsing-ambiguities.stderr | 26 +++++++++++++++++++ .../ui/impl-trait/impl_fn_associativity.rs | 9 +++++++ 7 files changed, 106 insertions(+) create mode 100644 src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs create mode 100644 src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr create mode 100644 src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs create mode 100644 src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr create mode 100644 src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs create mode 100644 src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs new file mode 100644 index 0000000000000..688ae1da5e30f --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs @@ -0,0 +1,7 @@ +use std::fmt::Debug; + +fn a() -> impl Fn(&u8) -> impl Debug { + |x| x //~ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr new file mode 100644 index 0000000000000..57f618d11f904 --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/impl-fn-hrtb-bounds-2.rs:4:9 + | +LL | |x| x + | -- ^ returning this value requires that `'1` must outlive `'2` + | || + | |return type of closure is &'2 u8 + | has type `&'1 u8` + +error: aborting due to previous error + diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs new file mode 100644 index 0000000000000..f7d9430a22637 --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs @@ -0,0 +1,13 @@ +use std::fmt::Debug; + +fn a() -> impl Fn(&u8) -> (impl Debug + '_) { + //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + |x| x +} + +fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { + //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + |x| x +} + +fn main() {} diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr new file mode 100644 index 0000000000000..6fe4534d9281f --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -0,0 +1,26 @@ +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/impl-fn-hrtb-bounds.rs:3:41 + | +LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { + | ^^ + | +note: lifetime declared here + --> $DIR/impl-fn-hrtb-bounds.rs:3:19 + | +LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { + | ^ + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/impl-fn-hrtb-bounds.rs:8:52 + | +LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { + | ^^ + | +note: lifetime declared here + --> $DIR/impl-fn-hrtb-bounds.rs:8:20 + | +LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { + | ^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs new file mode 100644 index 0000000000000..053912aa8166a --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs @@ -0,0 +1,14 @@ +use std::fmt::Debug; + +fn a() -> impl Fn(&u8) -> impl Debug + '_ { + //~^ ERROR ambiguous `+` in a type + //~^^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + |x| x +} + +fn b() -> impl Fn() -> impl Debug + Send { + //~^ ERROR ambiguous `+` in a type + || () +} + +fn main() {} diff --git a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr new file mode 100644 index 0000000000000..e54864443ae04 --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr @@ -0,0 +1,26 @@ +error: ambiguous `+` in a type + --> $DIR/impl-fn-parsing-ambiguities.rs:3:27 + | +LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { + | ^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + '_)` + +error: ambiguous `+` in a type + --> $DIR/impl-fn-parsing-ambiguities.rs:9:24 + | +LL | fn b() -> impl Fn() -> impl Debug + Send { + | ^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + Send)` + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/impl-fn-parsing-ambiguities.rs:3:40 + | +LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { + | ^^ + | +note: lifetime declared here + --> $DIR/impl-fn-parsing-ambiguities.rs:3:19 + | +LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { + | ^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/impl-trait/impl_fn_associativity.rs b/src/test/ui/impl-trait/impl_fn_associativity.rs index f5f1909cf58b0..6accaed98c9ab 100644 --- a/src/test/ui/impl-trait/impl_fn_associativity.rs +++ b/src/test/ui/impl-trait/impl_fn_associativity.rs @@ -9,8 +9,17 @@ fn ff_debug() -> impl Fn() -> impl Fn() -> impl Debug { || f_debug() } +fn multi() -> impl Fn() -> (impl Debug + Send) { + || () +} + fn main() { // Check that `ff_debug` is `() -> (() -> Debug)` and not `(() -> ()) -> Debug` let debug = ff_debug()()(); assert_eq!(format!("{:?}", debug), "()"); + + let x = multi()(); + assert_eq!(format!("{:?}", x), "()"); + fn assert_send(_: &impl Send) {} + assert_send(&x); } From 00f22771f6fb625fd66122fded49d5bee7083707 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 23 Jun 2022 19:12:13 +0400 Subject: [PATCH 13/20] Add even more tests for `impl Fn() -> impl Trait` --- src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs | 10 ++++++ .../ui/impl-trait/impl-fn-hrtb-bounds.stderr | 32 ++++++++++++++++++- .../impl-fn-predefined-lifetimes.rs | 12 +++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs index f7d9430a22637..25144c090485e 100644 --- a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs @@ -10,4 +10,14 @@ fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { |x| x } +fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + |x| x +} + +fn d() -> impl Fn() -> (impl Debug + '_) { + //~^ ERROR missing lifetime specifier + || () +} + fn main() {} diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr index 6fe4534d9281f..6985c66df8791 100644 --- a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -22,5 +22,35 @@ note: lifetime declared here LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { | ^^ -error: aborting due to 2 previous errors +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/impl-fn-hrtb-bounds.rs:13:52 + | +LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + | ^^ + | +note: lifetime declared here + --> $DIR/impl-fn-hrtb-bounds.rs:13:20 + | +LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + | ^^ + +error[E0106]: missing lifetime specifier + --> $DIR/impl-fn-hrtb-bounds.rs:18:38 + | +LL | fn d() -> impl Fn() -> (impl Debug + '_) { + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | fn d() -> impl for<'a> Fn() -> (impl Debug + 'a) { + | +++++++ ~~ +help: consider using the `'static` lifetime + | +LL | fn d() -> impl Fn() -> (impl Debug + 'static) { + | ~~~~~~~ + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs new file mode 100644 index 0000000000000..e2f6e600da433 --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -0,0 +1,12 @@ +// check-pass +use std::fmt::Debug; + +fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + |x| x +} + +fn _b<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) { + a() +} + +fn main() {} From cc752f56650c123d702d027aeb154eafbe3fdd50 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 25 Jul 2022 01:54:47 +0400 Subject: [PATCH 14/20] Feature gate `impl_trait_in_fn_trait_return` --- compiler/rustc_ast_lowering/src/path.rs | 5 ++++- compiler/rustc_feature/src/active.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 4b7ef960d4b61..b7cda13fa4b70 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -363,7 +363,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug // // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^ // ``` - FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => { + FnRetTy::Ty(ty) + if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) + && self.tcx.features().impl_trait_in_fn_trait_return => + { self.lower_ty(&ty, itctx) } FnRetTy::Ty(ty) => { diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 1b8d683b13361..5656409c0d471 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -414,6 +414,8 @@ declare_features! ( (active, half_open_range_patterns_in_slices, "CURRENT_RUSTC_VERSION", Some(67264), None), /// Allows `if let` guard in match arms. (active, if_let_guard, "1.47.0", Some(51114), None), + /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. + (active, impl_trait_in_fn_trait_return, "1.64.0", Some(99697), None), /// Allows using imported `main` function (active, imported_main, "1.53.0", Some(28937), None), /// Allows associated types in inherent impls. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3fe79370c374d..21016602ff8d2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -813,6 +813,7 @@ symbols! { impl_lint_pass, impl_macros, impl_trait_in_bindings, + impl_trait_in_fn_trait_return, implied_by, import, import_name_type, From d116859ad78efa743726acd91d05d5a0bc64c0fe Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 29 Jul 2022 00:18:32 +0400 Subject: [PATCH 15/20] --bless --- .../ui/impl-trait/impl-fn-hrtb-bounds-2.rs | 3 +- .../impl-trait/impl-fn-hrtb-bounds-2.stderr | 12 +-- src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs | 1 + .../ui/impl-trait/impl-fn-hrtb-bounds.stderr | 41 ++++---- .../impl-trait/impl-fn-parsing-ambiguities.rs | 1 + .../impl-fn-parsing-ambiguities.stderr | 8 +- .../impl-fn-predefined-lifetimes.rs | 3 +- .../impl-fn-predefined-lifetimes.stderr | 15 +++ .../ui/impl-trait/impl_fn_associativity.rs | 1 + src/test/ui/impl-trait/nested_impl_trait.rs | 1 + .../ui/impl-trait/nested_impl_trait.stderr | 14 +-- src/test/ui/impl-trait/where-allowed.rs | 1 + src/test/ui/impl-trait/where-allowed.stderr | 94 +++++++++---------- 13 files changed, 106 insertions(+), 89 deletions(-) create mode 100644 src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs index 688ae1da5e30f..b0aeded0ef75a 100644 --- a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs @@ -1,7 +1,8 @@ +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; fn a() -> impl Fn(&u8) -> impl Debug { - |x| x //~ ERROR lifetime may not live long enough + |x| x //~ ERROR hidden type for `impl Debug` captures lifetime that does not appear in bounds } fn main() {} diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr index 57f618d11f904..433b76b7afaa2 100644 --- a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr @@ -1,11 +1,11 @@ -error: lifetime may not live long enough - --> $DIR/impl-fn-hrtb-bounds-2.rs:4:9 +error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds + --> $DIR/impl-fn-hrtb-bounds-2.rs:5:9 | LL | |x| x - | -- ^ returning this value requires that `'1` must outlive `'2` - | || - | |return type of closure is &'2 u8 - | has type `&'1 u8` + | --- ^ + | | + | hidden type `&u8` captures the anonymous lifetime #1 defined here error: aborting due to previous error +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs index 25144c090485e..527a4586fd7e0 100644 --- a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs @@ -1,3 +1,4 @@ +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; fn a() -> impl Fn(&u8) -> (impl Debug + '_) { diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr index 6985c66df8791..443ffeb55cdee 100644 --- a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -1,56 +1,51 @@ +error[E0106]: missing lifetime specifier + --> $DIR/impl-fn-hrtb-bounds.rs:19:38 + | +LL | fn d() -> impl Fn() -> (impl Debug + '_) { + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn d() -> impl Fn() -> (impl Debug + 'static) { + | ~~~~~~~ + error: higher kinded lifetime bounds on nested opaque types are not supported yet - --> $DIR/impl-fn-hrtb-bounds.rs:3:41 + --> $DIR/impl-fn-hrtb-bounds.rs:4:41 | LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { | ^^ | note: lifetime declared here - --> $DIR/impl-fn-hrtb-bounds.rs:3:19 + --> $DIR/impl-fn-hrtb-bounds.rs:4:19 | LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { | ^ error: higher kinded lifetime bounds on nested opaque types are not supported yet - --> $DIR/impl-fn-hrtb-bounds.rs:8:52 + --> $DIR/impl-fn-hrtb-bounds.rs:9:52 | LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { | ^^ | note: lifetime declared here - --> $DIR/impl-fn-hrtb-bounds.rs:8:20 + --> $DIR/impl-fn-hrtb-bounds.rs:9:20 | LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { | ^^ error: higher kinded lifetime bounds on nested opaque types are not supported yet - --> $DIR/impl-fn-hrtb-bounds.rs:13:52 + --> $DIR/impl-fn-hrtb-bounds.rs:14:52 | LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | ^^ | note: lifetime declared here - --> $DIR/impl-fn-hrtb-bounds.rs:13:20 + --> $DIR/impl-fn-hrtb-bounds.rs:14:20 | LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | ^^ -error[E0106]: missing lifetime specifier - --> $DIR/impl-fn-hrtb-bounds.rs:18:38 - | -LL | fn d() -> impl Fn() -> (impl Debug + '_) { - | ^^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html -help: consider making the bound lifetime-generic with a new `'a` lifetime - | -LL | fn d() -> impl for<'a> Fn() -> (impl Debug + 'a) { - | +++++++ ~~ -help: consider using the `'static` lifetime - | -LL | fn d() -> impl Fn() -> (impl Debug + 'static) { - | ~~~~~~~ - error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs index 053912aa8166a..3e760710797eb 100644 --- a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs +++ b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs @@ -1,3 +1,4 @@ +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; fn a() -> impl Fn(&u8) -> impl Debug + '_ { diff --git a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr index e54864443ae04..cf6e5ef7baceb 100644 --- a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr +++ b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr @@ -1,23 +1,23 @@ error: ambiguous `+` in a type - --> $DIR/impl-fn-parsing-ambiguities.rs:3:27 + --> $DIR/impl-fn-parsing-ambiguities.rs:4:27 | LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { | ^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + '_)` error: ambiguous `+` in a type - --> $DIR/impl-fn-parsing-ambiguities.rs:9:24 + --> $DIR/impl-fn-parsing-ambiguities.rs:10:24 | LL | fn b() -> impl Fn() -> impl Debug + Send { | ^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + Send)` error: higher kinded lifetime bounds on nested opaque types are not supported yet - --> $DIR/impl-fn-parsing-ambiguities.rs:3:40 + --> $DIR/impl-fn-parsing-ambiguities.rs:4:40 | LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { | ^^ | note: lifetime declared here - --> $DIR/impl-fn-parsing-ambiguities.rs:3:19 + --> $DIR/impl-fn-parsing-ambiguities.rs:4:19 | LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { | ^ diff --git a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs index e2f6e600da433..5e2379b2f9af6 100644 --- a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs +++ b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -1,7 +1,8 @@ -// check-pass +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + //~^ ERROR hidden type for `impl Debug` captures lifetime that does not appear in bounds |x| x } diff --git a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr new file mode 100644 index 0000000000000..1247ffad7c324 --- /dev/null +++ b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -0,0 +1,15 @@ +error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds + --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 + | +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + | ^^^^^^^^^^^^^^^ + | +note: hidden type `&' u8` captures lifetime smaller than the function body + --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 + | +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/impl_fn_associativity.rs b/src/test/ui/impl-trait/impl_fn_associativity.rs index 6accaed98c9ab..71a8f9c77960d 100644 --- a/src/test/ui/impl-trait/impl_fn_associativity.rs +++ b/src/test/ui/impl-trait/impl_fn_associativity.rs @@ -1,4 +1,5 @@ // run-pass +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; fn f_debug() -> impl Fn() -> impl Debug { diff --git a/src/test/ui/impl-trait/nested_impl_trait.rs b/src/test/ui/impl-trait/nested_impl_trait.rs index 9b0dbacaded8d..e95fab3b65057 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.rs +++ b/src/test/ui/impl-trait/nested_impl_trait.rs @@ -1,3 +1,4 @@ +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; fn fine(x: impl Into) -> impl Into { x } diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr index e2ce7d15a0697..9a8f5a3406813 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.stderr +++ b/src/test/ui/impl-trait/nested_impl_trait.stderr @@ -1,5 +1,5 @@ error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:5:56 + --> $DIR/nested_impl_trait.rs:6:56 | LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } | ----------^^^^^^^^^^- @@ -8,7 +8,7 @@ LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:9:42 + --> $DIR/nested_impl_trait.rs:10:42 | LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ----------^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:13:37 + --> $DIR/nested_impl_trait.rs:14:37 | LL | fn bad_in_arg_position(_: impl Into) { } | ----------^^^^^^^^^^- @@ -26,7 +26,7 @@ LL | fn bad_in_arg_position(_: impl Into) { } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:18:44 + --> $DIR/nested_impl_trait.rs:19:44 | LL | fn bad(x: impl Into) -> impl Into { x } | ----------^^^^^^^^^^- @@ -35,13 +35,13 @@ LL | fn bad(x: impl Into) -> impl Into { x } | outer `impl Trait` error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return - --> $DIR/nested_impl_trait.rs:9:32 + --> $DIR/nested_impl_trait.rs:10:32 | LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `impl Debug: From>` is not satisfied - --> $DIR/nested_impl_trait.rs:5:46 + --> $DIR/nested_impl_trait.rs:6:46 | LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` @@ -50,7 +50,7 @@ LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } = note: required for `impl Into` to implement `Into` error[E0277]: the trait bound `impl Debug: From>` is not satisfied - --> $DIR/nested_impl_trait.rs:18:34 + --> $DIR/nested_impl_trait.rs:19:34 | LL | fn bad(x: impl Into) -> impl Into { x } | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` diff --git a/src/test/ui/impl-trait/where-allowed.rs b/src/test/ui/impl-trait/where-allowed.rs index d337ab422d746..ff63b04c2680d 100644 --- a/src/test/ui/impl-trait/where-allowed.rs +++ b/src/test/ui/impl-trait/where-allowed.rs @@ -1,5 +1,6 @@ //! A simple test for testing many permutations of allowedness of //! impl Trait +#![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; // Allowed diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr index 1b704d0d92465..3ad0a9f9d5c8b 100644 --- a/src/test/ui/impl-trait/where-allowed.stderr +++ b/src/test/ui/impl-trait/where-allowed.stderr @@ -1,5 +1,5 @@ error[E0666]: nested `impl Trait` is not allowed - --> $DIR/where-allowed.rs:46:51 + --> $DIR/where-allowed.rs:47:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | --------^^^^^^^^^^- @@ -8,7 +8,7 @@ LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/where-allowed.rs:55:57 + --> $DIR/where-allowed.rs:56:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | --------^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic | outer `impl Trait` error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:117:16 + --> $DIR/where-allowed.rs:118:16 | LL | type Out = impl Debug; | ^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | type Out = impl Debug; = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:152:23 + --> $DIR/where-allowed.rs:153:23 | LL | type InTypeAlias = impl Debug; | ^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | type InTypeAlias = impl Debug; = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:155:39 + --> $DIR/where-allowed.rs:156:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ @@ -44,109 +44,109 @@ LL | type InReturnInTypeAlias = fn() -> impl Debug; = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer param - --> $DIR/where-allowed.rs:15:40 + --> $DIR/where-allowed.rs:16:40 | LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return - --> $DIR/where-allowed.rs:19:42 + --> $DIR/where-allowed.rs:20:42 | LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer param - --> $DIR/where-allowed.rs:23:38 + --> $DIR/where-allowed.rs:24:38 | LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return - --> $DIR/where-allowed.rs:27:40 + --> $DIR/where-allowed.rs:28:40 | LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:31:49 + --> $DIR/where-allowed.rs:32:49 | LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:35:51 + --> $DIR/where-allowed.rs:36:51 | LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:39:55 + --> $DIR/where-allowed.rs:40:55 | LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:46:51 + --> $DIR/where-allowed.rs:47:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:51:53 + --> $DIR/where-allowed.rs:52:53 | LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:55:57 + --> $DIR/where-allowed.rs:56:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:63:38 + --> $DIR/where-allowed.rs:64:38 | LL | fn in_Fn_parameter_in_generics (_: F) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:67:40 + --> $DIR/where-allowed.rs:68:40 | LL | fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:80:32 + --> $DIR/where-allowed.rs:81:32 | LL | struct InBraceStructField { x: impl Debug } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in path - --> $DIR/where-allowed.rs:84:41 + --> $DIR/where-allowed.rs:85:41 | LL | struct InAdtInBraceStructField { x: Vec } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:88:27 + --> $DIR/where-allowed.rs:89:27 | LL | struct InTupleStructField(impl Debug); | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:93:25 + --> $DIR/where-allowed.rs:94:25 | LL | InBraceVariant { x: impl Debug }, | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:95:20 + --> $DIR/where-allowed.rs:96:20 | LL | InTupleVariant(impl Debug), | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return - --> $DIR/where-allowed.rs:106:23 + --> $DIR/where-allowed.rs:107:23 | LL | fn in_return() -> impl Debug; | ^^^^^^^^^^ @@ -155,7 +155,7 @@ LL | fn in_return() -> impl Debug; = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return - --> $DIR/where-allowed.rs:123:34 + --> $DIR/where-allowed.rs:124:34 | LL | fn in_trait_impl_return() -> impl Debug { () } | ^^^^^^^^^^ @@ -164,127 +164,127 @@ LL | fn in_trait_impl_return() -> impl Debug { () } = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` param - --> $DIR/where-allowed.rs:136:33 + --> $DIR/where-allowed.rs:137:33 | LL | fn in_foreign_parameters(_: impl Debug); | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` return - --> $DIR/where-allowed.rs:139:31 + --> $DIR/where-allowed.rs:140:31 | LL | fn in_foreign_return() -> impl Debug; | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return - --> $DIR/where-allowed.rs:155:39 + --> $DIR/where-allowed.rs:156:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait - --> $DIR/where-allowed.rs:160:16 + --> $DIR/where-allowed.rs:161:16 | LL | impl PartialEq for () { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:165:24 + --> $DIR/where-allowed.rs:166:24 | LL | impl PartialEq<()> for impl Debug { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:170:6 + --> $DIR/where-allowed.rs:171:6 | LL | impl impl Debug { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:176:24 + --> $DIR/where-allowed.rs:177:24 | LL | impl InInherentImplAdt { | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:182:11 + --> $DIR/where-allowed.rs:183:11 | LL | where impl Debug: Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:189:15 + --> $DIR/where-allowed.rs:190:15 | LL | where Vec: Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bound - --> $DIR/where-allowed.rs:196:24 + --> $DIR/where-allowed.rs:197:24 | LL | where T: PartialEq | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param - --> $DIR/where-allowed.rs:203:17 + --> $DIR/where-allowed.rs:204:17 | LL | where T: Fn(impl Debug) | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return - --> $DIR/where-allowed.rs:210:22 + --> $DIR/where-allowed.rs:211:22 | LL | where T: Fn() -> impl Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:216:40 + --> $DIR/where-allowed.rs:217:40 | LL | struct InStructGenericParamDefault(T); | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:220:36 + --> $DIR/where-allowed.rs:221:36 | LL | enum InEnumGenericParamDefault { Variant(T) } | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:224:38 + --> $DIR/where-allowed.rs:225:38 | LL | trait InTraitGenericParamDefault {} | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:228:41 + --> $DIR/where-allowed.rs:229:41 | LL | type InTypeAliasGenericParamDefault = T; | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:232:11 + --> $DIR/where-allowed.rs:233:11 | LL | impl T {} | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type - --> $DIR/where-allowed.rs:239:40 + --> $DIR/where-allowed.rs:240:40 | LL | fn in_method_generic_param_default(_: T) {} | ^^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding - --> $DIR/where-allowed.rs:245:29 + --> $DIR/where-allowed.rs:246:29 | LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in closure return - --> $DIR/where-allowed.rs:247:46 + --> $DIR/where-allowed.rs:248:46 | LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; | ^^^^^^^^^ error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:232:7 + --> $DIR/where-allowed.rs:233:7 | LL | impl T {} | ^^^^^^^^^^^^^^ @@ -294,7 +294,7 @@ LL | impl T {} = note: `#[deny(invalid_type_param_default)]` on by default error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:239:36 + --> $DIR/where-allowed.rs:240:36 | LL | fn in_method_generic_param_default(_: T) {} | ^^^^^^^^^^^^^^ @@ -303,7 +303,7 @@ LL | fn in_method_generic_param_default(_: T) {} = note: for more information, see issue #36887 error[E0118]: no nominal type found for inherent implementation - --> $DIR/where-allowed.rs:232:23 + --> $DIR/where-allowed.rs:233:23 | LL | impl T {} | ^ impl requires a nominal type From 690e0370081d39c2a4c459e5fd74a6e3728b73a9 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 29 Jul 2022 02:28:36 +0400 Subject: [PATCH 16/20] add a test for gate `impl_trait_in_fn_trait_return` --- .../feature-gate-impl_trait_in_fn_trait_return.rs | 6 ++++++ ...ture-gate-impl_trait_in_fn_trait_return.stderr | 15 +++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs create mode 100644 src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs new file mode 100644 index 0000000000000..0db8088f7eea4 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs @@ -0,0 +1,6 @@ +fn f() -> impl Fn() -> impl Sized { || () } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return +fn g() -> &'static dyn Fn() -> impl Sized { &|| () } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr new file mode 100644 index 0000000000000..c485bc5c3ab90 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr @@ -0,0 +1,15 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return + --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:1:24 + | +LL | fn f() -> impl Fn() -> impl Sized { || () } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return + --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32 + | +LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () } + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0562`. From e93982a78fc7725f4fd01c39b2c48b6a2028893f Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 25 Oct 2022 13:47:43 +0000 Subject: [PATCH 17/20] adopt to compiler changes --- compiler/rustc_ast_lowering/src/path.rs | 2 +- .../impl-fn-predefined-lifetimes.rs | 4 ++- .../impl-fn-predefined-lifetimes.stderr | 25 +++++++++++++------ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index b7cda13fa4b70..c6955741fd4c2 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -346,7 +346,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_parenthesized_parameter_data( &mut self, data: &ParenthesizedArgs, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> (GenericArgsCtor<'hir>, bool) { // Switch to `PassThrough` mode for anonymous lifetimes; this // means that we permit things like `&Ref`, where `Ref` has diff --git a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs index 5e2379b2f9af6..1577866237544 100644 --- a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs +++ b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -2,8 +2,10 @@ use std::fmt::Debug; fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { - //~^ ERROR hidden type for `impl Debug` captures lifetime that does not appear in bounds + //~^ ERROR cannot resolve opaque type + |x| x + //~^ ERROR concrete type differs from previous defining opaque type use } fn _b<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) { diff --git a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index 1247ffad7c324..7747319c1539b 100644 --- a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -1,15 +1,24 @@ -error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds - --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 +error: concrete type differs from previous defining opaque type use + --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 | -LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { - | ^^^^^^^^^^^^^^^ +LL | |x| x + | ^ expected `impl Debug + '_`, got `&u8` | -note: hidden type `&' u8` captures lifetime smaller than the function body +note: previous use here + --> $DIR/impl-fn-predefined-lifetimes.rs:7:5 + | +LL | |x| x + | ^^^^^ + +error[E0720]: cannot resolve opaque type --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 | LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ recursive opaque type +... +LL | |x| x + | ----- returning here with type `[closure@$DIR/impl-fn-predefined-lifetimes.rs:7:5: 7:8]` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0700`. +For more information about this error, try `rustc --explain E0720`. From bfac2daef9912244d8a913a57b83c4e1b485993d Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 26 Oct 2022 22:07:56 +0100 Subject: [PATCH 18/20] Ignore test on mingw32 --- src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile b/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile index 24d9742aef0b0..50fca7f24e616 100644 --- a/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile +++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile @@ -1,3 +1,8 @@ +# ignore-i686-pc-windows-gnu + +# This test doesn't work on 32-bit MinGW as cdylib has its own copy of unwinder +# so cross-DLL unwinding does not work. + include ../tools.mk all: From 92b314ba30c396fab7e4ffeabf3ebf3f6101516a Mon Sep 17 00:00:00 2001 From: Rageking8 Date: Fri, 21 Oct 2022 18:37:35 +0800 Subject: [PATCH 19/20] add test for issue 98634 --- src/test/ui/async-await/issue-98634.rs | 50 ++++++++++++++++++ src/test/ui/async-await/issue-98634.stderr | 60 ++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 src/test/ui/async-await/issue-98634.rs create mode 100644 src/test/ui/async-await/issue-98634.stderr diff --git a/src/test/ui/async-await/issue-98634.rs b/src/test/ui/async-await/issue-98634.rs new file mode 100644 index 0000000000000..b0d38687f01c4 --- /dev/null +++ b/src/test/ui/async-await/issue-98634.rs @@ -0,0 +1,50 @@ +// edition: 2021 + +use std::{ + future::Future, + pin::Pin, + task::{Context, Poll, Waker}, +}; + +pub struct StructAsync Pin>>> { + pub callback: F, +} + +impl Future for StructAsync +where + F: Fn() -> Pin>>, +{ + type Output = (); + + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + +async fn callback() {} + +struct Runtime; + +fn waker() -> &'static Waker { + todo!() +} + +impl Runtime { + #[track_caller] + pub fn block_on(&self, mut future: F) -> F::Output { + loop { + unsafe { + Pin::new_unchecked(&mut future).poll(&mut Context::from_waker(waker())); + } + } + } +} + +fn main() { + Runtime.block_on(async { + StructAsync { callback }.await; + //~^ ERROR expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + //~| ERROR expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + //~| ERROR expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + }); +} diff --git a/src/test/ui/async-await/issue-98634.stderr b/src/test/ui/async-await/issue-98634.stderr new file mode 100644 index 0000000000000..5160e48d88afd --- /dev/null +++ b/src/test/ui/async-await/issue-98634.stderr @@ -0,0 +1,60 @@ +error[E0271]: expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + --> $DIR/issue-98634.rs:45:23 + | +LL | StructAsync { callback }.await; + | ^^^^^^^^ expected struct `Pin`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-98634.rs:24:21 + | +LL | async fn callback() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected struct `Pin + 'static)>>` + found opaque type `impl Future` +note: required by a bound in `StructAsync` + --> $DIR/issue-98634.rs:9:35 + | +LL | pub struct StructAsync Pin>>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync` + +error[E0271]: expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + --> $DIR/issue-98634.rs:45:9 + | +LL | StructAsync { callback }.await; + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-98634.rs:24:21 + | +LL | async fn callback() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected struct `Pin + 'static)>>` + found opaque type `impl Future` +note: required by a bound in `StructAsync` + --> $DIR/issue-98634.rs:9:35 + | +LL | pub struct StructAsync Pin>>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync` + +error[E0271]: expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + --> $DIR/issue-98634.rs:45:33 + | +LL | StructAsync { callback }.await; + | ^^^^^^ expected struct `Pin`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-98634.rs:24:21 + | +LL | async fn callback() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected struct `Pin + 'static)>>` + found opaque type `impl Future` +note: required by a bound in `StructAsync` + --> $DIR/issue-98634.rs:9:35 + | +LL | pub struct StructAsync Pin>>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0271`. From b3f9277a17e455d51b1c8c88f56e224e37b4159c Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 28 Oct 2022 14:17:34 +0200 Subject: [PATCH 20/20] Remove unneeded attribute. --- library/core/src/ffi/c_str.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 9f7c960d88feb..8923f548adf72 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -250,7 +250,6 @@ impl CStr { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")] - #[rustc_allow_const_fn_unstable(const_eval_select)] pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { // SAFETY: The caller has provided a pointer that points to a valid C // string with a NUL terminator of size less than `isize::MAX`, whose