diff options
| author | bors <bors@rust-lang.org> | 2019-07-05 11:53:52 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-07-05 11:53:52 +0000 |
| commit | 853f30052d019a8ebe197a5adff3a29d6716a955 (patch) | |
| tree | edea92c0e1ce6501e5c23fd5d9c2874f15623d79 | |
| parent | f119bf2761ab11ca577fac9881678c04d3e7fdb0 (diff) | |
| parent | 18081890ea7c4f3cb38d51be5ddea4f51dc262c3 (diff) | |
Auto merge of #62407 - Centril:rollup-g0zmff7, r=Centril
Rollup of 10 pull requests
Successful merges:
- #62123 ( Remove needless lifetimes (std))
- #62150 (Implement mem::{zeroed,uninitialized} in terms of MaybeUninit.)
- #62169 (Derive which queries to save using the proc macro)
- #62238 (Fix code block information icon position)
- #62292 (Move `async || ...` closures into `#![feature(async_closure)]`)
- #62323 (Clarify unaligned fields in ptr::{read,write}_unaligned)
- #62324 (Reduce reliance on `await!(...)` macro)
- #62371 (Add tracking issue for Box::into_pin)
- #62383 (Improve error span for async type inference error)
- #62388 (Break out of the correct number of scopes in loops)
Failed merges:
r? @ghost
77 files changed, 496 insertions, 281 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 41966360377..01dee0a3943 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -320,7 +320,7 @@ impl<T: ?Sized> Box<T> { /// This conversion does not allocate on the heap and happens in place. /// /// This is also available via [`From`]. - #[unstable(feature = "box_into_pin", issue = "0")] + #[unstable(feature = "box_into_pin", issue = "62370")] pub fn into_pin(boxed: Box<T>) -> Pin<Box<T>> { // It's not possible to move or replace the insides of a `Pin<Box<T>>` // when `T: !Unpin`, so it's safe to pin it directly without any diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index ca35600e857..d466948a017 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -2032,7 +2032,7 @@ impl<K, V> BTreeMap<K, V> { /// assert_eq!(keys, [1, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn keys<'a>(&'a self) -> Keys<'a, K, V> { + pub fn keys(&self) -> Keys<'_, K, V> { Keys { inner: self.iter() } } @@ -2053,7 +2053,7 @@ impl<K, V> BTreeMap<K, V> { /// assert_eq!(values, ["hello", "goodbye"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn values<'a>(&'a self) -> Values<'a, K, V> { + pub fn values(&self) -> Values<'_, K, V> { Values { inner: self.iter() } } @@ -2557,8 +2557,8 @@ enum UnderflowResult<'a, K, V> { Stole(NodeRef<marker::Mut<'a>, K, V, marker::Internal>), } -fn handle_underfull_node<'a, K, V>(node: NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>) - -> UnderflowResult<'a, K, V> { +fn handle_underfull_node<K, V>(node: NodeRef<marker::Mut<'_>, K, V, marker::LeafOrInternal>) + -> UnderflowResult<'_, K, V> { let parent = if let Ok(parent) = node.ascend() { parent } else { diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index 581c66c7086..7cf077d61d6 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -394,7 +394,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> { } /// Temporarily takes out another, immutable reference to the same node. - fn reborrow<'a>(&'a self) -> NodeRef<marker::Immut<'a>, K, V, Type> { + fn reborrow(&self) -> NodeRef<marker::Immut<'_>, K, V, Type> { NodeRef { height: self.height, node: self.node, diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 1b0d3c19692..366191e2c85 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -552,7 +552,7 @@ impl String { /// assert_eq!("Hello �World", output); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str> { + pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> { let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks(); let (first_valid, first_broken) = if let Some(chunk) = iter.next() { diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 8e53022c287..67430e5bbda 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -700,17 +700,15 @@ extern "rust-intrinsic" { /// which is unsafe unless `T` is `Copy`. Also, even if T is /// `Copy`, an all-zero value may not correspond to any legitimate /// state for the type in question. + #[unstable(feature = "core_intrinsics", + reason = "intrinsics are unlikely to ever be stabilized, instead \ + they should be used through stabilized interfaces \ + in the rest of the standard library", + issue = "0")] + #[rustc_deprecated(reason = "no longer used by rustc, will be removed - use MaybeUnint instead", + since = "1.38.0")] pub fn init<T>() -> T; - /// Creates an uninitialized value. - /// - /// `uninit` is unsafe because there is no guarantee of what its - /// contents are. In particular its drop-flag may be set to any - /// state, which means it may claim either dropped or - /// undropped. In the general case one must use `ptr::write` to - /// initialize memory previous set to the result of `uninit`. - pub fn uninit<T>() -> T; - /// Moves a value out of scope without running drop glue. pub fn forget<T: ?Sized>(_: T); diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index d9757d78dce..39c390b4df6 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -498,7 +498,7 @@ macro_rules! impls{ /// # end: *const T, /// # phantom: PhantomData<&'a T>, /// # } -/// fn borrow_vec<'a, T>(vec: &'a Vec<T>) -> Slice<'a, T> { +/// fn borrow_vec<T>(vec: &Vec<T>) -> Slice<'_, T> { /// let ptr = vec.as_ptr(); /// Slice { /// start: ptr, diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index b31522db474..b62d81affdd 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -450,8 +450,7 @@ pub const fn needs_drop<T>() -> bool { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn zeroed<T>() -> T { - intrinsics::panic_if_uninhabited::<T>(); - intrinsics::init() + MaybeUninit::zeroed().assume_init() } /// Bypasses Rust's normal memory-initialization checks by pretending to @@ -476,8 +475,7 @@ pub unsafe fn zeroed<T>() -> T { #[rustc_deprecated(since = "1.38.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn uninitialized<T>() -> T { - intrinsics::panic_if_uninhabited::<T>(); - intrinsics::uninit() + MaybeUninit::uninit().assume_init() } /// Swaps the values at two mutable locations, without deinitializing either one. diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs index 3158f58e958..9cff474a760 100644 --- a/src/libcore/ops/index.rs +++ b/src/libcore/ops/index.rs @@ -105,7 +105,7 @@ pub trait Index<Idx: ?Sized> { /// impl Index<Side> for Balance { /// type Output = Weight; /// -/// fn index<'a>(&'a self, index: Side) -> &'a Self::Output { +/// fn index(&self, index: Side) -> &Self::Output { /// println!("Accessing {:?}-side of balance immutably", index); /// match index { /// Side::Left => &self.left, @@ -115,7 +115,7 @@ pub trait Index<Idx: ?Sized> { /// } /// /// impl IndexMut<Side> for Balance { -/// fn index_mut<'a>(&'a mut self, index: Side) -> &'a mut Self::Output { +/// fn index_mut(&mut self, index: Side) -> &mut Self::Output { /// println!("Accessing {:?}-side of balance mutably", index); /// match index { /// Side::Left => &mut self.left, diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index da781d7e9fe..2a6c2b1331e 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -625,42 +625,50 @@ pub unsafe fn read<T>(src: *const T) -> T { /// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value /// [valid]: ../ptr/index.html#safety /// -/// # Examples +/// ## On `packed` structs /// -/// Access members of a packed struct by reference: +/// It is currently impossible to create raw pointers to unaligned fields +/// of a packed struct. /// -/// ``` -/// use std::ptr; +/// Attempting to create a raw pointer to an `unaligned` struct field with +/// an expression such as `&packed.unaligned as *const FieldType` creates an +/// intermediate unaligned reference before converting that to a raw pointer. +/// That this reference is temporary and immediately cast is inconsequential +/// as the compiler always expects references to be properly aligned. +/// As a result, using `&packed.unaligned as *const FieldType` causes immediate +/// *undefined behavior* in your program. /// +/// An example of what not to do and how this relates to `read_unaligned` is: +/// +/// ```no_run /// #[repr(packed, C)] /// struct Packed { /// _padding: u8, /// unaligned: u32, /// } /// -/// let x = Packed { +/// let packed = Packed { /// _padding: 0x00, /// unaligned: 0x01020304, /// }; /// /// let v = unsafe { -/// // Take the address of a 32-bit integer which is not aligned. -/// // This must be done as a raw pointer; unaligned references are invalid. -/// let unaligned = &x.unaligned as *const u32; -/// -/// // Dereferencing normally will emit an aligned load instruction, -/// // causing undefined behavior. -/// // let v = *unaligned; // ERROR +/// // Here we attempt to take the address of a 32-bit integer which is not aligned. +/// let unaligned = +/// // A temporary unaligned reference is created here which results in +/// // undefined behavior regardless of whether the reference is used or not. +/// &packed.unaligned +/// // Casting to a raw pointer doesn't help; the mistake already happened. +/// as *const u32; /// -/// // Instead, use `read_unaligned` to read improperly aligned values. -/// let v = ptr::read_unaligned(unaligned); +/// let v = std::ptr::read_unaligned(unaligned); /// /// v /// }; -/// -/// // Accessing unaligned values directly is safe. -/// assert!(x.unaligned == v); /// ``` +/// +/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however. +// FIXME: Update docs based on outcome of RFC #2582 and friends. #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] pub unsafe fn read_unaligned<T>(src: *const T) -> T { @@ -789,38 +797,48 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { /// /// [valid]: ../ptr/index.html#safety /// -/// # Examples +/// ## On `packed` structs /// -/// Access fields in a packed struct: +/// It is currently impossible to create raw pointers to unaligned fields +/// of a packed struct. /// -/// ``` -/// use std::{mem, ptr}; +/// Attempting to create a raw pointer to an `unaligned` struct field with +/// an expression such as `&packed.unaligned as *const FieldType` creates an +/// intermediate unaligned reference before converting that to a raw pointer. +/// That this reference is temporary and immediately cast is inconsequential +/// as the compiler always expects references to be properly aligned. +/// As a result, using `&packed.unaligned as *const FieldType` causes immediate +/// *undefined behavior* in your program. /// +/// An example of what not to do and how this relates to `write_unaligned` is: +/// +/// ```no_run /// #[repr(packed, C)] -/// #[derive(Default)] /// struct Packed { /// _padding: u8, /// unaligned: u32, /// } /// /// let v = 0x01020304; -/// let mut x: Packed = unsafe { mem::zeroed() }; -/// -/// unsafe { -/// // Take a reference to a 32-bit integer which is not aligned. -/// let unaligned = &mut x.unaligned as *mut u32; +/// let mut packed: Packed = unsafe { std::mem::zeroed() }; /// -/// // Dereferencing normally will emit an aligned store instruction, -/// // causing undefined behavior because the pointer is not aligned. -/// // *unaligned = v; // ERROR +/// let v = unsafe { +/// // Here we attempt to take the address of a 32-bit integer which is not aligned. +/// let unaligned = +/// // A temporary unaligned reference is created here which results in +/// // undefined behavior regardless of whether the reference is used or not. +/// &mut packed.unaligned +/// // Casting to a raw pointer doesn't help; the mistake already happened. +/// as *mut u32; /// -/// // Instead, use `write_unaligned` to write improperly aligned values. -/// ptr::write_unaligned(unaligned, v); -/// } +/// std::ptr::write_unaligned(unaligned, v); /// -/// // Accessing unaligned values directly is safe. -/// assert!(x.unaligned == v); +/// v +/// }; /// ``` +/// +/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however. +// FIXME: Update docs based on outcome of RFC #2582 and friends. #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) { diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index d2082ab87e7..442a90ab3f8 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -422,11 +422,6 @@ rustc_queries! { "const-evaluating `{}`", tcx.def_path_str(key.value.instance.def.def_id()) } - cache_on_disk_if(_, opt_result) { - // Only store results without errors - // FIXME: We never store these - opt_result.map_or(true, |r| r.is_ok()) - } } /// Results of evaluating const items or constants embedded in diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 85153f99b19..56c9474170c 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -201,28 +201,22 @@ impl<'sess> OnDiskCache<'sess> { let mut query_result_index = EncodedQueryResultIndex::new(); time(tcx.sess, "encode query results", || { - use crate::ty::query::queries::*; let enc = &mut encoder; let qri = &mut query_result_index; - encode_query_results::<type_of<'_>, _>(tcx, enc, qri)?; - encode_query_results::<generics_of<'_>, _>(tcx, enc, qri)?; - encode_query_results::<predicates_of<'_>, _>(tcx, enc, qri)?; - encode_query_results::<used_trait_imports<'_>, _>(tcx, enc, qri)?; - encode_query_results::<typeck_tables_of<'_>, _>(tcx, enc, qri)?; - encode_query_results::<codegen_fulfill_obligation<'_>, _>(tcx, enc, qri)?; - encode_query_results::<optimized_mir<'_>, _>(tcx, enc, qri)?; - encode_query_results::<unsafety_check_result<'_>, _>(tcx, enc, qri)?; - encode_query_results::<borrowck<'_>, _>(tcx, enc, qri)?; - encode_query_results::<mir_borrowck<'_>, _>(tcx, enc, qri)?; - encode_query_results::<mir_const_qualif<'_>, _>(tcx, enc, qri)?; - encode_query_results::<const_is_rvalue_promotable_to_static<'_>, _>(tcx, enc, qri)?; - encode_query_results::<symbol_name<'_>, _>(tcx, enc, qri)?; - encode_query_results::<check_match<'_>, _>(tcx, enc, qri)?; - encode_query_results::<codegen_fn_attrs<'_>, _>(tcx, enc, qri)?; - encode_query_results::<specialization_graph_of<'_>, _>(tcx, enc, qri)?; - encode_query_results::<const_eval<'_>, _>(tcx, enc, qri)?; - // FIXME: Include const_eval_raw? + macro_rules! encode_queries { + ($($query:ident,)*) => { + $( + encode_query_results::<ty::query::queries::$query<'_>, _>( + tcx, + enc, + qri + )?; + )* + } + } + + rustc_cached_queries!(encode_queries!); Ok(()) })?; diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 7831c200114..69f8356f669 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -234,7 +234,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { return; } // Effectively no-ops - "uninit" | "forget" => { + "forget" => { return; } "needs_drop" => { diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs index d47bd0580d6..a8df7e197a8 100644 --- a/src/librustc_macros/src/query.rs +++ b/src/librustc_macros/src/query.rs @@ -414,6 +414,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { let mut dep_node_force_stream = quote! {}; let mut try_load_from_on_disk_cache_stream = quote! {}; let mut no_force_queries = Vec::new(); + let mut cached_queries = quote! {}; for group in groups.0 { let mut group_stream = quote! {}; @@ -427,6 +428,12 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { _ => quote! { #result_full }, }; + if modifiers.cache.is_some() { + cached_queries.extend(quote! { + #name, + }); + } + if modifiers.cache.is_some() && !modifiers.no_force { try_load_from_on_disk_cache_stream.extend(quote! { DepKind::#name => { @@ -549,6 +556,12 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { } } } + macro_rules! rustc_cached_queries { + ($($macro:tt)*) => { + $($macro)*(#cached_queries); + } + } + #query_description_stream impl DepNode { diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index f831f5105a4..75c64bb2644 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -228,10 +228,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }; // Step 5. Create everything else: the guards and the arms. + let match_scope = self.scopes.topmost(); + let arm_end_blocks: Vec<_> = arm_candidates.into_iter().map(|(arm, mut candidates)| { let arm_source_info = self.source_info(arm.span); - let region_scope = (arm.scope, arm_source_info); - self.in_scope(region_scope, arm.lint_level, |this| { + let arm_scope = (arm.scope, arm_source_info); + self.in_scope(arm_scope, arm.lint_level, |this| { let body = this.hir.mirror(arm.body.clone()); let scope = this.declare_bindings( None, @@ -248,7 +250,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { arm.guard.clone(), &fake_borrow_temps, scrutinee_span, - region_scope, + match_scope, ); } else { arm_block = this.cfg.start_new_block(); @@ -259,7 +261,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { arm.guard.clone(), &fake_borrow_temps, scrutinee_span, - region_scope, + match_scope, ); this.cfg.terminate( binding_end, @@ -1339,7 +1341,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { guard: Option<Guard<'tcx>>, fake_borrows: &Vec<(&Place<'tcx>, Local)>, scrutinee_span: Span, - region_scope: (region::Scope, SourceInfo), + region_scope: region::Scope, ) -> BasicBlock { debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 80a035d8287..bdcde5b33dc 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -604,9 +604,18 @@ where } let arg_scope_s = (arg_scope, source_info); - unpack!(block = builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| { - builder.args_and_body(block, &arguments, arg_scope, &body.value) - })); + // `return_block` is called when we evaluate a `return` expression, so + // we just use `START_BLOCK` here. + unpack!(block = builder.in_breakable_scope( + None, + START_BLOCK, + Place::RETURN_PLACE, + |builder| { + builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| { + builder.args_and_body(block, &arguments, arg_scope, &body.value) + }) + }, + )); // Attribute epilogue to function's closing brace let fn_end = span.shrink_to_hi(); let source_info = builder.source_info(fn_end); @@ -860,11 +869,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } let body = self.hir.mirror(ast_body); - // `return_block` is called when we evaluate a `return` expression, so - // we just use `START_BLOCK` here. - self.in_breakable_scope(None, START_BLOCK, Place::RETURN_PLACE, |this| { - this.into(&Place::RETURN_PLACE, block, body) - }) + self.into(&Place::RETURN_PLACE, block, body) } fn get_unit_temp(&mut self) -> Place<'tcx> { diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 1b5fa1c9770..a74d5d7ab2d 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -332,9 +332,9 @@ impl<'tcx> Scopes<'tcx> { } } - fn num_scopes_to(&self, region_scope: (region::Scope, SourceInfo), span: Span) -> usize { - let scope_count = 1 + self.scopes.iter().rev() - .position(|scope| scope.region_scope == region_scope.0) + fn num_scopes_above(&self, region_scope: region::Scope, span: Span) -> usize { + let scope_count = self.scopes.iter().rev() + .position(|scope| scope.region_scope == region_scope) .unwrap_or_else(|| { span_bug!(span, "region_scope {:?} does not enclose", region_scope) }); @@ -354,7 +354,7 @@ impl<'tcx> Scopes<'tcx> { /// Returns the topmost active scope, which is known to be alive until /// the next scope expression. - fn topmost(&self) -> region::Scope { + pub(super) fn topmost(&self) -> region::Scope { self.scopes.last().expect("topmost_scope: no scopes present").region_scope } @@ -514,7 +514,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } else { assert!(value.is_none(), "`return` and `break` should have a destination"); } - self.exit_scope(source_info.span, (region_scope, source_info), block, target_block); + self.exit_scope(source_info.span, region_scope, block, target_block); self.cfg.start_new_block().unit() } @@ -523,12 +523,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// needed. See module comment for details. pub fn exit_scope(&mut self, span: Span, - region_scope: (region::Scope, SourceInfo), + region_scope: region::Scope, mut block: BasicBlock, target: BasicBlock) { debug!("exit_scope(region_scope={:?}, block={:?}, target={:?})", region_scope, block, target); - let scope_count = self.scopes.num_scopes_to(region_scope, span); + let scope_count = self.scopes.num_scopes_above(region_scope, span); // If we are emitting a `drop` statement, we need to have the cached // diverge cleanup pads ready in case that drop panics. @@ -545,7 +545,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { continue; } let source_info = scope.source_info(span); - block = match scope.cached_exits.entry((target, region_scope.0)) { + block = match scope.cached_exits.entry((target, region_scope)) { Entry::Occupied(e) => { self.cfg.terminate(block, source_info, TerminatorKind::Goto { target: *e.get() }); diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index 0bd078dace4..7e4768d81b8 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -75,7 +75,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { // If unresolved type isn't a ty_var then unresolved_type_span is None self.fcx.need_type_info_err_in_generator( self.kind, - unresolved_type_span.unwrap_or(yield_data.span), + unresolved_type_span.unwrap_or(source_span), unresolved_type, ) .span_note(yield_data.span, &*note) diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 9b1a8913822..82a736bf9c5 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -145,7 +145,6 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { "rustc_peek" => (1, vec![param(0)], param(0)), "panic_if_uninhabited" => (1, Vec::new(), tcx.mk_unit()), "init" => (1, Vec::new(), param(0)), - "uninit" => (1, Vec::new(), param(0)), "forget" => (1, vec![param(0)], tcx.mk_unit()), "transmute" => (2, vec![ param(0) ], param(1)), "move_val_init" => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8ae96d86657..2fe40f4e10b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -392,7 +392,7 @@ impl fmt::Debug for Item { impl Item { /// Finds the `doc` attribute as a NameValue and returns the corresponding /// value found. - pub fn doc_value<'a>(&'a self) -> Option<&'a str> { + pub fn doc_value(&self) -> Option<&str> { self.attrs.doc_value() } /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined @@ -699,11 +699,11 @@ impl<'a> Iterator for ListAttributesIter<'a> { pub trait AttributesExt { /// Finds an attribute as List and returns the list of attributes nested inside. - fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a>; + fn lists(&self, name: Symbol) -> ListAttributesIter<'_>; } impl AttributesExt for [ast::Attribute] { - fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a> { + fn lists(&self, name: Symbol) -> ListAttributesIter<'_> { ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), @@ -952,7 +952,7 @@ impl Attributes { /// Finds the `doc` attribute as a NameValue and returns the corresponding /// value found. - pub fn doc_value<'a>(&'a self) -> Option<&'a str> { + pub fn doc_value(&self) -> Option<&str> { self.doc_strings.first().map(|s| s.as_str()) } @@ -1037,7 +1037,7 @@ impl Hash for Attributes { } impl AttributesExt for Attributes { - fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a> { + fn lists(&self, name: Symbol) -> ListAttributesIter<'_> { self.other_attrs.lists(name) } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 2d6503c9445..2d69c29dfae 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2541,7 +2541,7 @@ fn full_path(cx: &Context, item: &clean::Item) -> String { s } -fn shorter<'a>(s: Option<&'a str>) -> String { +fn shorter(s: Option<&str>) -> String { match s { Some(s) => s.lines() .skip_while(|s| s.chars().all(|c| c.is_whitespace())) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 0493bf7c5c0..59704dace4d 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -146,6 +146,10 @@ img { max-width: 100%; } +li { + position: relative; +} + .source .content { margin-top: 50px; max-width: none; diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs index 2564c611e54..2da7aceae8b 100644 --- a/src/librustdoc/html/toc.rs +++ b/src/librustdoc/html/toc.rs @@ -119,7 +119,7 @@ impl TocBuilder { /// Push a level `level` heading into the appropriate place in the /// hierarchy, returning a string containing the section number in /// `<num>.<num>.<num>` format. - pub fn push<'a>(&'a mut self, level: u32, name: String, id: String) -> &'a str { + pub fn push(&mut self, level: u32, name: String, id: String) -> &str { assert!(level >= 1); // collapse all previous sections into their parents until we diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index b0a37ea9c80..50a647f244d 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -17,7 +17,7 @@ use crate::html::markdown::{ErrorCodes, IdMap, Markdown, MarkdownWithToc, find_t use crate::test::{TestOptions, Collector}; /// Separate any lines at the start of the file that begin with `# ` or `%`. -fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) { +fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) { let mut metadata = Vec::new(); let mut count = 0; diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index a7e7c09f9ae..726306d60ce 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -1031,7 +1031,7 @@ impl Json { /// If the Json value is an Object, returns the value associated with the provided key. /// Otherwise, returns None. - pub fn find<'a>(&'a self, key: &str) -> Option<&'a Json>{ + pub fn find(&self, key: &str) -> Option<&Json> { match *self { Json::Object(ref map) => map.get(key), _ => None @@ -1052,7 +1052,7 @@ impl Json { /// If the Json value is an Object, performs a depth-first search until /// a value associated with the provided key is found. If no value is found /// or the Json value is not an Object, returns `None`. - pub fn search<'a>(&'a self, key: &str) -> Option<&'a Json> { + pub fn search(&self, key: &str) -> Option<&Json> { match self { &Json::Object(ref map) => { match map.get(key) { diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs index f8fcd3ff5a5..fbe36d10517 100644 --- a/src/libstd/sync/mpsc/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -140,7 +140,7 @@ fn wait_timeout_receiver<'a, 'b, T>(lock: &'a Mutex<State<T>>, new_guard } -fn abort_selection<'a, T>(guard: &mut MutexGuard<'a , State<T>>) -> bool { +fn abort_selection<T>(guard: &mut MutexGuard<'_, State<T>>) -> bool { match mem::replace(&mut guard.blocker, NoneBlocked) { NoneBlocked => true, BlockedSender(token) => { diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index b3ef5f3064c..1f5c785f419 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -673,7 +673,7 @@ impl UnixListener { /// } /// ``` #[stable(feature = "unix_socket_redox", since = "1.29.0")] - pub fn incoming<'a>(&'a self) -> Incoming<'a> { + pub fn incoming(&self) -> Incoming<'_> { Incoming { listener: self } } } diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 41090caee84..42edd5dbbea 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -198,7 +198,7 @@ impl SocketAddr { } } - fn address<'a>(&'a self) -> AddressKind<'a> { + fn address(&self) -> AddressKind<'_> { let len = self.len as usize - sun_path_offset(&self.addr); let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; @@ -894,7 +894,7 @@ impl UnixListener { /// } /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn incoming<'a>(&'a self) -> Incoming<'a> { + pub fn incoming(&self) -> Incoming<'_> { Incoming { listener: self } } } diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 1cb55539129..36fb1fb5ff6 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -195,7 +195,7 @@ fn wide_char_to_multi_byte(code_page: u32, } } -pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] { +pub fn truncate_utf16_at_nul(v: &[u16]) -> &[u16] { match v.iter().position(|c| *c == 0) { // don't include the 0 Some(i) => &v[..i], diff --git a/src/libstd/sys/windows/path.rs b/src/libstd/sys/windows/path.rs index f3178a5e9e6..7eae28cb14f 100644 --- a/src/libstd/sys/windows/path.rs +++ b/src/libstd/sys/windows/path.rs @@ -19,7 +19,7 @@ pub fn is_verbatim_sep(b: u8) -> bool { b == b'\\' } -pub fn parse_prefix<'a>(path: &'a OsStr) -> Option<Prefix<'a>> { +pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> { use crate::path::Prefix::*; unsafe { // The unsafety here stems from converting between &OsStr and &[u8] diff --git a/src/libstd/sys_common/io.rs b/src/libstd/sys_common/io.rs index 44b0963302d..8789abe55c3 100644 --- a/src/libstd/sys_common/io.rs +++ b/src/libstd/sys_common/io.rs @@ -16,7 +16,7 @@ pub mod test { p.join(path) } - pub fn path<'a>(&'a self) -> &'a Path { + pub fn path(&self) -> &Path { let TempDir(ref p) = *self; p } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 4a0c957333b..ab61f77f5cb 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -31,6 +31,7 @@ use crate::tokenstream::TokenTree; use errors::{Applicability, DiagnosticBuilder, Handler}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sync::Lock; use rustc_target::spec::abi::Abi; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use log::debug; @@ -573,6 +574,9 @@ declare_features! ( // Allows `impl Trait` with multiple unrelated lifetimes. (active, member_constraints, "1.37.0", Some(61977), None), + // Allows `async || body` closures. + (active, async_closure, "1.37.0", Some(62290), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- @@ -2191,9 +2195,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "labels on blocks are unstable"); } } - ast::ExprKind::Closure(_, ast::IsAsync::Async { .. }, ..) => { - gate_feature_post!(&self, async_await, e.span, "async closures are unstable"); - } ast::ExprKind::Async(..) => { gate_feature_post!(&self, async_await, e.span, "async blocks are unstable"); } @@ -2527,6 +2528,10 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], features } +fn for_each_in_lock<T>(vec: &Lock<Vec<T>>, f: impl Fn(&T)) { + vec.borrow().iter().for_each(f); +} + pub fn check_crate(krate: &ast::Crate, sess: &ParseSess, features: &Features, @@ -2539,27 +2544,26 @@ pub fn check_crate(krate: &ast::Crate, plugin_attributes, }; - sess - .param_attr_spans - .borrow() - .iter() - .for_each(|span| gate_feature!( - &ctx, - param_attrs, - *span, - "attributes on function parameters are unstable" - )); - - sess - .let_chains_spans - .borrow() - .iter() - .for_each(|span| gate_feature!( - &ctx, - let_chains, - *span, - "`let` expressions in this position are experimental" - )); + for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!( + &ctx, + param_attrs, + *span, + "attributes on function parameters are unstable" + )); + + for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!( + &ctx, + let_chains, + *span, + "`let` expressions in this position are experimental" + )); + + for_each_in_lock(&sess.async_closure_spans, |span| gate_feature!( + &ctx, + async_closure, + *span, + "async closures are unstable" + )); let visitor = &mut PostExpansionVisitor { context: &ctx, diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 49f714e4e46..3717bb435f6 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1452,6 +1452,7 @@ mod tests { ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), param_attr_spans: Lock::new(Vec::new()), let_chains_spans: Lock::new(Vec::new()), + async_closure_spans: Lock::new(Vec::new()), } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index e19eab371f4..4056905d5dd 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -57,6 +57,8 @@ pub struct ParseSess { pub param_attr_spans: Lock<Vec<Span>>, // Places where `let` exprs were used and should be feature gated according to `let_chains`. pub let_chains_spans: Lock<Vec<Span>>, + // Places where `async || ..` exprs were used and should be feature gated. + pub async_closure_spans: Lock<Vec<Span>>, } impl ParseSess { @@ -84,6 +86,7 @@ impl ParseSess { ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), param_attr_spans: Lock::new(Vec::new()), let_chains_spans: Lock::new(Vec::new()), + async_closure_spans: Lock::new(Vec::new()), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index cef14632e64..a95b6891fb9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3221,21 +3221,24 @@ impl<'a> Parser<'a> { -> PResult<'a, P<Expr>> { let lo = self.token.span; + let movability = if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable }; + let asyncness = if self.token.span.rust_2018() { self.parse_asyncness() } else { IsAsync::NotAsync }; - let capture_clause = if self.eat_keyword(kw::Move) { - CaptureBy::Value - } else { - CaptureBy::Ref - }; + if asyncness.is_async() { + // Feature gate `async ||` closures. + self.sess.async_closure_spans.borrow_mut().push(self.prev_span); + } + + let capture_clause = self.parse_capture_clause(); let decl = self.parse_fn_block_decl()?; let decl_hi = self.prev_span; let body = match decl.output { @@ -3257,7 +3260,7 @@ impl<'a> Parser<'a> { attrs)) } - // `else` token already eaten + /// `else` token already eaten fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> { if self.eat_keyword(kw::If) { return self.parse_if_expr(ThinVec::new()); @@ -3306,7 +3309,7 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs)) } - // parse `loop {...}`, `loop` token already eaten + /// Parse `loop {...}`, `loop` token already eaten. fn parse_loop_expr(&mut self, opt_label: Option<Label>, span_lo: Span, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { @@ -3316,17 +3319,20 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs)) } - /// Parses an `async move {...}` expression. - pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>) - -> PResult<'a, P<Expr>> - { - let span_lo = self.token.span; - self.expect_keyword(kw::Async)?; - let capture_clause = if self.eat_keyword(kw::Move) { + /// Parse an optional `move` prefix to a closure lke construct. + fn parse_capture_clause(&mut self) -> CaptureBy { + if self.eat_keyword(kw::Move) { CaptureBy::Value } else { CaptureBy::Ref - }; + } + } + + /// Parses an `async move? {...}` expression. + pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { + let span_lo = self.token.span; + self.expect_keyword(kw::Async)?; + let capture_clause = self.parse_capture_clause(); let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); Ok(self.mk_expr( diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index aee988d5148..233574dda5d 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -146,6 +146,7 @@ symbols! { associated_type_defaults, associated_types, async_await, + async_closure, attr, attributes, attr_literals, diff --git a/src/test/run-pass/async-await/async-fn-size.rs b/src/test/run-pass/async-await/async-fn-size.rs index c4e328560dd..7396918196c 100644 --- a/src/test/run-pass/async-await/async-fn-size.rs +++ b/src/test/run-pass/async-await/async-fn-size.rs @@ -1,6 +1,6 @@ // edition:2018 -#![feature(async_await, await_macro)] +#![feature(async_await)] #[path = "../auxiliary/arc_wake.rs"] mod arc_wake; @@ -58,31 +58,31 @@ fn wait(fut: impl Future<Output = u8>) -> u8 { fn base() -> WakeOnceThenComplete { WakeOnceThenComplete(false, 1) } async fn await1_level1() -> u8 { - await!(base()) + base().await } async fn await2_level1() -> u8 { - await!(base()) + await!(base()) + base().await + base().await } async fn await3_level1() -> u8 { - await!(base()) + await!(base()) + await!(base()) + base().await + base().await + base().await } async fn await3_level2() -> u8 { - await!(await3_level1()) + await!(await3_level1()) + await!(await3_level1()) + await3_level1().await + await3_level1().await + await3_level1().await } async fn await3_level3() -> u8 { - await!(await3_level2()) + await!(await3_level2()) + await!(await3_level2()) + await3_level2().await + await3_level2().await + await3_level2().await } async fn await3_level4() -> u8 { - await!(await3_level3()) + await!(await3_level3()) + await!(await3_level3()) + await3_level3().await + await3_level3().await + await3_level3().await } async fn await3_level5() -> u8 { - await!(await3_level4()) + await!(await3_level4()) + await!(await3_level4()) + await3_level4().await + await3_level4().await + await3_level4().await } fn main() { diff --git a/src/test/run-pass/async-await/issue-60709.rs b/src/test/run-pass/async-await/issue-60709.rs index 778d3ee0c70..5ebb18b999a 100644 --- a/src/test/run-pass/async-await/issue-60709.rs +++ b/src/test/run-pass/async-await/issue-60709.rs @@ -2,7 +2,7 @@ // handled incorrectly in generators. // compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018 -#![feature(async_await, await_macro)] +#![feature(async_await)] #![allow(unused)] use std::future::Future; @@ -22,7 +22,7 @@ impl Future for Never { fn main() { let fut = async { let _rc = Rc::new(()); // Also crashes with Arc - await!(Never()); + Never().await; }; let _bla = fut; // Moving the future is required. } diff --git a/src/test/run-pass/intrinsics/intrinsic-uninit.rs b/src/test/run-pass/intrinsics/intrinsic-uninit.rs deleted file mode 100644 index 9555efb639b..00000000000 --- a/src/test/run-pass/intrinsics/intrinsic-uninit.rs +++ /dev/null @@ -1,13 +0,0 @@ -// run-pass -// pretty-expanded FIXME #23616 - -#![feature(intrinsics)] - -mod rusti { - extern "rust-intrinsic" { - pub fn uninit<T>() -> T; - } -} -pub fn main() { - let _a : isize = unsafe {rusti::uninit()}; -} diff --git a/src/test/ui/async-await/async-await.rs b/src/test/ui/async-await/async-await.rs index 0eae1467fbf..29622c9d030 100644 --- a/src/test/ui/async-await/async-await.rs +++ b/src/test/ui/async-await/async-await.rs @@ -70,13 +70,6 @@ fn async_nonmove_block(x: u8) -> impl Future<Output = u8> { } } -fn async_closure(x: u8) -> impl Future<Output = u8> { - (async move |x: u8| -> u8 { - wake_and_yield_once().await; - x - })(x) -} - async fn async_fn(x: u8) -> u8 { wake_and_yield_once().await; x @@ -180,7 +173,6 @@ fn main() { test! { async_block, async_nonmove_block, - async_closure, async_fn, generic_async_fn, async_fn_with_internal_borrow, diff --git a/src/test/ui/async-await/async-closure-matches-expr.rs b/src/test/ui/async-await/async-closure-matches-expr.rs new file mode 100644 index 00000000000..90bd51ec5d0 --- /dev/null +++ b/src/test/ui/async-await/async-closure-matches-expr.rs @@ -0,0 +1,12 @@ +// compile-pass +// edition:2018 + +#![feature(async_await, async_closure)] + +macro_rules! match_expr { + ($x:expr) => {} +} + +fn main() { + match_expr!(async || {}); +} diff --git a/src/test/ui/async-await/async-closure.rs b/src/test/ui/async-await/async-closure.rs new file mode 100644 index 00000000000..f5dc9e24d2d --- /dev/null +++ b/src/test/ui/async-await/async-closure.rs @@ -0,0 +1,81 @@ +// run-pass + +// edition:2018 +// aux-build:arc_wake.rs + +#![feature(async_await, async_closure)] + +extern crate arc_wake; + +use std::pin::Pin; +use std::future::Future; +use std::sync::{ + Arc, + atomic::{self, AtomicUsize}, +}; +use std::task::{Context, Poll}; +use arc_wake::ArcWake; + +struct Counter { + wakes: AtomicUsize, +} + +impl ArcWake for Counter { + fn wake(self: Arc<Self>) { + Self::wake_by_ref(&self) + } + fn wake_by_ref(arc_self: &Arc<Self>) { + arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst); + } +} + +struct WakeOnceThenComplete(bool); + +fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) } + +impl Future for WakeOnceThenComplete { + type Output = (); + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + if self.0 { + Poll::Ready(()) + } else { + cx.waker().wake_by_ref(); + self.0 = true; + Poll::Pending + } + } +} + +fn async_closure(x: u8) -> impl Future<Output = u8> { + (async move |x: u8| -> u8 { + wake_and_yield_once().await; + x + })(x) +} + +fn test_future_yields_once_then_returns<F, Fut>(f: F) +where + F: FnOnce(u8) -> Fut, + Fut: Future<Output = u8>, +{ + let mut fut = Box::pin(f(9)); + let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) }); + let waker = ArcWake::into_waker(counter.clone()); + let mut cx = Context::from_waker(&waker); + assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst)); + assert_eq!(Poll::Pending, fut.as_mut().poll(&mut cx)); + assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst)); + assert_eq!(Poll::Ready(9), fut.as_mut().poll(&mut cx)); +} + +fn main() { + macro_rules! test { + ($($fn_name:expr,)*) => { $( + test_future_yields_once_then_returns($fn_name); + )* } + } + + test! { + async_closure, + } +} diff --git a/src/test/ui/async-await/async-error-span.rs b/src/test/ui/async-await/async-error-span.rs new file mode 100644 index 00000000000..d362348a3fd --- /dev/null +++ b/src/test/ui/async-await/async-error-span.rs @@ -0,0 +1,17 @@ +// edition:2018 +#![feature(async_await)] + +// Regression test for issue #62382 + +use std::future::Future; + +fn get_future() -> impl Future<Output = ()> { + panic!() +} + +async fn foo() { + let a; //~ ERROR type inside `async` object must be known in this context + get_future().await; +} + +fn main() {} diff --git a/src/test/ui/async-await/async-error-span.stderr b/src/test/ui/async-await/async-error-span.stderr new file mode 100644 index 00000000000..bd8966b9c7d --- /dev/null +++ b/src/test/ui/async-await/async-error-span.stderr @@ -0,0 +1,15 @@ +error[E0698]: type inside `async` object must be known in this context + --> $DIR/async-error-span.rs:13:9 + | +LL | let a; + | ^ cannot infer type + | +note: the type is part of the `async` object because of this `await` + --> $DIR/async-error-span.rs:14:5 + | +LL | get_future().await; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0698`. diff --git a/src/test/ui/async-await/async-fn-path-elision.rs b/src/test/ui/async-await/async-fn-path-elision.rs index 8db7631ef41..447e40dddd9 100644 --- a/src/test/ui/async-await/async-fn-path-elision.rs +++ b/src/test/ui/async-await/async-fn-path-elision.rs @@ -1,6 +1,6 @@ // edition:2018 -#![feature(async_await, await_macro)] +#![feature(async_await)] #![allow(dead_code)] struct HasLifetime<'a>(&'a bool); diff --git a/src/test/ui/async-await/async-matches-expr.rs b/src/test/ui/async-await/async-matches-expr.rs index e41a568ad29..a6f0211e41f 100644 --- a/src/test/ui/async-await/async-matches-expr.rs +++ b/src/test/ui/async-await/async-matches-expr.rs @@ -1,7 +1,7 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await, await_macro)] +#![feature(async_await)] macro_rules! match_expr { ($x:expr) => {} @@ -9,5 +9,4 @@ macro_rules! match_expr { fn main() { match_expr!(async {}); - match_expr!(async || {}); } diff --git a/src/test/ui/async-await/async-with-closure.rs b/src/test/ui/async-await/async-with-closure.rs index 2b69c9b701a..f7dc874affd 100644 --- a/src/test/ui/async-await/async-with-closure.rs +++ b/src/test/ui/async-await/async-with-closure.rs @@ -1,7 +1,7 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await, await_macro)] +#![feature(async_await)] trait MyClosure { type Args; @@ -20,7 +20,7 @@ async fn get_future<C: ?Sized + MyClosure>(_stream: MyStream<C>) {} async fn f() { let messages: MyStream<dyn FnMut()> = unimplemented!(); - await!(get_future(messages)); + get_future(messages).await; } fn main() {} diff --git a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs index f59f1160e70..92f3210ac89 100644 --- a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs +++ b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs @@ -1,7 +1,7 @@ // edition:2018 #![allow(non_camel_case_types)] -#![feature(async_await, await_macro)] +#![feature(async_await)] mod outer_mod { pub mod await { //~ ERROR expected identifier, found reserved keyword `await` diff --git a/src/test/ui/async-await/await-macro.rs b/src/test/ui/async-await/await-macro.rs index 7d8b7a257da..c37835d73e9 100644 --- a/src/test/ui/async-await/await-macro.rs +++ b/src/test/ui/async-await/await-macro.rs @@ -3,7 +3,7 @@ // edition:2018 // aux-build:arc_wake.rs -#![feature(async_await, await_macro)] +#![feature(async_await, async_closure, await_macro)] extern crate arc_wake; diff --git a/src/test/ui/async-await/await-unsize.rs b/src/test/ui/async-await/await-unsize.rs new file mode 100644 index 00000000000..d5e21257f4f --- /dev/null +++ b/src/test/ui/async-await/await-unsize.rs @@ -0,0 +1,16 @@ +// Regression test for #62312 + +// check-pass +// edition:2018 + +#![feature(async_await)] + +async fn make_boxed_object() -> Box<dyn Send> { + Box::new(()) as _ +} + +async fn await_object() { + let _ = make_boxed_object().await; +} + +fn main() {} diff --git a/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs index c2b59eecb99..dfd8b2e361e 100644 --- a/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs +++ b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs @@ -3,7 +3,7 @@ // run-pass #![allow(unused_variables)] -#![feature(async_await, await_macro)] +#![feature(async_await)] // Test that the drop order for parameters in a fn and async fn matches up. Also test that // parameters (used or unused) are not dropped until the async fn completes execution. diff --git a/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs index 708c5704984..2a74485afb4 100644 --- a/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs +++ b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs @@ -3,7 +3,7 @@ // run-pass #![allow(unused_variables)] -#![feature(async_await, await_macro)] +#![feature(async_await)] // Test that the drop order for parameters in a fn and async fn matches up. Also test that // parameters (used or unused) are not dropped until the async fn completes execution. diff --git a/src/test/ui/async-await/feature-async-closure.rs b/src/test/ui/async-await/feature-async-closure.rs new file mode 100644 index 00000000000..d07116b13a2 --- /dev/null +++ b/src/test/ui/async-await/feature-async-closure.rs @@ -0,0 +1,8 @@ +// edition:2018 +// gate-test-async_closure + +fn f() { + let _ = async || {}; //~ ERROR async closures are unstable +} + +fn main() {} diff --git a/src/test/ui/async-await/feature-async-closure.stderr b/src/test/ui/async-await/feature-async-closure.stderr new file mode 100644 index 00000000000..61909f8659e --- /dev/null +++ b/src/test/ui/async-await/feature-async-closure.stderr @@ -0,0 +1,12 @@ +error[E0658]: async closures are unstable + --> $DIR/feature-async-closure.rs:5:13 + | +LL | let _ = async || {}; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/62290 + = help: add #![feature(async_closure)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/async-await/issues/issue-53249.rs b/src/test/ui/async-await/issues/issue-53249.rs index c493878e4c2..c57dc6b0ef6 100644 --- a/src/test/ui/async-await/issues/issue-53249.rs +++ b/src/test/ui/async-await/issues/issue-53249.rs @@ -1,7 +1,7 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(arbitrary_self_types, async_await, await_macro)] +#![feature(arbitrary_self_types, async_await)] use std::task::{self, Poll}; use std::future::Future; @@ -37,11 +37,11 @@ impl<R, F> Future for Lazy<F> async fn __receive<WantFn, Fut>(want: WantFn) -> () where Fut: Future<Output = ()>, WantFn: Fn(&Box<dyn Send + 'static>) -> Fut, { - await!(lazy(|_| ())); + lazy(|_| ()).await; } pub fn basic_spawn_receive() { - async { await!(__receive(|_| async { () })) }; + async { __receive(|_| async { () }).await }; } fn main() {} diff --git a/src/test/ui/async-await/issues/issue-54974.rs b/src/test/ui/async-await/issues/issue-54974.rs index 0cfe859b13b..040989b33fc 100644 --- a/src/test/ui/async-await/issues/issue-54974.rs +++ b/src/test/ui/async-await/issues/issue-54974.rs @@ -1,7 +1,7 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await, await_macro)] +#![feature(async_await)] use std::sync::Arc; diff --git a/src/test/ui/async-await/issues/issue-55324.rs b/src/test/ui/async-await/issues/issue-55324.rs index deaba6904f4..4f383a51a88 100644 --- a/src/test/ui/async-await/issues/issue-55324.rs +++ b/src/test/ui/async-await/issues/issue-55324.rs @@ -1,13 +1,13 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await, await_macro)] +#![feature(async_await)] use std::future::Future; #[allow(unused)] async fn foo<F: Future<Output = i32>>(x: &i32, future: F) -> i32 { - let y = await!(future); + let y = future.await; *x + y } diff --git a/src/test/ui/async-await/issues/issue-58885.rs b/src/test/ui/async-await/issues/issue-58885.rs index 5868e022861..47744aeea60 100644 --- a/src/test/ui/async-await/issues/issue-58885.rs +++ b/src/test/ui/async-await/issues/issue-58885.rs @@ -1,7 +1,7 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await, await_macro)] +#![feature(async_await)] struct Xyz { a: u64, diff --git a/src/test/ui/async-await/issues/issue-59001.rs b/src/test/ui/async-await/issues/issue-59001.rs index ffa70d3b43c..9334ddb0af5 100644 --- a/src/test/ui/async-await/issues/issue-59001.rs +++ b/src/test/ui/async-await/issues/issue-59001.rs @@ -1,7 +1,7 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await, await_macro)] +#![feature(async_await)] use std::future::Future; diff --git a/src/test/ui/async-await/issues/issue-59972.rs b/src/test/ui/async-await/issues/issue-59972.rs index 31e7a65dc98..1b843720102 100644 --- a/src/test/ui/async-await/issues/issue-59972.rs +++ b/src/test/ui/async-await/issues/issue-59972.rs @@ -2,7 +2,7 @@ // compile-flags: --edition=2018 -#![feature(async_await, await_macro)] +#![feature(async_await)] pub enum Uninhabited { } @@ -15,7 +15,7 @@ async fn noop() { } #[allow(unused)] async fn contains_never() { let error = uninhabited_async(); - await!(noop()); + noop().await; let error2 = error; } diff --git a/src/test/ui/async-await/issues/issue-62009.rs b/src/test/ui/async-await/issues/issue-62009-1.rs index e2d58cac24d..ac6605bceff 100644 --- a/src/test/ui/async-await/issues/issue-62009.rs +++ b/src/test/ui/async-await/issues/issue-62009-1.rs @@ -11,8 +11,6 @@ fn main() { //~^ ERROR `await` is only allowed inside `async` functions and blocks let task1 = print_dur().await; }.await; - (async || 2333)().await; - //~^ ERROR `await` is only allowed inside `async` functions and blocks (|_| 2333).await; //~^ ERROR `await` is only allowed inside `async` functions and blocks //~^^ ERROR diff --git a/src/test/ui/async-await/issues/issue-62009.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr index 53d1f34fe4f..2bbb6d079ea 100644 --- a/src/test/ui/async-await/issues/issue-62009.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -1,5 +1,5 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-62009.rs:8:5 + --> $DIR/issue-62009-1.rs:8:5 | LL | fn main() { | ---- this is not `async` @@ -7,7 +7,7 @@ LL | async { let (); }.await; | ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-62009.rs:10:5 + --> $DIR/issue-62009-1.rs:10:5 | LL | fn main() { | ---- this is not `async` @@ -19,16 +19,7 @@ LL | | }.await; | |___________^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-62009.rs:14:5 - | -LL | fn main() { - | ---- this is not `async` -... -LL | (async || 2333)().await; - | ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks - -error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-62009.rs:16:5 + --> $DIR/issue-62009-1.rs:14:5 | LL | fn main() { | ---- this is not `async` @@ -36,14 +27,14 @@ LL | fn main() { LL | (|_| 2333).await; | ^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks -error[E0277]: the trait bound `[closure@$DIR/issue-62009.rs:16:5: 16:15]: std::future::Future` is not satisfied - --> $DIR/issue-62009.rs:16:5 +error[E0277]: the trait bound `[closure@$DIR/issue-62009-1.rs:14:5: 14:15]: std::future::Future` is not satisfied + --> $DIR/issue-62009-1.rs:14:5 | LL | (|_| 2333).await; - | ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009.rs:16:5: 16:15]` + | ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:14:5: 14:15]` | = note: required by `std::future::poll_with_tls_context` -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issues/issue-62009-2.rs b/src/test/ui/async-await/issues/issue-62009-2.rs new file mode 100644 index 00000000000..52b62eaa9e0 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-62009-2.rs @@ -0,0 +1,10 @@ +// edition:2018 + +#![feature(async_await, async_closure)] + +async fn print_dur() {} + +fn main() { + (async || 2333)().await; + //~^ ERROR `await` is only allowed inside `async` functions and blocks +} diff --git a/src/test/ui/async-await/issues/issue-62009-2.stderr b/src/test/ui/async-await/issues/issue-62009-2.stderr new file mode 100644 index 00000000000..79b6803263e --- /dev/null +++ b/src/test/ui/async-await/issues/issue-62009-2.stderr @@ -0,0 +1,10 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/issue-62009-2.rs:8:5 + | +LL | fn main() { + | ---- this is not `async` +LL | (async || 2333)().await; + | ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/multiple-lifetimes/hrtb.rs b/src/test/ui/async-await/multiple-lifetimes/hrtb.rs index 620b0080966..589e260d084 100644 --- a/src/test/ui/async-await/multiple-lifetimes/hrtb.rs +++ b/src/test/ui/async-await/multiple-lifetimes/hrtb.rs @@ -3,7 +3,7 @@ // Test that we can use async fns with multiple arbitrary lifetimes. -#![feature(arbitrary_self_types, async_await, await_macro)] +#![feature(async_await)] #![allow(dead_code)] use std::ops::Add; diff --git a/src/test/ui/async-await/no-args-non-move-async-closure.rs b/src/test/ui/async-await/no-args-non-move-async-closure.rs index 345f19b0623..62d4b3fb6f2 100644 --- a/src/test/ui/async-await/no-args-non-move-async-closure.rs +++ b/src/test/ui/async-await/no-args-non-move-async-closure.rs @@ -1,6 +1,6 @@ // edition:2018 -#![feature(async_await, await_macro)] +#![feature(async_await, async_closure)] fn main() { let _ = async |x: u8| {}; diff --git a/src/test/ui/async-await/recursive-async-impl-trait-type.rs b/src/test/ui/async-await/recursive-async-impl-trait-type.rs index a4e08011934..54f3339870b 100644 --- a/src/test/ui/async-await/recursive-async-impl-trait-type.rs +++ b/src/test/ui/async-await/recursive-async-impl-trait-type.rs @@ -2,10 +2,10 @@ // Test that impl trait does not allow creating recursive types that are // otherwise forbidden when using `async` and `await`. -#![feature(await_macro, async_await, generators)] +#![feature(async_await)] async fn recursive_async_function() -> () { //~ ERROR - await!(recursive_async_function()); + recursive_async_function().await; } fn main() {} diff --git a/src/test/ui/async-await/suggest-missing-await-closure.fixed b/src/test/ui/async-await/suggest-missing-await-closure.fixed new file mode 100644 index 00000000000..60c9a8581ac --- /dev/null +++ b/src/test/ui/async-await/suggest-missing-await-closure.fixed @@ -0,0 +1,23 @@ +// edition:2018 +// run-rustfix + +#![feature(async_await, async_closure)] + +fn take_u32(_x: u32) {} + +async fn make_u32() -> u32 { + 22 +} + +#[allow(unused)] +async fn suggest_await_in_async_closure() { + async || { + let x = make_u32(); + take_u32(x.await) + //~^ ERROR mismatched types [E0308] + //~| HELP consider using `.await` here + //~| SUGGESTION x.await + }; +} + +fn main() {} diff --git a/src/test/ui/async-await/suggest-missing-await-closure.rs b/src/test/ui/async-await/suggest-missing-await-closure.rs new file mode 100644 index 00000000000..cb992a27bc1 --- /dev/null +++ b/src/test/ui/async-await/suggest-missing-await-closure.rs @@ -0,0 +1,23 @@ +// edition:2018 +// run-rustfix + +#![feature(async_await, async_closure)] + +fn take_u32(_x: u32) {} + +async fn make_u32() -> u32 { + 22 +} + +#[allow(unused)] +async fn suggest_await_in_async_closure() { + async || { + let x = make_u32(); + take_u32(x) + //~^ ERROR mismatched types [E0308] + //~| HELP consider using `.await` here + //~| SUGGESTION x.await + }; +} + +fn main() {} diff --git a/src/test/ui/async-await/suggest-missing-await-closure.stderr b/src/test/ui/async-await/suggest-missing-await-closure.stderr new file mode 100644 index 00000000000..487ca6c0fc5 --- /dev/null +++ b/src/test/ui/async-await/suggest-missing-await-closure.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/suggest-missing-await-closure.rs:16:18 + | +LL | take_u32(x) + | ^ + | | + | expected u32, found opaque type + | help: consider using `.await` here: `x.await` + | + = note: expected type `u32` + found type `impl std::future::Future` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/async-await/suggest-missing-await.fixed b/src/test/ui/async-await/suggest-missing-await.fixed index 282be368c69..aa032682be8 100644 --- a/src/test/ui/async-await/suggest-missing-await.fixed +++ b/src/test/ui/async-await/suggest-missing-await.fixed @@ -18,15 +18,4 @@ async fn suggest_await_in_async_fn() { //~| SUGGESTION x.await } -#[allow(unused)] -async fn suggest_await_in_async_closure() { - async || { - let x = make_u32(); - take_u32(x.await) - //~^ ERROR mismatched types [E0308] - //~| HELP consider using `.await` here - //~| SUGGESTION x.await - }; -} - fn main() {} diff --git a/src/test/ui/async-await/suggest-missing-await.rs b/src/test/ui/async-await/suggest-missing-await.rs index 36103f050c1..2ca814fbb22 100644 --- a/src/test/ui/async-await/suggest-missing-await.rs +++ b/src/test/ui/async-await/suggest-missing-await.rs @@ -18,15 +18,4 @@ async fn suggest_await_in_async_fn() { //~| SUGGESTION x.await } -#[allow(unused)] -async fn suggest_await_in_async_closure() { - async || { - let x = make_u32(); - take_u32(x) - //~^ ERROR mismatched types [E0308] - //~| HELP consider using `.await` here - //~| SUGGESTION x.await - }; -} - fn main() {} diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index 59c20dcfbc9..9bae7150276 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -10,18 +10,6 @@ LL | take_u32(x) = note: expected type `u32` found type `impl std::future::Future` -error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:25:18 - | -LL | take_u32(x) - | ^ - | | - | expected u32, found opaque type - | help: consider using `.await` here: `x.await` - | - = note: expected type `u32` - found type `impl std::future::Future` - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/feature-gates/feature-gate-async-await.rs b/src/test/ui/feature-gates/feature-gate-async-await.rs index 9cfefef4129..78391c0e104 100644 --- a/src/test/ui/feature-gates/feature-gate-async-await.rs +++ b/src/test/ui/feature-gates/feature-gate-async-await.rs @@ -15,5 +15,4 @@ async fn foo() {} //~ ERROR async fn is unstable fn main() { let _ = async {}; //~ ERROR async blocks are unstable - let _ = async || {}; //~ ERROR async closures are unstable } diff --git a/src/test/ui/feature-gates/feature-gate-async-await.stderr b/src/test/ui/feature-gates/feature-gate-async-await.stderr index 43e41b45458..1ea4da8da0c 100644 --- a/src/test/ui/feature-gates/feature-gate-async-await.stderr +++ b/src/test/ui/feature-gates/feature-gate-async-await.stderr @@ -40,15 +40,6 @@ LL | let _ = async {}; = note: for more information, see https://github.com/rust-lang/rust/issues/50547 = help: add #![feature(async_await)] to the crate attributes to enable -error[E0658]: async closures are unstable - --> $DIR/feature-gate-async-await.rs:18:13 - | -LL | let _ = async || {}; - | ^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/50547 - = help: add #![feature(async_await)] to the crate attributes to enable - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/init-unsafe.rs b/src/test/ui/init-unsafe.rs index 92b21c4efa3..3d65cfc2340 100644 --- a/src/test/ui/init-unsafe.rs +++ b/src/test/ui/init-unsafe.rs @@ -1,3 +1,4 @@ +#![allow(deprecated)] #![feature(core_intrinsics)] use std::intrinsics::{init}; diff --git a/src/test/ui/init-unsafe.stderr b/src/test/ui/init-unsafe.stderr index 857142dff64..e1126316af3 100644 --- a/src/test/ui/init-unsafe.stderr +++ b/src/test/ui/init-unsafe.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/init-unsafe.rs:7:17 + --> $DIR/init-unsafe.rs:8:17 | LL | let stuff = init::<isize>(); | ^^^^^^^^^^^^^^^ call to unsafe function diff --git a/src/test/ui/loops/loop-break-unsize.rs b/src/test/ui/loops/loop-break-unsize.rs new file mode 100644 index 00000000000..974c63cea85 --- /dev/null +++ b/src/test/ui/loops/loop-break-unsize.rs @@ -0,0 +1,8 @@ +// Regression test for #62312 +// check-pass + +fn main() { + let _ = loop { + break Box::new(()) as Box<dyn Send>; + }; +} |
