diff options
238 files changed, 1649 insertions, 943 deletions
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 06eb8a185be..bf8a7eb293e 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -15,7 +15,6 @@ #![feature(dropck_eyepatch)] #![feature(new_uninit)] #![feature(maybe_uninit_slice)] -#![feature(min_specialization)] #![feature(decl_macro)] #![feature(pointer_byte_offsets)] #![feature(rustc_attrs)] @@ -44,23 +43,6 @@ fn outline<F: FnOnce() -> R, R>(f: F) -> R { f() } -/// An arena that can hold objects of only one type. -pub struct TypedArena<T> { - /// A pointer to the next object to be allocated. - ptr: Cell<*mut T>, - - /// A pointer to the end of the allocated area. When this pointer is - /// reached, a new chunk is allocated. - end: Cell<*mut T>, - - /// A vector of arena chunks. - chunks: RefCell<Vec<ArenaChunk<T>>>, - - /// Marker indicating that dropping the arena causes its owned - /// instances of `T` to be dropped. - _own: PhantomData<T>, -} - struct ArenaChunk<T = u8> { /// The raw storage for the arena chunk. storage: NonNull<[MaybeUninit<T>]>, @@ -130,6 +112,23 @@ impl<T> ArenaChunk<T> { const PAGE: usize = 4096; const HUGE_PAGE: usize = 2 * 1024 * 1024; +/// An arena that can hold objects of only one type. +pub struct TypedArena<T> { + /// A pointer to the next object to be allocated. + ptr: Cell<*mut T>, + + /// A pointer to the end of the allocated area. When this pointer is + /// reached, a new chunk is allocated. + end: Cell<*mut T>, + + /// A vector of arena chunks. + chunks: RefCell<Vec<ArenaChunk<T>>>, + + /// Marker indicating that dropping the arena causes its owned + /// instances of `T` to be dropped. + _own: PhantomData<T>, +} + impl<T> Default for TypedArena<T> { /// Creates a new `TypedArena`. fn default() -> TypedArena<T> { @@ -144,77 +143,6 @@ impl<T> Default for TypedArena<T> { } } -trait IterExt<T> { - fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T]; -} - -impl<I, T> IterExt<T> for I -where - I: IntoIterator<Item = T>, -{ - // This default collects into a `SmallVec` and then allocates by copying - // from it. The specializations below for types like `Vec` are more - // efficient, copying directly without the intermediate collecting step. - // This default could be made more efficient, like - // `DroplessArena::alloc_from_iter`, but it's not hot enough to bother. - #[inline] - default fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] { - let vec: SmallVec<[_; 8]> = self.into_iter().collect(); - vec.alloc_from_iter(arena) - } -} - -impl<T, const N: usize> IterExt<T> for std::array::IntoIter<T, N> { - #[inline] - fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] { - let len = self.len(); - if len == 0 { - return &mut []; - } - // Move the content to the arena by copying and then forgetting it. - let start_ptr = arena.alloc_raw_slice(len); - unsafe { - self.as_slice().as_ptr().copy_to_nonoverlapping(start_ptr, len); - mem::forget(self); - slice::from_raw_parts_mut(start_ptr, len) - } - } -} - -impl<T> IterExt<T> for Vec<T> { - #[inline] - fn alloc_from_iter(mut self, arena: &TypedArena<T>) -> &mut [T] { - let len = self.len(); - if len == 0 { - return &mut []; - } - // Move the content to the arena by copying and then forgetting it. - let start_ptr = arena.alloc_raw_slice(len); - unsafe { - self.as_ptr().copy_to_nonoverlapping(start_ptr, len); - self.set_len(0); - slice::from_raw_parts_mut(start_ptr, len) - } - } -} - -impl<A: smallvec::Array> IterExt<A::Item> for SmallVec<A> { - #[inline] - fn alloc_from_iter(mut self, arena: &TypedArena<A::Item>) -> &mut [A::Item] { - let len = self.len(); - if len == 0 { - return &mut []; - } - // Move the content to the arena by copying and then forgetting it. - let start_ptr = arena.alloc_raw_slice(len); - unsafe { - self.as_ptr().copy_to_nonoverlapping(start_ptr, len); - self.set_len(0); - slice::from_raw_parts_mut(start_ptr, len) - } - } -} - impl<T> TypedArena<T> { /// Allocates an object in the `TypedArena`, returning a reference to it. #[inline] @@ -270,8 +198,35 @@ impl<T> TypedArena<T> { #[inline] pub fn alloc_from_iter<I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] { + // This implementation is entirely separate to + // `DroplessIterator::alloc_from_iter`, even though conceptually they + // are the same. + // + // `DroplessIterator` (in the fast case) writes elements from the + // iterator one at a time into the allocated memory. That's easy + // because the elements don't implement `Drop`. But for `TypedArena` + // they do implement `Drop`, which means that if the iterator panics we + // could end up with some allocated-but-uninitialized elements, which + // will then cause UB in `TypedArena::drop`. + // + // Instead we use an approach where any iterator panic will occur + // before the memory is allocated. This function is much less hot than + // `DroplessArena::alloc_from_iter`, so it doesn't need to be + // hyper-optimized. assert!(mem::size_of::<T>() != 0); - iter.alloc_from_iter(self) + + let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect(); + if vec.is_empty() { + return &mut []; + } + // Move the content to the arena by copying and then forgetting it. + let len = vec.len(); + let start_ptr = self.alloc_raw_slice(len); + unsafe { + vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); + vec.set_len(0); + slice::from_raw_parts_mut(start_ptr, len) + } } /// Grows the arena. diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 300b1486f9b..09bfbd02198 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -446,7 +446,7 @@ impl Token { } } - /// Returns `true` if the token can appear at the start of an pattern. + /// Returns `true` if the token can appear at the start of a pattern. /// /// Shamelessly borrowed from `can_begin_expr`, only used for diagnostics right now. pub fn can_begin_pattern(&self) -> bool { diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 8115c4b55b0..aaeef1ff77d 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -99,7 +99,7 @@ ast_lowering_misplaced_double_dot = .note = only allowed in tuple, tuple struct, and slice patterns ast_lowering_misplaced_impl_trait = - `impl Trait` only allowed in function and inherent method return types, not in {$position} + `impl Trait` only allowed in function and inherent method argument and return types, not in {$position} ast_lowering_misplaced_relax_trait_bound = `?Trait` bounds are only permitted at the point where a type parameter is declared diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index afcf8b15cd8..45a9bebfcf6 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -410,15 +410,11 @@ fn expand_format_args<'hir>( let format_options = use_format_options.then(|| { // Generate: // &[format_spec_0, format_spec_1, format_spec_2] - let elements: Vec<_> = fmt - .template - .iter() - .filter_map(|piece| { - let FormatArgsPiece::Placeholder(placeholder) = piece else { return None }; - Some(make_format_spec(ctx, macsp, placeholder, &mut argmap)) - }) - .collect(); - ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements)) + let elements = ctx.arena.alloc_from_iter(fmt.template.iter().filter_map(|piece| { + let FormatArgsPiece::Placeholder(placeholder) = piece else { return None }; + Some(make_format_spec(ctx, macsp, placeholder, &mut argmap)) + })); + ctx.expr_array_ref(macsp, elements) }); let arguments = fmt.arguments.all_args(); @@ -477,10 +473,8 @@ fn expand_format_args<'hir>( // <core::fmt::Argument>::new_debug(&arg2), // … // ] - let elements: Vec<_> = arguments - .iter() - .zip(argmap) - .map(|(arg, ((_, ty), placeholder_span))| { + let elements = ctx.arena.alloc_from_iter(arguments.iter().zip(argmap).map( + |(arg, ((_, ty), placeholder_span))| { let placeholder_span = placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt()); let arg_span = match arg.kind { @@ -493,9 +487,9 @@ fn expand_format_args<'hir>( hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg), )); make_argument(ctx, placeholder_span, ref_arg, ty) - }) - .collect(); - ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements)) + }, + )); + ctx.expr_array_ref(macsp, elements) } else { // Generate: // &match (&arg0, &arg1, &…) { @@ -528,19 +522,14 @@ fn expand_format_args<'hir>( make_argument(ctx, placeholder_span, arg, ty) }, )); - let elements: Vec<_> = arguments - .iter() - .map(|arg| { - let arg_expr = ctx.lower_expr(&arg.expr); - ctx.expr( - arg.expr.span.with_ctxt(macsp.ctxt()), - hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg_expr), - ) - }) - .collect(); - let args_tuple = ctx - .arena - .alloc(ctx.expr(macsp, hir::ExprKind::Tup(ctx.arena.alloc_from_iter(elements)))); + let elements = ctx.arena.alloc_from_iter(arguments.iter().map(|arg| { + let arg_expr = ctx.lower_expr(&arg.expr); + ctx.expr( + arg.expr.span.with_ctxt(macsp.ctxt()), + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg_expr), + ) + })); + let args_tuple = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Tup(elements))); let array = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Array(args))); let match_arms = ctx.arena.alloc_from_iter([ctx.arm(args_pat, array)]); let match_expr = ctx.arena.alloc(ctx.expr_match( diff --git a/compiler/rustc_attr/Cargo.toml b/compiler/rustc_attr/Cargo.toml index 2c4c3a0c263..a14d2796817 100644 --- a/compiler/rustc_attr/Cargo.toml +++ b/compiler/rustc_attr/Cargo.toml @@ -6,14 +6,14 @@ edition = "2021" [lib] [dependencies] +rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } -rustc_serialize = { path = "../rustc_serialize" } -rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } -rustc_span = { path = "../rustc_span" } rustc_data_structures = { path = "../rustc_data_structures" } +rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } +rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } -rustc_ast = { path = "../rustc_ast" } +rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index ca4b3662a08..6f82d6f9323 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -162,7 +162,7 @@ pub enum StabilityLevel { is_soft: bool, /// If part of a feature is stabilized and a new feature is added for the remaining parts, /// then the `implied_by` attribute is used to indicate which now-stable feature previously - /// contained a item. + /// contained an item. /// /// ```pseudo-Rust /// #[unstable(feature = "foo", issue = "...")] @@ -846,7 +846,7 @@ pub fn find_deprecation( ), ); } else { - sess.emit_err(session_diagnostics::IncorrectMetaItem2 { + sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span, }); } diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index ee79545e304..86f27254db2 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -165,15 +165,6 @@ pub(crate) struct MissingIssue { pub span: Span, } -// FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring the error code. Consider -// changing this to `IncorrectMetaItem`. See #51489. -#[derive(Diagnostic)] -#[diag(attr_incorrect_meta_item, code = "E0551")] -pub(crate) struct IncorrectMetaItem2 { - #[primary_span] - pub span: Span, -} - // FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`? // It is more similar to `IncorrectReprFormatGeneric`. #[derive(Diagnostic)] diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index d676906ff5e..4488276e0e7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1364,7 +1364,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.note(format!( "a for loop advances the iterator for you, the result is stored in `{loop_bind}`." )); - err.help("if you want to call `next` on a iterator within the loop, consider using `while let`."); + err.help("if you want to call `next` on an iterator within the loop, consider using `while let`."); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 8ca57383e82..e6bde6a8c54 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1359,9 +1359,9 @@ fn suggest_ampmut<'tcx>( None => (false, decl_span), }; - // if the binding already exists and is a reference with a explicit + // if the binding already exists and is a reference with an explicit // lifetime, then we can suggest adding ` mut`. this is special-cased from - // the path without a explicit lifetime. + // the path without an explicit lifetime. if let Ok(src) = tcx.sess.source_map().span_to_snippet(span) && src.starts_with("&'") // note that `& 'a T` is invalid so this is correct. diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 990f098efc5..9c77767e7a7 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1967,7 +1967,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { kind: mut_borrow_kind })) | Write(WriteKind::MutableBorrow(BorrowKind::Mut { kind: mut_borrow_kind })) => { let is_local_mutation_allowed = match mut_borrow_kind { - // `ClosureCapture` is used for mutable variable with a immutable binding. + // `ClosureCapture` is used for mutable variable with an immutable binding. // This is only behaviour difference between `ClosureCapture` and mutable borrows. MutBorrowKind::ClosureCapture => LocalMutationIsAllowed::Yes, MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow => { diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index af437f36b9f..c73192f4404 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -164,7 +164,7 @@ struct UniversalRegionIndices<'tcx> { /// be able to map them to our internal `RegionVid`. This is /// basically equivalent to an `GenericArgs`, except that it also /// contains an entry for `ReStatic` -- it might be nice to just - /// use a args, and then handle `ReStatic` another way. + /// use an args, and then handle `ReStatic` another way. indices: FxHashMap<ty::Region<'tcx>, RegionVid>, /// The vid assigned to `'static`. Used only for diagnostics. @@ -290,7 +290,7 @@ impl<'tcx> UniversalRegions<'tcx> { (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize) } - /// Returns `true` if `r` is classified as an local region. + /// Returns `true` if `r` is classified as a local region. pub fn is_local_free_region(&self, r: RegionVid) -> bool { self.region_classification(r) == Some(RegionClassification::Local) } diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 5d775b9b532..5c7d7b20c5d 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -30,7 +30,7 @@ fn clif_sig_from_fn_abi<'tcx>( let inputs = fn_abi.args.iter().flat_map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter()); let (return_ptr, returns) = fn_abi.ret.get_abi_return(tcx); - // Sometimes the first param is an pointer to the place where the return value needs to be stored. + // Sometimes the first param is a pointer to the place where the return value needs to be stored. let params: Vec<_> = return_ptr.into_iter().chain(inputs).collect(); Signature { params, returns, call_conv } diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 8db6195d931..06b7703672f 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -112,7 +112,7 @@ impl<'ll> CodegenCx<'ll, '_> { } } - /// Return a LLVM type that has at most the required alignment, + /// Return an LLVM type that has at most the required alignment, /// and exactly the required size, as a best-effort padding array. pub(crate) fn type_padding_filler(&self, size: Size, align: Align) -> &'ll Type { let unit = Integer::approximate_align(self, align); diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index dc3dbd9d819..b1fde8e4d86 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -30,7 +30,7 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> { fn type_ptr_ext(&self, address_space: AddressSpace) -> Self::Type; fn element_type(&self, ty: Self::Type) -> Self::Type; - /// Returns the number of elements in `self` if it is a LLVM vector type. + /// Returns the number of elements in `self` if it is an LLVM vector type. fn vector_length(&self, ty: Self::Type) -> usize; fn float_width(&self, ty: Self::Type) -> usize; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index d380849fefe..c4d806c5161 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -237,7 +237,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { if self.const_kind() == hir::ConstContext::ConstFn { for (idx, local) in body.local_decls.iter_enumerated() { // Handle the return place below. - if idx == RETURN_PLACE || local.internal { + if idx == RETURN_PLACE { continue; } diff --git a/compiler/rustc_error_codes/src/error_codes/E0551.md b/compiler/rustc_error_codes/src/error_codes/E0551.md index 53db559a4fc..0e078fe71bf 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0551.md +++ b/compiler/rustc_error_codes/src/error_codes/E0551.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler + An invalid meta-item was used inside an attribute. Erroneous code example: -```compile_fail,E0551 +```compile_fail,E0539 #[deprecated(note)] // error! fn i_am_deprecated() {} ``` diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index b5a3437c992..6a1da615055 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1189,7 +1189,7 @@ fn report_trait_method_mismatch<'tcx>( let ap = Applicability::MachineApplicable; match sig.decl.output { hir::FnRetTy::DefaultReturn(sp) => { - let sugg = format!("-> {} ", trait_sig.output()); + let sugg = format!(" -> {}", trait_sig.output()); diag.span_suggestion_verbose(sp, msg, sugg, ap); } hir::FnRetTy::Return(hir_ty) => { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index d9e0e87eb47..bc5029a1d5e 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -23,8 +23,12 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( if !tcx.impl_method_has_trait_impl_trait_tys(impl_m.def_id) { return; } - // crate-private traits don't have any library guarantees, there's no need to do this check. - if !tcx.visibility(trait_m.container_id(tcx)).is_public() { + // unreachable traits don't have any library guarantees, there's no need to do this check. + if trait_m + .container_id(tcx) + .as_local() + .is_some_and(|trait_def_id| !tcx.effective_visibilities(()).is_reachable(trait_def_id)) + { return; } diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 85e0000ab47..9fb39a0e93b 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -192,5 +192,5 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc } } } - tcx.arena.alloc_from_iter(collector.variances.into_iter()) + tcx.arena.alloc_from_iter(collector.variances) } diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 1fa0ec173a7..c8ffd7d1506 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -113,7 +113,11 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig); - fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); + let return_or_body_span = match decl.output { + hir::FnRetTy::DefaultReturn(_) => body.value.span, + hir::FnRetTy::Return(ty) => ty.span, + }; + fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType); fcx.check_return_expr(&body.value, false); // We insert the deferred_generator_interiors entry after visiting the body. diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 1526988fbd9..8efccd5ba3e 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -110,7 +110,7 @@ pub struct AddressOfTemporaryTaken { pub enum AddReturnTypeSuggestion { #[suggestion( hir_typeck_add_return_type_add, - code = "-> {found} ", + code = " -> {found}", applicability = "machine-applicable" )] Add { @@ -120,7 +120,7 @@ pub enum AddReturnTypeSuggestion { }, #[suggestion( hir_typeck_add_return_type_missing_here, - code = "-> _ ", + code = " -> _", applicability = "has-placeholders" )] MissingHere { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index eead4da5e3e..d9d0dd93010 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -41,7 +41,6 @@ use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::InferOk; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::ObligationCause; -use rustc_middle::middle::stability; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; use rustc_middle::ty::error::{ ExpectedFound, @@ -1585,12 +1584,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_expr_struct_fields( adt_ty, expected, - expr.hir_id, + expr, qpath.span(), variant, fields, base_expr, - expr.span, ); self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized); @@ -1601,12 +1599,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, adt_ty: Ty<'tcx>, expected: Expectation<'tcx>, - expr_id: hir::HirId, + expr: &hir::Expr<'_>, span: Span, variant: &'tcx ty::VariantDef, ast_fields: &'tcx [hir::ExprField<'tcx>], base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, - expr_span: Span, ) { let tcx = self.tcx; @@ -1646,7 +1643,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // struct-like enums (yet...), but it's definitely not // a bug to have constructed one. if adt_kind != AdtKind::Enum { - tcx.check_stability(v_field.did, Some(expr_id), field.span, None); + tcx.check_stability(v_field.did, Some(expr.hir_id), field.span, None); } self.field_ty(field.span, v_field, args) @@ -1662,10 +1659,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.report_unknown_field( adt_ty, variant, + expr, field, ast_fields, adt.variant_descr(), - expr_span, ) }; @@ -1731,7 +1728,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter() .map(|f| { let fru_ty = self - .normalize(expr_span, self.field_ty(base_expr.span, f, fresh_args)); + .normalize(expr.span, self.field_ty(base_expr.span, f, fresh_args)); let ident = self.tcx.adjust_ident(f.ident(self.tcx), variant.def_id); if let Some(_) = remaining_fields.remove(&ident) { let target_ty = self.field_ty(base_expr.span, f, args); @@ -1814,7 +1811,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(adt, args) if adt.is_struct() => variant .fields .iter() - .map(|f| self.normalize(expr_span, f.ty(self.tcx, args))) + .map(|f| self.normalize(expr.span, f.ty(self.tcx, args))) .collect(), _ => { self.tcx @@ -1824,13 +1821,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } }; - self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr_id, fru_tys); + self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr.hir_id, fru_tys); } else if adt_kind != AdtKind::Union && !remaining_fields.is_empty() { debug!(?remaining_fields); let private_fields: Vec<&ty::FieldDef> = variant .fields .iter() - .filter(|field| !field.vis.is_accessible_from(tcx.parent_module(expr_id), tcx)) + .filter(|field| !field.vis.is_accessible_from(tcx.parent_module(expr.hir_id), tcx)) .collect(); if !private_fields.is_empty() { @@ -2049,16 +2046,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, ty: Ty<'tcx>, variant: &'tcx ty::VariantDef, + expr: &hir::Expr<'_>, field: &hir::ExprField<'_>, skip_fields: &[hir::ExprField<'_>], kind_name: &str, - expr_span: Span, ) -> ErrorGuaranteed { if variant.is_recovered() { let guar = self .tcx .sess - .delay_span_bug(expr_span, "parser recovered but no error was emitted"); + .delay_span_bug(expr.span, "parser recovered but no error was emitted"); self.set_tainted_by_errors(guar); return guar; } @@ -2102,7 +2099,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); err.span_label(field.ident.span, "field does not exist"); err.span_suggestion_verbose( - expr_span, + expr.span, format!( "`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax", adt = ty, @@ -2120,7 +2117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(variant_ident_span, format!("`{ty}` defined here")); err.span_label(field.ident.span, "field does not exist"); err.span_suggestion_verbose( - expr_span, + expr.span, format!("`{ty}` is a tuple {kind_name}, use the appropriate syntax",), format!("{ty}(/* fields */)"), Applicability::HasPlaceholders, @@ -2129,9 +2126,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, _ => { // prevent all specified fields from being suggested - let skip_fields: Vec<_> = skip_fields.iter().map(|x| x.ident.name).collect(); + let available_field_names = self.available_field_names(variant, expr, skip_fields); if let Some(field_name) = - self.suggest_field_name(variant, field.ident.name, &skip_fields, expr_span) + find_best_match_for_name(&available_field_names, field.ident.name, None) { err.span_suggestion( field.ident.span, @@ -2153,10 +2150,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("`{ty}` does not have this field"), ); } - let mut available_field_names = - self.available_field_names(variant, expr_span); - available_field_names - .retain(|name| skip_fields.iter().all(|skip| name != skip)); if available_field_names.is_empty() { err.note("all struct fields are already assigned"); } else { @@ -2174,63 +2167,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit() } - // Return a hint about the closest match in field names - fn suggest_field_name( - &self, - variant: &'tcx ty::VariantDef, - field: Symbol, - skip: &[Symbol], - // The span where stability will be checked - span: Span, - ) -> Option<Symbol> { - let names = variant - .fields - .iter() - .filter_map(|field| { - // ignore already set fields and private fields from non-local crates - // and unstable fields. - if skip.iter().any(|&x| x == field.name) - || (!variant.def_id.is_local() && !field.vis.is_public()) - || matches!( - self.tcx.eval_stability(field.did, None, span, None), - stability::EvalResult::Deny { .. } - ) - { - None - } else { - Some(field.name) - } - }) - .collect::<Vec<Symbol>>(); - - find_best_match_for_name(&names, field, None) - } - fn available_field_names( &self, variant: &'tcx ty::VariantDef, - access_span: Span, + expr: &hir::Expr<'_>, + skip_fields: &[hir::ExprField<'_>], ) -> Vec<Symbol> { - let body_owner_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id); variant .fields .iter() .filter(|field| { - let def_scope = self - .tcx - .adjust_ident_and_get_scope( - field.ident(self.tcx), - variant.def_id, - body_owner_hir_id, - ) - .1; - field.vis.is_accessible_from(def_scope, self.tcx) - && !matches!( - self.tcx.eval_stability(field.did, None, access_span, None), - stability::EvalResult::Deny { .. } - ) + skip_fields.iter().all(|&skip| skip.ident.name != field.name) + && self.is_field_suggestable(field, expr.hir_id, expr.span) }) - .filter(|field| !self.tcx.is_doc_hidden(field.did)) .map(|field| field.name) .collect() } @@ -2460,7 +2409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.suggest_first_deref_field(&mut err, expr, base, ident); } ty::Adt(def, _) if !def.is_enum() => { - self.suggest_fields_on_recordish(&mut err, def, ident, expr.span); + self.suggest_fields_on_recordish(&mut err, expr, def, ident); } ty::Param(param_ty) => { self.point_at_param_definition(&mut err, param_ty); @@ -2622,12 +2571,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn suggest_fields_on_recordish( &self, err: &mut Diagnostic, + expr: &hir::Expr<'_>, def: ty::AdtDef<'tcx>, field: Ident, - access_span: Span, ) { + let available_field_names = self.available_field_names(def.non_enum_variant(), expr, &[]); if let Some(suggested_field_name) = - self.suggest_field_name(def.non_enum_variant(), field.name, &[], access_span) + find_best_match_for_name(&available_field_names, field.name, None) { err.span_suggestion( field.span, @@ -2637,12 +2587,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } else { err.span_label(field.span, "unknown field"); - let struct_variant_def = def.non_enum_variant(); - let field_names = self.available_field_names(struct_variant_def, access_span); - if !field_names.is_empty() { + if !available_field_names.is_empty() { err.note(format!( "available fields are: {}", - self.name_series_display(field_names), + self.name_series_display(available_field_names), )); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index abb68989218..9999fa2e59c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -782,8 +782,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } hir::FnRetTy::Return(hir_ty) => { - let span = hir_ty.span; - if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind && let hir::Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(op_ty), @@ -799,28 +797,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!(?found); if found.is_suggestable(self.tcx, false) { if term.span.is_empty() { - err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() }); + err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span: term.span, found: found.to_string() }); return true; } else { - err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span, expected }); + err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span: term.span, expected }); } } - } - - // Only point to return type if the expected type is the return type, as if they - // are not, the expectation must have been caused by something else. - debug!("return type {:?}", hir_ty); - let ty = self.astconv().ast_ty_to_ty(hir_ty); - debug!("return type {:?}", ty); - debug!("expected type {:?}", expected); - let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into()); - let ty = Binder::bind_with_vars(ty, bound_vars); - let ty = self.normalize(span, ty); - let ty = self.tcx.erase_late_bound_regions(ty); - if self.can_coerce(expected, ty) { - err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span, expected }); - self.try_suggest_return_impl_trait(err, expected, ty, fn_id); - return true; + } else { + // Only point to return type if the expected type is the return type, as if they + // are not, the expectation must have been caused by something else. + debug!("return type {:?}", hir_ty); + let ty = self.astconv().ast_ty_to_ty(hir_ty); + debug!("return type {:?}", ty); + debug!("expected type {:?}", expected); + let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into()); + let ty = Binder::bind_with_vars(ty, bound_vars); + let ty = self.normalize(hir_ty.span, ty); + let ty = self.tcx.erase_late_bound_regions(ty); + if self.can_coerce(expected, ty) { + err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected }); + self.try_suggest_return_impl_trait(err, expected, ty, fn_id); + return true; + } } } _ => {} @@ -1687,4 +1685,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } } + + pub(crate) fn is_field_suggestable( + &self, + field: &ty::FieldDef, + hir_id: HirId, + span: Span, + ) -> bool { + // The field must be visible in the containing module. + field.vis.is_accessible_from(self.tcx.parent_module(hir_id), self.tcx) + // The field must not be unstable. + && !matches!( + self.tcx.eval_stability(field.did, None, rustc_span::DUMMY_SP, None), + rustc_middle::middle::stability::EvalResult::Deny { .. } + ) + // If the field is from an external crate it must not be `doc(hidden)`. + && (field.did.is_local() || !self.tcx.is_doc_hidden(field.did)) + // If the field is hygienic it must come from the same syntax context. + && self.tcx.def_ident_span(field.did).unwrap().normalize_to_macros_2_0().eq_ctxt(span) + } } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 6873382c4ac..cd6adb345e7 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -5,7 +5,6 @@ #![feature(box_patterns)] #![feature(min_specialization)] #![feature(control_flow_enum)] -#![feature(option_as_slice)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 8fc236f46b2..3f9c9b3381b 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -12,7 +12,6 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{HirId, Pat, PatKind}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeVisitableExt}; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::edit_distance::find_best_match_for_name; @@ -1408,6 +1407,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { adt.variant_descr(), &inexistent_fields, &mut unmentioned_fields, + pat, variant, args, )) @@ -1434,15 +1434,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let accessible_unmentioned_fields: Vec<_> = unmentioned_fields .iter() .copied() - .filter(|(field, _)| { - field.vis.is_accessible_from(tcx.parent_module(pat.hir_id), tcx) - && !matches!( - tcx.eval_stability(field.did, None, DUMMY_SP, None), - EvalResult::Deny { .. } - ) - // We only want to report the error if it is hidden and not local - && !(tcx.is_doc_hidden(field.did) && !field.did.is_local()) - }) + .filter(|(field, _)| self.is_field_suggestable(field, pat.hir_id, pat.span)) .collect(); if !has_rest_pat { @@ -1578,12 +1570,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind_name: &str, inexistent_fields: &[&hir::PatField<'tcx>], unmentioned_fields: &mut Vec<(&'tcx ty::FieldDef, Ident)>, + pat: &'tcx Pat<'tcx>, variant: &ty::VariantDef, args: &'tcx ty::List<ty::GenericArg<'tcx>>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let tcx = self.tcx; - let (field_names, t, plural) = if inexistent_fields.len() == 1 { - (format!("a field named `{}`", inexistent_fields[0].ident), "this", "") + let (field_names, t, plural) = if let [field] = inexistent_fields { + (format!("a field named `{}`", field.ident), "this", "") } else { ( format!( @@ -1620,10 +1613,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), ); - if unmentioned_fields.len() == 1 { - let input = - unmentioned_fields.iter().map(|(_, field)| field.name).collect::<Vec<_>>(); - let suggested_name = find_best_match_for_name(&input, pat_field.ident.name, None); + if let [(field_def, field)] = unmentioned_fields.as_slice() + && self.is_field_suggestable(field_def, pat.hir_id, pat.span) + { + let suggested_name = + find_best_match_for_name(&[field.name], pat_field.ident.name, None); if let Some(suggested_name) = suggested_name { err.span_suggestion( pat_field.ident.span, @@ -1646,22 +1640,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Lit(expr) if !self.can_coerce( self.typeck_results.borrow().expr_ty(expr), - self.field_ty( - unmentioned_fields[0].1.span, - unmentioned_fields[0].0, - args, - ), + self.field_ty(field.span, field_def, args), ) => {} _ => { - let unmentioned_field = unmentioned_fields[0].1.name; err.span_suggestion_short( pat_field.ident.span, format!( "`{}` has a field named `{}`", tcx.def_path_str(variant.def_id), - unmentioned_field + field.name, ), - unmentioned_field.to_string(), + field.name, Applicability::MaybeIncorrect, ); } @@ -1871,8 +1860,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fields: &'tcx [hir::PatField<'tcx>], ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" }; - let field_names = if unmentioned_fields.len() == 1 { - format!("field `{}`{}", unmentioned_fields[0].1, inaccessible) + let field_names = if let [(_, field)] = unmentioned_fields { + format!("field `{field}`{inaccessible}") } else { let fields = unmentioned_fields .iter() diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index ad4525c922b..3ff1a5c0c14 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -194,13 +194,13 @@ impl<'a> SourceKindMultiSuggestion<'a> { data: &'a FnRetTy<'a>, should_wrap_expr: Option<Span>, ) -> Self { - let (arrow, post) = match data { - FnRetTy::DefaultReturn(_) => ("-> ", " "), - _ => ("", ""), + let arrow = match data { + FnRetTy::DefaultReturn(_) => " -> ", + _ => "", }; let (start_span, start_span_code, end_span) = match should_wrap_expr { - Some(end_span) => (data.span(), format!("{arrow}{ty_info}{post}{{ "), Some(end_span)), - None => (data.span(), format!("{arrow}{ty_info}{post}"), None), + Some(end_span) => (data.span(), format!("{arrow}{ty_info} {{"), Some(end_span)), + None => (data.span(), format!("{arrow}{ty_info}"), None), }; Self::ClosureReturn { start_span, start_span_code, end_span } } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 7377c6e2f35..4cabb5c3266 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -5,6 +5,10 @@ lint_array_into_iter = .use_explicit_into_iter_suggestion = or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value +lint_async_fn_in_trait = use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified + .note = you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future` + .suggestion = you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send` + lint_atomic_ordering_fence = memory fences cannot have `Relaxed` ordering .help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst` diff --git a/compiler/rustc_lint/src/async_fn_in_trait.rs b/compiler/rustc_lint/src/async_fn_in_trait.rs new file mode 100644 index 00000000000..ff4c81e2fc9 --- /dev/null +++ b/compiler/rustc_lint/src/async_fn_in_trait.rs @@ -0,0 +1,128 @@ +use crate::lints::AsyncFnInTraitDiag; +use crate::LateContext; +use crate::LateLintPass; +use rustc_hir as hir; +use rustc_trait_selection::traits::error_reporting::suggestions::suggest_desugaring_async_fn_to_impl_future_in_trait; + +declare_lint! { + /// The `async_fn_in_trait` lint detects use of `async fn` in the + /// definition of a publicly-reachable trait. + /// + /// ### Example + /// + /// ```rust + /// # #![feature(async_fn_in_trait)] + /// pub trait Trait { + /// async fn method(&self); + /// } + /// # fn main() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// When `async fn` is used in a trait definition, the trait does not + /// promise that the opaque [`Future`] returned by the associated function + /// or method will implement any [auto traits] such as [`Send`]. This may + /// be surprising and may make the associated functions or methods on the + /// trait less useful than intended. On traits exposed publicly from a + /// crate, this may affect downstream crates whose authors cannot alter + /// the trait definition. + /// + /// For example, this code is invalid: + /// + /// ```rust,compile_fail + /// # #![feature(async_fn_in_trait)] + /// pub trait Trait { + /// async fn method(&self) {} + /// } + /// + /// fn test<T: Trait>(x: T) { + /// fn spawn<T: Send>(_: T) {} + /// spawn(x.method()); // Not OK. + /// } + /// ``` + /// + /// This lint exists to warn authors of publicly-reachable traits that + /// they may want to consider desugaring the `async fn` to a normal `fn` + /// that returns an opaque `impl Future<..> + Send` type. + /// + /// For example, instead of: + /// + /// ```rust + /// # #![feature(async_fn_in_trait)] + /// pub trait Trait { + /// async fn method(&self) {} + /// } + /// ``` + /// + /// The author of the trait may want to write: + /// + /// + /// ```rust + /// # #![feature(return_position_impl_trait_in_trait)] + /// use core::future::Future; + /// pub trait Trait { + /// fn method(&self) -> impl Future<Output = ()> + Send { async {} } + /// } + /// ``` + /// + /// This still allows the use of `async fn` within impls of the trait. + /// However, it also means that the trait will never be compatible with + /// impls where the returned [`Future`] of the method does not implement + /// `Send`. + /// + /// Conversely, if the trait is used only locally, if it is never used in + /// generic functions, or if it is only used in single-threaded contexts + /// that do not care whether the returned [`Future`] implements [`Send`], + /// then the lint may be suppressed. + /// + /// [`Future`]: https://doc.rust-lang.org/core/future/trait.Future.html + /// [`Send`]: https://doc.rust-lang.org/core/marker/trait.Send.html + /// [auto traits]: https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits + pub ASYNC_FN_IN_TRAIT, + Warn, + "use of `async fn` in definition of a publicly-reachable trait" +} + +declare_lint_pass!( + /// Lint for use of `async fn` in the definition of a publicly-reachable + /// trait. + AsyncFnInTrait => [ASYNC_FN_IN_TRAIT] +); + +impl<'tcx> LateLintPass<'tcx> for AsyncFnInTrait { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'tcx>) { + if let hir::TraitItemKind::Fn(sig, body) = item.kind + && let hir::IsAsync::Async(async_span) = sig.header.asyncness + { + // RTN can be used to bound `async fn` in traits in a better way than "always" + if cx.tcx.features().return_type_notation { + return; + } + + // Only need to think about library implications of reachable traits + if !cx.tcx.effective_visibilities(()).is_reachable(item.owner_id.def_id) { + return; + } + + let hir::FnRetTy::Return(hir::Ty { kind: hir::TyKind::OpaqueDef(def, ..), .. }) = + sig.decl.output + else { + // This should never happen, but let's not ICE. + return; + }; + let sugg = suggest_desugaring_async_fn_to_impl_future_in_trait( + cx.tcx, + sig, + body, + def.owner_id.def_id, + " + Send", + ); + cx.tcx.emit_spanned_lint(ASYNC_FN_IN_TRAIT, item.hir_id(), async_span, AsyncFnInTraitDiag { + sugg + }); + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 72c103f2d4a..af2132fb899 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -50,6 +50,7 @@ extern crate rustc_session; extern crate tracing; mod array_into_iter; +mod async_fn_in_trait; pub mod builtin; mod context; mod deref_into_dyn_supertrait; @@ -96,6 +97,7 @@ use rustc_session::lint::builtin::{ }; use array_into_iter::ArrayIntoIter; +use async_fn_in_trait::AsyncFnInTrait; use builtin::*; use deref_into_dyn_supertrait::*; use drop_forget_useless::*; @@ -234,6 +236,7 @@ late_lint_methods!( MapUnitFn: MapUnitFn, MissingDebugImplementations: MissingDebugImplementations, MissingDoc: MissingDoc, + AsyncFnInTrait: AsyncFnInTrait, ] ] ); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index c091c260a47..12694aa0bed 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1818,3 +1818,24 @@ pub struct UnusedAllocationDiag; #[derive(LintDiagnostic)] #[diag(lint_unused_allocation_mut)] pub struct UnusedAllocationMutDiag; + +pub struct AsyncFnInTraitDiag { + pub sugg: Option<Vec<(Span, String)>>, +} + +impl<'a> DecorateLint<'a, ()> for AsyncFnInTraitDiag { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + diag.note(fluent::lint_note); + if let Some(sugg) = self.sugg { + diag.multipart_suggestion(fluent::lint_suggestion, sugg, Applicability::MaybeIncorrect); + } + diag + } + + fn msg(&self) -> rustc_errors::DiagnosticMessage { + fluent::lint_async_fn_in_trait + } +} diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 0bb1c66da0c..7534c9c0a68 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -830,22 +830,6 @@ pub struct LocalDecl<'tcx> { // FIXME(matthewjasper) Don't store in this in `Body` pub local_info: ClearCrossCrate<Box<LocalInfo<'tcx>>>, - /// `true` if this is an internal local. - /// - /// These locals are not based on types in the source code and are only used - /// for a few desugarings at the moment. - /// - /// The generator transformation will sanity check the locals which are live - /// across a suspension point against the type components of the generator - /// which type checking knows are live across a suspension point. We need to - /// flag drop flags to avoid triggering this check as they are introduced - /// outside of type inference. - /// - /// This should be sound because the drop flags are fully algebraic, and - /// therefore don't affect the auto-trait or outlives properties of the - /// generator. - pub internal: bool, - /// The type of this local. pub ty: Ty<'tcx>, @@ -1058,7 +1042,7 @@ impl<'tcx> LocalDecl<'tcx> { self.source_info.span.desugaring_kind().is_some() } - /// Creates a new `LocalDecl` for a temporary: mutable, non-internal. + /// Creates a new `LocalDecl` for a temporary, mutable. #[inline] pub fn new(ty: Ty<'tcx>, span: Span) -> Self { Self::with_source_info(ty, SourceInfo::outermost(span)) @@ -1070,20 +1054,12 @@ impl<'tcx> LocalDecl<'tcx> { LocalDecl { mutability: Mutability::Mut, local_info: ClearCrossCrate::Set(Box::new(LocalInfo::Boring)), - internal: false, ty, user_ty: None, source_info, } } - /// Converts `self` into same `LocalDecl` except tagged as internal. - #[inline] - pub fn internal(mut self) -> Self { - self.internal = true; - self - } - /// Converts `self` into same `LocalDecl` except tagged as immutable. #[inline] pub fn immutable(mut self) -> Self { diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index da486c3465a..ce2ddec0116 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -127,7 +127,7 @@ impl<'tcx> MirPatch<'tcx> { Location { block: bb, statement_index: offset } } - pub fn new_internal_with_info( + pub fn new_local_with_info( &mut self, ty: Ty<'tcx>, span: Span, @@ -135,7 +135,7 @@ impl<'tcx> MirPatch<'tcx> { ) -> Local { let index = self.next_local; self.next_local += 1; - let mut new_decl = LocalDecl::new(ty, span).internal(); + let mut new_decl = LocalDecl::new(ty, span); **new_decl.local_info.as_mut().assert_crate_local() = local_info; self.new_locals.push(new_decl); Local::new(index) @@ -148,13 +148,6 @@ impl<'tcx> MirPatch<'tcx> { Local::new(index) } - pub fn new_internal(&mut self, ty: Ty<'tcx>, span: Span) -> Local { - let index = self.next_local; - self.next_local += 1; - self.new_locals.push(LocalDecl::new(ty, span).internal()); - Local::new(index) - } - pub fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock { let block = BasicBlock::new(self.patch_map.len()); debug!("MirPatch: new_block: {:?}: {:?}", block, data); diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 60f78bef0af..9bd682d37ab 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -815,7 +815,6 @@ macro_rules! make_mir_visitor { ty, user_ty, source_info, - internal: _, local_info: _, } = local_decl; diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index dff7ff8c66b..e4069e11df2 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -348,9 +348,10 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> { impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [ty::ValTree<'tcx>] { fn decode(decoder: &mut D) -> &'tcx Self { - decoder.interner().arena.alloc_from_iter( - (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(), - ) + decoder + .interner() + .arena + .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder))) } } @@ -368,9 +369,10 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AdtDef<'tcx> { impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] { fn decode(decoder: &mut D) -> &'tcx Self { - decoder.interner().arena.alloc_from_iter( - (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(), - ) + decoder + .interner() + .arena + .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder))) } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index d4089eef483..afb65ffbe8c 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -183,7 +183,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // The `Box<T>` temporary created here is not a part of the HIR, // and therefore is not considered during generator auto-trait // determination. See the comment about `box` at `yield_in_scope`. - let result = this.local_decls.push(LocalDecl::new(expr.ty, expr_span).internal()); + let result = this.local_decls.push(LocalDecl::new(expr.ty, expr_span)); this.cfg.push( block, Statement { source_info, kind: StatementKind::StorageLive(result) }, diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs index c8910c272b1..a4ab365fa9a 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs @@ -52,12 +52,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let local_info = match expr.kind { ExprKind::StaticRef { def_id, .. } => { assert!(!this.tcx.is_thread_local_static(def_id)); - local_decl.internal = true; LocalInfo::StaticRef { def_id, is_thread_local: false } } ExprKind::ThreadLocalRef(def_id) => { assert!(this.tcx.is_thread_local_static(def_id)); - local_decl.internal = true; LocalInfo::StaticRef { def_id, is_thread_local: true } } ExprKind::NamedConst { def_id, .. } | ExprKind::ConstParam { def_id, .. } => { diff --git a/compiler/rustc_mir_build/src/build/expr/mod.rs b/compiler/rustc_mir_build/src/build/expr/mod.rs index f5ae060d603..dfe85b858cd 100644 --- a/compiler/rustc_mir_build/src/build/expr/mod.rs +++ b/compiler/rustc_mir_build/src/build/expr/mod.rs @@ -44,7 +44,7 @@ //! the most suitable spot to implement it, and then just let the //! other fns cycle around. The handoff works like this: //! -//! - `into(place)` -> fallback is to create a rvalue with `as_rvalue` and assign it to `place` +//! - `into(place)` -> fallback is to create an rvalue with `as_rvalue` and assign it to `place` //! - `as_rvalue` -> fallback is to create an Operand with `as_operand` and use `Rvalue::use` //! - `as_operand` -> either invokes `as_constant` or `as_temp` //! - `as_constant` -> (no fallback) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 921a5ca1175..eb1c6a9824a 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1798,7 +1798,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let fake_borrow_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fake_borrow_deref_ty); let mut fake_borrow_temp = LocalDecl::new(fake_borrow_ty, temp_span); - fake_borrow_temp.internal = self.local_decls[matched_place.local].internal; fake_borrow_temp.local_info = ClearCrossCrate::Set(Box::new(LocalInfo::FakeBorrow)); let fake_borrow_temp = self.local_decls.push(fake_borrow_temp); @@ -2268,7 +2267,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ty: var_ty, user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) }, source_info, - internal: false, local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::Var( VarBindingForm { binding_mode, @@ -2298,7 +2296,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ty: Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, var_ty), user_ty: None, source_info, - internal: false, local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User( BindingForm::RefForGuard, ))), diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs index c96e99ef0e7..c263de79c3b 100644 --- a/compiler/rustc_mir_build/src/build/misc.rs +++ b/compiler/rustc_mir_build/src/build/misc.rs @@ -15,9 +15,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// N.B., **No cleanup is scheduled for this temporary.** You should /// call `schedule_drop` once the temporary is initialized. pub(crate) fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> { - // Mark this local as internal to avoid temporaries with types not present in the - // user's code resulting in ICEs from the generator transform. - let temp = self.local_decls.push(LocalDecl::new(ty, span).internal()); + let temp = self.local_decls.push(LocalDecl::new(ty, span)); let place = Place::from(temp); debug!("temp: created temp {:?} with type {:?}", place, self.local_decls[temp].ty); place diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 4cf6a349af7..bc151cc7058 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -725,7 +725,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue` // statement. fn add_dummy_assignment(&mut self, span: Span, block: BasicBlock, source_info: SourceInfo) { - let local_decl = LocalDecl::new(Ty::new_unit(self.tcx), span).internal(); + let local_decl = LocalDecl::new(Ty::new_unit(self.tcx), span); let temp_place = Place::from(self.local_decls.push(local_decl)); self.cfg.push_assign_unit(block, source_info, temp_place, self.tcx); } diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs index 1cc049d5a22..e5be7c0ca76 100644 --- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -24,6 +24,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> { rvalue: &mut Rvalue<'tcx>, location: Location, ) { + // We don't need to do anything for deref temps as they are + // not part of the source code, but used for desugaring purposes. + if self.local_decls[place.local].is_deref_temp() { + return; + } let mut place_ty = place.ty(self.local_decls, self.tcx).ty; let mut rval_ty = rvalue.ty(self.local_decls, self.tcx); // Not erasing this causes `Free Regions` errors in validator, @@ -48,7 +53,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> { // // gets transformed to // let temp: rval_ty = rval; // let place: place_ty = temp as place_ty; -// pub fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let patch = MirPatch::new(body); let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls }; diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index bacabc62ee4..c428007707e 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -179,7 +179,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { // Check the base local: it might be an unsafe-to-access static. We only check derefs of the // temporary holding the static pointer to avoid duplicate errors // <https://github.com/rust-lang/rust/pull/78068#issuecomment-731753506>. - if decl.internal && place.projection.first() == Some(&ProjectionElem::Deref) { + if place.projection.first() == Some(&ProjectionElem::Deref) { // If the projection root is an artificial local that we introduced when // desugaring `static`, give a more specific error message // (avoid the general "raw pointer" clause below, that would only be confusing). diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs index 95898b5b73c..42be7457018 100644 --- a/compiler/rustc_mir_transform/src/deref_separator.rs +++ b/compiler/rustc_mir_transform/src/deref_separator.rs @@ -37,7 +37,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> { for (idx, (p_ref, p_elem)) in place.iter_projections().enumerate() { if !p_ref.projection.is_empty() && p_elem == ProjectionElem::Deref { let ty = p_ref.ty(self.local_decls, self.tcx).ty; - let temp = self.patcher.new_internal_with_info( + let temp = self.patcher.new_local_with_info( ty, self.local_decls[p_ref.local].source_info.span, LocalInfo::DerefTemp, diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index e51f771e00d..1c917a85c03 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -69,7 +69,7 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> { let (unique_ty, nonnull_ty, ptr_ty) = build_ptr_tys(tcx, base_ty.boxed_ty(), self.unique_did, self.nonnull_did); - let ptr_local = self.patch.new_internal(ptr_ty, source_info.span); + let ptr_local = self.patch.new_temp(ptr_ty, source_info.span); self.patch.add_assign( location, diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index b62d7da2a4c..d18fdaaf22f 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -271,7 +271,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let tcx = self.tcx; let patch = &mut self.patch; debug!("create_drop_flag({:?})", self.body.span); - self.drop_flags[index].get_or_insert_with(|| patch.new_internal(tcx.types.bool, span)); + self.drop_flags[index].get_or_insert_with(|| patch.new_temp(tcx.types.bool, span)); } fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> { diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 8a807d786a5..c16f07a453c 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -321,7 +321,7 @@ impl<'tcx> TransformVisitor<'tcx> { // Create a statement which reads the discriminant into a temporary fn get_discr(&self, body: &mut Body<'tcx>) -> (Statement<'tcx>, Place<'tcx>) { - let temp_decl = LocalDecl::new(self.discr_ty, body.span).internal(); + let temp_decl = LocalDecl::new(self.discr_ty, body.span); let local_decls_len = body.local_decls.push(temp_decl); let temp = Place::from(local_decls_len); diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index b53e0852c09..32dfb743905 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -616,9 +616,7 @@ impl<'tcx> Inliner<'tcx> { // If there are any locals without storage markers, give them storage only for the // duration of the call. for local in callee_body.vars_and_temps_iter() { - if !callee_body.local_decls[local].internal - && integrator.always_live_locals.contains(local) - { + if integrator.always_live_locals.contains(local) { let new_local = integrator.map_local(local); caller_body[callsite.block].statements.push(Statement { source_info: callsite.source_info, @@ -641,9 +639,7 @@ impl<'tcx> Inliner<'tcx> { n += 1; } for local in callee_body.vars_and_temps_iter().rev() { - if !callee_body.local_decls[local].internal - && integrator.always_live_locals.contains(local) - { + if integrator.always_live_locals.contains(local) { let new_local = integrator.map_local(local); caller_body[block].statements.push(Statement { source_info: callsite.source_info, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 22381844d6d..c0a09b7a761 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -467,7 +467,6 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<' /// After this series of passes, no lifetime analysis based on borrowing can be done. fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let passes: &[&dyn MirPass<'tcx>] = &[ - &add_subtyping_projections::Subtyper, &cleanup_post_borrowck::CleanupPostBorrowck, &remove_noop_landing_pads::RemoveNoopLandingPads, &simplify::SimplifyCfg::EarlyOpt, @@ -483,6 +482,7 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // These next passes must be executed together &add_call_guards::CriticalCallEdges, &reveal_all::RevealAll, // has to be done before drop elaboration, since we need to drop opaque types, too. + &add_subtyping_projections::Subtyper, // calling this after reveal_all ensures that we don't deal with opaque types &elaborate_drops::ElaborateDrops, // This will remove extraneous landing pads which are no longer // necessary as well as well as forcing any call in a non-unwinding diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs index 55f1eac6f84..1626cf3c035 100644 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -46,16 +46,18 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) .collect::<Vec<_>>(), ); + self.super_place(place, _context, _location); } #[inline] - fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, _: Location) { + fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) { // We have to use `try_normalize_erasing_regions` here, since it's // possible that we visit impossible-to-satisfy where clauses here, // see #91745 if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.const_) { constant.const_ = c; } + self.super_constant(constant, location); } #[inline] diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index a25b0f1f893..0a64b2f806a 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -247,7 +247,7 @@ impl<'a> Parser<'a> { )?; FnRetTy::Ty(ty) } else { - FnRetTy::Default(self.token.span.shrink_to_lo()) + FnRetTy::Default(self.prev_token.span.shrink_to_hi()) }) } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 493daf314ce..f853039f72c 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -1,6 +1,7 @@ -// This implements the dead-code warning pass. It follows middle::reachable -// closely. The idea is that all reachable symbols are live, codes called -// from live codes are live, and everything else is dead. +// This implements the dead-code warning pass. +// All reachable symbols are live, code called from live code is live, code with certain lint +// expectations such as `#[expect(unused)]` and `#[expect(dead_code)]` is live, and everything else +// is dead. use hir::def_id::{LocalDefIdMap, LocalDefIdSet}; use itertools::Itertools; @@ -747,7 +748,7 @@ fn live_symbols_and_ignored_derived_traits( (symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits) } -struct DeadVariant { +struct DeadItem { def_id: LocalDefId, name: Symbol, level: lint::Level, @@ -785,7 +786,13 @@ impl<'tcx> DeadVisitor<'tcx> { ShouldWarnAboutField::Yes(is_positional) } - fn warn_multiple_dead_codes( + // # Panics + // All `dead_codes` must have the same lint level, otherwise we will intentionally ICE. + // This is because we emit a multi-spanned lint using the lint level of the `dead_codes`'s + // first local def id. + // Prefer calling `Self.warn_dead_code` or `Self.warn_dead_code_grouped_by_lint_level` + // since those methods group by lint level before calling this method. + fn lint_at_single_level( &self, dead_codes: &[LocalDefId], participle: &str, @@ -796,6 +803,15 @@ impl<'tcx> DeadVisitor<'tcx> { return; }; let tcx = self.tcx; + + let first_hir_id = tcx.hir().local_def_id_to_hir_id(first_id); + let first_lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, first_hir_id).0; + assert!(dead_codes.iter().skip(1).all(|id| { + let hir_id = tcx.hir().local_def_id_to_hir_id(*id); + let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0; + level == first_lint_level + })); + let names: Vec<_> = dead_codes.iter().map(|&def_id| tcx.item_name(def_id.to_def_id())).collect(); let spans: Vec<_> = dead_codes @@ -876,31 +892,26 @@ impl<'tcx> DeadVisitor<'tcx> { } }; - self.tcx.emit_spanned_lint( - lint, - tcx.hir().local_def_id_to_hir_id(first_id), - MultiSpan::from_spans(spans), - diag, - ); + self.tcx.emit_spanned_lint(lint, first_hir_id, MultiSpan::from_spans(spans), diag); } - fn warn_dead_fields_and_variants( + fn warn_multiple( &self, def_id: LocalDefId, participle: &str, - dead_codes: Vec<DeadVariant>, + dead_codes: Vec<DeadItem>, is_positional: bool, ) { let mut dead_codes = dead_codes .iter() .filter(|v| !v.name.as_str().starts_with('_')) - .collect::<Vec<&DeadVariant>>(); + .collect::<Vec<&DeadItem>>(); if dead_codes.is_empty() { return; } dead_codes.sort_by_key(|v| v.level); for (_, group) in &dead_codes.into_iter().group_by(|v| v.level) { - self.warn_multiple_dead_codes( + self.lint_at_single_level( &group.map(|v| v.def_id).collect::<Vec<_>>(), participle, Some(def_id), @@ -910,7 +921,7 @@ impl<'tcx> DeadVisitor<'tcx> { } fn warn_dead_code(&mut self, id: LocalDefId, participle: &str) { - self.warn_multiple_dead_codes(&[id], participle, None, false); + self.lint_at_single_level(&[id], participle, None, false); } fn check_definition(&mut self, def_id: LocalDefId) { @@ -954,17 +965,16 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { if let hir::ItemKind::Impl(impl_item) = tcx.hir().item(item).kind { let mut dead_items = Vec::new(); for item in impl_item.items { - let did = item.id.owner_id.def_id; - if !visitor.is_live_code(did) { - dead_items.push(did) + let def_id = item.id.owner_id.def_id; + if !visitor.is_live_code(def_id) { + let name = tcx.item_name(def_id.to_def_id()); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0; + + dead_items.push(DeadItem { def_id, name, level }) } } - visitor.warn_multiple_dead_codes( - &dead_items, - "used", - Some(item.owner_id.def_id), - false, - ); + visitor.warn_multiple(item.owner_id.def_id, "used", dead_items, false); } if !live_symbols.contains(&item.owner_id.def_id) { @@ -988,7 +998,7 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { // Record to group diagnostics. let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0; - dead_variants.push(DeadVariant { def_id, name: variant.name, level }); + dead_variants.push(DeadItem { def_id, name: variant.name, level }); continue; } @@ -1013,21 +1023,16 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { hir_id, ) .0; - Some(DeadVariant { def_id, name: field.name, level }) + Some(DeadItem { def_id, name: field.name, level }) } else { None } }) .collect(); - visitor.warn_dead_fields_and_variants(def_id, "read", dead_fields, is_positional) + visitor.warn_multiple(def_id, "read", dead_fields, is_positional); } - visitor.warn_dead_fields_and_variants( - item.owner_id.def_id, - "constructed", - dead_variants, - false, - ); + visitor.warn_multiple(item.owner_id.def_id, "constructed", dead_variants, false); } } diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index c6c97ce35e8..7d1122c2fd2 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -15,7 +15,7 @@ use rustc_middle::mir::interpret::{alloc_range, AllocId}; use rustc_middle::ty::{self, Ty, TyCtxt, Variance}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_target::abi::FieldIdx; -use stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx}; +use stable_mir::mir::{CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx}; use stable_mir::ty::{FloatTy, GenericParamDef, IntTy, Movability, RigidTy, Span, TyKind, UintTy}; use stable_mir::{self, opaque, Context}; use tracing::debug; @@ -106,7 +106,14 @@ impl<'tcx> Context for Tables<'tcx> { .collect(), }) .collect(), - locals: mir.local_decls.iter().map(|decl| self.intern_ty(decl.ty)).collect(), + locals: mir + .local_decls + .iter() + .map(|decl| stable_mir::mir::LocalDecl { + ty: self.intern_ty(decl.ty), + span: decl.source_info.span.stable(self), + }) + .collect(), } } @@ -223,41 +230,64 @@ pub(crate) trait Stable<'tcx> { impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> { type T = stable_mir::mir::Statement; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { - use rustc_middle::mir::StatementKind::*; - match &self.kind { - Assign(assign) => { - stable_mir::mir::Statement::Assign(assign.0.stable(tables), assign.1.stable(tables)) - } - FakeRead(fake_read_place) => stable_mir::mir::Statement::FakeRead( - fake_read_place.0.stable(tables), - fake_read_place.1.stable(tables), + Statement { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) } + } +} + +impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> { + type T = stable_mir::mir::StatementKind; + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + match self { + mir::StatementKind::Assign(assign) => stable_mir::mir::StatementKind::Assign( + assign.0.stable(tables), + assign.1.stable(tables), ), - SetDiscriminant { place: plc, variant_index: idx } => { - stable_mir::mir::Statement::SetDiscriminant { - place: plc.as_ref().stable(tables), - variant_index: idx.stable(tables), + mir::StatementKind::FakeRead(fake_read_place) => { + stable_mir::mir::StatementKind::FakeRead( + fake_read_place.0.stable(tables), + fake_read_place.1.stable(tables), + ) + } + mir::StatementKind::SetDiscriminant { place, variant_index } => { + stable_mir::mir::StatementKind::SetDiscriminant { + place: place.as_ref().stable(tables), + variant_index: variant_index.stable(tables), } } - Deinit(place) => stable_mir::mir::Statement::Deinit(place.stable(tables)), - StorageLive(place) => stable_mir::mir::Statement::StorageLive(place.stable(tables)), - StorageDead(place) => stable_mir::mir::Statement::StorageDead(place.stable(tables)), - Retag(retag, place) => { - stable_mir::mir::Statement::Retag(retag.stable(tables), place.stable(tables)) + mir::StatementKind::Deinit(place) => { + stable_mir::mir::StatementKind::Deinit(place.stable(tables)) + } + + mir::StatementKind::StorageLive(place) => { + stable_mir::mir::StatementKind::StorageLive(place.stable(tables)) + } + + mir::StatementKind::StorageDead(place) => { + stable_mir::mir::StatementKind::StorageDead(place.stable(tables)) + } + mir::StatementKind::Retag(retag, place) => { + stable_mir::mir::StatementKind::Retag(retag.stable(tables), place.stable(tables)) + } + mir::StatementKind::PlaceMention(place) => { + stable_mir::mir::StatementKind::PlaceMention(place.stable(tables)) } - PlaceMention(place) => stable_mir::mir::Statement::PlaceMention(place.stable(tables)), - AscribeUserType(place_projection, variance) => { - stable_mir::mir::Statement::AscribeUserType { + mir::StatementKind::AscribeUserType(place_projection, variance) => { + stable_mir::mir::StatementKind::AscribeUserType { place: place_projection.as_ref().0.stable(tables), projections: place_projection.as_ref().1.stable(tables), variance: variance.stable(tables), } } - Coverage(coverage) => stable_mir::mir::Statement::Coverage(opaque(coverage)), - Intrinsic(intrinstic) => { - stable_mir::mir::Statement::Intrinsic(intrinstic.stable(tables)) + mir::StatementKind::Coverage(coverage) => { + stable_mir::mir::StatementKind::Coverage(opaque(coverage)) + } + mir::StatementKind::Intrinsic(intrinstic) => { + stable_mir::mir::StatementKind::Intrinsic(intrinstic.stable(tables)) + } + mir::StatementKind::ConstEvalCounter => { + stable_mir::mir::StatementKind::ConstEvalCounter } - ConstEvalCounter => stable_mir::mir::Statement::ConstEvalCounter, - Nop => stable_mir::mir::Statement::Nop, + mir::StatementKind::Nop => stable_mir::mir::StatementKind::Nop, } } } @@ -806,11 +836,20 @@ impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> { impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> { type T = stable_mir::mir::Terminator; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { - use rustc_middle::mir::TerminatorKind::*; use stable_mir::mir::Terminator; - match &self.kind { - Goto { target } => Terminator::Goto { target: target.as_usize() }, - SwitchInt { discr, targets } => Terminator::SwitchInt { + Terminator { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) } + } +} + +impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { + type T = stable_mir::mir::TerminatorKind; + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use stable_mir::mir::TerminatorKind; + match self { + mir::TerminatorKind::Goto { target } => { + TerminatorKind::Goto { target: target.as_usize() } + } + mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt { discr: discr.stable(tables), targets: targets .iter() @@ -821,42 +860,60 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> { .collect(), otherwise: targets.otherwise().as_usize(), }, - UnwindResume => Terminator::Resume, - UnwindTerminate(_) => Terminator::Abort, - Return => Terminator::Return, - Unreachable => Terminator::Unreachable, - Drop { place, target, unwind, replace: _ } => Terminator::Drop { - place: place.stable(tables), - target: target.as_usize(), - unwind: unwind.stable(tables), - }, - Call { func, args, destination, target, unwind, call_source: _, fn_span: _ } => { - Terminator::Call { - func: func.stable(tables), - args: args.iter().map(|arg| arg.stable(tables)).collect(), - destination: destination.stable(tables), - target: target.map(|t| t.as_usize()), + mir::TerminatorKind::UnwindResume => TerminatorKind::Resume, + mir::TerminatorKind::UnwindTerminate(_) => TerminatorKind::Abort, + mir::TerminatorKind::Return => TerminatorKind::Return, + mir::TerminatorKind::Unreachable => TerminatorKind::Unreachable, + mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => { + TerminatorKind::Drop { + place: place.stable(tables), + target: target.as_usize(), unwind: unwind.stable(tables), } } - Assert { cond, expected, msg, target, unwind } => Terminator::Assert { - cond: cond.stable(tables), - expected: *expected, - msg: msg.stable(tables), - target: target.as_usize(), + mir::TerminatorKind::Call { + func, + args, + destination, + target, + unwind, + call_source: _, + fn_span: _, + } => TerminatorKind::Call { + func: func.stable(tables), + args: args.iter().map(|arg| arg.stable(tables)).collect(), + destination: destination.stable(tables), + target: target.map(|t| t.as_usize()), unwind: unwind.stable(tables), }, - InlineAsm { template, operands, options, line_spans, destination, unwind } => { - Terminator::InlineAsm { - template: format!("{template:?}"), - operands: operands.iter().map(|operand| operand.stable(tables)).collect(), - options: format!("{options:?}"), - line_spans: format!("{line_spans:?}"), - destination: destination.map(|d| d.as_usize()), + mir::TerminatorKind::Assert { cond, expected, msg, target, unwind } => { + TerminatorKind::Assert { + cond: cond.stable(tables), + expected: *expected, + msg: msg.stable(tables), + target: target.as_usize(), unwind: unwind.stable(tables), } } - Yield { .. } | GeneratorDrop | FalseEdge { .. } | FalseUnwind { .. } => unreachable!(), + mir::TerminatorKind::InlineAsm { + template, + operands, + options, + line_spans, + destination, + unwind, + } => TerminatorKind::InlineAsm { + template: format!("{template:?}"), + operands: operands.iter().map(|operand| operand.stable(tables)).collect(), + options: format!("{options:?}"), + line_spans: format!("{line_spans:?}"), + destination: destination.map(|d| d.as_usize()), + unwind: unwind.stable(tables), + }, + mir::TerminatorKind::Yield { .. } + | mir::TerminatorKind::GeneratorDrop + | mir::TerminatorKind::FalseEdge { .. } + | mir::TerminatorKind::FalseUnwind { .. } => unreachable!(), } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 15f2ba809a4..b7c73501280 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -4000,14 +4000,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // ... whose signature is `async` (i.e. this is an AFIT) let (sig, body) = item.expect_fn(); - let hir::IsAsync::Async(async_span) = sig.header.asyncness else { - return; - }; - let Ok(async_span) = - self.tcx.sess.source_map().span_extend_while(async_span, |c| c.is_whitespace()) - else { - return; - }; let hir::FnRetTy::Return(hir::Ty { kind: hir::TyKind::OpaqueDef(def, ..), .. }) = sig.decl.output else { @@ -4021,55 +4013,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { return; } - let future = self.tcx.hir().item(*def).expect_opaque_ty(); - let Some(hir::GenericBound::LangItemTrait(_, _, _, generics)) = future.bounds.get(0) else { - // `async fn` should always lower to a lang item bound... but don't ICE. - return; - }; - let Some(hir::TypeBindingKind::Equality { term: hir::Term::Ty(future_output_ty) }) = - generics.bindings.get(0).map(|binding| binding.kind) - else { - // Also should never happen. + let Some(sugg) = suggest_desugaring_async_fn_to_impl_future_in_trait( + self.tcx, + *sig, + *body, + opaque_def_id.expect_local(), + &format!(" + {auto_trait}"), + ) else { return; }; let function_name = self.tcx.def_path_str(fn_def_id); - - let mut sugg = if future_output_ty.span.is_empty() { - vec![ - (async_span, String::new()), - ( - future_output_ty.span, - format!(" -> impl std::future::Future<Output = ()> + {auto_trait}"), - ), - ] - } else { - vec![ - ( - future_output_ty.span.shrink_to_lo(), - "impl std::future::Future<Output = ".to_owned(), - ), - (future_output_ty.span.shrink_to_hi(), format!("> + {auto_trait}")), - (async_span, String::new()), - ] - }; - - // If there's a body, we also need to wrap it in `async {}` - if let hir::TraitFn::Provided(body) = body { - let body = self.tcx.hir().body(*body); - let body_span = body.value.span; - let body_span_without_braces = - body_span.with_lo(body_span.lo() + BytePos(1)).with_hi(body_span.hi() - BytePos(1)); - if body_span_without_braces.is_empty() { - sugg.push((body_span_without_braces, " async {} ".to_owned())); - } else { - sugg.extend([ - (body_span_without_braces.shrink_to_lo(), "async {".to_owned()), - (body_span_without_braces.shrink_to_hi(), "} ".to_owned()), - ]); - } - } - err.multipart_suggestion( format!( "`{auto_trait}` can be made part of the associated future's \ @@ -4321,3 +4275,65 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceImplTraitFolder<'tcx> { self.tcx } } + +pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>( + tcx: TyCtxt<'tcx>, + sig: hir::FnSig<'tcx>, + body: hir::TraitFn<'tcx>, + opaque_def_id: LocalDefId, + add_bounds: &str, +) -> Option<Vec<(Span, String)>> { + let hir::IsAsync::Async(async_span) = sig.header.asyncness else { + return None; + }; + let Ok(async_span) = tcx.sess.source_map().span_extend_while(async_span, |c| c.is_whitespace()) + else { + return None; + }; + + let future = tcx.hir().get_by_def_id(opaque_def_id).expect_item().expect_opaque_ty(); + let Some(hir::GenericBound::LangItemTrait(_, _, _, generics)) = future.bounds.get(0) else { + // `async fn` should always lower to a lang item bound... but don't ICE. + return None; + }; + let Some(hir::TypeBindingKind::Equality { term: hir::Term::Ty(future_output_ty) }) = + generics.bindings.get(0).map(|binding| binding.kind) + else { + // Also should never happen. + return None; + }; + + let mut sugg = if future_output_ty.span.is_empty() { + vec![ + (async_span, String::new()), + ( + future_output_ty.span, + format!(" -> impl std::future::Future<Output = ()>{add_bounds}"), + ), + ] + } else { + vec![ + (future_output_ty.span.shrink_to_lo(), "impl std::future::Future<Output = ".to_owned()), + (future_output_ty.span.shrink_to_hi(), format!(">{add_bounds}")), + (async_span, String::new()), + ] + }; + + // If there's a body, we also need to wrap it in `async {}` + if let hir::TraitFn::Provided(body) = body { + let body = tcx.hir().body(body); + let body_span = body.value.span; + let body_span_without_braces = + body_span.with_lo(body_span.lo() + BytePos(1)).with_hi(body_span.hi() - BytePos(1)); + if body_span_without_braces.is_empty() { + sugg.push((body_span_without_braces, " async {} ".to_owned())); + } else { + sugg.extend([ + (body_span_without_braces.shrink_to_lo(), "async {".to_owned()), + (body_span_without_braces.shrink_to_hi(), "} ".to_owned()), + ]); + } + } + + Some(sugg) +} diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index e41073937be..f23c100a686 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -316,7 +316,7 @@ fn vtable_entries<'tcx>( dump_vtable_entries(tcx, sp, trait_ref, &entries); } - tcx.arena.alloc_from_iter(entries.into_iter()) + tcx.arena.alloc_from_iter(entries) } /// Find slot base for trait methods within vtable entries of another trait diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 16183403d67..b118ddaab2b 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -528,7 +528,7 @@ fn fn_abi_adjust_for_abi<'tcx>( arg.make_indirect(); } else { // We want to pass small aggregates as immediates, but using - // a LLVM aggregate type for this leads to bad optimizations, + // an LLVM aggregate type for this leads to bad optimizations, // so we pick an appropriately sized integer type instead. arg.cast_to(Reg { kind: RegKind::Integer, size }); } diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 383cc996b9e..35487d3b698 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -71,7 +71,7 @@ pub(crate) fn destructure_const<'tcx>( _ => bug!("cannot destructure constant {:?}", const_), }; - let fields = tcx.arena.alloc_from_iter(fields.into_iter()); + let fields = tcx.arena.alloc_from_iter(fields); ty::DestructuredConst { variant, fields } } diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 6f8f7b06fa3..72f026ee8de 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -5,7 +5,13 @@ use crate::{ty::Ty, Span}; #[derive(Clone, Debug)] pub struct Body { pub blocks: Vec<BasicBlock>, - pub locals: Vec<Ty>, + pub locals: Vec<LocalDecl>, +} + +#[derive(Clone, Debug)] +pub struct LocalDecl { + pub ty: Ty, + pub span: Span, } #[derive(Clone, Debug)] @@ -15,7 +21,13 @@ pub struct BasicBlock { } #[derive(Clone, Debug)] -pub enum Terminator { +pub struct Terminator { + pub kind: TerminatorKind, + pub span: Span, +} + +#[derive(Clone, Debug)] +pub enum TerminatorKind { Goto { target: usize, }, @@ -179,7 +191,13 @@ pub enum NonDivergingIntrinsic { } #[derive(Clone, Debug)] -pub enum Statement { +pub struct Statement { + pub kind: StatementKind, + pub span: Span, +} + +#[derive(Clone, Debug)] +pub enum StatementKind { Assign(Place, Rvalue), FakeRead(FakeReadCause, Place), SetDiscriminant { place: Place, variant_index: VariantIdx }, diff --git a/library/alloc/src/collections/btree/dedup_sorted_iter.rs b/library/alloc/src/collections/btree/dedup_sorted_iter.rs index 17ee78045a9..cd6a88f3291 100644 --- a/library/alloc/src/collections/btree/dedup_sorted_iter.rs +++ b/library/alloc/src/collections/btree/dedup_sorted_iter.rs @@ -1,6 +1,6 @@ use core::iter::Peekable; -/// A iterator for deduping the key of a sorted iterator. +/// An iterator for deduping the key of a sorted iterator. /// When encountering the duplicated key, only the last key-value pair is yielded. /// /// Used by [`BTreeMap::bulk_build_from_sorted_iter`][1]. diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index d37888c27bd..5bf221b429f 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -133,6 +133,10 @@ impl<'a> Argument<'a> { Self::new(x, USIZE_MARKER) } + // FIXME: Transmuting formatter in new and indirectly branching to/calling + // it here is an explicit CFI violation. + #[allow(inline_no_sanitize)] + #[no_sanitize(cfi, kcfi)] #[inline(always)] pub(super) fn fmt(&self, f: &mut Formatter<'_>) -> Result { (self.formatter)(self.value, f) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index ab8d9f33b08..7fa7e83a744 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -238,6 +238,7 @@ #![feature(negative_impls)] #![feature(never_type)] #![feature(no_core)] +#![feature(no_sanitize)] #![feature(platform_intrinsics)] #![feature(prelude_import)] #![feature(repr_simd)] diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 290f649f9ac..f60626b00dc 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -377,6 +377,13 @@ impl f32 { pub const MANTISSA_DIGITS: u32 = 24; /// Approximate number of significant digits in base 10. + /// + /// This is the maximum <i>x</i> such that any decimal number with <i>x</i> + /// significant digits can be converted to `f32` and back without loss. + /// + /// Equal to floor(log<sub>10</sub> 2<sup>[`MANTISSA_DIGITS`] − 1</sup>). + /// + /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const DIGITS: u32 = 6; @@ -384,31 +391,62 @@ impl f32 { /// /// This is the difference between `1.0` and the next larger representable number. /// + /// Equal to 2<sup>1 − [`MANTISSA_DIGITS`]</sup>. + /// /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon + /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const EPSILON: f32 = 1.19209290e-07_f32; /// Smallest finite `f32` value. + /// + /// Equal to −[`MAX`]. + /// + /// [`MAX`]: f32::MAX #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN: f32 = -3.40282347e+38_f32; /// Smallest positive normal `f32` value. + /// + /// Equal to 2<sup>[`MIN_EXP`] − 1</sup>. + /// + /// [`MIN_EXP`]: f32::MIN_EXP #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_POSITIVE: f32 = 1.17549435e-38_f32; /// Largest finite `f32` value. + /// + /// Equal to + /// (1 − 2<sup>−[`MANTISSA_DIGITS`]</sup>) 2<sup>[`MAX_EXP`]</sup>. + /// + /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS + /// [`MAX_EXP`]: f32::MAX_EXP #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX: f32 = 3.40282347e+38_f32; /// One greater than the minimum possible normal power of 2 exponent. + /// + /// If <i>x</i> = `MIN_EXP`, then normal numbers + /// ≥ 0.5 × 2<sup><i>x</i></sup>. #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_EXP: i32 = -125; /// Maximum possible power of 2 exponent. + /// + /// If <i>x</i> = `MAX_EXP`, then normal numbers + /// < 1 × 2<sup><i>x</i></sup>. #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX_EXP: i32 = 128; - /// Minimum possible normal power of 10 exponent. + /// Minimum <i>x</i> for which 10<sup><i>x</i></sup> is normal. + /// + /// Equal to ceil(log<sub>10</sub> [`MIN_POSITIVE`]). + /// + /// [`MIN_POSITIVE`]: f32::MIN_POSITIVE #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_10_EXP: i32 = -37; - /// Maximum possible power of 10 exponent. + /// Maximum <i>x</i> for which 10<sup><i>x</i></sup> is normal. + /// + /// Equal to floor(log<sub>10</sub> [`MAX`]). + /// + /// [`MAX`]: f32::MAX #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX_10_EXP: i32 = 38; @@ -820,7 +858,7 @@ impl f32 { /// let angle = std::f32::consts::PI; /// /// let abs_difference = (angle.to_degrees() - 180.0).abs(); - /// + /// # #[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))] /// assert!(abs_difference <= f32::EPSILON); /// ``` #[must_use = "this returns the result of the operation, \ diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 7569d2cd6ca..0a87021d8c1 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -376,6 +376,13 @@ impl f64 { #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MANTISSA_DIGITS: u32 = 53; /// Approximate number of significant digits in base 10. + /// + /// This is the maximum <i>x</i> such that any decimal number with <i>x</i> + /// significant digits can be converted to `f64` and back without loss. + /// + /// Equal to floor(log<sub>10</sub> 2<sup>[`MANTISSA_DIGITS`] − 1</sup>). + /// + /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const DIGITS: u32 = 15; @@ -383,31 +390,62 @@ impl f64 { /// /// This is the difference between `1.0` and the next larger representable number. /// + /// Equal to 2<sup>1 − [`MANTISSA_DIGITS`]</sup>. + /// /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon + /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const EPSILON: f64 = 2.2204460492503131e-16_f64; /// Smallest finite `f64` value. + /// + /// Equal to −[`MAX`]. + /// + /// [`MAX`]: f64::MAX #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN: f64 = -1.7976931348623157e+308_f64; /// Smallest positive normal `f64` value. + /// + /// Equal to 2<sup>[`MIN_EXP`] − 1</sup>. + /// + /// [`MIN_EXP`]: f64::MIN_EXP #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_POSITIVE: f64 = 2.2250738585072014e-308_f64; /// Largest finite `f64` value. + /// + /// Equal to + /// (1 − 2<sup>−[`MANTISSA_DIGITS`]</sup>) 2<sup>[`MAX_EXP`]</sup>. + /// + /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS + /// [`MAX_EXP`]: f64::MAX_EXP #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX: f64 = 1.7976931348623157e+308_f64; /// One greater than the minimum possible normal power of 2 exponent. + /// + /// If <i>x</i> = `MIN_EXP`, then normal numbers + /// ≥ 0.5 × 2<sup><i>x</i></sup>. #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_EXP: i32 = -1021; /// Maximum possible power of 2 exponent. + /// + /// If <i>x</i> = `MAX_EXP`, then normal numbers + /// < 1 × 2<sup><i>x</i></sup>. #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX_EXP: i32 = 1024; - /// Minimum possible normal power of 10 exponent. + /// Minimum <i>x</i> for which 10<sup><i>x</i></sup> is normal. + /// + /// Equal to ceil(log<sub>10</sub> [`MIN_POSITIVE`]). + /// + /// [`MIN_POSITIVE`]: f64::MIN_POSITIVE #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_10_EXP: i32 = -307; - /// Maximum possible power of 10 exponent. + /// Maximum <i>x</i> for which 10<sup><i>x</i></sup> is normal. + /// + /// Equal to floor(log<sub>10</sub> [`MAX`]). + /// + /// [`MAX`]: f64::MAX #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX_10_EXP: i32 = 308; diff --git a/library/core/src/option.rs b/library/core/src/option.rs index f2909a81d49..9899014e85a 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -743,8 +743,6 @@ impl<T> Option<T> { /// # Examples /// /// ```rust - /// #![feature(option_as_slice)] - /// /// assert_eq!( /// [Some(1234).as_slice(), None.as_slice()], /// [&[1234][..], &[][..]], @@ -755,15 +753,13 @@ impl<T> Option<T> { /// borrowing) [`[_]::first`](slice::first): /// /// ```rust - /// #![feature(option_as_slice)] - /// /// for i in [Some(1234_u16), None] { /// assert_eq!(i.as_ref(), i.as_slice().first()); /// } /// ``` #[inline] #[must_use] - #[unstable(feature = "option_as_slice", issue = "108545")] + #[stable(feature = "option_as_slice", since = "CURRENT_RUSTC_VERSION")] pub fn as_slice(&self) -> &[T] { // SAFETY: When the `Option` is `Some`, we're using the actual pointer // to the payload, with a length of 1, so this is equivalent to @@ -794,8 +790,6 @@ impl<T> Option<T> { /// # Examples /// /// ```rust - /// #![feature(option_as_slice)] - /// /// assert_eq!( /// [Some(1234).as_mut_slice(), None.as_mut_slice()], /// [&mut [1234][..], &mut [][..]], @@ -806,8 +800,6 @@ impl<T> Option<T> { /// our original `Option`: /// /// ```rust - /// #![feature(option_as_slice)] - /// /// let mut x = Some(1234); /// x.as_mut_slice()[0] += 1; /// assert_eq!(x, Some(1235)); @@ -817,13 +809,11 @@ impl<T> Option<T> { /// is [`[_]::first_mut`](slice::first_mut): /// /// ```rust - /// #![feature(option_as_slice)] - /// /// assert_eq!(Some(123).as_mut_slice().first_mut(), Some(&mut 123)) /// ``` #[inline] #[must_use] - #[unstable(feature = "option_as_slice", issue = "108545")] + #[stable(feature = "option_as_slice", since = "CURRENT_RUSTC_VERSION")] pub fn as_mut_slice(&mut self) -> &mut [T] { // SAFETY: When the `Option` is `Some`, we're using the actual pointer // to the payload, with a length of 1, so this is equivalent to diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6f78778f01a..02f4d5bc7ae 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -270,6 +270,7 @@ #![feature(allow_internal_unstable)] #![feature(c_unwind)] #![feature(cfg_target_thread_local)] +#![feature(cfi_encoding)] #![feature(concat_idents)] #![feature(const_mut_refs)] #![feature(const_trait_impl)] @@ -292,6 +293,7 @@ #![feature(needs_panic_runtime)] #![feature(negative_impls)] #![feature(never_type)] +#![feature(no_sanitize)] #![feature(platform_intrinsics)] #![feature(prelude_import)] #![feature(rustc_attrs)] diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs index fba2a676f28..e9d19766592 100644 --- a/library/std/src/sys/unix/thread_local_dtor.rs +++ b/library/std/src/sys/unix/thread_local_dtor.rs @@ -11,28 +11,47 @@ // Note, however, that we run on lots older linuxes, as well as cross // compiling from a newer linux to an older linux, so we also have a // fallback implementation to use as well. +#[allow(unexpected_cfgs)] #[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "redox", target_os = "hurd"))] +// FIXME: The Rust compiler currently omits weakly function definitions (i.e., +// __cxa_thread_atexit_impl) and its metadata from LLVM IR. +#[no_sanitize(cfi, kcfi)] pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { use crate::mem; use crate::sys_common::thread_local_dtor::register_dtor_fallback; + /// This is necessary because the __cxa_thread_atexit_impl implementation + /// std links to by default may be a C or C++ implementation that was not + /// compiled using the Clang integer normalization option. + #[cfg(not(sanitizer_cfi_normalize_integers))] + #[cfi_encoding = "i"] + #[repr(transparent)] + pub struct c_int(pub libc::c_int); + extern "C" { #[linkage = "extern_weak"] static __dso_handle: *mut u8; #[linkage = "extern_weak"] - static __cxa_thread_atexit_impl: *const libc::c_void; + static __cxa_thread_atexit_impl: Option< + extern "C" fn( + unsafe extern "C" fn(*mut libc::c_void), + *mut libc::c_void, + *mut libc::c_void, + ) -> c_int, + >; } - if !__cxa_thread_atexit_impl.is_null() { - type F = unsafe extern "C" fn( - dtor: unsafe extern "C" fn(*mut u8), - arg: *mut u8, - dso_handle: *mut u8, - ) -> libc::c_int; - mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl)( - dtor, - t, - &__dso_handle as *const _ as *mut _, - ); + + if let Some(f) = __cxa_thread_atexit_impl { + unsafe { + f( + mem::transmute::< + unsafe extern "C" fn(*mut u8), + unsafe extern "C" fn(*mut libc::c_void), + >(dtor), + t.cast(), + &__dso_handle as *const _ as *mut _, + ); + } return; } register_dtor_fallback(t, dtor); diff --git a/src/doc/rustc/src/platform-support/mips-release-6.md b/src/doc/rustc/src/platform-support/mips-release-6.md index 3f1912fc6f9..9203a31e9f4 100644 --- a/src/doc/rustc/src/platform-support/mips-release-6.md +++ b/src/doc/rustc/src/platform-support/mips-release-6.md @@ -67,7 +67,7 @@ The following procedure outlines the build process for the MIPS64 R6 target with ### Prerequisite: Disable debuginfo -A LLVM bug makes rustc crash if debug or debug info generation is enabled. You need to edit `config.toml` to disable this: +An LLVM bug makes rustc crash if debug or debug info generation is enabled. You need to edit `config.toml` to disable this: ```toml [rust] diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 49389b28c8f..502853f39ae 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -197,22 +197,26 @@ Shadow byte legend (one shadow byte represents 8 application bytes): # ControlFlowIntegrity -The LLVM Control Flow Integrity (CFI) support in the Rust compiler provides -forward-edge control flow protection for both Rust-compiled code only and for C -or C++ and Rust -compiled code mixed-language binaries, also known as “mixed -binaries” (i.e., for when C or C++ and Rust -compiled code share the same -virtual address space), by aggregating function pointers in groups identified by -their return and parameter types. - -LLVM CFI can be enabled with `-Zsanitizer=cfi` and requires LTO (i.e., `-Clto`). -Cross-language LLVM CFI can be enabled with `-Zsanitizer=cfi`, and requires the -`-Zsanitizer-cfi-normalize-integers` option to be used with Clang -`-fsanitize-cfi-icall-normalize-integers` for normalizing integer types, and -proper (i.e., non-rustc) LTO (i.e., `-Clinker-plugin-lto`). +The LLVM CFI support in the Rust compiler provides forward-edge control flow +protection for both Rust-compiled code only and for C or C++ and Rust -compiled +code mixed-language binaries, also known as “mixed binaries” (i.e., for when C +or C++ and Rust -compiled code share the same virtual address space), by +aggregating function pointers in groups identified by their return and parameter +types. + +LLVM CFI can be enabled with `-Zsanitizer=cfi` and requires LTO (i.e., +`-Clinker-plugin-lto` or `-Clto`). Cross-language LLVM CFI can be enabled with +`-Zsanitizer=cfi`, and requires the `-Zsanitizer-cfi-normalize-integers` option +to be used with Clang `-fsanitize-cfi-icall-experimental-normalize-integers` +option for cross-language LLVM CFI support, and proper (i.e., non-rustc) LTO +(i.e., `-Clinker-plugin-lto`). + +It is recommended to rebuild the standard library with CFI enabled by using the +Cargo build-std feature (i.e., `-Zbuild-std`) when enabling CFI. See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details. -## Example +## Example 1: Redirecting control flow using an indirect branch/call to an invalid destination ```rust,ignore (making doc tests pass cross-platform is hard) #![feature(naked_functions)] @@ -239,7 +243,7 @@ pub extern "C" fn add_two(x: i32) { nop nop nop - lea eax, [edi+2] + lea eax, [rdi+2] ret ", options(noreturn) @@ -258,8 +262,9 @@ fn main() { println!("With CFI enabled, you should not see the next answer"); let f: fn(i32) -> i32 = unsafe { - // Offsets 0-8 make it land in the landing pad/nop block, and offsets 1-8 are - // invalid branch/call destinations (i.e., within the body of the function). + // Offset 0 is a valid branch/call destination (i.e., the function entry + // point), but offsets 1-8 within the landing pad/nop block are invalid + // branch/call destinations (i.e., within the body of the function). mem::transmute::<*const u8, fn(i32) -> i32>((add_two as *const u8).offset(5)) }; let next_answer = do_twice(f, 5); @@ -267,38 +272,40 @@ fn main() { println!("The next answer is: {}", next_answer); } ``` -Fig. 1. Modified example from the [Advanced Functions and -Closures][rust-book-ch19-05] chapter of the [The Rust Programming -Language][rust-book] book. +Fig. 1. Redirecting control flow using an indirect branch/call to an invalid +destination (i.e., within the body of the function). ```shell $ cargo run --release Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1) - Finished release [optimized] target(s) in 0.76s + Finished release [optimized] target(s) in 0.42s Running `target/release/rust-cfi-1` The answer is: 12 With CFI enabled, you should not see the next answer The next answer is: 14 $ ``` -Fig. 2. Build and execution of the modified example with LLVM CFI disabled. +Fig. 2. Build and execution of Fig. 1 with LLVM CFI disabled. ```shell -$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release +$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu + ... Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1) - Finished release [optimized] target(s) in 3.39s - Running `target/release/rust-cfi-1` + Finished release [optimized] target(s) in 1m 08s + Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-1` The answer is: 12 With CFI enabled, you should not see the next answer Illegal instruction $ ``` -Fig. 3. Build and execution of the modified example with LLVM CFI enabled. +Fig. 3. Build and execution of Fig. 1 with LLVM CFI enabled. When LLVM CFI is enabled, if there are any attempts to change/hijack control flow using an indirect branch/call to an invalid destination, the execution is terminated (see Fig. 3). +## Example 2: Redirecting control flow using an indirect branch/call to a function with a different number of parameters + ```rust use std::mem; @@ -327,39 +334,42 @@ fn main() { println!("The next answer is: {}", next_answer); } ``` -Fig. 4. Another modified example from the [Advanced Functions and -Closures][rust-book-ch19-05] chapter of the [The Rust Programming -Language][rust-book] book. +Fig. 4. Redirecting control flow using an indirect branch/call to a function +with a different number of parameters than arguments intended/passed in the +call/branch site. ```shell $ cargo run --release Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2) - Finished release [optimized] target(s) in 0.76s + Finished release [optimized] target(s) in 0.43s Running `target/release/rust-cfi-2` The answer is: 12 With CFI enabled, you should not see the next answer The next answer is: 14 $ ``` -Fig. 5. Build and execution of the modified example with LLVM CFI disabled. +Fig. 5. Build and execution of Fig. 4 with LLVM CFI disabled. ```shell -$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release +$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu + ... Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2) - Finished release [optimized] target(s) in 3.38s - Running `target/release/rust-cfi-2` + Finished release [optimized] target(s) in 1m 08s + Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-2` The answer is: 12 With CFI enabled, you should not see the next answer Illegal instruction $ ``` -Fig. 6. Build and execution of the modified example with LLVM CFI enabled. +Fig. 6. Build and execution of Fig. 4 with LLVM CFI enabled. When LLVM CFI is enabled, if there are any attempts to change/hijack control flow using an indirect branch/call to a function with different number of parameters than arguments intended/passed in the call/branch site, the execution is also terminated (see Fig. 6). +## Example 3: Redirecting control flow using an indirect branch/call to a function with different return and parameter types + ```rust use std::mem; @@ -388,42 +398,46 @@ fn main() { println!("The next answer is: {}", next_answer); } ``` -Fig. 7. Another modified example from the [Advanced Functions and -Closures][rust-book-ch19-05] chapter of the [The Rust Programming -Language][rust-book] book. +Fig. 7. Redirecting control flow using an indirect branch/call to a function +with different return and parameter types than the return type expected and +arguments intended/passed at the call/branch site. ```shell $ cargo run --release Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3) - Finished release [optimized] target(s) in 0.74s + Finished release [optimized] target(s) in 0.44s Running `target/release/rust-cfi-3` The answer is: 12 With CFI enabled, you should not see the next answer The next answer is: 14 $ ``` -Fig. 8. Build and execution of the modified example with LLVM CFI disabled. +Fig. 8. Build and execution of Fig. 7 with LLVM CFI disabled. ```shell -$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release +$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu + ... Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3) - Finished release [optimized] target(s) in 3.40s - Running `target/release/rust-cfi-3` + Finished release [optimized] target(s) in 1m 07s + Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-3` The answer is: 12 With CFI enabled, you should not see the next answer Illegal instruction $ ``` -Fig. 9. Build and execution of the modified example with LLVM CFI enabled. +Fig. 9. Build and execution of Fig. 7 with LLVM CFI enabled. When LLVM CFI is enabled, if there are any attempts to change/hijack control flow using an indirect branch/call to a function with different return and parameter types than the return type expected and arguments intended/passed in the call/branch site, the execution is also terminated (see Fig. 9). +## Example 4: Redirecting control flow using an indirect branch/call to a function with different return and parameter types across the FFI boundary + ```ignore (cannot-test-this-because-uses-custom-build) int -do_twice(int (*fn)(int), int arg) { +do_twice(int (*fn)(int), int arg) +{ return fn(arg) + fn(arg); } ``` @@ -459,54 +473,49 @@ fn main() { println!("The next answer is: {}", next_answer); } ``` -Fig. 11. Another modified example from the [Advanced Functions and -Closures][rust-book-ch19-05] chapter of the [The Rust Programming -Language][rust-book] book. +Fig. 11. Redirecting control flow using an indirect branch/call to a function +with different return and parameter types than the return type expected and +arguments intended/passed in the call/branch site, across the FFI boundary. ```shell $ make -mkdir -p target/debug -clang -I. -Isrc -Wall -flto -fvisibility=hidden -c -emit-llvm src/foo.c -o target/debug/libfoo.bc -llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc -RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build - Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1) - Finished dev [unoptimized + debuginfo] target(s) in 0.45s -$ ./target/debug/main +mkdir -p target/release +clang -I. -Isrc -Wall -c src/foo.c -o target/release/libfoo.o +llvm-ar rcs target/release/libfoo.a target/release/libfoo.o +RUSTFLAGS="-L./target/release -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build --release + Compiling rust-cfi-4 v0.1.0 (/home/rcvalle/rust-cfi-4) + Finished release [optimized] target(s) in 0.49s +$ ./target/release/rust-cfi-4 The answer is: 12 With CFI enabled, you should not see the next answer The next answer is: 14 $ ``` -Fig. 12. Build and execution of the modified example with LLVM CFI disabled. +Fig. 12. Build and execution of Figs. 10–11 with LLVM CFI disabled. ```shell $ make -mkdir -p target/debug -clang -I. -Isrc -Wall -flto -fvisibility=hidden -fsanitize=cfi -fsanitize-cfi-icall-normalize-integers -c -emit-llvm src/foo.c -o target/debug/libfoo.bc -llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc -RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers" cargo build - Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1) - Finished dev [unoptimized + debuginfo] target(s) in 0.45s -$ ./target/debug/main +mkdir -p target/release +clang -I. -Isrc -Wall -flto -fsanitize=cfi -fsanitize-cfi-icall-experimental-normalize-integers -fvisibility=hidden -c -emit-llvm src/foo.c -o target/release/libfoo.bc +llvm-ar rcs target/release/libfoo.a target/release/libfoo.bc +RUSTFLAGS="-L./target/release -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers" cargo build -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu + ... + Compiling rust-cfi-4 v0.1.0 (/home/rcvalle/rust-cfi-4) + Finished release [optimized] target(s) in 1m 06s +$ ./target/x86_64-unknown-linux-gnu/release/rust-cfi-4 The answer is: 12 With CFI enabled, you should not see the next answer Illegal instruction $ ``` -Fig. 13. Build and execution of the modified example with LLVM CFI enabled. - -When LLVM CFI is enabled, if there are any attempts to change/hijack control -flow using an indirect branch/call to a function with different return and -parameter types than the return type expected and arguments intended/passed in -the call/branch site, even across the FFI boundary and for extern "C" function -types indirectly called (i.e., callbacks/function pointers) across the FFI -boundary, in C or C++ and Rust -compiled code mixed-language binaries, also -known as “mixed binaries” (i.e., for when C or C++ and Rust -compiled code share -the same virtual address space), the execution is also terminated (see Fig. 13). - - -[rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html -[rust-book]: https://doc.rust-lang.org/book/title-page.html +Fig. 13. Build and execution of FIgs. 10–11 with LLVM CFI enabled. + +When LLVM CFI is enabled, if there are any attempts to redirect control flow +using an indirect branch/call to a function with different return and parameter +types than the return type expected and arguments intended/passed in the +call/branch site, even across the FFI boundary and for extern "C" function types +indirectly called (i.e., callbacks/function pointers) across the FFI boundary, +the execution is also terminated (see Fig. 13). # HWAddressSanitizer diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 937aac8d25e..24c0ea3f60a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -102,14 +102,10 @@ pub(super) fn check( ]), ("None", "unwrap_or_else", _) => match args[0].kind { hir::ExprKind::Closure(hir::Closure { - fn_decl: - hir::FnDecl { - output: hir::FnRetTy::DefaultReturn(span) | hir::FnRetTy::Return(hir::Ty { span, .. }), - .. - }, + body, .. }) => Some(vec![ - (expr.span.with_hi(span.hi()), String::new()), + (expr.span.with_hi(cx.tcx.hir().body(*body).value.span.lo()), String::new()), (expr.span.with_lo(args[0].span.hi()), String::new()), ]), _ => None, diff --git a/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr b/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr index a52e1fcb9e3..8b9d159b59c 100644 --- a/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr +++ b/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr @@ -2,7 +2,7 @@ error: this function has too many arguments (11/10) --> $DIR/too_many_arguments.rs:4:1 | LL | fn too_many(p1: u8, p2: u8, p3: u8, p4: u8, p5: u8, p6: u8, p7: u8, p8: u8, p9: u8, p10: u8, p11: u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::too-many-arguments` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]` diff --git a/src/tools/clippy/tests/ui/functions.stderr b/src/tools/clippy/tests/ui/functions.stderr index 371ea161260..4b06cd03889 100644 --- a/src/tools/clippy/tests/ui/functions.stderr +++ b/src/tools/clippy/tests/ui/functions.stderr @@ -2,7 +2,7 @@ error: this function has too many arguments (8/7) --> $DIR/functions.rs:8:1 | LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::too-many-arguments` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]` @@ -17,7 +17,7 @@ LL | | two: u32, ... | LL | | eight: () LL | | ) { - | |__^ + | |_^ error: this function has too many arguments (8/7) --> $DIR/functions.rs:48:5 @@ -29,7 +29,7 @@ error: this function has too many arguments (8/7) --> $DIR/functions.rs:58:5 | LL | fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this public function might dereference a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:68:34 diff --git a/src/tools/clippy/tests/ui/must_use_unit.stderr b/src/tools/clippy/tests/ui/must_use_unit.stderr index e67d9b5b9d8..f2ee185857d 100644 --- a/src/tools/clippy/tests/ui/must_use_unit.stderr +++ b/src/tools/clippy/tests/ui/must_use_unit.stderr @@ -4,7 +4,7 @@ error: this unit-returning function has a `#[must_use]` attribute LL | #[must_use] | ----------- help: remove the attribute LL | pub fn must_use_default() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::must-use-unit` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::must_use_unit)]` @@ -23,7 +23,7 @@ error: this unit-returning function has a `#[must_use]` attribute LL | #[must_use = "With note"] | ------------------------- help: remove the attribute LL | pub fn must_use_with_note() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed index 87df1f8cb08..b17343aa9ba 100644 --- a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed @@ -23,7 +23,7 @@ fn unwrap_option_none() { let _val: u16 = 234; let _val: u16 = 234; let _val: u16 = { 234 }; - let _val: u16 = { 234 }; + let _val: u16 = { 234 }; panic!(); panic!("this always happens"); @@ -31,7 +31,7 @@ fn unwrap_option_none() { 234; 234; { 234 }; - { 234 }; + { 234 }; } fn unwrap_result_ok() { diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr index 013907f59c4..4940091be60 100644 --- a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr @@ -116,7 +116,7 @@ LL | let _val: u16 = None.unwrap_or_else(|| -> u16 { 234 }); help: remove the `None` and `unwrap_or_else()` | LL - let _val: u16 = None.unwrap_or_else(|| -> u16 { 234 }); -LL + let _val: u16 = { 234 }; +LL + let _val: u16 = { 234 }; | error: used `unwrap()` on `None` value @@ -187,7 +187,7 @@ LL | None::<u16>.unwrap_or_else(|| -> u16 { 234 }); help: remove the `None` and `unwrap_or_else()` | LL - None::<u16>.unwrap_or_else(|| -> u16 { 234 }); -LL + { 234 }; +LL + { 234 }; | error: used `unwrap()` on `Ok` value diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index d5bc38303e0..002cffa9b0c 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -2599,7 +2599,8 @@ fn rewrite_fn_base( if where_clause_str.is_empty() { if let ast::FnRetTy::Default(ret_span) = fd.output { match recover_missing_comment_in_span( - mk_sp(params_span.hi(), ret_span.hi()), + // from after the closing paren to right before block or semicolon + mk_sp(ret_span.lo(), span.hi()), shape, context, last_line_width(&result), diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff index 7ba51ccdbf6..d585ae89e82 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff @@ -20,6 +20,7 @@ _2 = const u8::MAX; StorageLive(_3); _3 = const 1_u8; + StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable]; + _4 = const (0_u8, true); @@ -29,6 +30,7 @@ bb1: { - _1 = move (_4.0: u8); + _1 = const 0_u8; + StorageDead(_4); StorageDead(_3); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff index 545b7f22f6e..9fe39090638 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff @@ -20,6 +20,7 @@ _2 = const u8::MAX; StorageLive(_3); _3 = const 1_u8; + StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue]; + _4 = const (0_u8, true); @@ -29,6 +30,7 @@ bb1: { - _1 = move (_4.0: u8); + _1 = const 0_u8; + StorageDead(_4); StorageDead(_3); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff index 9a68d3b51b5..87bb1454c96 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff @@ -20,6 +20,7 @@ _2 = const u8::MAX; StorageLive(_3); _3 = const 1_u8; + StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable]; + _4 = CheckedAdd(const u8::MAX, const 1_u8); @@ -29,6 +30,7 @@ bb1: { - _1 = move (_4.0: u8); + _1 = const 0_u8; + StorageDead(_4); StorageDead(_3); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff index c1d281ab788..b2f13640a4c 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff @@ -20,6 +20,7 @@ _2 = const u8::MAX; StorageLive(_3); _3 = const 1_u8; + StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue]; + _4 = CheckedAdd(const u8::MAX, const 1_u8); @@ -29,6 +30,7 @@ bb1: { - _1 = move (_4.0: u8); + _1 = const 0_u8; + StorageDead(_4); StorageDead(_3); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir index 721fac27d88..10b81e59b5f 100644 --- a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir @@ -41,6 +41,8 @@ fn foo(_1: T, _2: i32) -> (i32, T) { _7 = (move _8,); StorageLive(_9); _9 = move (_7.0: i32); + StorageLive(_10); + StorageLive(_12); StorageLive(_11); _10 = ((*_6).0: &i32); _11 = (*_10); @@ -50,6 +52,8 @@ fn foo(_1: T, _2: i32) -> (i32, T) { _0 = (move _11, move _13); StorageDead(_13); StorageDead(_11); + StorageDead(_12); + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_7); diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff index 4a816e024c5..06ee8c464d5 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff @@ -7,12 +7,11 @@ let mut _2: std::pin::Pin<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>; let mut _3: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; let mut _4: {generator@$DIR/inline_generator.rs:16:5: 16:8}; -+ let mut _6: bool; ++ let mut _5: bool; scope 1 { debug _r => _1; } + scope 2 (inlined g) { -+ let mut _5: {generator@$DIR/inline_generator.rs:16:5: 16:8}; + } + scope 3 (inlined Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>::new) { + debug pointer => _3; @@ -23,10 +22,10 @@ + } + } + scope 6 (inlined g::{closure#0}) { -+ debug a => _6; -+ let mut _7: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; -+ let mut _8: u32; -+ let mut _9: i32; ++ debug a => _5; ++ let mut _6: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; ++ let mut _7: u32; ++ let mut _8: i32; + } bb0: { @@ -35,24 +34,25 @@ StorageLive(_3); StorageLive(_4); - _4 = g() -> [return: bb1, unwind unreachable]; -+ StorageLive(_5); -+ _5 = {generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)}; -+ _4 = move (_5 as subtype {generator@$DIR/inline_generator.rs:16:5: 16:8}); -+ StorageDead(_5); ++ _4 = {generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)}; + _3 = &mut _4; + _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}> { pointer: move _3 }; + StorageDead(_3); ++ StorageLive(_5); ++ _5 = const false; + StorageLive(_6); -+ _6 = const false; -+ _7 = (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); -+ _8 = discriminant((*_7)); -+ switchInt(move _8) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9]; ++ StorageLive(_7); ++ _6 = (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); ++ _7 = discriminant((*_6)); ++ switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9]; } bb1: { - _3 = &mut _4; - _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>::new(move _3) -> [return: bb2, unwind unreachable]; ++ StorageDead(_7); + StorageDead(_6); ++ StorageDead(_5); + StorageDead(_2); + drop(_4) -> [return: bb2, unwind unreachable]; } @@ -69,8 +69,8 @@ bb3: { - StorageDead(_2); - drop(_4) -> [return: bb4, unwind unreachable]; -+ StorageLive(_9); -+ switchInt(_6) -> [0: bb4, otherwise: bb5]; ++ StorageLive(_8); ++ switchInt(_5) -> [0: bb4, otherwise: bb5]; } bb4: { @@ -78,18 +78,18 @@ - _0 = const (); - StorageDead(_1); - return; -+ _9 = const 13_i32; ++ _8 = const 13_i32; + goto -> bb6; + } + + bb5: { -+ _9 = const 7_i32; ++ _8 = const 7_i32; + goto -> bb6; + } + + bb6: { -+ _1 = GeneratorState::<i32, bool>::Yielded(move _9); -+ discriminant((*_7)) = 3; ++ _1 = GeneratorState::<i32, bool>::Yielded(move _8); ++ discriminant((*_6)) = 3; + goto -> bb1; + } + @@ -98,10 +98,10 @@ + } + + bb8: { -+ StorageLive(_9); -+ StorageDead(_9); -+ _1 = GeneratorState::<i32, bool>::Complete(_6); -+ discriminant((*_7)) = 1; ++ StorageLive(_8); ++ StorageDead(_8); ++ _1 = GeneratorState::<i32, bool>::Complete(_5); ++ discriminant((*_6)) = 1; + goto -> bb1; + } + diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff index 2b910cd6543..da29ba5f50d 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff @@ -7,12 +7,11 @@ let mut _2: std::pin::Pin<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>; let mut _3: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; let mut _4: {generator@$DIR/inline_generator.rs:16:5: 16:8}; -+ let mut _6: bool; ++ let mut _5: bool; scope 1 { debug _r => _1; } + scope 2 (inlined g) { -+ let mut _5: {generator@$DIR/inline_generator.rs:16:5: 16:8}; + } + scope 3 (inlined Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>::new) { + debug pointer => _3; @@ -23,10 +22,10 @@ + } + } + scope 6 (inlined g::{closure#0}) { -+ debug a => _6; -+ let mut _7: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; -+ let mut _8: u32; -+ let mut _9: i32; ++ debug a => _5; ++ let mut _6: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; ++ let mut _7: u32; ++ let mut _8: i32; + } bb0: { @@ -38,10 +37,7 @@ - } - - bb1: { -+ StorageLive(_5); -+ _5 = {generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)}; -+ _4 = move (_5 as subtype {generator@$DIR/inline_generator.rs:16:5: 16:8}); -+ StorageDead(_5); ++ _4 = {generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)}; _3 = &mut _4; - _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>::new(move _3) -> [return: bb2, unwind: bb5]; - } @@ -50,16 +46,20 @@ + _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}> { pointer: move _3 }; StorageDead(_3); - _1 = <{generator@$DIR/inline_generator.rs:16:5: 16:8} as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb5]; ++ StorageLive(_5); ++ _5 = const false; + StorageLive(_6); -+ _6 = const false; -+ _7 = (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); -+ _8 = discriminant((*_7)); -+ switchInt(move _8) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11]; ++ StorageLive(_7); ++ _6 = (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); ++ _7 = discriminant((*_6)); ++ switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11]; } - bb3: { + bb1: { ++ StorageDead(_7); + StorageDead(_6); ++ StorageDead(_5); StorageDead(_2); - drop(_4) -> [return: bb4, unwind: bb6]; + drop(_4) -> [return: bb2, unwind: bb4]; @@ -85,23 +85,23 @@ + } + + bb5: { -+ StorageLive(_9); -+ switchInt(_6) -> [0: bb6, otherwise: bb7]; ++ StorageLive(_8); ++ switchInt(_5) -> [0: bb6, otherwise: bb7]; + } + + bb6: { -+ _9 = const 13_i32; ++ _8 = const 13_i32; + goto -> bb8; + } + + bb7: { -+ _9 = const 7_i32; ++ _8 = const 7_i32; + goto -> bb8; + } + + bb8: { -+ _1 = GeneratorState::<i32, bool>::Yielded(move _9); -+ discriminant((*_7)) = 3; ++ _1 = GeneratorState::<i32, bool>::Yielded(move _8); ++ discriminant((*_6)) = 3; + goto -> bb1; + } + @@ -110,10 +110,10 @@ + } + + bb10: { -+ StorageLive(_9); -+ StorageDead(_9); -+ _1 = GeneratorState::<i32, bool>::Complete(_6); -+ discriminant((*_7)) = 1; ++ StorageLive(_8); ++ StorageDead(_8); ++ _1 = GeneratorState::<i32, bool>::Complete(_5); ++ discriminant((*_6)) = 1; + goto -> bb1; + } + diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff index dc0ab255afd..b90e0505c54 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff @@ -122,9 +122,14 @@ + _3 = const _; + _2 = Vec::<u32> { buf: move _3, len: const 0_usize }; + StorageDead(_3); ++ StorageLive(_4); ++ StorageLive(_5); ++ StorageLive(_6); ++ StorageLive(_7); + _4 = SizeOf(std::vec::Vec<u32>); + _5 = AlignOf(std::vec::Vec<u32>); + StorageLive(_8); ++ StorageLive(_10); + StorageLive(_11); + StorageLive(_12); + StorageLive(_13); @@ -178,10 +183,15 @@ + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); ++ StorageDead(_10); + StorageDead(_8); + _1 = ShallowInitBox(move _6, std::vec::Vec<u32>); + _7 = (((_1.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>); + (*_7) = move _2; ++ StorageDead(_7); ++ StorageDead(_6); ++ StorageDead(_5); ++ StorageDead(_4); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind unreachable]; diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff index 675292f06d6..f9c637caa18 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff @@ -122,9 +122,14 @@ + _3 = const _; + _2 = Vec::<u32> { buf: move _3, len: const 0_usize }; + StorageDead(_3); ++ StorageLive(_4); ++ StorageLive(_5); ++ StorageLive(_6); ++ StorageLive(_7); + _4 = SizeOf(std::vec::Vec<u32>); + _5 = AlignOf(std::vec::Vec<u32>); + StorageLive(_8); ++ StorageLive(_10); + StorageLive(_11); + StorageLive(_12); + StorageLive(_13); @@ -195,10 +200,15 @@ + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); ++ StorageDead(_10); + StorageDead(_8); + _1 = ShallowInitBox(move _6, std::vec::Vec<u32>); + _7 = (((_1.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>); + (*_7) = move _2; ++ StorageDead(_7); ++ StorageDead(_6); ++ StorageDead(_5); ++ StorageDead(_4); + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb1, unwind: bb2]; diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff index 3d0c1072527..688ab9c563a 100644 --- a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff @@ -18,6 +18,7 @@ bb0: { - _0 = inner() -> [return: bb1, unwind unreachable]; + StorageLive(_1); ++ StorageLive(_2); + _1 = const _; + _0 = index() -> [return: bb1, unwind unreachable]; } @@ -40,6 +41,7 @@ + + bb4: { + StorageDead(_3); ++ StorageDead(_2); + StorageDead(_1); return; } diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff index 16a19f4a356..e4d2b1a7ffb 100644 --- a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff @@ -18,6 +18,7 @@ bb0: { - _0 = inner() -> [return: bb1, unwind continue]; + StorageLive(_1); ++ StorageLive(_2); + _1 = const _; + _0 = index() -> [return: bb1, unwind continue]; } @@ -40,6 +41,7 @@ + + bb4: { + StorageDead(_3); ++ StorageDead(_2); + StorageDead(_1); return; } diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index 6837da27a96..62d7e839f5a 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -17,9 +17,13 @@ fn b(_1: &mut Box<T>) -> &mut T { StorageLive(_3); StorageLive(_4); _4 = &mut (*_1); + StorageLive(_5); + StorageLive(_6); _5 = deref_copy (*_4); _6 = (((_5.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); _3 = &mut (*_6); + StorageDead(_6); + StorageDead(_5); _2 = &mut (*_3); StorageDead(_4); _0 = &mut (*_2); diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index d09bfc33ff1..bc0aa06a752 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -15,9 +15,13 @@ fn d(_1: &Box<T>) -> &T { StorageLive(_2); StorageLive(_3); _3 = &(*_1); + StorageLive(_4); + StorageLive(_5); _4 = deref_copy (*_3); _5 = (((_4.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); _2 = &(*_5); + StorageDead(_5); + StorageDead(_4); _0 = &(*_2); StorageDead(_3); StorageDead(_2); diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff index e3c57347392..018b6c1ee95 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff @@ -30,6 +30,7 @@ _2 = move _1; - _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable]; + StorageLive(_3); ++ StorageLive(_4); + _4 = discriminant(_2); + switchInt(move _4) -> [1: bb2, otherwise: bb1]; } @@ -40,6 +41,7 @@ + + bb2: { + _0 = move ((_2 as Some).0: T); ++ StorageDead(_4); + StorageDead(_3); StorageDead(_2); return; diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff index fc638cb3ace..47845758a3f 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff @@ -30,6 +30,7 @@ _2 = move _1; - _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2]; + StorageLive(_3); ++ StorageLive(_4); + _4 = discriminant(_2); + switchInt(move _4) -> [1: bb2, otherwise: bb1]; } @@ -44,6 +45,7 @@ - resume; + bb2: { + _0 = move ((_2 as Some).0: T); ++ StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + return; diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir index fcc4d43ced6..392f085bd4d 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir @@ -25,12 +25,14 @@ fn unwrap_unchecked(_1: Option<T>) -> T { bb0: { StorageLive(_3); + StorageLive(_2); _2 = discriminant(_1); switchInt(move _2) -> [1: bb1, otherwise: bb2]; } bb1: { _0 = move ((_1 as Some).0: T); + StorageDead(_2); StorageDead(_3); return; } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir index fcc4d43ced6..392f085bd4d 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir @@ -25,12 +25,14 @@ fn unwrap_unchecked(_1: Option<T>) -> T { bb0: { StorageLive(_3); + StorageLive(_2); _2 = discriminant(_1); switchInt(move _2) -> [1: bb1, otherwise: bb2]; } bb1: { _0 = move ((_1 as Some).0: T); + StorageDead(_2); StorageDead(_3); return; } diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir index f8c85941813..55ccf6a8b45 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir @@ -30,6 +30,7 @@ fn num_to_digit(_1: char) -> u32 { } bb1: { + StorageLive(_3); _3 = discriminant(_2); StorageDead(_7); StorageDead(_2); @@ -37,11 +38,13 @@ fn num_to_digit(_1: char) -> u32 { } bb2: { + StorageDead(_3); StorageLive(_4); _4 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind unreachable]; } bb3: { + StorageLive(_5); _5 = discriminant(_4); switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb6]; } @@ -52,6 +55,7 @@ fn num_to_digit(_1: char) -> u32 { bb5: { _0 = move ((_4 as Some).0: u32); + StorageDead(_5); StorageDead(_4); goto -> bb8; } @@ -61,6 +65,7 @@ fn num_to_digit(_1: char) -> u32 { } bb7: { + StorageDead(_3); _0 = const 0_u32; goto -> bb8; } diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir index df7392edc50..cb70a83e7f8 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir @@ -30,6 +30,7 @@ fn num_to_digit(_1: char) -> u32 { } bb1: { + StorageLive(_3); _3 = discriminant(_2); StorageDead(_7); StorageDead(_2); @@ -37,11 +38,13 @@ fn num_to_digit(_1: char) -> u32 { } bb2: { + StorageDead(_3); StorageLive(_4); _4 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind continue]; } bb3: { + StorageLive(_5); _5 = discriminant(_4); switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb6]; } @@ -52,6 +55,7 @@ fn num_to_digit(_1: char) -> u32 { bb5: { _0 = move ((_4 as Some).0: u32); + StorageDead(_5); StorageDead(_4); goto -> bb8; } @@ -61,6 +65,7 @@ fn num_to_digit(_1: char) -> u32 { } bb7: { + StorageDead(_3); _0 = const 0_u32; goto -> bb8; } diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir index 75f81c5aaca..e3c81061a46 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir @@ -36,8 +36,10 @@ fn step_forward(_1: u32, _2: usize) -> u32 { bb1: { StorageLive(_5); + StorageLive(_4); _4 = discriminant(_3); _5 = Eq(_4, const 1_isize); + StorageDead(_4); _6 = Not(move _5); StorageDead(_5); switchInt(move _6) -> [0: bb2, otherwise: bb3]; diff --git a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir index 48b780aea62..80a470c9482 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir @@ -18,6 +18,7 @@ fn ezmap(_1: Option<i32>) -> Option<i32> { } bb0: { + StorageLive(_2); _2 = discriminant(_1); switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; } @@ -37,6 +38,7 @@ fn ezmap(_1: Option<i32>) -> Option<i32> { } bb3: { + StorageDead(_2); return; } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index ed286beb4ca..9c10e96b0ea 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -98,6 +98,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 StorageLive(_35); StorageLive(_11); _11 = _8; + StorageLive(_12); + StorageLive(_13); _12 = deref_copy _4; _13 = deref_copy _11; StorageLive(_14); @@ -107,6 +109,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 _16 = Le(move _14, move _15); StorageDead(_15); StorageDead(_14); + StorageDead(_13); + StorageDead(_12); switchInt(move _16) -> [0: bb1, otherwise: bb2]; } @@ -126,6 +130,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 StorageLive(_37); StorageLive(_17); _17 = _6; + StorageLive(_18); + StorageLive(_19); _18 = deref_copy _10; _19 = deref_copy _17; StorageLive(_20); @@ -135,6 +141,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 _22 = Le(move _20, move _21); StorageDead(_21); StorageDead(_20); + StorageDead(_19); + StorageDead(_18); switchInt(move _22) -> [0: bb3, otherwise: bb8]; } @@ -151,6 +159,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 StorageLive(_39); StorageLive(_23); _23 = _4; + StorageLive(_24); + StorageLive(_25); _24 = deref_copy _8; _25 = deref_copy _23; StorageLive(_26); @@ -160,6 +170,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 _28 = Le(move _26, move _27); StorageDead(_27); StorageDead(_26); + StorageDead(_25); + StorageDead(_24); switchInt(move _28) -> [0: bb5, otherwise: bb6]; } @@ -179,6 +191,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 StorageLive(_41); StorageLive(_29); _29 = _10; + StorageLive(_30); + StorageLive(_31); _30 = deref_copy _6; _31 = deref_copy _29; StorageLive(_32); @@ -188,6 +202,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 _0 = Le(move _32, move _33); StorageDead(_33); StorageDead(_32); + StorageDead(_31); + StorageDead(_30); StorageDead(_29); StorageDead(_41); StorageDead(_40); diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index ca1528b6ab1..491db551a7d 100644 --- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -48,6 +48,7 @@ bb0: { StorageLive(_3); + StorageLive(_9); StorageLive(_10); StorageLive(_11); _9 = discriminant(_1); @@ -57,6 +58,7 @@ bb1: { StorageDead(_11); StorageDead(_10); + StorageDead(_9); _5 = discriminant(_3); switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; } diff --git a/tests/rustdoc/issue-25001.rs b/tests/rustdoc/anchor-id-duplicate-method-name-25001.rs index 268fae59496..ffb0765d3c3 100644 --- a/tests/rustdoc/issue-25001.rs +++ b/tests/rustdoc/anchor-id-duplicate-method-name-25001.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/25001 +#![crate_name="issue_25001"] + // @has issue_25001/struct.Foo.html pub struct Foo<T>(T); diff --git a/tests/rustdoc/issue-28478.rs b/tests/rustdoc/anchor-id-trait-tymethod-28478.rs index 497276e6826..5685040dc1e 100644 --- a/tests/rustdoc/issue-28478.rs +++ b/tests/rustdoc/anchor-id-trait-tymethod-28478.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/28478 +#![crate_name="issue_28478"] + #![feature(associated_type_defaults)] // @has issue_28478/trait.Bar.html diff --git a/tests/rustdoc/issue-21474.rs b/tests/rustdoc/deduplicate-glob-import-impl-21474.rs index 5de26abace6..2a675b4b6ef 100644 --- a/tests/rustdoc/issue-21474.rs +++ b/tests/rustdoc/deduplicate-glob-import-impl-21474.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/21474 +#![crate_name="issue_21474"] + pub use inner::*; mod inner { diff --git a/tests/rustdoc/issue-22025.rs b/tests/rustdoc/deduplicate-trait-impl-22025.rs index a721a15f463..65a556e3a70 100644 --- a/tests/rustdoc/issue-22025.rs +++ b/tests/rustdoc/deduplicate-trait-impl-22025.rs @@ -1,6 +1,9 @@ // aux-build:issue-22025.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/22025 +#![crate_name="issue_22025"] + extern crate issue_22025; pub use issue_22025::foo::{Foo, Bar}; diff --git a/tests/rustdoc/doctest-hide-empty-line-23106.rs b/tests/rustdoc/doctest-hide-empty-line-23106.rs new file mode 100644 index 00000000000..8e1e2cf098c --- /dev/null +++ b/tests/rustdoc/doctest-hide-empty-line-23106.rs @@ -0,0 +1,10 @@ +// compile-flags:--test + +// https://github.com/rust-lang/rust/issues/23106 +#![crate_name="issue_23106"] + +/// ``` +/// # +/// ``` +pub fn main() { +} diff --git a/tests/rustdoc/issue-23744.rs b/tests/rustdoc/doctest-markdown-inline-parse-23744.rs index 642817396b2..128e2daba07 100644 --- a/tests/rustdoc/issue-23744.rs +++ b/tests/rustdoc/doctest-markdown-inline-parse-23744.rs @@ -1,5 +1,8 @@ // compile-flags:--test +// https://github.com/rust-lang/rust/issues/23744 +#![crate_name="issue_23744"] + /// Example of rustdoc incorrectly parsing <code>```rust,should_panic</code>. /// /// ```should_panic diff --git a/tests/rustdoc/issue-25944.rs b/tests/rustdoc/doctest-multi-line-string-literal-25944.rs index 49625294bbe..eec796e4fbf 100644 --- a/tests/rustdoc/issue-25944.rs +++ b/tests/rustdoc/doctest-multi-line-string-literal-25944.rs @@ -1,5 +1,8 @@ // compile-flags:--test +// https://github.com/rust-lang/rust/issues/25944 +#![crate_name="issue_25944"] + /// ``` /// let a = r#" /// foo diff --git a/tests/rustdoc/issue-22038.rs b/tests/rustdoc/extern-fn-22038.rs index de6cc78707c..72d39c32a1c 100644 --- a/tests/rustdoc/issue-22038.rs +++ b/tests/rustdoc/extern-fn-22038.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/22038 +#![crate_name="issue_22038"] + extern "C" { // @has issue_22038/fn.foo1.html \ // '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn foo1()' diff --git a/tests/rustdoc/issue-28927.rs b/tests/rustdoc/ice-reexport-crate-root-28927.rs index 38a520850b6..26debfc60e4 100644 --- a/tests/rustdoc/issue-28927.rs +++ b/tests/rustdoc/ice-reexport-crate-root-28927.rs @@ -2,5 +2,8 @@ // aux-build:issue-28927-1.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/28927 +#![crate_name="issue_28927"] + pub extern crate issue_28927_1 as inner1; pub use inner1 as foo; diff --git a/tests/rustdoc/issue-21092.rs b/tests/rustdoc/impl-assoc-type-21092.rs index b054145a483..f01f098a92f 100644 --- a/tests/rustdoc/issue-21092.rs +++ b/tests/rustdoc/impl-assoc-type-21092.rs @@ -1,6 +1,9 @@ // aux-build:issue-21092.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/21092 +#![crate_name="issue_21092"] + extern crate issue_21092; // @has issue_21092/struct.Bar.html diff --git a/tests/rustdoc/auxiliary/issue-21801.rs b/tests/rustdoc/inline_cross/auxiliary/issue-21801.rs index 732612ff000..732612ff000 100644 --- a/tests/rustdoc/auxiliary/issue-21801.rs +++ b/tests/rustdoc/inline_cross/auxiliary/issue-21801.rs diff --git a/tests/rustdoc/auxiliary/issue-23207-1.rs b/tests/rustdoc/inline_cross/auxiliary/issue-23207-1.rs index 8531d5f1acd..8531d5f1acd 100644 --- a/tests/rustdoc/auxiliary/issue-23207-1.rs +++ b/tests/rustdoc/inline_cross/auxiliary/issue-23207-1.rs diff --git a/tests/rustdoc/auxiliary/issue-23207-2.rs b/tests/rustdoc/inline_cross/auxiliary/issue-23207-2.rs index b92b1665316..b92b1665316 100644 --- a/tests/rustdoc/auxiliary/issue-23207-2.rs +++ b/tests/rustdoc/inline_cross/auxiliary/issue-23207-2.rs diff --git a/tests/rustdoc/auxiliary/issue-27362-aux.rs b/tests/rustdoc/inline_cross/auxiliary/issue-27362-aux.rs index 077bdc33e66..077bdc33e66 100644 --- a/tests/rustdoc/auxiliary/issue-27362-aux.rs +++ b/tests/rustdoc/inline_cross/auxiliary/issue-27362-aux.rs diff --git a/tests/rustdoc/issue-27362.rs b/tests/rustdoc/inline_cross/const-fn-27362.rs index 097e4e3b03d..39b904662e0 100644 --- a/tests/rustdoc/issue-27362.rs +++ b/tests/rustdoc/inline_cross/const-fn-27362.rs @@ -1,6 +1,9 @@ // aux-build:issue-27362-aux.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/27362 +#![crate_name="issue_27362"] + extern crate issue_27362_aux; pub use issue_27362_aux::*; diff --git a/tests/rustdoc/issue-23207.rs b/tests/rustdoc/inline_cross/deduplicate-inlined-items-23207.rs index 1a4b849ee82..4e9596db589 100644 --- a/tests/rustdoc/issue-23207.rs +++ b/tests/rustdoc/inline_cross/deduplicate-inlined-items-23207.rs @@ -2,6 +2,9 @@ // aux-build:issue-23207-2.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/23207 +#![crate_name="issue_23207"] + extern crate issue_23207_2; // @has issue_23207/fmt/index.html diff --git a/tests/rustdoc/issue-21801.rs b/tests/rustdoc/inline_cross/sugar-closure-crate-21801.rs index 29d2ec64c20..bcbb2e9f408 100644 --- a/tests/rustdoc/issue-21801.rs +++ b/tests/rustdoc/inline_cross/sugar-closure-crate-21801.rs @@ -1,6 +1,9 @@ // aux-build:issue-21801.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/21801 +#![crate_name="issue_21801"] + extern crate issue_21801; // @has issue_21801/struct.Foo.html diff --git a/tests/rustdoc/issue-23106.rs b/tests/rustdoc/issue-23106.rs deleted file mode 100644 index 8cda2fc3380..00000000000 --- a/tests/rustdoc/issue-23106.rs +++ /dev/null @@ -1,7 +0,0 @@ -// compile-flags:--test - -/// ``` -/// # -/// ``` -pub fn main() { -} diff --git a/tests/rustdoc/issue-23812.rs b/tests/rustdoc/macro-doc-comment-23812.rs index 08fd1833bce..57c18510b1e 100644 --- a/tests/rustdoc/issue-23812.rs +++ b/tests/rustdoc/macro-doc-comment-23812.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/23812 +#![crate_name="issue_23812"] + macro_rules! doc { (#[$outer:meta] mod $i:ident { #![$inner:meta] }) => ( diff --git a/tests/rustdoc/issue-27862.rs b/tests/rustdoc/markdown-table-escape-pipe-27862.rs index 77522f1be23..9af75d24888 100644 --- a/tests/rustdoc/issue-27862.rs +++ b/tests/rustdoc/markdown-table-escape-pipe-27862.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/27862 +#![crate_name="issue_27862"] + /// Tests | Table /// ------|------------- /// t = b | id = \|x\| x diff --git a/tests/rustdoc/issue-23511.rs b/tests/rustdoc/search-index-primitive-inherent-method-23511.rs index 21d02842431..1d0fe27e192 100644 --- a/tests/rustdoc/issue-23511.rs +++ b/tests/rustdoc/search-index-primitive-inherent-method-23511.rs @@ -2,6 +2,9 @@ #![feature(rustdoc_internals)] #![no_std] +// https://github.com/rust-lang/rust/issues/23511 +#![crate_name="issue_23511"] + pub mod str { #![rustc_doc_primitive = "str"] diff --git a/tests/rustdoc/issue-26606.rs b/tests/rustdoc/src-link-external-macro-26606.rs index d5cb2c710cd..de717a5273b 100644 --- a/tests/rustdoc/issue-26606.rs +++ b/tests/rustdoc/src-link-external-macro-26606.rs @@ -2,10 +2,13 @@ // ignore-cross-compile // build-aux-docs +// https://github.com/rust-lang/rust/issues/26606 +#![crate_name="issue_26606"] + // @has issue_26606_macro/macro.make_item.html #[macro_use] extern crate issue_26606_macro; // @has issue_26606/constant.FOO.html -// @has - '//a[@href="../src/issue_26606/issue-26606.rs.html#11"]' 'source' +// @has - '//a[@href="../src/issue_26606/src-link-external-macro-26606.rs.html#14"]' 'source' make_item!(FOO); diff --git a/tests/rustdoc/issue-26995.rs b/tests/rustdoc/src-mod-path-absolute-26995.rs index fedc9f51749..b67fd9b26db 100644 --- a/tests/rustdoc/issue-26995.rs +++ b/tests/rustdoc/src-mod-path-absolute-26995.rs @@ -1,6 +1,9 @@ // ignore-windows // compile-flags: --no-defaults +// https://github.com/rust-lang/rust/issues/26995 +#![crate_name="issue_26995"] + // @has src/issue_26995/dev/null.html // @has issue_26995/null/index.html '//a/@href' '../../src/issue_26995/dev/null.html' #[path="/dev/null"] diff --git a/tests/rustdoc/issue-27759.rs b/tests/rustdoc/staged-api-feature-issue-27759.rs index 65e0f7cb87b..56a45a600da 100644 --- a/tests/rustdoc/issue-27759.rs +++ b/tests/rustdoc/staged-api-feature-issue-27759.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/27759 +#![crate_name="issue_27759"] + #![feature(staged_api)] #![doc(issue_tracker_base_url = "http://issue_url/")] diff --git a/tests/rustdoc/issue-27104.rs b/tests/rustdoc/strip-priv-imports-pass-27104.rs index 9f2fd907114..e400a8f5011 100644 --- a/tests/rustdoc/issue-27104.rs +++ b/tests/rustdoc/strip-priv-imports-pass-27104.rs @@ -2,6 +2,9 @@ // aux-build:empty.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/27104 +#![crate_name="issue_27104"] + // @has issue_27104/index.html // @!hasraw - 'extern crate std' // @!hasraw - 'use std::prelude::' diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index ce4ee3c2463..d482f62ff06 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -47,12 +47,12 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { assert_eq!(body.blocks.len(), 1); let block = &body.blocks[0]; assert_eq!(block.statements.len(), 1); - match &block.statements[0] { - stable_mir::mir::Statement::Assign(..) => {} + match &block.statements[0].kind { + stable_mir::mir::StatementKind::Assign(..) => {} other => panic!("{other:?}"), } - match &block.terminator { - stable_mir::mir::Terminator::Return => {} + match &block.terminator.kind { + stable_mir::mir::TerminatorKind::Return => {} other => panic!("{other:?}"), } @@ -61,8 +61,8 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { assert_eq!(body.locals.len(), 7); assert_eq!(body.blocks.len(), 4); let block = &body.blocks[0]; - match &block.terminator { - stable_mir::mir::Terminator::Call { .. } => {} + match &block.terminator.kind { + stable_mir::mir::TerminatorKind::Call { .. } => {} other => panic!("{other:?}"), } @@ -70,27 +70,27 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { let body = types.body(); assert_eq!(body.locals.len(), 6); assert_matches!( - body.locals[0].kind(), + body.locals[0].ty.kind(), stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Bool) ); assert_matches!( - body.locals[1].kind(), + body.locals[1].ty.kind(), stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Bool) ); assert_matches!( - body.locals[2].kind(), + body.locals[2].ty.kind(), stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Char) ); assert_matches!( - body.locals[3].kind(), + body.locals[3].ty.kind(), stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Int(stable_mir::ty::IntTy::I32)) ); assert_matches!( - body.locals[4].kind(), + body.locals[4].ty.kind(), stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Uint(stable_mir::ty::UintTy::U64)) ); assert_matches!( - body.locals[5].kind(), + body.locals[5].ty.kind(), stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Float( stable_mir::ty::FloatTy::F64 )) @@ -100,8 +100,8 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { let body = drop.body(); assert_eq!(body.blocks.len(), 2); let block = &body.blocks[0]; - match &block.terminator { - stable_mir::mir::Terminator::Drop { .. } => {} + match &block.terminator.kind { + stable_mir::mir::TerminatorKind::Drop { .. } => {} other => panic!("{other:?}"), } @@ -109,15 +109,15 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { let body = assert.body(); assert_eq!(body.blocks.len(), 2); let block = &body.blocks[0]; - match &block.terminator { - stable_mir::mir::Terminator::Assert { .. } => {} + match &block.terminator.kind { + stable_mir::mir::TerminatorKind::Assert { .. } => {} other => panic!("{other:?}"), } let monomorphic = get_item(&items, (DefKind::Fn, "monomorphic")).unwrap(); for block in monomorphic.body().blocks { - match &block.terminator { - stable_mir::mir::Terminator::Call { func, .. } => match func { + match &block.terminator.kind { + stable_mir::mir::TerminatorKind::Call { func, .. } => match func { stable_mir::mir::Operand::Constant(c) => match &c.literal.literal { stable_mir::ty::ConstantKind::Allocated(alloc) => { assert!(alloc.bytes.is_empty()); @@ -127,7 +127,7 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { mut args, )) => { let func = def.body(); - match func.locals[1] + match func.locals[1].ty .fold(&mut args) .continue_value() .unwrap() @@ -149,7 +149,7 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { }, other => panic!("{other:?}"), }, - stable_mir::mir::Terminator::Return => {} + stable_mir::mir::TerminatorKind::Return => {} other => panic!("{other:?}"), } } diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr index 927422fa8dc..200856caa25 100644 --- a/tests/ui/associated-consts/issue-105330.stderr +++ b/tests/ui/associated-consts/issue-105330.stderr @@ -33,7 +33,7 @@ LL | fn main<A: TraitWAssocConst<A=32>>() { = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers --> $DIR/issue-105330.rs:6:27 | LL | impl TraitWAssocConst for impl Demo { diff --git a/tests/ui/associated-type-bounds/issue-71443-1.stderr b/tests/ui/associated-type-bounds/issue-71443-1.stderr index 15cc9646b2c..09c8ec2e289 100644 --- a/tests/ui/associated-type-bounds/issue-71443-1.stderr +++ b/tests/ui/associated-type-bounds/issue-71443-1.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-71443-1.rs:6:5 | LL | fn hello<F: for<'a> Iterator<Item: 'a>>() { - | - help: try adding a return type: `-> Incorrect` + | - help: try adding a return type: `-> Incorrect` LL | Incorrect | ^^^^^^^^^ expected `()`, found `Incorrect` diff --git a/tests/ui/async-await/in-trait/async-associated-types.rs b/tests/ui/async-await/in-trait/async-associated-types.rs index 3e2739a164f..14f18811c1e 100644 --- a/tests/ui/async-await/in-trait/async-associated-types.rs +++ b/tests/ui/async-await/in-trait/async-associated-types.rs @@ -9,12 +9,14 @@ use std::fmt::Debug; trait MyTrait<'a, 'b, T> where Self: 'a, T: Debug + Sized + 'b { type MyAssoc; + #[allow(async_fn_in_trait)] async fn foo(&'a self, key: &'b T) -> Self::MyAssoc; } impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U { type MyAssoc = (&'a U, &'b T); + #[allow(async_fn_in_trait)] async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { (self, key) } diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs index 06413fe6f82..8143f0bca03 100644 --- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs +++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs @@ -6,10 +6,12 @@ use std::future::Future; trait AsyncTrait { + #[allow(async_fn_in_trait)] async fn default_impl() { assert!(false); } + #[allow(async_fn_in_trait)] async fn call_default_impl() { Self::default_impl().await } diff --git a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs index 3505690f1ec..5d5aa817b4c 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs @@ -10,6 +10,7 @@ use std::pin::Pin; use std::task::Poll; pub trait MyTrait { + #[allow(async_fn_in_trait)] async fn foo(&self) -> i32; } diff --git a/tests/ui/async-await/in-trait/async-example-desugared.rs b/tests/ui/async-await/in-trait/async-example-desugared.rs index 0a5023176fe..7987645c97b 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared.rs @@ -8,6 +8,7 @@ use std::future::Future; trait MyTrait { + #[allow(async_fn_in_trait)] async fn foo(&self) -> i32; } diff --git a/tests/ui/async-await/in-trait/async-example.rs b/tests/ui/async-await/in-trait/async-example.rs index abf94ef7450..8c80c21eabe 100644 --- a/tests/ui/async-await/in-trait/async-example.rs +++ b/tests/ui/async-await/in-trait/async-example.rs @@ -5,7 +5,10 @@ #![allow(incomplete_features)] trait MyTrait { + #[allow(async_fn_in_trait)] async fn foo(&self) -> i32; + + #[allow(async_fn_in_trait)] async fn bar(&self) -> i32; } diff --git a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs index d5481d277e4..96cda4e35da 100644 --- a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs +++ b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs @@ -7,6 +7,7 @@ use std::fmt::Debug; trait MyTrait<'a, 'b, T> { + #[allow(async_fn_in_trait)] async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized; } diff --git a/tests/ui/async-await/in-trait/async-lifetimes.rs b/tests/ui/async-await/in-trait/async-lifetimes.rs index f298e45d239..4b0264bc8d0 100644 --- a/tests/ui/async-await/in-trait/async-lifetimes.rs +++ b/tests/ui/async-await/in-trait/async-lifetimes.rs @@ -5,6 +5,7 @@ #![allow(incomplete_features)] trait MyTrait<'a, 'b, T> { + #[allow(async_fn_in_trait)] async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T); } diff --git a/tests/ui/async-await/in-trait/early-bound-1.rs b/tests/ui/async-await/in-trait/early-bound-1.rs index 6b3b142014b..bc410cc2954 100644 --- a/tests/ui/async-await/in-trait/early-bound-1.rs +++ b/tests/ui/async-await/in-trait/early-bound-1.rs @@ -5,6 +5,7 @@ #![allow(incomplete_features)] pub trait Foo { + #[allow(async_fn_in_trait)] async fn foo(&mut self); } diff --git a/tests/ui/async-await/in-trait/early-bound-2.rs b/tests/ui/async-await/in-trait/early-bound-2.rs index 270443229b0..1974b1d9f7a 100644 --- a/tests/ui/async-await/in-trait/early-bound-2.rs +++ b/tests/ui/async-await/in-trait/early-bound-2.rs @@ -5,6 +5,7 @@ #![allow(incomplete_features)] pub trait Foo { + #[allow(async_fn_in_trait)] async fn foo(&mut self); } diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.rs b/tests/ui/async-await/in-trait/fn-not-async-err2.rs index 78017429f73..e1703415dbd 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err2.rs +++ b/tests/ui/async-await/in-trait/fn-not-async-err2.rs @@ -11,7 +11,7 @@ trait MyTrait { impl MyTrait for i32 { fn foo(&self) -> impl Future<Output = i32> { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in `impl` method return types async { *self } } } diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.stderr b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr index 37d9669c012..a7c897f786e 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err2.stderr +++ b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `impl` method return types --> $DIR/fn-not-async-err2.rs:13:22 | LL | fn foo(&self) -> impl Future<Output = i32> { diff --git a/tests/ui/async-await/in-trait/implied-bounds.rs b/tests/ui/async-await/in-trait/implied-bounds.rs index 52bceb3cc5c..40eebad86c2 100644 --- a/tests/ui/async-await/in-trait/implied-bounds.rs +++ b/tests/ui/async-await/in-trait/implied-bounds.rs @@ -7,6 +7,8 @@ trait TcpStack { type Connection<'a>: Sized where Self: 'a; fn connect<'a>(&'a self) -> Self::Connection<'a>; + + #[allow(async_fn_in_trait)] async fn async_connect<'a>(&'a self) -> Self::Connection<'a>; } diff --git a/tests/ui/async-await/in-trait/issue-102138.rs b/tests/ui/async-await/in-trait/issue-102138.rs index f61b34ed99e..3d9cef0210f 100644 --- a/tests/ui/async-await/in-trait/issue-102138.rs +++ b/tests/ui/async-await/in-trait/issue-102138.rs @@ -10,6 +10,8 @@ async fn yield_now() {} trait AsyncIterator { type Item; + + #[allow(async_fn_in_trait)] async fn next(&mut self) -> Option<Self::Item>; } diff --git a/tests/ui/async-await/in-trait/issue-102219.rs b/tests/ui/async-await/in-trait/issue-102219.rs index 9a35f6515cb..4a23e4be4f7 100644 --- a/tests/ui/async-await/in-trait/issue-102219.rs +++ b/tests/ui/async-await/in-trait/issue-102219.rs @@ -6,5 +6,6 @@ #![allow(incomplete_features)] trait T { + #[allow(async_fn_in_trait)] async fn foo(); } diff --git a/tests/ui/async-await/in-trait/issue-102310.rs b/tests/ui/async-await/in-trait/issue-102310.rs index 49c3e9feeb4..327d432a6a6 100644 --- a/tests/ui/async-await/in-trait/issue-102310.rs +++ b/tests/ui/async-await/in-trait/issue-102310.rs @@ -5,6 +5,7 @@ #![allow(incomplete_features)] pub trait SpiDevice { + #[allow(async_fn_in_trait)] async fn transaction<F, R>(&mut self); } diff --git a/tests/ui/async-await/in-trait/issue-104678.rs b/tests/ui/async-await/in-trait/issue-104678.rs index e396df4e5d1..0a334707505 100644 --- a/tests/ui/async-await/in-trait/issue-104678.rs +++ b/tests/ui/async-await/in-trait/issue-104678.rs @@ -8,6 +8,7 @@ use std::future::Future; pub trait Pool { type Conn; + #[allow(async_fn_in_trait)] async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>( &'a self, callback: F, diff --git a/tests/ui/async-await/in-trait/missing-feature-flag.stderr b/tests/ui/async-await/in-trait/missing-feature-flag.stderr index f6aba1fcdbf..87a7e85bfbb 100644 --- a/tests/ui/async-await/in-trait/missing-feature-flag.stderr +++ b/tests/ui/async-await/in-trait/missing-feature-flag.stderr @@ -7,6 +7,12 @@ LL | async fn foo(_: T) -> &'static str; LL | impl<T> MyTrait<T> for MyStruct {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation +error[E0308]: mismatched types + --> $DIR/missing-feature-flag.rs:16:42 + | +LL | async fn foo(_: i32) -> &'static str {} + | ^^ expected `&str`, found `()` + error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/missing-feature-flag.rs:16:5 | @@ -18,12 +24,6 @@ LL | async fn foo(_: i32) -> &'static str {} | = note: to specialize, `foo` in the parent `impl` must be marked `default` -error[E0308]: mismatched types - --> $DIR/missing-feature-flag.rs:16:42 - | -LL | async fn foo(_: i32) -> &'static str {} - | ^^ expected `&str`, found `()` - error: aborting due to 3 previous errors Some errors have detailed explanations: E0046, E0308, E0520. diff --git a/tests/ui/async-await/in-trait/nested-rpit.rs b/tests/ui/async-await/in-trait/nested-rpit.rs index 9cdc23bbc78..8c43e1b07e2 100644 --- a/tests/ui/async-await/in-trait/nested-rpit.rs +++ b/tests/ui/async-await/in-trait/nested-rpit.rs @@ -9,6 +9,7 @@ use std::future::Future; use std::marker::PhantomData; trait Lockable<K, V> { + #[allow(async_fn_in_trait)] async fn lock_all_entries(&self) -> impl Future<Output = Guard<'_>>; } diff --git a/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs b/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs index c4008f2b7e7..f8fe0d1bde8 100644 --- a/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs +++ b/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs @@ -11,6 +11,7 @@ pub struct SharedState {} pub trait State { + #[allow(async_fn_in_trait)] async fn execute(self, shared_state: &SharedState); } diff --git a/tests/ui/async-await/in-trait/warn.rs b/tests/ui/async-await/in-trait/warn.rs new file mode 100644 index 00000000000..4f981c31f5c --- /dev/null +++ b/tests/ui/async-await/in-trait/warn.rs @@ -0,0 +1,23 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![deny(async_fn_in_trait)] + +pub trait Foo { + async fn not_send(); + //~^ ERROR use of `async fn` in public traits is discouraged +} + +mod private { + pub trait FooUnreachable { + async fn not_send(); + // No warning + } +} + +pub(crate) trait FooCrate { + async fn not_send(); + // No warning +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/warn.stderr b/tests/ui/async-await/in-trait/warn.stderr new file mode 100644 index 00000000000..eac41a6e924 --- /dev/null +++ b/tests/ui/async-await/in-trait/warn.stderr @@ -0,0 +1,20 @@ +error: use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified + --> $DIR/warn.rs:7:5 + | +LL | async fn not_send(); + | ^^^^^ + | + = note: you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future` +note: the lint level is defined here + --> $DIR/warn.rs:4:9 + | +LL | #![deny(async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^ +help: you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send` + | +LL - async fn not_send(); +LL + fn not_send() -> impl std::future::Future<Output = ()> + Send; + | + +error: aborting due to previous error + diff --git a/tests/ui/block-result/block-must-not-have-result-res.stderr b/tests/ui/block-result/block-must-not-have-result-res.stderr index 0080d06dd20..b7427462bcb 100644 --- a/tests/ui/block-result/block-must-not-have-result-res.stderr +++ b/tests/ui/block-result/block-must-not-have-result-res.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/block-must-not-have-result-res.rs:5:9 | LL | fn drop(&mut self) { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | true | ^^^^ expected `()`, found `bool` diff --git a/tests/ui/block-result/issue-20862.stderr b/tests/ui/block-result/issue-20862.stderr index 17b524fe311..1df3a683620 100644 --- a/tests/ui/block-result/issue-20862.stderr +++ b/tests/ui/block-result/issue-20862.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-20862.rs:2:5 | LL | fn foo(x: i32) { - | - help: a return type might be missing here: `-> _` + | - help: a return type might be missing here: `-> _` LL | |y| x + y | ^^^^^^^^^ expected `()`, found closure | diff --git a/tests/ui/block-result/issue-22645.stderr b/tests/ui/block-result/issue-22645.stderr index 677b40aaa9d..1064848f513 100644 --- a/tests/ui/block-result/issue-22645.stderr +++ b/tests/ui/block-result/issue-22645.stderr @@ -17,7 +17,7 @@ error[E0308]: mismatched types --> $DIR/issue-22645.rs:15:3 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | let b = Bob + 3.5; LL | b + 3 | ^^^^^ expected `()`, found `Bob` diff --git a/tests/ui/block-result/issue-5500.stderr b/tests/ui/block-result/issue-5500.stderr index 8cd4bd65871..417991e9e0b 100644 --- a/tests/ui/block-result/issue-5500.stderr +++ b/tests/ui/block-result/issue-5500.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-5500.rs:2:5 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | &panic!() | ^^^^^^^^^ expected `()`, found `&_` | diff --git a/tests/ui/closures/add_semicolon_non_block_closure.stderr b/tests/ui/closures/add_semicolon_non_block_closure.stderr index ed829fc98f8..6f9c309edda 100644 --- a/tests/ui/closures/add_semicolon_non_block_closure.stderr +++ b/tests/ui/closures/add_semicolon_non_block_closure.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/add_semicolon_non_block_closure.rs:8:12 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | foo(|| bar()) | ^^^^^ expected `()`, found `i32` | diff --git a/tests/ui/closures/binder/implicit-return.stderr b/tests/ui/closures/binder/implicit-return.stderr index 5bfb9711334..35db34ce21d 100644 --- a/tests/ui/closures/binder/implicit-return.stderr +++ b/tests/ui/closures/binder/implicit-return.stderr @@ -1,8 +1,8 @@ error: implicit types in closure signatures are forbidden when `for<...>` is present - --> $DIR/implicit-return.rs:4:34 + --> $DIR/implicit-return.rs:4:33 | LL | let _f = for<'a> |_: &'a ()| {}; - | ------- ^ + | ------- ^ | | | `for<...>` is here diff --git a/tests/ui/closures/binder/implicit-stuff.stderr b/tests/ui/closures/binder/implicit-stuff.stderr index 779a08a44e5..cec2a60ba28 100644 --- a/tests/ui/closures/binder/implicit-stuff.stderr +++ b/tests/ui/closures/binder/implicit-stuff.stderr @@ -41,10 +41,10 @@ LL | let _ = for<'a> |x: &'a ()| -> &() { x }; | ^ explicit lifetime name needed here error: implicit types in closure signatures are forbidden when `for<...>` is present - --> $DIR/implicit-stuff.rs:5:22 + --> $DIR/implicit-stuff.rs:5:21 | LL | let _ = for<> || {}; - | ----- ^ + | ----- ^ | | | `for<...>` is here diff --git a/tests/ui/codegen/issue-79865-llvm-miscompile.rs b/tests/ui/codegen/issue-79865-llvm-miscompile.rs index b77f09f8e9a..6f994a5cb74 100644 --- a/tests/ui/codegen/issue-79865-llvm-miscompile.rs +++ b/tests/ui/codegen/issue-79865-llvm-miscompile.rs @@ -4,7 +4,7 @@ // Regression test for issue #79865. // The assertion will fail when compiled with Rust 1.56..=1.59 -// due to a LLVM miscompilation. +// due to an LLVM miscompilation. use std::arch::x86_64::*; diff --git a/tests/ui/codemap_tests/tab.stderr b/tests/ui/codemap_tests/tab.stderr index c3f19d20d39..d2de7486557 100644 --- a/tests/ui/codemap_tests/tab.stderr +++ b/tests/ui/codemap_tests/tab.stderr @@ -8,7 +8,7 @@ error[E0308]: mismatched types --> $DIR/tab.rs:8:2 | LL | fn foo() { - | - help: try adding a return type: `-> &'static str` + | - help: try adding a return type: `-> &'static str` LL | "bar boo" | ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&str` diff --git a/tests/ui/compare-method/bad-self-type.stderr b/tests/ui/compare-method/bad-self-type.stderr index f632a53f264..a87b713c2b4 100644 --- a/tests/ui/compare-method/bad-self-type.stderr +++ b/tests/ui/compare-method/bad-self-type.stderr @@ -28,10 +28,10 @@ LL | fn foo(self); found signature `fn(Box<MyFuture>)` error[E0053]: method `bar` has an incompatible type for trait - --> $DIR/bad-self-type.rs:24:18 + --> $DIR/bad-self-type.rs:24:17 | LL | fn bar(self) {} - | ^ expected `Option<()>`, found `()` + | ^ expected `Option<()>`, found `()` | note: type in trait --> $DIR/bad-self-type.rs:18:21 diff --git a/tests/ui/consts/const-adt-align-mismatch.rs b/tests/ui/consts/const-adt-align-mismatch.rs index bd51bc9f215..89b3a9b744b 100644 --- a/tests/ui/consts/const-adt-align-mismatch.rs +++ b/tests/ui/consts/const-adt-align-mismatch.rs @@ -12,7 +12,7 @@ enum Foo { } // NOTE(eddyb) Don't make this a const, needs to be a static -// so it is always instantiated as a LLVM constant value. +// so it is always instantiated as an LLVM constant value. static FOO: Foo = Foo::C; fn main() { diff --git a/tests/ui/debuginfo/sroa-fragment-debuginfo.rs b/tests/ui/debuginfo/sroa-fragment-debuginfo.rs index 9c3c359e395..fc3bbb88efe 100644 --- a/tests/ui/debuginfo/sroa-fragment-debuginfo.rs +++ b/tests/ui/debuginfo/sroa-fragment-debuginfo.rs @@ -1,4 +1,4 @@ -// Verify that we do not trigger a LLVM assertion by creating zero-sized DWARF fragments. +// Verify that we do not trigger an LLVM assertion by creating zero-sized DWARF fragments. // // build-pass // compile-flags: -g -Zmir-opt-level=0 -Zmir-enable-passes=+ScalarReplacementOfAggregates diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr index 8b2b480d195..383212ad9b4 100644 --- a/tests/ui/deprecation/deprecation-sanity.stderr +++ b/tests/ui/deprecation/deprecation-sanity.stderr @@ -16,25 +16,25 @@ error[E0541]: unknown meta item 'reason' LL | #[deprecated(since = "a", note = "a", reason)] | ^^^^^^ expected one of `since`, `note` -error[E0551]: incorrect meta item +error[E0539]: incorrect meta item --> $DIR/deprecation-sanity.rs:7:31 | LL | #[deprecated(since = "a", note)] | ^^^^ -error[E0551]: incorrect meta item +error[E0539]: incorrect meta item --> $DIR/deprecation-sanity.rs:10:18 | LL | #[deprecated(since, note = "a")] | ^^^^^ -error[E0551]: incorrect meta item +error[E0539]: incorrect meta item --> $DIR/deprecation-sanity.rs:13:31 | LL | #[deprecated(since = "a", note(b))] | ^^^^^^^ -error[E0551]: incorrect meta item +error[E0539]: incorrect meta item --> $DIR/deprecation-sanity.rs:16:18 | LL | #[deprecated(since(b), note = "a")] @@ -70,5 +70,5 @@ LL | #[deprecated = "hello"] error: aborting due to 10 previous errors -Some errors have detailed explanations: E0538, E0541, E0551, E0565. +Some errors have detailed explanations: E0538, E0539, E0541, E0565. For more information about an error, try `rustc --explain E0538`. diff --git a/tests/ui/did_you_mean/auxiliary/doc-hidden-fields.rs b/tests/ui/did_you_mean/auxiliary/doc-hidden-fields.rs new file mode 100644 index 00000000000..4e2ee97403c --- /dev/null +++ b/tests/ui/did_you_mean/auxiliary/doc-hidden-fields.rs @@ -0,0 +1,6 @@ +#[derive(Default)] +pub struct B { + #[doc(hidden)] + pub hello: i32, + pub bye: i32, +} diff --git a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs new file mode 100644 index 00000000000..6040f3f30a7 --- /dev/null +++ b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs @@ -0,0 +1,38 @@ +// Regression test for issue #93210. + +// aux-crate:doc_hidden_fields=doc-hidden-fields.rs +// edition: 2021 + +#[derive(Default)] +pub struct A { + #[doc(hidden)] + pub hello: i32, + pub bye: i32, +} + +#[derive(Default)] +pub struct C { + pub hello: i32, + pub bye: i32, +} + +fn main() { + // We want to list the field `hello` despite being marked + // `doc(hidden)` because it's defined in this crate. + A::default().hey; + //~^ ERROR no field `hey` on type `A` + //~| NOTE unknown field + //~| NOTE available fields are: `hello`, `bye` + + // Here we want to hide the field `hello` since it's marked + // `doc(hidden)` and comes from an external crate. + doc_hidden_fields::B::default().hey; + //~^ ERROR no field `hey` on type `B` + //~| NOTE unknown field + //~| NOTE available fields are: `bye` + + C::default().hey; + //~^ ERROR no field `hey` on type `C` + //~| NOTE unknown field + //~| NOTE available fields are: `hello`, `bye` +} diff --git a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr new file mode 100644 index 00000000000..b7fe3b79b47 --- /dev/null +++ b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr @@ -0,0 +1,27 @@ +error[E0609]: no field `hey` on type `A` + --> $DIR/dont-suggest-doc-hidden-fields.rs:22:18 + | +LL | A::default().hey; + | ^^^ unknown field + | + = note: available fields are: `hello`, `bye` + +error[E0609]: no field `hey` on type `B` + --> $DIR/dont-suggest-doc-hidden-fields.rs:29:37 + | +LL | doc_hidden_fields::B::default().hey; + | ^^^ unknown field + | + = note: available fields are: `bye` + +error[E0609]: no field `hey` on type `C` + --> $DIR/dont-suggest-doc-hidden-fields.rs:34:18 + | +LL | C::default().hey; + | ^^^ unknown field + | + = note: available fields are: `hello`, `bye` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.rs b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.rs new file mode 100644 index 00000000000..fb7040b2df0 --- /dev/null +++ b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.rs @@ -0,0 +1,47 @@ +// Regression test for issue #116334. +// Don't include hygienic fields from different syntax contexts in +// the list of available or similarly named fields. + +#![feature(decl_macro)] + +macro compound($Ty:ident) { + #[derive(Default)] + struct $Ty { + field: u32, // field `field` is hygienic + } +} + +macro component($Ty:ident) { + struct $Ty(u64); // field `0` is hygienic (but still accessible via the constructor) +} + +compound! { Compound } +component! { Component } + +fn main() { + let ty = Compound::default(); + + let _ = ty.field; //~ ERROR no field `field` on type `Compound` + let _ = ty.fieeld; //~ ERROR no field `fieeld` on type `Compound` + + let Compound { field } = ty; + //~^ ERROR struct `Compound` does not have a field named `field` + //~| ERROR pattern requires `..` due to inaccessible fields + //~| HELP ignore the inaccessible and unused fields + + let ty = Component(90); + + let _ = ty.0; //~ ERROR no field `0` on type `Component` +} + +environment!(); + +macro environment() { + struct Crate { field: () } + + // Here, we do want to suggest `field` even though it's hygienic + // precisely because they come from the same syntax context. + const CRATE: Crate = Crate { fiel: () }; + //~^ ERROR struct `Crate` has no field named `fiel` + //~| HELP a field with a similar name exists +} diff --git a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr new file mode 100644 index 00000000000..7066d29760e --- /dev/null +++ b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr @@ -0,0 +1,50 @@ +error[E0560]: struct `Crate` has no field named `fiel` + --> $DIR/dont-suggest-hygienic-fields.rs:44:34 + | +LL | environment!(); + | -------------- in this macro invocation +... +LL | const CRATE: Crate = Crate { fiel: () }; + | ^^^^ help: a field with a similar name exists: `field` + | + = note: this error originates in the macro `environment` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `field` on type `Compound` + --> $DIR/dont-suggest-hygienic-fields.rs:24:16 + | +LL | let _ = ty.field; + | ^^^^^ unknown field + +error[E0609]: no field `fieeld` on type `Compound` + --> $DIR/dont-suggest-hygienic-fields.rs:25:16 + | +LL | let _ = ty.fieeld; + | ^^^^^^ unknown field + +error[E0026]: struct `Compound` does not have a field named `field` + --> $DIR/dont-suggest-hygienic-fields.rs:27:20 + | +LL | let Compound { field } = ty; + | ^^^^^ struct `Compound` does not have this field + +error: pattern requires `..` due to inaccessible fields + --> $DIR/dont-suggest-hygienic-fields.rs:27:9 + | +LL | let Compound { field } = ty; + | ^^^^^^^^^^^^^^^^^^ + | +help: ignore the inaccessible and unused fields + | +LL | let Compound { field, .. } = ty; + | ++++ + +error[E0609]: no field `0` on type `Component` + --> $DIR/dont-suggest-hygienic-fields.rs:34:16 + | +LL | let _ = ty.0; + | ^ unknown field + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0026, E0560, E0609. +For more information about an error, try `rustc --explain E0026`. diff --git a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs b/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs deleted file mode 100644 index 0efc7daa3e1..00000000000 --- a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs +++ /dev/null @@ -1,24 +0,0 @@ -#[derive(Default)] -pub struct A { - #[doc(hidden)] - pub hello: i32, - pub bye: i32, -} - -#[derive(Default)] -pub struct B { - pub hello: i32, - pub bye: i32, -} - -fn main() { - A::default().hey; - //~^ ERROR no field `hey` on type `A` - //~| NOTE unknown field - //~| NOTE available fields are: `bye` - - B::default().hey; - //~^ ERROR no field `hey` on type `B` - //~| NOTE unknown field - //~| NOTE available fields are: `hello`, `bye` -} diff --git a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr b/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr deleted file mode 100644 index 784986d3b95..00000000000 --- a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0609]: no field `hey` on type `A` - --> $DIR/issue-93210-ignore-doc-hidden.rs:15:18 - | -LL | A::default().hey; - | ^^^ unknown field - | - = note: available fields are: `bye` - -error[E0609]: no field `hey` on type `B` - --> $DIR/issue-93210-ignore-doc-hidden.rs:20:18 - | -LL | B::default().hey; - | ^^^ unknown field - | - = note: available fields are: `hello`, `bye` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs index 49fb10e6029..152c7a8de66 100644 --- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -54,20 +54,20 @@ fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) } const _cdef: impl Tr1<As1: Copy> = S1; //~^ ERROR associated type bounds are unstable -//~| ERROR `impl Trait` only allowed in function and inherent method return types +//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. // const _cdef_dyn: &dyn Tr1<As1: Copy> = &S1; static _sdef: impl Tr1<As1: Copy> = S1; //~^ ERROR associated type bounds are unstable -//~| ERROR `impl Trait` only allowed in function and inherent method return types +//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. // static _sdef_dyn: &dyn Tr1<As1: Copy> = &S1; fn main() { let _: impl Tr1<As1: Copy> = S1; //~^ ERROR associated type bounds are unstable - //~| ERROR `impl Trait` only allowed in function and inherent method return types + //~| ERROR `impl Trait` only allowed in function and inherent method argument and return types // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. // let _: &dyn Tr1<As1: Copy> = &S1; } diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr index 4233a8af9b6..f2bceda9bea 100644 --- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -115,19 +115,19 @@ LL | let _: impl Tr1<As1: Copy> = S1; = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types --> $DIR/feature-gate-associated_type_bounds.rs:55:14 | LL | const _cdef: impl Tr1<As1: Copy> = S1; | ^^^^^^^^^^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types --> $DIR/feature-gate-associated_type_bounds.rs:61:15 | LL | static _sdef: impl Tr1<As1: Copy> = S1; | ^^^^^^^^^^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/feature-gate-associated_type_bounds.rs:68:12 | LL | let _: impl Tr1<As1: Copy> = S1; diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs index 0db8088f7ee..1b9530fa82f 100644 --- a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs +++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs @@ -1,6 +1,6 @@ fn f() -> impl Fn() -> impl Sized { || () } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return fn g() -> &'static dyn Fn() -> impl Sized { &|| () } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr index c8c3e13d7fc..f0c0cd040e0 100644 --- a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr +++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:1:24 | LL | fn f() -> impl Fn() -> impl Sized { || () } @@ -7,7 +7,7 @@ LL | fn f() -> impl Fn() -> impl Sized { || () } = note: see issue #99697 <https://github.com/rust-lang/rust/issues/99697> for more information = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32 | LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () } diff --git a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs index 637765fff11..a8d6365ca79 100644 --- a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs +++ b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs @@ -5,14 +5,14 @@ #![feature(async_fn_in_trait)] trait Foo { - fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return - fn baz() -> Box<impl std::fmt::Display>; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return + fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return + fn baz() -> Box<impl std::fmt::Display>; //~ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return } // Both return_position_impl_trait_in_trait and async_fn_in_trait are required for this (see also // feature-gate-async_fn_in_trait.rs) trait AsyncFoo { - async fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return + async fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr index 0082b6fafee..86f138fabdb 100644 --- a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr +++ b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return types --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:8:17 | LL | fn bar() -> impl Sized; @@ -7,7 +7,7 @@ LL | fn bar() -> impl Sized; = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return types --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:9:21 | LL | fn baz() -> Box<impl std::fmt::Display>; @@ -16,7 +16,7 @@ LL | fn baz() -> Box<impl std::fmt::Display>; = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return types --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:15:23 | LL | async fn bar() -> impl Sized; diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr index 1bdb2574ead..f6230b76463 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr @@ -1,5 +1,5 @@ error[E0658]: return type notation is experimental - --> $DIR/feature-gate-return_type_notation.rs:14:17 + --> $DIR/feature-gate-return_type_notation.rs:15:17 | LL | fn foo<T: Trait<m(): Send>>() {} | ^^^^^^^^^ @@ -8,7 +8,7 @@ LL | fn foo<T: Trait<m(): Send>>() {} = help: add `#![feature(return_type_notation)]` to the crate attributes to enable error: parenthesized generic arguments cannot be used in associated type constraints - --> $DIR/feature-gate-return_type_notation.rs:14:17 + --> $DIR/feature-gate-return_type_notation.rs:15:17 | LL | fn foo<T: Trait<m(): Send>>() {} | ^-- @@ -16,7 +16,7 @@ LL | fn foo<T: Trait<m(): Send>>() {} | help: remove these parentheses error[E0220]: associated type `m` not found for `Trait` - --> $DIR/feature-gate-return_type_notation.rs:14:17 + --> $DIR/feature-gate-return_type_notation.rs:15:17 | LL | fn foo<T: Trait<m(): Send>>() {} | ^ associated type `m` not found diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr index dd6ebb61038..c7f52d7cddc 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr @@ -1,5 +1,5 @@ warning: return type notation is experimental - --> $DIR/feature-gate-return_type_notation.rs:14:17 + --> $DIR/feature-gate-return_type_notation.rs:15:17 | LL | fn foo<T: Trait<m(): Send>>() {} | ^^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.rs b/tests/ui/feature-gates/feature-gate-return_type_notation.rs index ae12495b5dc..c0c285cef3c 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.rs +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.rs @@ -7,6 +7,7 @@ #![feature(async_fn_in_trait)] trait Trait { + #[allow(async_fn_in_trait)] async fn m(); } diff --git a/tests/ui/impl-trait/impl-subtyper.rs b/tests/ui/impl-trait/impl-subtyper.rs new file mode 100644 index 00000000000..2d99cdd4f50 --- /dev/null +++ b/tests/ui/impl-trait/impl-subtyper.rs @@ -0,0 +1,18 @@ +// check-pass + +#![crate_type = "lib"] +fn checkpoints() -> impl Iterator { + Some(()).iter().flat_map(|_| std::iter::once(())) +} + +fn block_checkpoints() -> impl Iterator { + checkpoints() +} + +fn iter_raw() -> impl Iterator { + let mut iter = block_checkpoints(); + + (0..9).map(move |_| { + iter.next(); + }) +} diff --git a/tests/ui/impl-trait/impl-subtyper2.rs b/tests/ui/impl-trait/impl-subtyper2.rs new file mode 100644 index 00000000000..2e0acbae68b --- /dev/null +++ b/tests/ui/impl-trait/impl-subtyper2.rs @@ -0,0 +1,7 @@ +// check-pass + +fn ages() -> Option<impl Iterator> { + None::<std::slice::Iter<()>> +} + +fn main(){} diff --git a/tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs b/tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs index 2a61c5cc8df..5de9c01e3e0 100644 --- a/tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs +++ b/tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs @@ -9,6 +9,7 @@ trait AsyncLendingIterator { where Self: 'a; + #[allow(async_fn_in_trait)] async fn next(&mut self) -> Option<Self::Item<'_>>; } diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs index 25133214dc6..9c60cf4e72a 100644 --- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs +++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs @@ -7,6 +7,7 @@ use std::fmt::Debug; trait Foo { + #[allow(async_fn_in_trait)] async fn baz(&self) -> impl Debug { "" } diff --git a/tests/ui/impl-trait/in-trait/default-body.rs b/tests/ui/impl-trait/in-trait/default-body.rs index b0baf5bb10d..d3ea9fbeabc 100644 --- a/tests/ui/impl-trait/in-trait/default-body.rs +++ b/tests/ui/impl-trait/in-trait/default-body.rs @@ -7,6 +7,7 @@ use std::fmt::Debug; trait Foo { + #[allow(async_fn_in_trait)] async fn baz(&self) -> &str { "" } diff --git a/tests/ui/impl-trait/in-trait/early.rs b/tests/ui/impl-trait/in-trait/early.rs index 9c1c2b50339..bb5718b4934 100644 --- a/tests/ui/impl-trait/in-trait/early.rs +++ b/tests/ui/impl-trait/in-trait/early.rs @@ -5,6 +5,7 @@ #![allow(incomplete_features)] pub trait Foo { + #[allow(async_fn_in_trait)] async fn bar<'a: 'a>(&'a mut self); } diff --git a/tests/ui/impl-trait/in-trait/refine.rs b/tests/ui/impl-trait/in-trait/refine.rs index a91f9b3e722..f00478b0bb9 100644 --- a/tests/ui/impl-trait/in-trait/refine.rs +++ b/tests/ui/impl-trait/in-trait/refine.rs @@ -45,4 +45,15 @@ impl Late for D { //~^ ERROR impl method signature does not match trait method signature } +mod unreachable { + pub trait UnreachablePub { + fn bar() -> impl Sized; + } + + struct E; + impl UnreachablePub for E { + fn bar() {} + } +} + fn main() {} diff --git a/tests/ui/impl-trait/in-trait/refine.stderr b/tests/ui/impl-trait/in-trait/refine.stderr index 29aa08e25bb..1d9852c682c 100644 --- a/tests/ui/impl-trait/in-trait/refine.stderr +++ b/tests/ui/impl-trait/in-trait/refine.stderr @@ -30,8 +30,8 @@ LL | fn bar() {} = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate help: replace the return type so that it matches the trait | -LL | fn bar() -> impl Sized {} - | +++++++++++++ +LL | fn bar()-> impl Sized {} + | +++++++++++++ error: impl trait in impl method signature does not match trait method signature --> $DIR/refine.rs:22:17 diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed index d9f775a6c84..58d83384a23 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed @@ -4,12 +4,15 @@ #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] trait Trait { + #[allow(async_fn_in_trait)] async fn foo(); + #[allow(async_fn_in_trait)] async fn bar() -> i32; fn test(&self) -> impl Sized + '_; + #[allow(async_fn_in_trait)] async fn baz(&self) -> &i32; } diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.rs b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs index 26979b5149b..c27229806e1 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.rs +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs @@ -4,12 +4,15 @@ #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] trait Trait { + #[allow(async_fn_in_trait)] async fn foo(); + #[allow(async_fn_in_trait)] async fn bar() -> i32; fn test(&self) -> impl Sized + '_; + #[allow(async_fn_in_trait)] async fn baz(&self) -> &i32; } diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr index 44f98896eb3..29f6bad86dc 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr @@ -1,15 +1,15 @@ error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `test`, `baz` - --> $DIR/suggest-missing-item.rs:18:1 + --> $DIR/suggest-missing-item.rs:21:1 | LL | async fn foo(); | --------------- `foo` from trait -LL | +... LL | async fn bar() -> i32; | ---------------------- `bar` from trait LL | LL | fn test(&self) -> impl Sized + '_; | ---------------------------------- `test` from trait -LL | +... LL | async fn baz(&self) -> &i32; | ---------------------------- `baz` from trait ... diff --git a/tests/ui/impl-trait/issues/issue-54600.rs b/tests/ui/impl-trait/issues/issue-54600.rs index 3024fedf7b5..ccf2767012e 100644 --- a/tests/ui/impl-trait/issues/issue-54600.rs +++ b/tests/ui/impl-trait/issues/issue-54600.rs @@ -2,6 +2,6 @@ use std::fmt::Debug; fn main() { let x: Option<impl Debug> = Some(44_u32); - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types println!("{:?}", x); } diff --git a/tests/ui/impl-trait/issues/issue-54600.stderr b/tests/ui/impl-trait/issues/issue-54600.stderr index 7ef063af952..9a8e3675b95 100644 --- a/tests/ui/impl-trait/issues/issue-54600.stderr +++ b/tests/ui/impl-trait/issues/issue-54600.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-54600.rs:4:19 | LL | let x: Option<impl Debug> = Some(44_u32); diff --git a/tests/ui/impl-trait/issues/issue-54840.rs b/tests/ui/impl-trait/issues/issue-54840.rs index 8f1e0ece03a..910d23f1d93 100644 --- a/tests/ui/impl-trait/issues/issue-54840.rs +++ b/tests/ui/impl-trait/issues/issue-54840.rs @@ -3,5 +3,5 @@ use std::ops::Add; fn main() { let i: i32 = 0; let j: &impl Add = &i; - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types } diff --git a/tests/ui/impl-trait/issues/issue-54840.stderr b/tests/ui/impl-trait/issues/issue-54840.stderr index 1d1316f0e11..67cabf44950 100644 --- a/tests/ui/impl-trait/issues/issue-54840.stderr +++ b/tests/ui/impl-trait/issues/issue-54840.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-54840.rs:5:13 | LL | let j: &impl Add = &i; diff --git a/tests/ui/impl-trait/issues/issue-58504.rs b/tests/ui/impl-trait/issues/issue-58504.rs index e5865d0dfff..f1d7b94ef2d 100644 --- a/tests/ui/impl-trait/issues/issue-58504.rs +++ b/tests/ui/impl-trait/issues/issue-58504.rs @@ -8,5 +8,5 @@ fn mk_gen() -> impl Generator<Return=!, Yield=()> { fn main() { let gens: [impl Generator<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ]; - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types } diff --git a/tests/ui/impl-trait/issues/issue-58504.stderr b/tests/ui/impl-trait/issues/issue-58504.stderr index 26ec2a4f9cf..1be676ee075 100644 --- a/tests/ui/impl-trait/issues/issue-58504.stderr +++ b/tests/ui/impl-trait/issues/issue-58504.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-58504.rs:10:16 | LL | let gens: [impl Generator<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ]; diff --git a/tests/ui/impl-trait/issues/issue-58956.rs b/tests/ui/impl-trait/issues/issue-58956.rs index 68cfcd9ba4f..5d5566860c0 100644 --- a/tests/ui/impl-trait/issues/issue-58956.rs +++ b/tests/ui/impl-trait/issues/issue-58956.rs @@ -5,9 +5,9 @@ impl Lam for B {} pub struct Wrap<T>(T); const _A: impl Lam = { - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types let x: Wrap<impl Lam> = Wrap(B); - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types x.0 }; diff --git a/tests/ui/impl-trait/issues/issue-58956.stderr b/tests/ui/impl-trait/issues/issue-58956.stderr index 2b4d0abdffc..5ee33352afa 100644 --- a/tests/ui/impl-trait/issues/issue-58956.stderr +++ b/tests/ui/impl-trait/issues/issue-58956.stderr @@ -1,10 +1,10 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types --> $DIR/issue-58956.rs:7:11 | LL | const _A: impl Lam = { | ^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-58956.rs:9:17 | LL | let x: Wrap<impl Lam> = Wrap(B); diff --git a/tests/ui/impl-trait/issues/issue-70971.rs b/tests/ui/impl-trait/issues/issue-70971.rs index f8ae18bacd6..c24259a71eb 100644 --- a/tests/ui/impl-trait/issues/issue-70971.rs +++ b/tests/ui/impl-trait/issues/issue-70971.rs @@ -1,4 +1,4 @@ fn main() { let x : (impl Copy,) = (true,); - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types } diff --git a/tests/ui/impl-trait/issues/issue-70971.stderr b/tests/ui/impl-trait/issues/issue-70971.stderr index d066256bfb0..5609f8b9b01 100644 --- a/tests/ui/impl-trait/issues/issue-70971.stderr +++ b/tests/ui/impl-trait/issues/issue-70971.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-70971.rs:2:14 | LL | let x : (impl Copy,) = (true,); diff --git a/tests/ui/impl-trait/issues/issue-79099.rs b/tests/ui/impl-trait/issues/issue-79099.rs index da53594f3d0..22c66491ce9 100644 --- a/tests/ui/impl-trait/issues/issue-79099.rs +++ b/tests/ui/impl-trait/issues/issue-79099.rs @@ -1,7 +1,7 @@ struct Bug { V1: [(); { let f: impl core::future::Future<Output = u8> = async { 1 }; - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types //~| expected identifier 1 }], diff --git a/tests/ui/impl-trait/issues/issue-79099.stderr b/tests/ui/impl-trait/issues/issue-79099.stderr index 580250a62fe..82fc03c61b3 100644 --- a/tests/ui/impl-trait/issues/issue-79099.stderr +++ b/tests/ui/impl-trait/issues/issue-79099.stderr @@ -9,7 +9,7 @@ LL | let f: impl core::future::Future<Output = u8> = async { 1 }; = help: pass `--edition 2021` to `rustc` = note: for more on editions, read https://doc.rust-lang.org/edition-guide -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-79099.rs:3:16 | LL | let f: impl core::future::Future<Output = u8> = async { 1 }; diff --git a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs index 344f359529b..3224145bffe 100644 --- a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs +++ b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs @@ -1,8 +1,8 @@ struct Foo<T = impl Copy>(T); -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types type Result<T, E = impl std::error::Error> = std::result::Result<T, E>; -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // should not cause ICE fn x() -> Foo { diff --git a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr index 656bd047061..56be4577d51 100644 --- a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr +++ b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr @@ -1,10 +1,10 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/issue-83929-impl-trait-in-generic-default.rs:1:16 | LL | struct Foo<T = impl Copy>(T); | ^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/issue-83929-impl-trait-in-generic-default.rs:4:20 | LL | type Result<T, E = impl std::error::Error> = std::result::Result<T, E>; diff --git a/tests/ui/impl-trait/issues/issue-84919.rs b/tests/ui/impl-trait/issues/issue-84919.rs index a0b73743a2b..77d27d7c06b 100644 --- a/tests/ui/impl-trait/issues/issue-84919.rs +++ b/tests/ui/impl-trait/issues/issue-84919.rs @@ -3,7 +3,7 @@ impl Trait for () {} fn foo<'a: 'a>() { let _x: impl Trait = (); - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types } fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-84919.stderr b/tests/ui/impl-trait/issues/issue-84919.stderr index 36010fdef36..20b131b8bd2 100644 --- a/tests/ui/impl-trait/issues/issue-84919.stderr +++ b/tests/ui/impl-trait/issues/issue-84919.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-84919.rs:5:13 | LL | let _x: impl Trait = (); diff --git a/tests/ui/impl-trait/issues/issue-86642.rs b/tests/ui/impl-trait/issues/issue-86642.rs index e6e95771400..49f8944ac4a 100644 --- a/tests/ui/impl-trait/issues/issue-86642.rs +++ b/tests/ui/impl-trait/issues/issue-86642.rs @@ -1,5 +1,5 @@ static x: impl Fn(&str) -> Result<&str, ()> = move |source| { - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types let res = (move |source| Ok(source))(source); let res = res.or((move |source| Ok(source))(source)); res diff --git a/tests/ui/impl-trait/issues/issue-86642.stderr b/tests/ui/impl-trait/issues/issue-86642.stderr index b6f8a54f35a..6d3be3fff0e 100644 --- a/tests/ui/impl-trait/issues/issue-86642.stderr +++ b/tests/ui/impl-trait/issues/issue-86642.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types --> $DIR/issue-86642.rs:1:11 | LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| { diff --git a/tests/ui/impl-trait/issues/issue-87295.rs b/tests/ui/impl-trait/issues/issue-87295.rs index aeb8f83326e..eb44020ac0e 100644 --- a/tests/ui/impl-trait/issues/issue-87295.rs +++ b/tests/ui/impl-trait/issues/issue-87295.rs @@ -14,5 +14,5 @@ impl<F> Struct<F> { fn main() { let _do_not_waste: Struct<impl Trait<Output = i32>> = Struct::new(()); - //~^ `impl Trait` only allowed in function and inherent method return types + //~^ `impl Trait` only allowed in function and inherent method argument and return types } diff --git a/tests/ui/impl-trait/issues/issue-87295.stderr b/tests/ui/impl-trait/issues/issue-87295.stderr index ec59b719c10..3fe4ee73c80 100644 --- a/tests/ui/impl-trait/issues/issue-87295.stderr +++ b/tests/ui/impl-trait/issues/issue-87295.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-87295.rs:16:31 | LL | let _do_not_waste: Struct<impl Trait<Output = i32>> = Struct::new(()); diff --git a/tests/ui/impl-trait/nested_impl_trait.rs b/tests/ui/impl-trait/nested_impl_trait.rs index e95fab3b650..c036b9e367a 100644 --- a/tests/ui/impl-trait/nested_impl_trait.rs +++ b/tests/ui/impl-trait/nested_impl_trait.rs @@ -9,7 +9,7 @@ fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x } fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {} //~^ ERROR nested `impl Trait` is not allowed -//~| `impl Trait` only allowed in function and inherent method return types +//~| `impl Trait` only allowed in function and inherent method argument and return types fn bad_in_arg_position(_: impl Into<impl Debug>) { } //~^ ERROR nested `impl Trait` is not allowed diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr index ffe84b8e86f..f1cafd958b0 100644 --- a/tests/ui/impl-trait/nested_impl_trait.stderr +++ b/tests/ui/impl-trait/nested_impl_trait.stderr @@ -34,7 +34,7 @@ LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x } | | nested `impl Trait` here | outer `impl Trait` -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types --> $DIR/nested_impl_trait.rs:10:32 | LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {} diff --git a/tests/ui/impl-trait/where-allowed.rs b/tests/ui/impl-trait/where-allowed.rs index 509d2716649..d3fab326e74 100644 --- a/tests/ui/impl-trait/where-allowed.rs +++ b/tests/ui/impl-trait/where-allowed.rs @@ -16,47 +16,47 @@ fn in_adt_in_parameters(_: Vec<impl Debug>) { panic!() } // Disallowed fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Allowed fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } // Disallowed fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types //~^^ ERROR nested `impl Trait` is not allowed // Disallowed fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types //~| ERROR nested `impl Trait` is not allowed // Allowed @@ -64,11 +64,11 @@ fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() // Disallowed fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Allowed @@ -81,22 +81,22 @@ fn in_impl_Trait_in_return() -> impl IntoIterator<Item = impl IntoIterator> { // Disallowed struct InBraceStructField { x: impl Debug } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed struct InAdtInBraceStructField { x: Vec<impl Debug> } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed struct InTupleStructField(impl Debug); -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed enum InEnum { InBraceVariant { x: impl Debug }, - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types InTupleVariant(impl Debug), - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Allowed @@ -107,7 +107,7 @@ trait InTraitDefnParameters { // Disallowed trait InTraitDefnReturn { fn in_return() -> impl Debug; - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Allowed and disallowed in trait impls @@ -124,7 +124,7 @@ impl DummyTrait for () { // Allowed fn in_trait_impl_return() -> impl Debug { () } - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Allowed @@ -137,10 +137,10 @@ impl DummyType { // Disallowed extern "C" { fn in_foreign_parameters(_: impl Debug); - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types fn in_foreign_return() -> impl Debug; - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Allowed @@ -156,97 +156,97 @@ type InTypeAlias<R> = impl Debug; //~^ ERROR `impl Trait` in type aliases is unstable type InReturnInTypeAlias<R> = fn() -> impl Debug; -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types //~| ERROR `impl Trait` in type aliases is unstable // Disallowed in impl headers impl PartialEq<impl Debug> for () { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Disallowed in impl headers impl PartialEq<()> for impl Debug { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Disallowed in inherent impls impl impl Debug { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Disallowed in inherent impls struct InInherentImplAdt<T> { t: T } impl InInherentImplAdt<impl Debug> { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } // Disallowed in where clauses fn in_fn_where_clause() where impl Debug: Debug -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types { } // Disallowed in where clauses fn in_adt_in_fn_where_clause() where Vec<impl Debug>: Debug -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types { } // Disallowed fn in_trait_parameter_in_fn_where_clause<T>() where T: PartialEq<impl Debug> -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types { } // Disallowed fn in_Fn_parameter_in_fn_where_clause<T>() where T: Fn(impl Debug) -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types { } // Disallowed fn in_Fn_return_in_fn_where_clause<T>() where T: Fn() -> impl Debug -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types { } // Disallowed struct InStructGenericParamDefault<T = impl Debug>(T); -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed enum InEnumGenericParamDefault<T = impl Debug> { Variant(T) } -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed trait InTraitGenericParamDefault<T = impl Debug> {} -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed type InTypeAliasGenericParamDefault<T = impl Debug> = T; -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types // Disallowed impl <T = impl Debug> T {} //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions //~| WARNING this was previously accepted by the compiler but is being phased out -//~| ERROR `impl Trait` only allowed in function and inherent method return types +//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types //~| ERROR no nominal type found // Disallowed fn in_method_generic_param_default<T = impl Debug>(_: T) {} //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions //~| WARNING this was previously accepted by the compiler but is being phased out -//~| ERROR `impl Trait` only allowed in function and inherent method return types +//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types fn main() { let _in_local_variable: impl Fn() = || {}; - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types let _in_return_in_local_variable = || -> impl Fn() { || {} }; - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index 3e293437975..bd7c9a94793 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -43,109 +43,109 @@ LL | type InReturnInTypeAlias<R> = fn() -> impl Debug; = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer params --> $DIR/where-allowed.rs:18:40 | LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types --> $DIR/where-allowed.rs:22:42 | LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer params --> $DIR/where-allowed.rs:26:38 | LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types --> $DIR/where-allowed.rs:30:40 | LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params --> $DIR/where-allowed.rs:34:49 | LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types --> $DIR/where-allowed.rs:38:51 | LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params --> $DIR/where-allowed.rs:42:55 | LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params --> $DIR/where-allowed.rs:49:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types --> $DIR/where-allowed.rs:54:53 | LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params --> $DIR/where-allowed.rs:58:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params --> $DIR/where-allowed.rs:66:38 | LL | fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types --> $DIR/where-allowed.rs:70:40 | LL | fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types --> $DIR/where-allowed.rs:83:32 | LL | struct InBraceStructField { x: impl Debug } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types --> $DIR/where-allowed.rs:87:41 | LL | struct InAdtInBraceStructField { x: Vec<impl Debug> } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types --> $DIR/where-allowed.rs:91:27 | LL | struct InTupleStructField(impl Debug); | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types --> $DIR/where-allowed.rs:96:25 | LL | InBraceVariant { x: impl Debug }, | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types --> $DIR/where-allowed.rs:98:20 | LL | InTupleVariant(impl Debug), | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return types --> $DIR/where-allowed.rs:109:23 | LL | fn in_return() -> impl Debug; @@ -154,7 +154,7 @@ LL | fn in_return() -> impl Debug; = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `impl` method return types --> $DIR/where-allowed.rs:126:34 | LL | fn in_trait_impl_return() -> impl Debug { () } @@ -163,121 +163,121 @@ LL | fn in_trait_impl_return() -> impl Debug { () } = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `extern fn` params --> $DIR/where-allowed.rs:139:33 | LL | fn in_foreign_parameters(_: impl Debug); | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `extern fn` return types --> $DIR/where-allowed.rs:142:31 | LL | fn in_foreign_return() -> impl Debug; | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types --> $DIR/where-allowed.rs:158:39 | LL | type InReturnInTypeAlias<R> = fn() -> impl Debug; | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in traits +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in traits --> $DIR/where-allowed.rs:163:16 | LL | impl PartialEq<impl Debug> for () { | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers --> $DIR/where-allowed.rs:168:24 | LL | impl PartialEq<()> for impl Debug { | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers --> $DIR/where-allowed.rs:173:6 | LL | impl impl Debug { | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers --> $DIR/where-allowed.rs:179:24 | LL | impl InInherentImplAdt<impl Debug> { | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bounds +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in bounds --> $DIR/where-allowed.rs:185:11 | LL | where impl Debug: Debug | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bounds +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in bounds --> $DIR/where-allowed.rs:192:15 | LL | where Vec<impl Debug>: Debug | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bounds +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in bounds --> $DIR/where-allowed.rs:199:24 | LL | where T: PartialEq<impl Debug> | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params --> $DIR/where-allowed.rs:206:17 | LL | where T: Fn(impl Debug) | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types --> $DIR/where-allowed.rs:213:22 | LL | where T: Fn() -> impl Debug | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/where-allowed.rs:219:40 | LL | struct InStructGenericParamDefault<T = impl Debug>(T); | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/where-allowed.rs:223:36 | LL | enum InEnumGenericParamDefault<T = impl Debug> { Variant(T) } | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/where-allowed.rs:227:38 | LL | trait InTraitGenericParamDefault<T = impl Debug> {} | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/where-allowed.rs:231:41 | LL | type InTypeAliasGenericParamDefault<T = impl Debug> = T; | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/where-allowed.rs:235:11 | LL | impl <T = impl Debug> T {} | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults --> $DIR/where-allowed.rs:242:40 | LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {} | ^^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/where-allowed.rs:248:29 | LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in closure return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in closure return types --> $DIR/where-allowed.rs:250:46 | LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; diff --git a/tests/ui/issues/issue-47715.rs b/tests/ui/issues/issue-47715.rs index b8088c18dad..0a770593bc9 100644 --- a/tests/ui/issues/issue-47715.rs +++ b/tests/ui/issues/issue-47715.rs @@ -7,22 +7,22 @@ trait Iterable { } struct Container<T: Iterable<Item = impl Foo>> { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types field: T } enum Enum<T: Iterable<Item = impl Foo>> { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types A(T), } union Union<T: Iterable<Item = impl Foo> + Copy> { - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types x: T, } type Type<T: Iterable<Item = impl Foo>> = T; -//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types fn main() { } diff --git a/tests/ui/issues/issue-47715.stderr b/tests/ui/issues/issue-47715.stderr index dadea34b688..2ded98781c6 100644 --- a/tests/ui/issues/issue-47715.stderr +++ b/tests/ui/issues/issue-47715.stderr @@ -1,22 +1,22 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics --> $DIR/issue-47715.rs:9:37 | LL | struct Container<T: Iterable<Item = impl Foo>> { | ^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics --> $DIR/issue-47715.rs:14:30 | LL | enum Enum<T: Iterable<Item = impl Foo>> { | ^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics --> $DIR/issue-47715.rs:19:32 | LL | union Union<T: Iterable<Item = impl Foo> + Copy> { | ^^^^^^^^ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics --> $DIR/issue-47715.rs:24:30 | LL | type Type<T: Iterable<Item = impl Foo>> = T; diff --git a/tests/ui/issues/issue-66667-function-cmp-cycle.stderr b/tests/ui/issues/issue-66667-function-cmp-cycle.stderr index d9a960ce197..cec8117702a 100644 --- a/tests/ui/issues/issue-66667-function-cmp-cycle.stderr +++ b/tests/ui/issues/issue-66667-function-cmp-cycle.stderr @@ -19,7 +19,7 @@ error[E0308]: mismatched types --> $DIR/issue-66667-function-cmp-cycle.rs:2:5 | LL | fn first() { - | - help: try adding a return type: `-> bool` + | - help: try adding a return type: `-> bool` LL | second == 1 | ^^^^^^^^^^^ expected `()`, found `bool` @@ -44,7 +44,7 @@ error[E0308]: mismatched types --> $DIR/issue-66667-function-cmp-cycle.rs:8:5 | LL | fn second() { - | - help: try adding a return type: `-> bool` + | - help: try adding a return type: `-> bool` LL | first == 1 | ^^^^^^^^^^ expected `()`, found `bool` @@ -69,7 +69,7 @@ error[E0308]: mismatched types --> $DIR/issue-66667-function-cmp-cycle.rs:14:5 | LL | fn bar() { - | - help: try adding a return type: `-> bool` + | - help: try adding a return type: `-> bool` LL | bar == 1 | ^^^^^^^^ expected `()`, found `bool` diff --git a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr index 2bb29f911a1..14bfcc3d04d 100644 --- a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr +++ b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr @@ -1,8 +1,8 @@ error[E0308]: lang item `start` function has wrong type - --> $DIR/start_lang_item_args.rs:29:84 + --> $DIR/start_lang_item_args.rs:29:83 | LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {} - | ^ expected `isize`, found `()` + | ^ expected `isize`, found `()` | = note: expected signature `fn(fn() -> _, _, _, _) -> isize` found signature `fn(fn() -> _, _, _, _)` diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs new file mode 100644 index 00000000000..1e2ff12a206 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs @@ -0,0 +1,30 @@ +// check-pass +// incremental + +#![feature(lint_reasons)] +#![warn(unused)] + +struct OneUnused; +struct TwoUnused; + +impl OneUnused { + #[expect(unused)] + fn unused() {} +} + +impl TwoUnused { + #[expect(unused)] + fn unused1(){} + + // This unused method has `#[expect(unused)]`, so the compiler should not emit a warning. + // This ui test was added after a regression in the compiler where it did not recognize multiple + // `#[expect(unused)]` annotations inside of impl blocks. + // issue 114416 + #[expect(unused)] + fn unused2(){} +} + +fn main() { + let _ = OneUnused; + let _ = TwoUnused; +} diff --git a/tests/ui/loops/loop-break-value.stderr b/tests/ui/loops/loop-break-value.stderr index 6c83bc7575c..a691960f962 100644 --- a/tests/ui/loops/loop-break-value.stderr +++ b/tests/ui/loops/loop-break-value.stderr @@ -319,7 +319,7 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:159:15 | LL | fn main() { - | - expected `()` because of this return type + | - expected `()` because of this return type ... LL | loop { // point at the return type | ---- this loop is expected to be of type `()` diff --git a/tests/ui/mismatched_types/issue-19109.stderr b/tests/ui/mismatched_types/issue-19109.stderr index 5cef64bb169..ca819d93a50 100644 --- a/tests/ui/mismatched_types/issue-19109.stderr +++ b/tests/ui/mismatched_types/issue-19109.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-19109.rs:4:5 | LL | fn function(t: &mut dyn Trait) { - | - help: try adding a return type: `-> *mut dyn Trait` + | - help: try adding a return type: `-> *mut dyn Trait` LL | t as *mut dyn Trait | ^^^^^^^^^^^^^^^^^^^ expected `()`, found `*mut dyn Trait` | diff --git a/tests/ui/offset-of/offset-of-output-type.stderr b/tests/ui/offset-of/offset-of-output-type.stderr index 6133f3263ab..233d4987643 100644 --- a/tests/ui/offset-of/offset-of-output-type.stderr +++ b/tests/ui/offset-of/offset-of-output-type.stderr @@ -42,7 +42,7 @@ error[E0308]: mismatched types --> $DIR/offset-of-output-type.rs:19:5 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type ... LL | offset_of!(S, v) | ^^^^^^^^^^^^^^^^ expected `()`, found `usize` diff --git a/tests/ui/parser/recover-quantified-closure.stderr b/tests/ui/parser/recover-quantified-closure.stderr index 39eec80f658..37e93cbee7b 100644 --- a/tests/ui/parser/recover-quantified-closure.stderr +++ b/tests/ui/parser/recover-quantified-closure.stderr @@ -25,10 +25,10 @@ LL | for <Foo>::Bar in x {} = help: consider removing `for<...>` error: implicit types in closure signatures are forbidden when `for<...>` is present - --> $DIR/recover-quantified-closure.rs:2:25 + --> $DIR/recover-quantified-closure.rs:2:24 | LL | for<'a> |x: &'a u8| *x + 1; - | ------- ^ + | ------- ^ | | | `for<...>` is here diff --git a/tests/ui/proc-macro/issue-37788.stderr b/tests/ui/proc-macro/issue-37788.stderr index e437bb90b1d..0a116d6f80d 100644 --- a/tests/ui/proc-macro/issue-37788.stderr +++ b/tests/ui/proc-macro/issue-37788.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-37788.rs:8:5 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE. LL | std::cell::Cell::new(0) | ^^^^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;` diff --git a/tests/ui/proc-macro/resolved-located-at.stderr b/tests/ui/proc-macro/resolved-located-at.stderr index 0b4dbcba682..a4f838521fd 100644 --- a/tests/ui/proc-macro/resolved-located-at.stderr +++ b/tests/ui/proc-macro/resolved-located-at.stderr @@ -10,7 +10,7 @@ error[E0308]: mismatched types --> $DIR/resolved-located-at.rs:7:27 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | resolve_located_at!(a b) | ^ expected `()`, found `S` | diff --git a/tests/ui/proc-macro/span-preservation.stderr b/tests/ui/proc-macro/span-preservation.stderr index 8c15cb9de98..3ad9c539f84 100644 --- a/tests/ui/proc-macro/span-preservation.stderr +++ b/tests/ui/proc-macro/span-preservation.stderr @@ -38,7 +38,7 @@ error[E0308]: mismatched types --> $DIR/span-preservation.rs:39:5 | LL | extern "C" fn bar() { - | - help: try adding a return type: `-> i32` + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer @@ -46,7 +46,7 @@ error[E0308]: mismatched types --> $DIR/span-preservation.rs:44:5 | LL | extern "C" fn baz() { - | - help: try adding a return type: `-> i32` + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer @@ -54,7 +54,7 @@ error[E0308]: mismatched types --> $DIR/span-preservation.rs:49:5 | LL | extern "Rust" fn rust_abi() { - | - help: try adding a return type: `-> i32` + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer @@ -62,7 +62,7 @@ error[E0308]: mismatched types --> $DIR/span-preservation.rs:54:5 | LL | extern "\x43" fn c_abi_escaped() { - | - help: try adding a return type: `-> i32` + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer diff --git a/tests/ui/return/return-struct.stderr b/tests/ui/return/return-struct.stderr index e6c0363e363..282e6498ebe 100644 --- a/tests/ui/return/return-struct.stderr +++ b/tests/ui/return/return-struct.stderr @@ -17,7 +17,7 @@ error[E0308]: mismatched types --> $DIR/return-struct.rs:15:5 | LL | fn bar() { - | - help: try adding a return type: `-> Age` + | - help: try adding a return type: `-> Age` LL | let mut age = 29; LL | Age::Years(age, 55) | ^^^^^^^^^^^^^^^^^^^ expected `()`, found `Age` @@ -26,7 +26,7 @@ error[E0308]: mismatched types --> $DIR/return-struct.rs:20:5 | LL | fn baz() { - | - help: try adding a return type: `-> S` + | - help: try adding a return type: `-> S` LL | S | ^ expected `()`, found `S` diff --git a/tests/ui/suggestions/issue-83892.stderr b/tests/ui/suggestions/issue-83892.stderr index baf6b1447e6..5e471819b27 100644 --- a/tests/ui/suggestions/issue-83892.stderr +++ b/tests/ui/suggestions/issue-83892.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-83892.rs:9:15 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | match () { LL | () => func() | ^^^^^^ expected `()`, found `u8` diff --git a/tests/ui/suggestions/return-closures.stderr b/tests/ui/suggestions/return-closures.stderr index f0810bbb254..97c13200ac3 100644 --- a/tests/ui/suggestions/return-closures.stderr +++ b/tests/ui/suggestions/return-closures.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/return-closures.rs:3:5 | LL | fn foo() { - | - help: try adding a return type: `-> impl for<'a> Fn(&'a i32) -> i32` + | - help: try adding a return type: `-> impl for<'a> Fn(&'a i32) -> i32` LL | LL | |x: &i32| 1i32 | ^^^^^^^^^^^^^^ expected `()`, found closure @@ -14,7 +14,7 @@ error[E0308]: mismatched types --> $DIR/return-closures.rs:9:5 | LL | fn bar(i: impl Sized) { - | - help: a return type might be missing here: `-> _` + | - help: a return type might be missing here: `-> _` LL | LL | || i | ^^^^ expected `()`, found closure diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.fixed b/tests/ui/suggestions/suggest-ret-on-async-w-late.fixed new file mode 100644 index 00000000000..0a08383317f --- /dev/null +++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.fixed @@ -0,0 +1,14 @@ +// edition: 2021 +// run-rustfix + +#![allow(unused)] + +// Make sure we don't ICE when suggesting a return type +// for an async fn that has late-bound vars... + +async fn ice(_: &i32) -> bool { + true + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.rs b/tests/ui/suggestions/suggest-ret-on-async-w-late.rs index 459b94f943b..5c8f185bd4b 100644 --- a/tests/ui/suggestions/suggest-ret-on-async-w-late.rs +++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.rs @@ -1,4 +1,7 @@ // edition: 2021 +// run-rustfix + +#![allow(unused)] // Make sure we don't ICE when suggesting a return type // for an async fn that has late-bound vars... diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr b/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr index 36cabab758f..352f6da3607 100644 --- a/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr +++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr @@ -1,8 +1,8 @@ error[E0308]: mismatched types - --> $DIR/suggest-ret-on-async-w-late.rs:7:5 + --> $DIR/suggest-ret-on-async-w-late.rs:10:5 | LL | async fn ice(_: &i32) { - | --------------------- help: try adding a return type: `-> bool` + | - help: try adding a return type: `-> bool` LL | true | ^^^^ expected `()`, found `bool` diff --git a/tests/ui/type-alias-impl-trait/normalize-alias-type.rs b/tests/ui/type-alias-impl-trait/normalize-alias-type.rs new file mode 100644 index 00000000000..7c62002b931 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/normalize-alias-type.rs @@ -0,0 +1,32 @@ +// check-pass +// compile-flags: -Z mir-opt-level=3 +#![feature(type_alias_impl_trait)] +#![crate_type = "lib"] +pub trait Tr { + fn get(&self) -> u32; +} + +impl Tr for (u32,) { + #[inline] + fn get(&self) -> u32 { self.0 } +} + +pub fn tr1() -> impl Tr { + (32,) +} + +pub fn tr2() -> impl Tr { + struct Inner { + x: X, + } + type X = impl Tr; + impl Tr for Inner { + fn get(&self) -> u32 { + self.x.get() + } + } + + Inner { + x: tr1(), + } +} diff --git a/tests/ui/type-alias-impl-trait/tait-normalize.rs b/tests/ui/type-alias-impl-trait/tait-normalize.rs new file mode 100644 index 00000000000..26d94dbb42a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/tait-normalize.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +fn enum_upvar() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + let x = move || match foo { + None => (), + Some((a, b)) => (), + }; +} + +fn main(){} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs index 857066c78c9..9796823a724 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs @@ -4,7 +4,7 @@ // FIXME: this is ruled out for now but should work type Foo = fn() -> impl Send; -//~^ ERROR: `impl Trait` only allowed in function and inherent method return types +//~^ ERROR: `impl Trait` only allowed in function and inherent method argument and return types fn make_foo() -> Foo { || 15 diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr index ff375b2ff86..e57c59d6165 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr @@ -1,4 +1,4 @@ -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types --> $DIR/type-alias-impl-trait-fn-type.rs:6:20 | LL | type Foo = fn() -> impl Send; diff --git a/tests/ui/type/subtyping-opaque-type.rs b/tests/ui/type/subtyping-opaque-type.rs new file mode 100644 index 00000000000..beda232ea8b --- /dev/null +++ b/tests/ui/type/subtyping-opaque-type.rs @@ -0,0 +1,19 @@ +// check-pass +// compile-flags: -Zvalidate-mir +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl<R: Duh, F: FnMut() -> R> Trait for F { + type Assoc = R; +} + +fn foo() -> impl Trait<Assoc = impl Send> { + || 42 +} + +fn main() {} diff --git a/tests/ui/typeck/issue-104513-ice.rs b/tests/ui/typeck/issue-104513-ice.rs index bcac0fa1e70..4968d3f51fe 100644 --- a/tests/ui/typeck/issue-104513-ice.rs +++ b/tests/ui/typeck/issue-104513-ice.rs @@ -1,6 +1,6 @@ struct S; fn f() { let _: S<impl Oops> = S; //~ ERROR cannot find trait `Oops` in this scope - //~^ ERROR `impl Trait` only allowed in function and inherent method return types + //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types } fn main() {} diff --git a/tests/ui/typeck/issue-104513-ice.stderr b/tests/ui/typeck/issue-104513-ice.stderr index 09187d7863a..56c6b336154 100644 --- a/tests/ui/typeck/issue-104513-ice.stderr +++ b/tests/ui/typeck/issue-104513-ice.stderr @@ -4,7 +4,7 @@ error[E0405]: cannot find trait `Oops` in this scope LL | let _: S<impl Oops> = S; | ^^^^ not found in this scope -error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings +error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings --> $DIR/issue-104513-ice.rs:3:14 | LL | let _: S<impl Oops> = S; diff --git a/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr index dc4bc5b5f44..6c3302f29c2 100644 --- a/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr +++ b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-57673-ice-on-deref-of-boxed-trait.rs:5:5 | LL | fn ice(x: Box<dyn Iterator<Item=()>>) { - | - help: try adding a return type: `-> (dyn Iterator<Item = ()> + 'static)` + | - help: try adding a return type: `-> (dyn Iterator<Item = ()> + 'static)` LL | *x | ^^ expected `()`, found `dyn Iterator` | diff --git a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr index e367e04c375..c46f4ec1ec3 100644 --- a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr +++ b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-90027-async-fn-return-suggestion.rs:4:5 | LL | async fn hello() { - | ---------------- help: try adding a return type: `-> i32` + | - help: try adding a return type: `-> i32` LL | 0 | ^ expected `()`, found integer @@ -10,7 +10,7 @@ error[E0308]: mismatched types --> $DIR/issue-90027-async-fn-return-suggestion.rs:9:5 | LL | async fn world() -> () { - | ---------------------- expected `()` because of return type + | -- expected `()` because of return type LL | 0 | ^ expected `()`, found integer diff --git a/tests/ui/typeck/issue-91267.stderr b/tests/ui/typeck/issue-91267.stderr index 72acd9c673b..7e48b251980 100644 --- a/tests/ui/typeck/issue-91267.stderr +++ b/tests/ui/typeck/issue-91267.stderr @@ -14,7 +14,7 @@ error[E0308]: mismatched types --> $DIR/issue-91267.rs:4:5 | LL | fn main() { - | - expected `()` because of default return type + | - expected `()` because of default return type LL | type_ascribe!(0, u8<e<5>=e>) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `u8` |
