diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 2bef4c9122456..3edb832b9a09b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1527,6 +1527,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { generics, body.as_deref(), ); + walk_list!(self, visit_attribute, &item.attrs); self.visit_fn(kind, item.span, item.id); } AssocItemKind::Type(_) => { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index cc8b8f72cf359..a12f939ff2686 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -119,7 +119,9 @@ pub fn predicates_for_generics<'tcx>( /// Determines whether the type `ty` is known to meet `bound` and /// returns true if so. Returns false if `ty` either does not meet -/// `bound` or is not known to meet bound. +/// `bound` or is not known to meet bound (note that this is +/// conservative towards *no impl*, which is the opposite of the +/// `evaluate` methods). pub fn type_known_to_meet_bound_modulo_regions<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -127,8 +129,50 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( def_id: DefId, ) -> bool { let trait_ref = ty::TraitRef::new(infcx.tcx, def_id, [ty]); - let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, trait_ref); - infcx.predicate_must_hold_modulo_regions(&obligation) + pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref) +} + +/// FIXME(@lcnr): this function doesn't seem right and shouldn't exist? +/// +/// Ping me on zulip if you want to use this method and need help with finding +/// an appropriate replacement. +#[instrument(level = "debug", skip(infcx, param_env, pred), ret)] +fn pred_known_to_hold_modulo_regions<'tcx>( + infcx: &InferCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + pred: impl ToPredicate<'tcx>, +) -> bool { + let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, pred); + + let result = infcx.evaluate_obligation_no_overflow(&obligation); + debug!(?result); + + if result.must_apply_modulo_regions() { + true + } else if result.may_apply() { + // Sometimes obligations are ambiguous because the recursive evaluator + // is not smart enough, so we fall back to fulfillment when we're not certain + // that an obligation holds or not. Even still, we must make sure that + // the we do no inference in the process of checking this obligation. + let goal = infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env)); + infcx.probe(|_| { + let ocx = ObligationCtxt::new(infcx); + ocx.register_obligation(obligation); + + let errors = ocx.select_all_or_error(); + match errors.as_slice() { + // Only known to hold if we did no inference. + [] => infcx.shallow_resolve(goal) == goal, + + errors => { + debug!(?errors); + false + } + } + }) + } else { + false + } } #[instrument(level = "debug", skip(tcx, elaborated_env))] diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 6756b5dec2318..489a947c1a9fe 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -794,6 +794,9 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( let Some(clause) = clause.as_projection_clause() else { return ControlFlow::Continue(()); }; + if clause.projection_def_id() != obligation.predicate.def_id { + return ControlFlow::Continue(()); + } let is_match = selcx.infcx.probe(|_| selcx.match_projection_projections(obligation, clause, true)); diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 63654a453ddee..19c092c5ddf3f 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -13,6 +13,7 @@ pub trait SpannedTypeVisitor<'tcx> { fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> Self::Result; } +#[instrument(level = "trace", skip(tcx, visitor))] pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( tcx: TyCtxt<'tcx>, item: LocalDefId, @@ -36,7 +37,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( for (hir, ty) in hir_sig.inputs.iter().zip(ty_sig.inputs().iter()) { try_visit!(visitor.visit(hir.span, ty.map_bound(|x| *x))); } - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { + for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, pred)); } } @@ -54,7 +55,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // Associated types in traits don't necessarily have a type that we can visit try_visit!(visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())); } - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { + for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, pred)); } } @@ -76,7 +77,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( let ty = field.ty(tcx, args); try_visit!(visitor.visit(span, ty)); } - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { + for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, pred)); } } @@ -95,12 +96,12 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( _ => tcx.def_span(item), }; try_visit!(visitor.visit(span, tcx.type_of(item).instantiate_identity())); - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { + for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, pred)); } } DefKind::TraitAlias | DefKind::Trait => { - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { + for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, pred)); } } diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs index cf45b9c23962c..fee80c02d4a6f 100644 --- a/library/std/src/sys/pal/hermit/thread.rs +++ b/library/std/src/sys/pal/hermit/thread.rs @@ -2,7 +2,7 @@ use super::abi; use super::thread_local_dtor::run_dtors; -use crate::ffi::{CStr, CString}; +use crate::ffi::CStr; use crate::io; use crate::mem; use crate::num::NonZero; @@ -71,10 +71,6 @@ impl Thread { // nope } - pub fn get_name() -> Option { - None - } - #[inline] pub fn sleep(dur: Duration) { unsafe { diff --git a/library/std/src/sys/pal/itron/thread.rs b/library/std/src/sys/pal/itron/thread.rs index 814a102dd09ae..9c1387bf4083a 100644 --- a/library/std/src/sys/pal/itron/thread.rs +++ b/library/std/src/sys/pal/itron/thread.rs @@ -8,7 +8,7 @@ use super::{ }; use crate::{ cell::UnsafeCell, - ffi::{CStr, CString}, + ffi::CStr, hint, io, mem::ManuallyDrop, num::NonZero, @@ -204,10 +204,6 @@ impl Thread { // nope } - pub fn get_name() -> Option { - None - } - pub fn sleep(dur: Duration) { for timeout in dur2reltims(dur) { expect_success(unsafe { abi::dly_tsk(timeout) }, &"dly_tsk"); diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs index 77f68bf73348f..c797fde7fbdca 100644 --- a/library/std/src/sys/pal/sgx/thread.rs +++ b/library/std/src/sys/pal/sgx/thread.rs @@ -1,6 +1,6 @@ #![cfg_attr(test, allow(dead_code))] // why is this necessary? use super::unsupported; -use crate::ffi::{CStr, CString}; +use crate::ffi::CStr; use crate::io; use crate::num::NonZero; use crate::time::Duration; @@ -133,10 +133,6 @@ impl Thread { // which succeeds as-is with the SGX target. } - pub fn get_name() -> Option { - None - } - pub fn sleep(dur: Duration) { usercalls::wait_timeout(0, dur, || true); } diff --git a/library/std/src/sys/pal/teeos/thread.rs b/library/std/src/sys/pal/teeos/thread.rs index b76bcf9bbb0af..77f9040ead540 100644 --- a/library/std/src/sys/pal/teeos/thread.rs +++ b/library/std/src/sys/pal/teeos/thread.rs @@ -1,7 +1,7 @@ use core::convert::TryInto; use crate::cmp; -use crate::ffi::{CStr, CString}; +use crate::ffi::CStr; use crate::io; use crate::mem; use crate::num::NonZero; @@ -101,10 +101,6 @@ impl Thread { // contact the teeos rustzone team. } - pub fn get_name() -> Option { - None - } - /// only main thread could wait for sometime in teeos pub fn sleep(dur: Duration) { let sleep_millis = dur.as_millis(); diff --git a/library/std/src/sys/pal/uefi/thread.rs b/library/std/src/sys/pal/uefi/thread.rs index b3a4f9c53e36c..3d8fa27251f01 100644 --- a/library/std/src/sys/pal/uefi/thread.rs +++ b/library/std/src/sys/pal/uefi/thread.rs @@ -1,5 +1,5 @@ use super::unsupported; -use crate::ffi::{CStr, CString}; +use crate::ffi::CStr; use crate::io; use crate::num::NonZero; use crate::ptr::NonNull; @@ -23,10 +23,6 @@ impl Thread { // nope } - pub fn get_name() -> Option { - None - } - pub fn sleep(dur: Duration) { let boot_services: NonNull = crate::os::uefi::env::boot_services().expect("can't sleep").cast(); diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 6520ca9fc48ef..865c19b73e0ae 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -1,5 +1,5 @@ use crate::cmp; -use crate::ffi::{CStr, CString}; +use crate::ffi::CStr; use crate::io; use crate::mem; use crate::num::NonZero; @@ -225,44 +225,6 @@ impl Thread { // Newlib, Emscripten, and VxWorks have no way to set a thread name. } - #[cfg(target_os = "linux")] - pub fn get_name() -> Option { - const TASK_COMM_LEN: usize = 16; - let mut name = vec![0u8; TASK_COMM_LEN]; - let res = unsafe { - libc::pthread_getname_np(libc::pthread_self(), name.as_mut_ptr().cast(), name.len()) - }; - if res != 0 { - return None; - } - name.truncate(name.iter().position(|&c| c == 0)?); - CString::new(name).ok() - } - - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] - pub fn get_name() -> Option { - let mut name = vec![0u8; libc::MAXTHREADNAMESIZE]; - let res = unsafe { - libc::pthread_getname_np(libc::pthread_self(), name.as_mut_ptr().cast(), name.len()) - }; - if res != 0 { - return None; - } - name.truncate(name.iter().position(|&c| c == 0)?); - CString::new(name).ok() - } - - #[cfg(not(any( - target_os = "linux", - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos" - )))] - pub fn get_name() -> Option { - None - } - #[cfg(not(target_os = "espidf"))] pub fn sleep(dur: Duration) { let mut secs = dur.as_secs(); diff --git a/library/std/src/sys/pal/unsupported/thread.rs b/library/std/src/sys/pal/unsupported/thread.rs index b3a91ee1d4cb6..cd1ae7f7d11cd 100644 --- a/library/std/src/sys/pal/unsupported/thread.rs +++ b/library/std/src/sys/pal/unsupported/thread.rs @@ -1,5 +1,5 @@ use super::unsupported; -use crate::ffi::{CStr, CString}; +use crate::ffi::CStr; use crate::io; use crate::num::NonZero; use crate::time::Duration; @@ -22,10 +22,6 @@ impl Thread { // nope } - pub fn get_name() -> Option { - None - } - pub fn sleep(_dur: Duration) { panic!("can't sleep"); } diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs index 4b116052f8f8e..77d8b4378e7d5 100644 --- a/library/std/src/sys/pal/wasi/thread.rs +++ b/library/std/src/sys/pal/wasi/thread.rs @@ -1,4 +1,4 @@ -use crate::ffi::{CStr, CString}; +use crate::ffi::CStr; use crate::io; use crate::mem; use crate::num::NonZero; @@ -134,10 +134,6 @@ impl Thread { // nope } - pub fn get_name() -> Option { - None - } - pub fn sleep(dur: Duration) { let nanos = dur.as_nanos(); assert!(nanos <= u64::MAX as u128); diff --git a/library/std/src/sys/pal/wasm/atomics/thread.rs b/library/std/src/sys/pal/wasm/atomics/thread.rs index 3923ff821d9d3..49f936f14498c 100644 --- a/library/std/src/sys/pal/wasm/atomics/thread.rs +++ b/library/std/src/sys/pal/wasm/atomics/thread.rs @@ -1,5 +1,4 @@ use crate::ffi::CStr; -use crate::ffi::CString; use crate::io; use crate::num::NonZero; use crate::sys::unsupported; @@ -18,9 +17,6 @@ impl Thread { pub fn yield_now() {} pub fn set_name(_name: &CStr) {} - pub fn get_name() -> Option { - None - } pub fn sleep(dur: Duration) { use crate::arch::wasm32; diff --git a/library/std/src/sys/pal/windows/thread.rs b/library/std/src/sys/pal/windows/thread.rs index 970bd9c6ce7e6..e74367d92af72 100644 --- a/library/std/src/sys/pal/windows/thread.rs +++ b/library/std/src/sys/pal/windows/thread.rs @@ -9,7 +9,6 @@ use crate::sys::handle::Handle; use crate::sys::stack_overflow; use crate::sys_common::FromInner; use crate::time::Duration; -use alloc::ffi::CString; use core::ffi::c_void; use super::time::WaitableTimer; @@ -68,29 +67,6 @@ impl Thread { }; } - pub fn get_name() -> Option { - unsafe { - let mut ptr = core::ptr::null_mut(); - let result = c::GetThreadDescription(c::GetCurrentThread(), &mut ptr); - if result < 0 { - return None; - } - let name = String::from_utf16_lossy({ - let mut len = 0; - while *ptr.add(len) != 0 { - len += 1; - } - core::slice::from_raw_parts(ptr, len) - }) - .into_bytes(); - // Attempt to free the memory. - // This should never fail but if it does then there's not much we can do about it. - let result = c::LocalFree(ptr.cast::()); - debug_assert!(result.is_null()); - if name.is_empty() { None } else { Some(CString::from_vec_unchecked(name)) } - } - } - pub fn join(self) { let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(), c::INFINITE) }; if rc == c::WAIT_FAILED { diff --git a/library/std/src/sys/pal/xous/thread.rs b/library/std/src/sys/pal/xous/thread.rs index f95ceb7343bd1..21f5954d6e2d2 100644 --- a/library/std/src/sys/pal/xous/thread.rs +++ b/library/std/src/sys/pal/xous/thread.rs @@ -1,4 +1,4 @@ -use crate::ffi::{CStr, CString}; +use crate::ffi::CStr; use crate::io; use crate::num::NonZero; use crate::os::xous::ffi::{ @@ -113,10 +113,6 @@ impl Thread { // nope } - pub fn get_name() -> Option { - None - } - pub fn sleep(dur: Duration) { // Because the sleep server works on units of `usized milliseconds`, split // the messages up into these chunks. This means we may run into issues diff --git a/library/std/src/sys_common/thread_info.rs b/library/std/src/sys_common/thread_info.rs index ec1428ea40ec6..8d51732e03588 100644 --- a/library/std/src/sys_common/thread_info.rs +++ b/library/std/src/sys_common/thread_info.rs @@ -1,7 +1,6 @@ #![allow(dead_code)] // stack_guard isn't used right now on all platforms use crate::cell::OnceCell; -use crate::sys; use crate::sys::thread::guard::Guard; use crate::thread::Thread; @@ -24,8 +23,7 @@ impl ThreadInfo { { THREAD_INFO .try_with(move |thread_info| { - let thread = - thread_info.thread.get_or_init(|| Thread::new(sys::thread::Thread::get_name())); + let thread = thread_info.thread.get_or_init(|| Thread::new(None)); f(thread, &thread_info.stack_guard) }) .ok() diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 589a5fdad1d7e..af649f9312615 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -69,26 +69,6 @@ fn test_named_thread_truncation() { result.unwrap().join().unwrap(); } -#[cfg(any( - all(target_os = "windows", not(target_vendor = "win7")), - target_os = "linux", - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos" -))] -#[test] -fn test_get_os_named_thread() { - use crate::sys::thread::Thread; - // Spawn a new thread to avoid interfering with other tests running on this thread. - let handler = thread::spawn(|| { - let name = c"test me please"; - Thread::set_name(name); - assert_eq!(name, Thread::get_name().unwrap().as_c_str()); - }); - handler.join().unwrap(); -} - #[test] #[should_panic] fn test_invalid_named_thread() { diff --git a/tests/ui/attributes/validation-on-associated-items-issue-121537.rs b/tests/ui/attributes/validation-on-associated-items-issue-121537.rs new file mode 100644 index 0000000000000..60e5a21eec774 --- /dev/null +++ b/tests/ui/attributes/validation-on-associated-items-issue-121537.rs @@ -0,0 +1,7 @@ +trait MyTrait { + #[doc = MyTrait] + //~^ ERROR attribute value must be a literal + fn myfun(); +} + +fn main() {} diff --git a/tests/ui/attributes/validation-on-associated-items-issue-121537.stderr b/tests/ui/attributes/validation-on-associated-items-issue-121537.stderr new file mode 100644 index 0000000000000..9c37bb8231790 --- /dev/null +++ b/tests/ui/attributes/validation-on-associated-items-issue-121537.stderr @@ -0,0 +1,8 @@ +error: attribute value must be a literal + --> $DIR/validation-on-associated-items-issue-121537.rs:2:13 + | +LL | #[doc = MyTrait] + | ^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/privacy/generic_struct_field_projection.rs b/tests/ui/privacy/generic_struct_field_projection.rs new file mode 100644 index 0000000000000..c5bb1233c27b9 --- /dev/null +++ b/tests/ui/privacy/generic_struct_field_projection.rs @@ -0,0 +1,38 @@ +//! To determine all the types that need to be private when looking at `Struct`, we +//! used to invoke `predicates_of` to also look at types in `where` bounds. +//! Unfortunately this also computes the inferred outlives bounds, which means for +//! every field we check that if it is of type `&'a T` then `T: 'a` and if it is of +//! struct type, we check that the struct satisfies its lifetime parameters by looking +//! at its inferred outlives bounds. This means we end up with a `::Assoc: 'a` +//! in the outlives bounds of `Struct`. While this is trivially provable, privacy +//! only sees `Foo` and `Trait` and determines that `Foo` is private and then errors. +//! So now we invoke `explicit_predicates_of` to make sure we only care about user-written +//! predicates. + +//@ check-pass + +mod baz { + struct Foo; + + pub trait Trait { + type Assoc; + } + + impl Trait for Foo { + type Assoc = (); + } + + pub struct Bar<'a, T: Trait> { + source: &'a T::Assoc, + } + + pub struct Baz<'a> { + mode: Bar<'a, Foo>, + } +} + +pub struct Struct<'a> { + lexer: baz::Baz<'a>, +} + +fn main() {} diff --git a/tests/ui/traits/make-sure-to-filter-projections-by-def-id.rs b/tests/ui/traits/make-sure-to-filter-projections-by-def-id.rs new file mode 100644 index 0000000000000..27a3aad733c22 --- /dev/null +++ b/tests/ui/traits/make-sure-to-filter-projections-by-def-id.rs @@ -0,0 +1,38 @@ +//@ check-pass + +#![recursion_limit = "1024"] +// Really high recursion limit ^ + +// Test that ensures we're filtering projections by def id before matching +// them in `match_projection_projections`. + +use std::ops::{Add, Sub}; + +pub trait Scalar {} + +pub trait VectorCommon: Sized { + type T: Scalar; +} + +pub trait VectorOpsByValue: + VectorCommon + Add + Sub +{ +} + +pub trait VectorView<'a>: + VectorOpsByValue + VectorOpsByValue +{ + type Owned; +} + +pub trait Vector: VectorOpsByValue + for<'a> VectorOpsByValue> { + type View<'a>: VectorView<'a, T = Self::T, Owned = Self> + where + Self: 'a; +} + +pub trait MatrixCommon { + type V: Vector; +} + +fn main() {} diff --git a/tests/ui/traits/pred-known-to-hold-modulo-regions-unsized-tail.rs b/tests/ui/traits/pred-known-to-hold-modulo-regions-unsized-tail.rs new file mode 100644 index 0000000000000..4e8c19d600d61 --- /dev/null +++ b/tests/ui/traits/pred-known-to-hold-modulo-regions-unsized-tail.rs @@ -0,0 +1,244 @@ +// This is a non-regression test for issues #108721 and its duplicate #123275 (hopefully, because +// the test is still convoluted and the ICE is fiddly). +// +// `pred_known_to_hold_modulo_regions` prevented "unexpected unsized tail" ICEs with warp/hyper but +// was unknowingly removed in #120463. + +//@ build-pass: the ICE happened in codegen + +use std::future::Future; +trait TryFuture: Future { + type Ok; +} +impl TryFuture for F +where + F: ?Sized + Future>, +{ + type Ok = T; +} +trait Executor {} +struct Exec {} +trait HttpBody { + type Data; +} +trait ConnStreamExec {} +impl ConnStreamExec for Exec where H2Stream: Send {} +impl ConnStreamExec for E where E: Executor {} +struct H2Stream { + _fut: F, +} +trait NewSvcExec> { + fn execute_new_svc(&mut self, _fut: NewSvcTask) { + unimplemented!() + } +} +impl NewSvcExec for Exec where W: Watcher {} +trait Watcher { + type Future; +} +struct NoopWatcher; +impl Watcher for NoopWatcher +where + S: HttpService, + E: ConnStreamExec, +{ + type Future = Option<<::ResBody as HttpBody>::Data>; +} +trait Service { + type Response; + type Future; +} +trait HttpService { + type ResBody: HttpBody; + type Future; +} +struct Body {} +impl HttpBody for Body { + type Data = String; +} +impl HttpService for S +where + S: Service<(), Response = ()>, +{ + type ResBody = Body; + type Future = S::Future; +} +trait MakeServiceRef { + type ResBody; + type Service: HttpService; +} +impl MakeServiceRef for T +where + T: for<'a> Service<&'a Target, Response = S, Future = F>, + S: HttpService, +{ + type Service = S; + type ResBody = S::ResBody; +} +fn make_service_fn(_f: F) -> MakeServiceFn +where + F: FnMut(&Target) -> Ret, + Ret: Future, +{ + unimplemented!() +} +struct MakeServiceFn { + _func: F, +} +impl<'t, F, Ret, Target, Svc> Service<&'t Target> for MakeServiceFn +where + F: FnMut(&Target) -> Ret, + Ret: Future>, +{ + type Response = Svc; + type Future = Option<()>; +} +struct AddrIncoming {} +struct Server { + _incoming: I, + _make_service: S, + _protocol: E, +} +impl Server +where + S: MakeServiceRef<(), ResBody = B>, + B: HttpBody, + E: ConnStreamExec<::Future>, + E: NewSvcExec, +{ + fn serve(&mut self) { + let fut = NewSvcTask::new(); + self._protocol.execute_new_svc(fut); + } +} +fn serve(_make_service: S) -> Server { + unimplemented!() +} +struct NewSvcTask> { + _state: State, +} +struct State> { + _fut: W::Future, +} +impl> NewSvcTask { + fn new() -> Self { + unimplemented!() + } +} +trait Filter { + type Extract; + type Future; + fn map(self, _fun: F) -> MapFilter + where + Self: Sized, + { + unimplemented!() + } + fn wrap_with(self, _wrapper: W) -> W::Wrapped + where + Self: Sized, + W: Wrap, + { + unimplemented!() + } +} +fn service(_filter: F) -> FilteredService +where + F: Filter, +{ + unimplemented!() +} +struct FilteredService { + _filter: F, +} +impl Service<()> for FilteredService +where + F: Filter, +{ + type Response = (); + type Future = FilteredFuture; +} +struct FilteredFuture { + _fut: F, +} +struct MapFilter { + _filter: T, + _func: F, +} +impl Filter for MapFilter +where + T: Filter, + F: Func, +{ + type Extract = F::Output; + type Future = MapFilterFuture; +} +struct MapFilterFuture { + _extract: T::Future, + _func: F, +} +trait Wrap { + type Wrapped; +} +fn make_filter_fn(_func: F) -> FilterFn +where + F: Fn() -> U, +{ + unimplemented!() +} +struct FilterFn { + _func: F, +} +impl Filter for FilterFn +where + F: Fn() -> U, + U: TryFuture, + U::Ok: Send, +{ + type Extract = U::Ok; + type Future = Option; +} +fn trace(_func: F) -> Trace +where + F: Fn(), +{ + unimplemented!() +} +struct Trace { + _func: F, +} +impl Wrap for Trace { + type Wrapped = WithTrace; +} +struct WithTrace { + _filter: F, + _trace: FN, +} +impl Filter for WithTrace +where + F: Filter, +{ + type Extract = (); + type Future = (F::Future, fn(F::Extract)); +} +trait Func { + type Output; +} +impl Func<()> for F +where + F: Fn() -> R, +{ + type Output = R; +} +fn main() { + let make_service = make_service_fn(|_| { + let tracer = trace(|| unimplemented!()); + let filter = make_filter_fn(|| std::future::ready(Some(()))) + .map(|| "Hello, world") + .wrap_with(tracer); + let svc = service(filter); + std::future::ready(Some(svc)) + }); + let mut server = serve(make_service); + server.serve(); +}