diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index be5b247bb9f0b..8946ac43bc65a 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -824,7 +824,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( } ty => unreachable!("bswap {}", ty), } - }; + } let res = CValue::by_val(swap(&mut fx.bcx, arg), fx.layout_of(T)); ret.write_cvalue(fx, res); }; diff --git a/compiler/rustc_error_codes/src/error_codes/E0373.md b/compiler/rustc_error_codes/src/error_codes/E0373.md index fd96987793115..effa597aad918 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0373.md +++ b/compiler/rustc_error_codes/src/error_codes/E0373.md @@ -50,3 +50,24 @@ fn foo() -> Box u32> { Now that the closure has its own copy of the data, there's no need to worry about safety. + +This error may also be encountered while using `async` blocks: + +```compile_fail,E0373,edition2018 +use std::future::Future; + +async fn f() { + let v = vec![1, 2, 3i32]; + spawn(async { //~ ERROR E0373 + println!("{:?}", v) + }); +} + +fn spawn(future: F) { + unimplemented!() +} +``` + +Similarly to closures, `async` blocks are not executed immediately and may +capture closed-over data by reference. For more information, see +https://rust-lang.github.io/async-book/03_async_await/01_chapter.html. diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index db02ee67910b2..0fda20cbb0884 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -1318,21 +1318,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Applicability::MachineApplicable, ); - let msg = match category { + match category { ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => { - format!("{} is returned here", kind) + let msg = format!("{} is returned here", kind); + err.span_note(constraint_span, &msg); } ConstraintCategory::CallArgument => { fr_name.highlight_region_name(&mut err); - format!("function requires argument type to outlive `{}`", fr_name) + if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) { + err.note( + "async blocks are not executed immediately and must either take a \ + reference or ownership of outside variables they use", + ); + } else { + let msg = format!("function requires argument type to outlive `{}`", fr_name); + err.span_note(constraint_span, &msg); + } } _ => bug!( "report_escaping_closure_capture called with unexpected constraint \ category: `{:?}`", category ), - }; - err.span_note(constraint_span, &msg); + } + err } diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 76051d9e1dffd..4dfdbe0a5b45b 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -630,10 +630,16 @@ impl BinaryHeap { // and about 2 * (len1 + len2) comparisons in the worst case // while `extend` takes O(len2 * log(len1)) operations // and about 1 * len2 * log_2(len1) comparisons in the worst case, - // assuming len1 >= len2. + // assuming len1 >= len2. For larger heaps, the crossover point + // no longer follows this reasoning and was determined empirically. #[inline] fn better_to_rebuild(len1: usize, len2: usize) -> bool { - 2 * (len1 + len2) < len2 * log2_fast(len1) + let tot_len = len1 + len2; + if tot_len <= 2048 { + 2 * tot_len < len2 * log2_fast(len1) + } else { + 2 * tot_len < len2 * 11 + } } if better_to_rebuild(self.len(), other.len()) { diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index c5ab7a39ff0ca..fa0fbaa35c95c 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1261,6 +1261,40 @@ impl<'b, T: ?Sized> Ref<'b, T> { Ref { value: f(orig.value), borrow: orig.borrow } } + /// Makes a new `Ref` for an optional component of the borrowed data. The + /// original guard is returned as an `Err(..)` if the closure returns + /// `None`. + /// + /// The `RefCell` is already immutably borrowed, so this cannot fail. + /// + /// This is an associated function that needs to be used as + /// `Ref::filter_map(...)`. A method would interfere with methods of the same + /// name on the contents of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_filter_map)] + /// + /// use std::cell::{RefCell, Ref}; + /// + /// let c = RefCell::new(vec![1, 2, 3]); + /// let b1: Ref> = c.borrow(); + /// let b2: Result, _> = Ref::filter_map(b1, |v| v.get(1)); + /// assert_eq!(*b2.unwrap(), 2); + /// ``` + #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "81061")] + #[inline] + pub fn filter_map(orig: Ref<'b, T>, f: F) -> Result, Self> + where + F: FnOnce(&T) -> Option<&U>, + { + match f(orig.value) { + Some(value) => Ok(Ref { value, borrow: orig.borrow }), + None => Err(orig), + } + } + /// Splits a `Ref` into multiple `Ref`s for different components of the /// borrowed data. /// @@ -1372,6 +1406,58 @@ impl<'b, T: ?Sized> RefMut<'b, T> { RefMut { value: f(value), borrow } } + /// Makes a new `RefMut` for an optional component of the borrowed data. The + /// original guard is returned as an `Err(..)` if the closure returns + /// `None`. + /// + /// The `RefCell` is already mutably borrowed, so this cannot fail. + /// + /// This is an associated function that needs to be used as + /// `RefMut::filter_map(...)`. A method would interfere with methods of the + /// same name on the contents of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_filter_map)] + /// + /// use std::cell::{RefCell, RefMut}; + /// + /// let c = RefCell::new(vec![1, 2, 3]); + /// + /// { + /// let b1: RefMut> = c.borrow_mut(); + /// let mut b2: Result, _> = RefMut::filter_map(b1, |v| v.get_mut(1)); + /// + /// if let Ok(mut b2) = b2 { + /// *b2 += 2; + /// } + /// } + /// + /// assert_eq!(*c.borrow(), vec![1, 4, 3]); + /// ``` + #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "81061")] + #[inline] + pub fn filter_map(orig: RefMut<'b, T>, f: F) -> Result, Self> + where + F: FnOnce(&mut T) -> Option<&mut U>, + { + // FIXME(nll-rfc#40): fix borrow-check + let RefMut { value, borrow } = orig; + let value = value as *mut T; + // SAFETY: function holds onto an exclusive reference for the duration + // of its call through `orig`, and the pointer is only de-referenced + // inside of the function call never allowing the exclusive reference to + // escape. + match f(unsafe { &mut *value }) { + Some(value) => Ok(RefMut { value, borrow }), + None => { + // SAFETY: same as above. + Err(RefMut { value: unsafe { &mut *value }, borrow }) + } + } + } + /// Splits a `RefMut` into multiple `RefMut`s for different components of the /// borrowed data. /// diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 6851f3fcd2fc7..42c9d9f0cc039 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -84,7 +84,7 @@ impl Poll> { impl Poll>> { /// Changes the success value of this `Poll` with the closure provided. - #[unstable(feature = "poll_map", issue = "63514")] + #[stable(feature = "poll_map", since = "1.51.0")] pub fn map_ok(self, f: F) -> Poll>> where F: FnOnce(T) -> U, @@ -98,7 +98,7 @@ impl Poll>> { } /// Changes the error value of this `Poll` with the closure provided. - #[unstable(feature = "poll_map", issue = "63514")] + #[stable(feature = "poll_map", since = "1.51.0")] pub fn map_err(self, f: F) -> Poll>> where F: FnOnce(E) -> U, diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index ec9ce4c820c69..62065e27dd966 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -814,12 +814,22 @@ impl<'a> Builder<'a> { cargo.env("REAL_LIBRARY_PATH", e); } + // Found with `rg "init_env_logger\("`. If anyone uses `init_env_logger` + // from out of tree it shouldn't matter, since x.py is only used for + // building in-tree. + let color_logs = ["RUSTDOC_LOG_COLOR", "RUSTC_LOG_COLOR", "RUST_LOG_COLOR"]; match self.build.config.color { Color::Always => { cargo.arg("--color=always"); + for log in &color_logs { + cargo.env(log, "always"); + } } Color::Never => { cargo.arg("--color=never"); + for log in &color_logs { + cargo.env(log, "never"); + } } Color::Auto => {} // nothing to do } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 545f432def5a7..cafb65bc7f9cb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -219,7 +219,6 @@ impl Clean for CrateNum { impl Clean for doctree::Module<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let mut items: Vec = vec![]; - items.extend(self.imports.iter().flat_map(|x| x.clean(cx))); items.extend(self.foreigns.iter().map(|x| x.clean(cx))); items.extend(self.mods.iter().map(|x| x.clean(cx))); items.extend(self.items.iter().map(|x| x.clean(cx)).flatten()); @@ -2015,7 +2014,7 @@ impl Clean> for (&hir::Item<'_>, Option) { ItemKind::Fn(ref sig, ref generics, body_id) => { clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) } - hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => { + ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => { let items = item_ids .iter() .map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx)) @@ -2034,6 +2033,9 @@ impl Clean> for (&hir::Item<'_>, Option) { ItemKind::ExternCrate(orig_name) => { return clean_extern_crate(item, name, orig_name, cx); } + ItemKind::Use(path, kind) => { + return clean_use_statement(item, name, path, kind, cx); + } _ => unreachable!("not yet converted"), }; @@ -2155,105 +2157,97 @@ fn clean_extern_crate( }] } -impl Clean> for doctree::Import<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Vec { - // We need this comparison because some imports (for std types for example) - // are "inserted" as well but directly by the compiler and they should not be - // taken into account. - if self.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) { - return Vec::new(); - } - - let (doc_meta_item, please_inline) = self.attrs.lists(sym::doc).get_word_attr(sym::inline); - let pub_underscore = self.vis.node.is_pub() && self.name == kw::Underscore; - - if pub_underscore && please_inline { - rustc_errors::struct_span_err!( - cx.tcx.sess, - doc_meta_item.unwrap().span(), - E0780, - "anonymous imports cannot be inlined" - ) - .span_label(self.span, "anonymous import") - .emit(); - } +fn clean_use_statement( + import: &hir::Item<'_>, + name: Symbol, + path: &hir::Path<'_>, + kind: hir::UseKind, + cx: &DocContext<'_>, +) -> Vec { + // We need this comparison because some imports (for std types for example) + // are "inserted" as well but directly by the compiler and they should not be + // taken into account. + if import.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) { + return Vec::new(); + } + + let (doc_meta_item, please_inline) = import.attrs.lists(sym::doc).get_word_attr(sym::inline); + let pub_underscore = import.vis.node.is_pub() && name == kw::Underscore; + + if pub_underscore && please_inline { + rustc_errors::struct_span_err!( + cx.tcx.sess, + doc_meta_item.unwrap().span(), + E0780, + "anonymous imports cannot be inlined" + ) + .span_label(import.span, "anonymous import") + .emit(); + } - // We consider inlining the documentation of `pub use` statements, but we - // forcefully don't inline if this is not public or if the - // #[doc(no_inline)] attribute is present. - // Don't inline doc(hidden) imports so they can be stripped at a later stage. - let mut denied = !self.vis.node.is_pub() - || pub_underscore - || self.attrs.iter().any(|a| { - a.has_name(sym::doc) - && match a.meta_item_list() { - Some(l) => { - attr::list_contains_name(&l, sym::no_inline) - || attr::list_contains_name(&l, sym::hidden) - } - None => false, + // We consider inlining the documentation of `pub use` statements, but we + // forcefully don't inline if this is not public or if the + // #[doc(no_inline)] attribute is present. + // Don't inline doc(hidden) imports so they can be stripped at a later stage. + let mut denied = !import.vis.node.is_pub() + || pub_underscore + || import.attrs.iter().any(|a| { + a.has_name(sym::doc) + && match a.meta_item_list() { + Some(l) => { + attr::list_contains_name(&l, sym::no_inline) + || attr::list_contains_name(&l, sym::hidden) } - }); - // Also check whether imports were asked to be inlined, in case we're trying to re-export a - // crate in Rust 2018+ - let path = self.path.clean(cx); - let inner = if self.glob { - if !denied { - let mut visited = FxHashSet::default(); - if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) { - return items; + None => false, } + }); + + // Also check whether imports were asked to be inlined, in case we're trying to re-export a + // crate in Rust 2018+ + let def_id = cx.tcx.hir().local_def_id(import.hir_id).to_def_id(); + let path = path.clean(cx); + let inner = if kind == hir::UseKind::Glob { + if !denied { + let mut visited = FxHashSet::default(); + if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) { + return items; } - Import::new_glob(resolve_use_source(cx, path), true) - } else { - let name = self.name; - if !please_inline { - if let Res::Def(DefKind::Mod, did) = path.res { - if !did.is_local() && did.index == CRATE_DEF_INDEX { - // if we're `pub use`ing an extern crate root, don't inline it unless we - // were specifically asked for it - denied = true; - } + } + Import::new_glob(resolve_use_source(cx, path), true) + } else { + if !please_inline { + if let Res::Def(DefKind::Mod, did) = path.res { + if !did.is_local() && did.index == CRATE_DEF_INDEX { + // if we're `pub use`ing an extern crate root, don't inline it unless we + // were specifically asked for it + denied = true; } } - if !denied { - let mut visited = FxHashSet::default(); + } + if !denied { + let mut visited = FxHashSet::default(); - if let Some(mut items) = inline::try_inline( + if let Some(mut items) = inline::try_inline( + cx, + cx.tcx.parent_module(import.hir_id).to_def_id(), + path.res, + name, + Some(import.attrs), + &mut visited, + ) { + items.push(Item::from_def_id_and_parts( + def_id, + None, + ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)), cx, - cx.tcx.parent_module(self.id).to_def_id(), - path.res, - name, - Some(self.attrs), - &mut visited, - ) { - items.push(Item { - name: None, - attrs: box self.attrs.clean(cx), - source: self.span.clean(cx), - def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(), - visibility: self.vis.clean(cx), - kind: box ImportItem(Import::new_simple( - self.name, - resolve_use_source(cx, path), - false, - )), - }); - return items; - } + )); + return items; } - Import::new_simple(name, resolve_use_source(cx, path), true) - }; + } + Import::new_simple(name, resolve_use_source(cx, path), true) + }; - vec![Item { - name: None, - attrs: box self.attrs.clean(cx), - source: self.span.clean(cx), - def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(), - visibility: self.vis.clean(cx), - kind: box ImportItem(inner), - }] - } + vec![Item::from_def_id_and_parts(def_id, None, ImportItem(inner), cx)] } impl Clean for (&hir::ForeignItem<'_>, Option) { diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index cf51162cfb52f..3de97f2dd2e59 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -500,6 +500,12 @@ crate fn make_test( } } + // Reset errors so that they won't be reported as compiler bugs when dropping the + // handler. Any errors in the tests will be reported when the test file is compiled, + // Note that we still need to cancel the errors above otherwise `DiagnosticBuilder` + // will panic on drop. + sess.span_diagnostic.reset_err_count(); + (found_main, found_extern_crate, found_macro) }) }); diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 4710c91f929bd..f90623c03118b 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -2,7 +2,6 @@ //! manner (and with prettier names) before cleaning. crate use self::StructType::*; -use rustc_ast as ast; use rustc_span::{self, Span, Symbol}; use rustc_hir as hir; @@ -11,7 +10,6 @@ crate struct Module<'hir> { crate name: Option, crate where_outer: Span, crate where_inner: Span, - crate imports: Vec>, crate mods: Vec>, crate id: hir::HirId, // (item, renamed) @@ -28,7 +26,6 @@ impl Module<'hir> { id: hir::CRATE_HIR_ID, where_outer: rustc_span::DUMMY_SP, where_inner: rustc_span::DUMMY_SP, - imports: Vec::new(), mods: Vec::new(), items: Vec::new(), foreigns: Vec::new(), @@ -48,17 +45,6 @@ crate enum StructType { Unit, } -#[derive(Debug)] -crate struct Import<'hir> { - crate name: Symbol, - crate id: hir::HirId, - crate vis: &'hir hir::Visibility<'hir>, - crate attrs: &'hir [ast::Attribute], - crate path: &'hir hir::Path<'hir>, - crate glob: bool, - crate span: Span, -} - crate fn struct_type_from_def(vdata: &hir::VariantData<'_>) -> StructType { match *vdata { hir::VariantData::Struct(..) => Plain, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index f701352c486ba..7d161ca3648cc 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -316,15 +316,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - om.imports.push(Import { - name, - id: item.hir_id, - vis: &item.vis, - attrs: &item.attrs, - path, - glob: is_glob, - span: item.span, - }); + om.items.push((item, renamed)) } hir::ItemKind::Mod(ref m) => { om.mods.push(self.visit_mod_contents( diff --git a/src/test/rustdoc-json/compare.py b/src/test/rustdoc-json/compare.py index b0c5b16a19700..6a921266336e0 100644 --- a/src/test/rustdoc-json/compare.py +++ b/src/test/rustdoc-json/compare.py @@ -7,6 +7,9 @@ # and then create `yourtest.expected` by stripping unnecessary details from `yourtest.json`. If # you're on windows, replace `\` with `/`. +# WARNING: The error messages produced by this may be misleading, in the case of list re-ordering +# it may point to apparently unrelated keys. + import copy import sys import json diff --git a/src/test/rustdoc-json/nested.expected b/src/test/rustdoc-json/nested.expected index 65bb0c5fa0367..80070e75f1e5e 100644 --- a/src/test/rustdoc-json/nested.expected +++ b/src/test/rustdoc-json/nested.expected @@ -41,8 +41,8 @@ "inner": { "is_crate": false, "items": [ - "0:7", - "0:4" + "0:4", + "0:7" ] }, "kind": "module", diff --git a/src/test/rustdoc-ui/issue-80992.rs b/src/test/rustdoc-ui/issue-80992.rs new file mode 100644 index 0000000000000..8983439bb64d3 --- /dev/null +++ b/src/test/rustdoc-ui/issue-80992.rs @@ -0,0 +1,11 @@ +// check-pass +// compile-flags:--test +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" + +pub fn test() -> Result<(), ()> { + //! ```compile_fail + //! fn test() -> Result< {} + //! ``` + Ok(()) +} diff --git a/src/test/rustdoc-ui/issue-80992.stdout b/src/test/rustdoc-ui/issue-80992.stdout new file mode 100644 index 0000000000000..1dd19f468274c --- /dev/null +++ b/src/test/rustdoc-ui/issue-80992.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/issue-80992.rs - test (line 7) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.rs b/src/test/ui/async-await/issues/issue-78938-async-block.rs new file mode 100644 index 0000000000000..36f7160198526 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-78938-async-block.rs @@ -0,0 +1,33 @@ +// edition:2018 + +use std::{sync::Arc, future::Future, pin::Pin, task::{Context, Poll}}; + +async fn f() { + let room_ref = Arc::new(Vec::new()); + + let gameloop_handle = spawn(async { //~ ERROR E0373 + game_loop(Arc::clone(&room_ref)) + }); + gameloop_handle.await; +} + +fn game_loop(v: Arc>) {} + +fn spawn(future: F) -> JoinHandle +where + F: Future + Send + 'static, + F::Output: Send + 'static, +{ + loop {} +} + +struct JoinHandle; + +impl Future for JoinHandle { + type Output = (); + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + loop {} + } +} + +fn main() {} diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.stderr b/src/test/ui/async-await/issues/issue-78938-async-block.stderr new file mode 100644 index 0000000000000..01ffc48d6542e --- /dev/null +++ b/src/test/ui/async-await/issues/issue-78938-async-block.stderr @@ -0,0 +1,21 @@ +error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function + --> $DIR/issue-78938-async-block.rs:8:39 + | +LL | let gameloop_handle = spawn(async { + | _______________________________________^ +LL | | game_loop(Arc::clone(&room_ref)) + | | -------- `room_ref` is borrowed here +LL | | }); + | |_____^ may outlive borrowed value `room_ref` + | + = note: async blocks are not executed immediately and must either take a reference or ownership of outside variables they use +help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword + | +LL | let gameloop_handle = spawn(async move { +LL | game_loop(Arc::clone(&room_ref)) +LL | }); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs b/src/test/ui/feature-gates/feature-gate-const_refs_to_cell.rs similarity index 100% rename from src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs rename to src/test/ui/feature-gates/feature-gate-const_refs_to_cell.rs diff --git a/src/test/ui/feature-gate-edition_macro_pats.rs b/src/test/ui/feature-gates/feature-gate-edition_macro_pats.rs similarity index 100% rename from src/test/ui/feature-gate-edition_macro_pats.rs rename to src/test/ui/feature-gates/feature-gate-edition_macro_pats.rs diff --git a/src/test/ui/feature-gate-edition_macro_pats.stderr b/src/test/ui/feature-gates/feature-gate-edition_macro_pats.stderr similarity index 100% rename from src/test/ui/feature-gate-edition_macro_pats.stderr rename to src/test/ui/feature-gates/feature-gate-edition_macro_pats.stderr diff --git a/src/test/ui/wasm/wasm-hang-issue-76281.rs b/src/test/ui/wasm/wasm-hang-issue-76281.rs new file mode 100644 index 0000000000000..a4adfa6d04461 --- /dev/null +++ b/src/test/ui/wasm/wasm-hang-issue-76281.rs @@ -0,0 +1,12 @@ +// only-wasm32 +// compile-flags: -C opt-level=2 +// build-pass + +// Regression test for #76281. +// This seems like an issue related to LLVM rather than +// libs-impl so place here. + +fn main() { + let mut v: Vec<&()> = Vec::new(); + v.sort_by_key(|&r| r as *const ()); +}