diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 24e2985cf567a..77b7ee38bde04 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -16,7 +16,7 @@ use rustc_hir::def::Res; use rustc_hir::definitions::DefPathData; use rustc_session::errors::report_lit_error; use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; -use rustc_span::symbol::{kw, sym, Ident}; +use rustc_span::symbol::{sym, Ident}; use rustc_span::DUMMY_SP; use thin_vec::thin_vec; @@ -585,38 +585,14 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ExprKind<'hir> { let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span))); - // Resume argument type, which should be `&mut Context<'_>`. - // NOTE: Using the `'static` lifetime here is technically cheating. - // The `Future::poll` argument really is `&'a mut Context<'b>`, but we cannot - // express the fact that we are not storing it across yield-points yet, - // and we would thus run into lifetime errors. - // See . - // Our lowering makes sure we are not mis-using the `_task_context` input type - // in the sense that we are indeed not using it across yield points. We - // get a fresh `&mut Context` for each resume / call of `Future::poll`. - // This "cheating" was previously done with a `ResumeTy` that contained a raw - // pointer, and a `get_context` accessor that pulled the `Context` lifetimes - // out of thin air. - let context_lifetime_ident = Ident::with_dummy_span(kw::StaticLifetime); - let context_lifetime = self.arena.alloc(hir::Lifetime { - hir_id: self.next_id(), - ident: context_lifetime_ident, - res: hir::LifetimeName::Static, - }); - let context_path = - hir::QPath::LangItem(hir::LangItem::Context, self.lower_span(span), None); - let context_ty = hir::MutTy { - ty: self.arena.alloc(hir::Ty { - hir_id: self.next_id(), - kind: hir::TyKind::Path(context_path), - span: self.lower_span(span), - }), - mutbl: hir::Mutability::Mut, - }; + // Resume argument type: `ResumeTy` + let unstable_span = + self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); + let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span, None); let input_ty = hir::Ty { hir_id: self.next_id(), - kind: hir::TyKind::Rptr(context_lifetime, context_ty), - span: self.lower_span(span), + kind: hir::TyKind::Path(resume_ty), + span: unstable_span, }; // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`. @@ -674,9 +650,12 @@ impl<'hir> LoweringContext<'_, 'hir> { .map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))); let hir_id = self.lower_node_id(closure_node_id); - let unstable_span = - self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); if track_caller { + let unstable_span = self.mark_span_with_reason( + DesugaringKind::Async, + span, + self.allow_gen_future.clone(), + ); self.lower_attrs( hir_id, &[Attribute { @@ -719,7 +698,7 @@ impl<'hir> LoweringContext<'_, 'hir> { /// mut __awaitee => loop { /// match unsafe { ::std::future::Future::poll( /// <::std::pin::Pin>::new_unchecked(&mut __awaitee), - /// task_context, + /// ::std::future::get_context(task_context), /// ) } { /// ::std::task::Poll::Ready(result) => break result, /// ::std::task::Poll::Pending => {} @@ -760,7 +739,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // unsafe { // ::std::future::Future::poll( // ::std::pin::Pin::new_unchecked(&mut __awaitee), - // task_context, + // ::std::future::get_context(task_context), // ) // } let poll_expr = { @@ -778,10 +757,16 @@ impl<'hir> LoweringContext<'_, 'hir> { arena_vec![self; ref_mut_awaitee], Some(expr_hir_id), ); + let get_context = self.expr_call_lang_item_fn_mut( + gen_future_span, + hir::LangItem::GetContext, + arena_vec![self; task_context], + Some(expr_hir_id), + ); let call = self.expr_call_lang_item_fn( span, hir::LangItem::FuturePoll, - arena_vec![self; new_unchecked, task_context], + arena_vec![self; new_unchecked, get_context], Some(expr_hir_id), ); self.arena.alloc(self.expr_unsafe(call)) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 882430694e16d..fe2e4b36cd0f1 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -253,7 +253,7 @@ pub fn each_linked_rlib( }; for &cnum in crates { match fmts.get(cnum.as_usize() - 1) { - Some(&Linkage::NotLinked | &Linkage::IncludedFromDylib) => continue, + Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue, Some(_) => {} None => return Err(errors::LinkRlibError::MissingFormat), } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index b51257df713ea..038509031b180 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -286,9 +286,10 @@ language_item_table! { // FIXME(swatinem): the following lang items are used for async lowering and // should become obsolete eventually. + ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None; IdentityFuture, sym::identity_future, identity_future_fn, Target::Fn, GenericRequirement::None; + GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None; - Context, sym::Context, context, Target::Struct, GenericRequirement::None; FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6125384549723..9e446c96db319 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -165,7 +165,6 @@ symbols! { Capture, Center, Clone, - Context, Continue, Copy, Count, @@ -265,6 +264,7 @@ symbols! { Relaxed, Release, Result, + ResumeTy, Return, Right, Rust, @@ -754,6 +754,7 @@ symbols! { generic_associated_types_extended, generic_const_exprs, generic_param_attrs, + get_context, global_allocator, global_asm, globs, diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs index 6f0bbf0672d44..a0476d542e642 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi.rs +++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs @@ -104,6 +104,10 @@ pub fn target() -> Target { // `args::args()` makes the WASI API calls itself. options.main_needs_argc_argv = false; + // And, WASI mangles the name of "main" to distinguish between different + // signatures. + options.entry_name = "__main_void".into(); + Target { llvm_target: "wasm32-wasi".into(), pointer_width: 32, diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index 2a8e12fd4cf60..f2b961d62e00c 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -44,7 +44,7 @@ pub use poll_fn::{poll_fn, PollFn}; /// non-Send/Sync as well, and we don't want that. /// /// It also simplifies the HIR lowering of `.await`. -// FIXME(swatinem): This type can be removed when bumping the bootstrap compiler +#[cfg_attr(not(bootstrap), lang = "ResumeTy")] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] #[derive(Debug, Copy, Clone)] @@ -61,7 +61,6 @@ unsafe impl Sync for ResumeTy {} /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). // This is `const` to avoid extra errors after we recover from `const async fn` -// FIXME(swatinem): This fn can be removed when bumping the bootstrap compiler #[cfg_attr(bootstrap, lang = "from_generator")] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] @@ -103,8 +102,7 @@ where GenFuture(gen) } -// FIXME(swatinem): This fn can be removed when bumping the bootstrap compiler -#[cfg_attr(bootstrap, lang = "get_context")] +#[lang = "get_context"] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] #[must_use] @@ -115,10 +113,6 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { unsafe { &mut *cx.0.as_ptr().cast() } } -// FIXME(swatinem): This fn is currently needed to work around shortcomings -// in type and lifetime inference. -// See the comment at the bottom of `LoweringContext::make_async_expr` and -// . #[cfg_attr(not(bootstrap), lang = "identity_future")] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 9ab9b0ba1c797..0cff972df3a5a 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -174,7 +174,6 @@ impl RawWakerVTable { /// Currently, `Context` only serves to provide access to a [`&Waker`](Waker) /// which can be used to wake the current task. #[stable(feature = "futures_api", since = "1.36.0")] -#[cfg_attr(not(bootstrap), lang = "Context")] pub struct Context<'a> { waker: &'a Waker, // Ensure we future-proof against variance changes by forcing diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 5ce62224d35e5..1e1c657b0bf22 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -246,8 +246,6 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { _ => {} } } - let lines = origtext.lines().filter_map(|l| map_line(l).for_html()); - let text = lines.intersperse("\n".into()).collect::(); let parse_result = match kind { CodeBlockKind::Fenced(ref lang) => { @@ -260,7 +258,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> {
{}
\ ", lang, - Escape(&text), + Escape(&origtext), ) .into(), )); @@ -270,6 +268,9 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { CodeBlockKind::Indented => Default::default(), }; + let lines = origtext.lines().filter_map(|l| map_line(l).for_html()); + let text = lines.intersperse("\n".into()).collect::(); + compile_fail = parse_result.compile_fail; should_panic = parse_result.should_panic; ignore = parse_result.ignore; diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index e4f72a057892f..68b31a6ee083d 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -309,3 +309,40 @@ fn test_find_testable_code_line() { t("```rust\n```\n```rust\n```", &[1, 3]); t("```rust\n```\n ```rust\n```", &[1, 3]); } + +#[test] +fn test_ascii_with_prepending_hashtag() { + fn t(input: &str, expect: &str) { + let mut map = IdMap::new(); + let output = Markdown { + content: input, + links: &[], + ids: &mut map, + error_codes: ErrorCodes::Yes, + edition: DEFAULT_EDITION, + playground: &None, + heading_offset: HeadingOffset::H2, + } + .into_string(); + assert_eq!(output, expect, "original: {}", input); + } + + t( + r#"```ascii +#..#.####.#....#.....##.. +#..#.#....#....#....#..#. +####.###..#....#....#..#. +#..#.#....#....#....#..#. +#..#.#....#....#....#..#. +#..#.####.####.####..##.. +```"#, + "
\
+#..#.####.#....#.....##..
+#..#.#....#....#....#..#.
+####.###..#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.####.####.####..##..
+
", + ); +} diff --git a/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr b/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr index 616623ee07759..3be7f370da3f5 100644 --- a/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr +++ b/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr @@ -40,7 +40,7 @@ LL | async fn bar2(_: T) -> ! { LL | | panic!() LL | | } | |_^ - = note: required because it captures the following types: `&mut Context<'_>`, `Option`, `impl Future`, `()` + = note: required because it captures the following types: `ResumeTy`, `Option`, `impl Future`, `()` note: required because it's used within this `async fn` body --> $DIR/async-await-let-else.rs:21:32 | diff --git a/src/test/ui/async-await/issue-68112.drop_tracking.stderr b/src/test/ui/async-await/issue-68112.drop_tracking.stderr index 1c90bedae790c..f2802698fd5b6 100644 --- a/src/test/ui/async-await/issue-68112.drop_tracking.stderr +++ b/src/test/ui/async-await/issue-68112.drop_tracking.stderr @@ -57,7 +57,7 @@ note: required because it appears within the type `impl Future impl Future>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required because it captures the following types: `&mut Context<'_>`, `impl Future>>`, `()`, `Ready` + = note: required because it captures the following types: `ResumeTy`, `impl Future>>`, `()`, `Ready` note: required because it's used within this `async` block --> $DIR/issue-68112.rs:60:20 | diff --git a/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr b/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr index e09ae7fedd805..38eb85b302fd5 100644 --- a/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr +++ b/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr @@ -57,7 +57,7 @@ note: required because it appears within the type `impl Future impl Future>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required because it captures the following types: `&mut Context<'_>`, `impl Future>>`, `()`, `i32`, `Ready` + = note: required because it captures the following types: `ResumeTy`, `impl Future>>`, `()`, `i32`, `Ready` note: required because it's used within this `async` block --> $DIR/issue-68112.rs:60:20 | diff --git a/src/test/ui/async-await/issue-69446-fnmut-capture.stderr b/src/test/ui/async-await/issue-69446-fnmut-capture.stderr index e6ad2f0d444bb..3d2b0402bc52c 100644 --- a/src/test/ui/async-await/issue-69446-fnmut-capture.stderr +++ b/src/test/ui/async-await/issue-69446-fnmut-capture.stderr @@ -14,9 +14,6 @@ LL | | }); | = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape - = note: requirement occurs because of a mutable reference to `Context<'_>` - = note: mutable references are invariant over their type parameter - = help: see for more information about variance error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr index a8fd97cde8f7a..721234aa4a782 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr @@ -18,7 +18,7 @@ LL | async fn baz(_c: impl FnMut() -> T) where T: Future { | ___________________________________________________________________^ LL | | } | |_^ - = note: required because it captures the following types: `&mut Context<'_>`, `impl Future`, `()` + = note: required because it captures the following types: `ResumeTy`, `impl Future`, `()` note: required because it's used within this `async` block --> $DIR/issue-70935-complex-spans.rs:16:5 | diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr index 25876d5084015..17b4ef7bdc671 100644 --- a/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr +++ b/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr @@ -11,7 +11,7 @@ LL | async fn foo() { | = help: within `impl Future`, the trait `Send` is not implemented for `NotSend` = note: required because it appears within the type `(NotSend,)` - = note: required because it captures the following types: `&mut Context<'_>`, `(NotSend,)`, `()`, `impl Future` + = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `()`, `impl Future` note: required because it's used within this `async fn` body --> $DIR/partial-drop-partial-reinit.rs:31:16 | diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr index dba2a620779f0..34d8a159f1064 100644 --- a/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr +++ b/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr @@ -11,7 +11,7 @@ LL | async fn foo() { | = help: within `impl Future`, the trait `Send` is not implemented for `NotSend` = note: required because it appears within the type `(NotSend,)` - = note: required because it captures the following types: `&mut Context<'_>`, `(NotSend,)`, `impl Future`, `()` + = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `impl Future`, `()` note: required because it's used within this `async fn` body --> $DIR/partial-drop-partial-reinit.rs:31:16 | diff --git a/src/test/ui/lto/auxiliary/thinlto-dylib.rs b/src/test/ui/lto/auxiliary/thinlto-dylib.rs new file mode 100644 index 0000000000000..9d17c35dafc25 --- /dev/null +++ b/src/test/ui/lto/auxiliary/thinlto-dylib.rs @@ -0,0 +1,23 @@ +// Auxiliary crate for test issue-105637: the LTOed dylib which had duplicate symbols from libstd, +// breaking the panic hook feature. +// +// This simulates the `rustc_driver` crate, and the main crate simulates rustc's main binary hooking +// into this driver. + +// compile-flags: -Zdylib-lto -C lto=thin + +use std::panic; + +pub fn main() { + // Install the hook we want to see executed + panic::set_hook(Box::new(|_| { + eprintln!("LTOed auxiliary crate panic hook"); + })); + + // Trigger the panic hook with an ICE + run_compiler(); +} + +fn run_compiler() { + panic!("ICEing"); +} diff --git a/src/test/ui/lto/issue-105637.rs b/src/test/ui/lto/issue-105637.rs new file mode 100644 index 0000000000000..0d9f0bec00fd3 --- /dev/null +++ b/src/test/ui/lto/issue-105637.rs @@ -0,0 +1,28 @@ +// Regression test for issue #105637: `-Zdylib-lto` with LTO duplicated symbols from other dylibs, +// in this case from libstd. +// +// That manifested as both `rustc_driver` and rustc's "main" (`compiler/rustc`) having their own +// `std::panicking::HOOK` static, and the hook in rustc's main (the default stdlib's) being executed +// when rustc ICEs, instead of the overriden hook from `rustc_driver` (which also displays the query +// stack and information on how to open a GH issue for the encountered ICE). +// +// In this test, we reproduce this setup by installing a panic hook in both the main and an LTOed +// dylib: the last hook set should be the one being executed, the dylib's. + +// aux-build: thinlto-dylib.rs +// run-fail +// check-run-results + +extern crate thinlto_dylib; + +use std::panic; + +fn main() { + // We don't want to see this panic hook executed + std::panic::set_hook(Box::new(|_| { + eprintln!("main crate panic hook"); + })); + + // Have the LTOed dylib install its own hook and panic, we want to see its hook executed. + thinlto_dylib::main(); +} diff --git a/src/test/ui/lto/issue-105637.run.stderr b/src/test/ui/lto/issue-105637.run.stderr new file mode 100644 index 0000000000000..43388e7763ee2 --- /dev/null +++ b/src/test/ui/lto/issue-105637.run.stderr @@ -0,0 +1 @@ +LTOed auxiliary crate panic hook diff --git a/src/test/ui/regions/closure-in-projection-issue-97405.rs b/src/test/ui/regions/closure-in-projection-issue-97405.rs index 88b1c1396516d..e567d5c2723f2 100644 --- a/src/test/ui/regions/closure-in-projection-issue-97405.rs +++ b/src/test/ui/regions/closure-in-projection-issue-97405.rs @@ -22,11 +22,11 @@ fn good_generic_fn() { // This should fail because `T` ends up in the upvars of the closure. fn bad_generic_fn(t: T) { assert_static(opaque(async move { t; }).next()); - //~^ ERROR the parameter type `T` may not live long enough + //~^ ERROR the associated type `::Item` may not live long enough assert_static(opaque(move || { t; }).next()); //~^ ERROR the associated type `::Item` may not live long enough assert_static(opaque(opaque(async move { t; }).next()).next()); - //~^ ERROR the parameter type `T` may not live long enough + //~^ ERROR the associated type `::Item` may not live long enough } fn main() {} diff --git a/src/test/ui/regions/closure-in-projection-issue-97405.stderr b/src/test/ui/regions/closure-in-projection-issue-97405.stderr index 907964aaf379e..c08f1059ebf58 100644 --- a/src/test/ui/regions/closure-in-projection-issue-97405.stderr +++ b/src/test/ui/regions/closure-in-projection-issue-97405.stderr @@ -1,13 +1,11 @@ -error[E0310]: the parameter type `T` may not live long enough +error[E0310]: the associated type `::Item` may not live long enough --> $DIR/closure-in-projection-issue-97405.rs:24:5 | LL | assert_static(opaque(async move { t; }).next()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds - | -help: consider adding an explicit lifetime bound... + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | fn bad_generic_fn(t: T) { - | +++++++++ + = help: consider adding an explicit lifetime bound `::Item: 'static`... + = note: ...so that the type `::Item` will meet its required lifetime bounds error[E0310]: the associated type `::Item` may not live long enough --> $DIR/closure-in-projection-issue-97405.rs:26:5 @@ -18,16 +16,14 @@ LL | assert_static(opaque(move || { t; }).next()); = help: consider adding an explicit lifetime bound `::Item: 'static`... = note: ...so that the type `::Item` will meet its required lifetime bounds -error[E0310]: the parameter type `T` may not live long enough +error[E0310]: the associated type `::Item` may not live long enough --> $DIR/closure-in-projection-issue-97405.rs:28:5 | LL | assert_static(opaque(opaque(async move { t; }).next()).next()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds - | -help: consider adding an explicit lifetime bound... + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | fn bad_generic_fn(t: T) { - | +++++++++ + = help: consider adding an explicit lifetime bound `::Item: 'static`... + = note: ...so that the type `::Item` will meet its required lifetime bounds error: aborting due to 3 previous errors