diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index d66774040f782..6a0ace04d4b61 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -242,6 +242,17 @@ impl Attribute { } } + pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> { + match self.kind { + AttrKind::DocComment(kind, data) => Some((data, kind)), + AttrKind::Normal(ref item, _) if item.path == sym::doc => item + .meta_kind() + .and_then(|kind| kind.value_str()) + .map(|data| (data, CommentKind::Line)), + _ => None, + } + } + pub fn doc_str(&self) -> Option { match self.kind { AttrKind::DocComment(.., data) => Some(data), diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs index 0a391123dd381..612ee71f350f1 100644 --- a/compiler/rustc_ast/src/util/comments.rs +++ b/compiler/rustc_ast/src/util/comments.rs @@ -1,3 +1,4 @@ +use crate::token::CommentKind; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, CharPos, FileName, Pos, Symbol}; @@ -25,7 +26,7 @@ pub struct Comment { /// Makes a doc string more presentable to users. /// Used by rustdoc and perhaps other tools, but not by rustc. -pub fn beautify_doc_string(data: Symbol) -> Symbol { +pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol { fn get_vertical_trim(lines: &[&str]) -> Option<(usize, usize)> { let mut i = 0; let mut j = lines.len(); @@ -42,10 +43,28 @@ pub fn beautify_doc_string(data: Symbol) -> Symbol { if i != 0 || j != lines.len() { Some((i, j)) } else { None } } - fn get_horizontal_trim(lines: &[&str]) -> Option { + fn get_horizontal_trim(lines: &[&str], kind: CommentKind) -> Option { let mut i = usize::MAX; let mut first = true; + // In case we have doc comments like `/**` or `/*!`, we want to remove stars if they are + // present. However, we first need to strip the empty lines so they don't get in the middle + // when we try to compute the "horizontal trim". + let lines = if kind == CommentKind::Block { + let mut i = 0; + let mut j = lines.len(); + + while i < j && lines[i].trim().is_empty() { + i += 1; + } + while j > i && lines[j - 1].trim().is_empty() { + j -= 1; + } + &lines[i..j] + } else { + lines + }; + for line in lines { for (j, c) in line.chars().enumerate() { if j > i || !"* \t".contains(c) { @@ -79,11 +98,13 @@ pub fn beautify_doc_string(data: Symbol) -> Symbol { } else { &mut lines }; - if let Some(horizontal) = get_horizontal_trim(&lines) { + if let Some(horizontal) = get_horizontal_trim(&lines, kind) { changes = true; // remove a "[ \t]*\*" block from each line, if possible for line in lines.iter_mut() { - *line = &line[horizontal + 1..]; + if horizontal + 1 < line.len() { + *line = &line[horizontal + 1..]; + } } } if changes { diff --git a/compiler/rustc_ast/src/util/comments/tests.rs b/compiler/rustc_ast/src/util/comments/tests.rs index 6d137f3774fe7..98f692a7724e2 100644 --- a/compiler/rustc_ast/src/util/comments/tests.rs +++ b/compiler/rustc_ast/src/util/comments/tests.rs @@ -5,7 +5,7 @@ use rustc_span::create_default_session_globals_then; fn test_block_doc_comment_1() { create_default_session_globals_then(|| { let comment = "\n * Test \n ** Test\n * Test\n"; - let stripped = beautify_doc_string(Symbol::intern(comment)); + let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block); assert_eq!(stripped.as_str(), " Test \n* Test\n Test"); }) } @@ -14,7 +14,7 @@ fn test_block_doc_comment_1() { fn test_block_doc_comment_2() { create_default_session_globals_then(|| { let comment = "\n * Test\n * Test\n"; - let stripped = beautify_doc_string(Symbol::intern(comment)); + let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block); assert_eq!(stripped.as_str(), " Test\n Test"); }) } @@ -23,7 +23,7 @@ fn test_block_doc_comment_2() { fn test_block_doc_comment_3() { create_default_session_globals_then(|| { let comment = "\n let a: *i32;\n *a = 5;\n"; - let stripped = beautify_doc_string(Symbol::intern(comment)); + let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block); assert_eq!(stripped.as_str(), " let a: *i32;\n *a = 5;"); }) } @@ -31,13 +31,13 @@ fn test_block_doc_comment_3() { #[test] fn test_line_doc_comment() { create_default_session_globals_then(|| { - let stripped = beautify_doc_string(Symbol::intern(" test")); + let stripped = beautify_doc_string(Symbol::intern(" test"), CommentKind::Line); assert_eq!(stripped.as_str(), " test"); - let stripped = beautify_doc_string(Symbol::intern("! test")); + let stripped = beautify_doc_string(Symbol::intern("! test"), CommentKind::Line); assert_eq!(stripped.as_str(), "! test"); - let stripped = beautify_doc_string(Symbol::intern("test")); + let stripped = beautify_doc_string(Symbol::intern("test"), CommentKind::Line); assert_eq!(stripped.as_str(), "test"); - let stripped = beautify_doc_string(Symbol::intern("!test")); + let stripped = beautify_doc_string(Symbol::intern("!test"), CommentKind::Line); assert_eq!(stripped.as_str(), "!test"); }) } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f7fe194d207d3..acf65259f61cf 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -667,7 +667,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( cmd.env_remove(k); } - if sess.opts.debugging_opts.print_link_args { + if sess.opts.prints.contains(&PrintRequest::LinkArgs) { println!("{:?}", &cmd); } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 694c679c1586e..19fa6812b45d9 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -645,9 +645,9 @@ impl RustcDefaultCalls { temps_dir: &Option, ) -> Compilation { use rustc_session::config::PrintRequest::*; - // PrintRequest::NativeStaticLibs is special - printed during linking + // NativeStaticLibs and LinkArgs are special - printed during linking // (empty iterator returns true) - if sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs) { + if sess.opts.prints.iter().all(|&p| p == NativeStaticLibs || p == LinkArgs) { return Compilation::Continue; } @@ -738,7 +738,8 @@ impl RustcDefaultCalls { codegen_backend.print(*req, sess); } // Any output here interferes with Cargo's parsing of other printed output - PrintRequest::NativeStaticLibs => {} + NativeStaticLibs => {} + LinkArgs => {} } } Compilation::Stop diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 43aa0ae265a09..a9dbdd483fe6f 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2726,6 +2726,10 @@ pub struct FnHeader { } impl FnHeader { + pub fn is_async(&self) -> bool { + matches!(&self.asyncness, IsAsync::Async) + } + pub fn is_const(&self) -> bool { matches!(&self.constness, Constness::Const) } @@ -3169,7 +3173,7 @@ impl<'hir> Node<'hir> { } } - pub fn fn_decl(&self) -> Option<&FnDecl<'hir>> { + pub fn fn_decl(&self) -> Option<&'hir FnDecl<'hir>> { match self { Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) @@ -3181,6 +3185,15 @@ impl<'hir> Node<'hir> { } } + pub fn fn_sig(&self) -> Option<&'hir FnSig<'hir>> { + match self { + Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) + | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) + | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig), + _ => None, + } + } + pub fn body_id(&self) -> Option { match self { Node::TraitItem(TraitItem { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e98b9c3b03c5a..14ab635a2ae2b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -65,11 +65,11 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_hir::{Item, ItemKind, Node}; use rustc_middle::dep_graph::DepContext; -use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ self, + error::TypeError, subst::{GenericArgKind, Subst, SubstsRef}, - Region, Ty, TyCtxt, TypeFoldable, + Binder, Region, Ty, TyCtxt, TypeFoldable, }; use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span}; use rustc_target::spec::abi; @@ -1765,7 +1765,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.note_error_origin(diag, cause, exp_found, terr); } - pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option> { + pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option>> { if let ty::Opaque(def_id, substs) = ty.kind() { let future_trait = self.tcx.require_lang_item(LangItem::Future, None); // Future::Output @@ -1775,13 +1775,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { for (predicate, _) in bounds { let predicate = predicate.subst(self.tcx, substs); - if let ty::PredicateKind::Projection(projection_predicate) = - predicate.kind().skip_binder() - { - if projection_predicate.projection_ty.item_def_id == item_def_id { - // We don't account for multiple `Future::Output = Ty` contraints. - return projection_predicate.term.ty(); - } + let output = predicate + .kind() + .map_bound(|kind| match kind { + ty::PredicateKind::Projection(projection_predicate) + if projection_predicate.projection_ty.item_def_id == item_def_id => + { + projection_predicate.term.ty() + } + _ => None, + }) + .transpose(); + if output.is_some() { + // We don't account for multiple `Future::Output = Ty` contraints. + return output; } } } @@ -1823,8 +1830,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } match ( - self.get_impl_future_output_ty(exp_found.expected), - self.get_impl_future_output_ty(exp_found.found), + self.get_impl_future_output_ty(exp_found.expected).map(Binder::skip_binder), + self.get_impl_future_output_ty(exp_found.found).map(Binder::skip_binder), ) { (Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match cause.code() { ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs index ac57796763fb3..4eec492b3aeb9 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -106,90 +106,47 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { None => String::new(), }; - let (span_1, span_2, main_label, span_label, future_return_type) = - match (sup_is_ret_type, sub_is_ret_type) { - (None, None) => { - let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id { - ( - "this type is declared with multiple lifetimes...".to_owned(), - "...but data with one lifetime flows into the other here".to_owned(), - ) - } else { - ( - "these two types are declared with different lifetimes...".to_owned(), - format!("...but data{} flows{} here", span_label_var1, span_label_var2), - ) - }; - (ty_sup.span, ty_sub.span, main_label_1, span_label_1, None) - } + debug!( + "try_report_anon_anon_conflict: sub_is_ret_type={:?} sup_is_ret_type={:?}", + sub_is_ret_type, sup_is_ret_type + ); - (Some(ret_span), _) => { - let sup_future = self.future_return_type(scope_def_id_sup); - let (return_type, action) = if sup_future.is_some() { - ("returned future", "held across an await point") - } else { - ("return type", "returned") - }; + let mut err = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch"); - ( - ty_sub.span, - ret_span, - format!( - "this parameter and the {} are declared with different lifetimes...", - return_type - ), - format!("...but data{} is {} here", span_label_var1, action), - sup_future, - ) - } - (_, Some(ret_span)) => { - let sub_future = self.future_return_type(scope_def_id_sub); - let (return_type, action) = if sub_future.is_some() { - ("returned future", "held across an await point") - } else { - ("return type", "returned") - }; + match (sup_is_ret_type, sub_is_ret_type) { + (ret_capture @ Some(ret_span), _) | (_, ret_capture @ Some(ret_span)) => { + let param_span = + if sup_is_ret_type == ret_capture { ty_sub.span } else { ty_sup.span }; + + err.span_label( + param_span, + "this parameter and the return type are declared with different lifetimes...", + ); + err.span_label(ret_span, ""); + err.span_label(span, format!("...but data{} is returned here", span_label_var1)); + } - ( + (None, None) => { + if ty_sup.hir_id == ty_sub.hir_id { + err.span_label(ty_sup.span, "this type is declared with multiple lifetimes..."); + err.span_label(ty_sub.span, ""); + err.span_label(span, "...but data with one lifetime flows into the other here"); + } else { + err.span_label( ty_sup.span, - ret_span, - format!( - "this parameter and the {} are declared with different lifetimes...", - return_type - ), - format!("...but data{} is {} here", span_label_var1, action), - sub_future, - ) + "these two types are declared with different lifetimes...", + ); + err.span_label(ty_sub.span, ""); + err.span_label( + span, + format!("...but data{} flows{} here", span_label_var1, span_label_var2), + ); } - }; - - let mut err = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch"); - - err.span_label(span_1, main_label); - err.span_label(span_2, String::new()); - err.span_label(span, span_label); + } + } self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err); - if let Some(t) = future_return_type { - let snip = self - .tcx() - .sess - .source_map() - .span_to_snippet(t.span) - .ok() - .and_then(|s| match (&t.kind, s.as_str()) { - (rustc_hir::TyKind::Tup(&[]), "") => Some("()".to_string()), - (_, "") => None, - _ => Some(s), - }) - .unwrap_or_else(|| "{unnamed_type}".to_string()); - - err.span_label( - t.span, - &format!("this `async fn` implicitly returns an `impl Future`", snip), - ); - } err.emit(); Some(ErrorReported) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index 07bba00056630..b1535701bb399 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -1,6 +1,5 @@ use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::Node; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_lifetime as rl; @@ -25,25 +24,19 @@ pub(crate) fn find_anon_type<'tcx>( tcx: TyCtxt<'tcx>, region: Region<'tcx>, br: &ty::BoundRegionKind, -) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnDecl<'tcx>)> { +) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnSig<'tcx>)> { if let Some(anon_reg) = tcx.is_suitable_region(region) { let hir_id = tcx.hir().local_def_id_to_hir_id(anon_reg.def_id); - let fndecl = match tcx.hir().get(hir_id) { - Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref m, ..), .. }) - | Node::TraitItem(&hir::TraitItem { - kind: hir::TraitItemKind::Fn(ref m, ..), .. - }) - | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref m, ..), .. }) => { - &m.decl - } - _ => return None, + let Some(fn_sig) = tcx.hir().get(hir_id).fn_sig() else { + return None }; - fndecl + fn_sig + .decl .inputs .iter() .find_map(|arg| find_component_for_bound_region(tcx, arg, br)) - .map(|ty| (ty, &**fndecl)) + .map(|ty| (ty, fn_sig)) } else { None } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index 3fa71d1a3d817..6d71d702cc89b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -4,7 +4,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; -use rustc_middle::ty::{self, DefIdTree, Region, Ty}; +use rustc_middle::ty::{self, Binder, DefIdTree, Region, Ty, TypeFoldable}; use rustc_span::Span; /// Information about the anonymous region we are searching for. @@ -94,81 +94,42 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }) } - pub(super) fn future_return_type( - &self, - local_def_id: LocalDefId, - ) -> Option<&rustc_hir::Ty<'_>> { - if let Some(hir::IsAsync::Async) = self.asyncness(local_def_id) { - if let rustc_middle::ty::Opaque(def_id, _) = - self.tcx().type_of(local_def_id).fn_sig(self.tcx()).output().skip_binder().kind() - { - match self.tcx().hir().get_if_local(*def_id) { - Some(hir::Node::Item(hir::Item { - kind: - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - bounds, - origin: hir::OpaqueTyOrigin::AsyncFn(..), - .. - }), - .. - })) => { - for b in bounds.iter() { - if let hir::GenericBound::LangItemTrait( - hir::LangItem::Future, - _span, - _hir_id, - generic_args, - ) = b - { - for type_binding in generic_args.bindings.iter() { - if type_binding.ident.name == rustc_span::sym::Output { - if let hir::TypeBindingKind::Equality { - term: hir::Term::Ty(ty), - } = type_binding.kind - { - return Some(ty); - } - } - } - } - } - } - _ => {} - } - } - } - None - } - - pub(super) fn asyncness(&self, local_def_id: LocalDefId) -> Option { - // similar to the asyncness fn in rustc_ty_utils::ty - let hir_id = self.tcx().hir().local_def_id_to_hir_id(local_def_id); - let node = self.tcx().hir().get(hir_id); - let fn_kind = node.fn_kind()?; - Some(fn_kind.asyncness()) - } - // Here, we check for the case where the anonymous region - // is in the return type. + // is in the return type as written by the user. // FIXME(#42703) - Need to handle certain cases here. pub(super) fn is_return_type_anon( &self, scope_def_id: LocalDefId, br: ty::BoundRegionKind, - decl: &hir::FnDecl<'_>, + hir_sig: &hir::FnSig<'_>, ) -> Option { - let ret_ty = self.tcx().type_of(scope_def_id); - if let ty::FnDef(_, _) = ret_ty.kind() { - let sig = ret_ty.fn_sig(self.tcx()); - let late_bound_regions = - self.tcx().collect_referenced_late_bound_regions(&sig.output()); - if late_bound_regions.iter().any(|r| *r == br) { - return Some(decl.output.span()); - } + let fn_ty = self.tcx().type_of(scope_def_id); + if let ty::FnDef(_, _) = fn_ty.kind() { + let ret_ty = fn_ty.fn_sig(self.tcx()).output(); + let span = hir_sig.decl.output.span(); + let future_output = if hir_sig.header.is_async() { + ret_ty.map_bound(|ty| self.infcx.get_impl_future_output_ty(ty)).transpose() + } else { + None + }; + return match future_output { + Some(output) if self.includes_region(output, br) => Some(span), + None if self.includes_region(ret_ty, br) => Some(span), + _ => None, + }; } None } + fn includes_region( + &self, + ty: Binder<'tcx, impl TypeFoldable<'tcx>>, + region: ty::BoundRegionKind, + ) -> bool { + let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(&ty); + late_bound_regions.iter().any(|r| *r == region) + } + // Here we check for the case where anonymous region // corresponds to self and if yes, we display E0312. // FIXME(#42700) - Need to format self properly to diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 0e27a82b2b13b..44acbd3cf2159 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -678,7 +678,6 @@ fn test_debugging_options_tracking_hash() { // `pre_link_arg` is omitted because it just forwards to `pre_link_args`. untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]); untracked!(profile_closures, true); - untracked!(print_link_args, true); untracked!(print_llvm_passes, true); untracked!(print_mono_items, Some(String::from("abc"))); untracked!(print_type_sizes, true); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 66a89492abd84..38e1669d33197 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1247,7 +1247,7 @@ declare_lint! { /// [`UnsafeCell`]: https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html MUTABLE_TRANSMUTES, Deny, - "mutating transmuted &mut T from &T may cause undefined behavior" + "transmuting &T to &mut T is undefined behavior, even if the reference is unused" } declare_lint_pass!(MutableTransmutes => [MUTABLE_TRANSMUTES]); @@ -1259,8 +1259,8 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes { get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind())) { if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not { - let msg = "mutating transmuted &mut T from &T may cause undefined behavior, \ - consider instead using an UnsafeCell"; + let msg = "transmuting &T to &mut T is undefined behavior, \ + even if the reference is unused, consider instead using an UnsafeCell"; cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| lint.build(msg).emit()); } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e7b99995ca4ae..8d591d6781235 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1210,11 +1210,25 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_ty(Error(DelaySpanBugEmitted(()))) } - /// Like `err` but for constants. + /// Like [TyCtxt::ty_error] but for constants. #[track_caller] pub fn const_error(self, ty: Ty<'tcx>) -> &'tcx Const<'tcx> { - self.sess - .delay_span_bug(DUMMY_SP, "ty::ConstKind::Error constructed but no error reported."); + self.const_error_with_message( + ty, + DUMMY_SP, + "ty::ConstKind::Error constructed but no error reported", + ) + } + + /// Like [TyCtxt::ty_error_with_message] but for constants. + #[track_caller] + pub fn const_error_with_message>( + self, + ty: Ty<'tcx>, + span: S, + msg: &str, + ) -> &'tcx Const<'tcx> { + self.sess.delay_span_bug(span, msg); self.mk_const(ty::Const { val: ty::ConstKind::Error(DelaySpanBugEmitted(())), ty }) } diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs index 77bc209539b34..cda9ba9dcc87f 100644 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs @@ -3,8 +3,7 @@ use crate::MirPass; use rustc_data_structures::stable_set::FxHashSet; use rustc_middle::mir::{ - BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, SwitchTargets, - TerminatorKind, + BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, SwitchTargets, TerminatorKind, }; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{Ty, TyCtxt}; @@ -56,7 +55,10 @@ fn variant_discriminants<'tcx>( match &layout.variants { Variants::Single { index } => { let mut res = FxHashSet::default(); - res.insert(index.as_u32() as u128); + res.insert( + ty.discriminant_for_variant(tcx, *index) + .map_or(index.as_u32() as u128, |discr| discr.val), + ); res } Variants::Multiple { variants, .. } => variants @@ -75,16 +77,9 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if body.source.promoted.is_some() { - return; - } - trace!("UninhabitedEnumBranching starting for {:?}", body.source); - let basic_block_count = body.basic_blocks().len(); - - for bb in 0..basic_block_count { - let bb = BasicBlock::from_usize(bb); + for bb in body.basic_blocks().indices() { trace!("processing block {:?}", bb); let Some(discriminant_ty) = get_switched_on_type(&body.basic_blocks()[bb], tcx, body) else { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 2c96899197351..0b4579b299d09 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1148,19 +1148,11 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { if self.visit(ty).is_break() { return; } + } else { + // We don't do anything for const infers here. } } else { - let local_id = self.tcx.hir().local_def_id(inf.hir_id); - if let Some(did) = self.tcx.opt_const_param_of(local_id) { - if self.visit_def_id(did, "inferred", &"").is_break() { - return; - } - } - - // FIXME see above note for same issue. - if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, &inf.to_ty())).is_break() { - return; - } + bug!("visit_infer without typeck_results"); } intravisit::walk_inf(self, inf); } diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 21cb93cc5f48b..b95fe1b0549bd 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -821,9 +821,9 @@ impl<'tcx> SaveContext<'tcx> { let mut result = String::new(); for attr in attrs { - if let Some(val) = attr.doc_str() { + if let Some((val, kind)) = attr.doc_str_and_comment_kind() { // FIXME: Should save-analysis beautify doc strings itself or leave it to users? - result.push_str(beautify_doc_string(val).as_str()); + result.push_str(beautify_doc_string(val, kind).as_str()); result.push('\n'); } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 62b351f5e0279..92ad0723f4879 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -565,6 +565,7 @@ pub enum PrintRequest { TargetSpec, NativeStaticLibs, StackProtectorStrategies, + LinkArgs, } #[derive(Copy, Clone)] @@ -1187,7 +1188,8 @@ pub fn rustc_short_optgroups() -> Vec { "Compiler information to print on stdout", "[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\ target-cpus|target-features|relocation-models|code-models|\ - tls-models|target-spec-json|native-static-libs|stack-protector-strategies]", + tls-models|target-spec-json|native-static-libs|stack-protector-strategies\ + link-args]", ), opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), @@ -1619,6 +1621,7 @@ fn collect_print_requests( ); } } + "link-args" => PrintRequest::LinkArgs, req => early_error(error_format, &format!("unknown print request `{}`", req)), })); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c48d8d689c10e..e7ab8fffdf35c 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1339,8 +1339,6 @@ options! { See #77382 and #74551."), print_fuel: Option = (None, parse_opt_string, [TRACKED], "make rustc print the total optimization fuel used by a crate"), - print_link_args: bool = (false, parse_bool, [UNTRACKED], - "print the arguments passed to the linker (default: no)"), print_llvm_passes: bool = (false, parse_bool, [UNTRACKED], "print the LLVM optimization passes being run (default: no)"), print_mono_items: Option = (None, parse_opt_string, [UNTRACKED], diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 7c53e49e280d6..d9b3f51b5bd24 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -6,7 +6,7 @@ mod errors; mod generics; use crate::bounds::Bounds; -use crate::collect::PlaceholderHirTyCollector; +use crate::collect::HirPlaceholderCollector; use crate::errors::{ AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits, TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified, @@ -2504,7 +2504,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!(?bound_vars); // We proactively collect all the inferred type params to emit a single error per fn def. - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); for ty in decl.inputs { visitor.visit_ty(ty); } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 3e73cc659ec46..f6abeff60cd94 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1909,7 +1909,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => return, }; let mut add_label = true; - if let ty::Adt(def, _) = output_ty.kind() { + if let ty::Adt(def, _) = output_ty.skip_binder().kind() { // no field access on enum type if !def.is_enum() { if def diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 473c848ad8f13..be4c9ec99b9c6 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -609,14 +609,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); let ty = self.normalize_associated_types_in(expr.span, ty); let ty = match self.tcx.asyncness(fn_id.owner) { - hir::IsAsync::Async => self.tcx.infer_ctxt().enter(|infcx| { - infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| { - span_bug!( - fn_decl.output.span(), - "failed to get output type of async function" - ) + hir::IsAsync::Async => self + .tcx + .infer_ctxt() + .enter(|infcx| { + infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| { + span_bug!( + fn_decl.output.span(), + "failed to get output type of async function" + ) + }) }) - }), + .skip_binder(), hir::IsAsync::NotAsync => ty, }; if self.can_coerce(found, ty) { diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 56f4d5afe400d..96ab800afaffe 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1274,7 +1274,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, ) { let output_ty = match self.infcx.get_impl_future_output_ty(ty) { - Some(output_ty) => self.resolve_vars_if_possible(output_ty), + Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(), _ => return, }; let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 403aa16689fcf..cf519a9ab3274 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -112,9 +112,9 @@ pub struct ItemCtxt<'tcx> { /////////////////////////////////////////////////////////////////////////// #[derive(Default)] -crate struct PlaceholderHirTyCollector(crate Vec); +crate struct HirPlaceholderCollector(crate Vec); -impl<'v> Visitor<'v> for PlaceholderHirTyCollector { +impl<'v> Visitor<'v> for HirPlaceholderCollector { fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { if let hir::TyKind::Infer = t.kind { self.0.push(t.span); @@ -131,6 +131,12 @@ impl<'v> Visitor<'v> for PlaceholderHirTyCollector { _ => {} } } + fn visit_array_length(&mut self, length: &'v hir::ArrayLen) { + if let &hir::ArrayLen::Infer(_, span) = length { + self.0.push(span); + } + intravisit::walk_array_len(self, length) + } } struct CollectItemTypesVisitor<'tcx> { @@ -175,7 +181,7 @@ crate fn placeholder_type_error<'tcx>( sugg.push((span, format!(", {}", type_name))); } - let mut err = bad_placeholder(tcx, "type", placeholder_types, kind); + let mut err = bad_placeholder(tcx, placeholder_types, kind); // Suggest, but only if it is not a function in const or static if suggest { @@ -233,7 +239,7 @@ fn reject_placeholder_type_signatures_in_item<'tcx>( _ => return, }; - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_item(item); placeholder_type_error( @@ -311,7 +317,6 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { fn bad_placeholder<'tcx>( tcx: TyCtxt<'tcx>, - placeholder_kind: &'static str, mut spans: Vec, kind: &'static str, ) -> rustc_errors::DiagnosticBuilder<'tcx> { @@ -322,8 +327,7 @@ fn bad_placeholder<'tcx>( tcx.sess, spans.clone(), E0121, - "the {} placeholder `_` is not allowed within types on item signatures for {}", - placeholder_kind, + "the placeholder `_` is not allowed within types on item signatures for {}", kind ); for span in spans { @@ -381,7 +385,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { } fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { - self.tcx().ty_error_with_message(span, "bad_placeholder_type") + self.tcx().ty_error_with_message(span, "bad placeholder type") } fn ct_infer( @@ -390,13 +394,11 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { _: Option<&ty::GenericParamDef>, span: Span, ) -> &'tcx Const<'tcx> { - bad_placeholder(self.tcx(), "const", vec![span], "generic").emit(); - // Typeck doesn't expect erased regions to be returned from `type_of`. let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match r { ty::ReErased => self.tcx.lifetimes.re_static, _ => r, }); - self.tcx().const_error(ty) + self.tcx().const_error_with_message(ty, span, "bad placeholder constant") } fn projected_ty_from_poly_trait_ref( @@ -743,7 +745,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { match item.kind { hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.def_id), hir::ForeignItemKind::Static(..) => { - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_foreign_item(item); placeholder_type_error( tcx, @@ -826,7 +828,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => { // (#75889): Account for `const C: dyn Fn() -> _ = "";` if let hir::TyKind::TraitObject(..) = ty.kind { - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_item(it); placeholder_type_error( tcx, @@ -862,7 +864,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { hir::TraitItemKind::Const(..) => { tcx.ensure().type_of(trait_item_id.def_id); // Account for `const C: _;`. - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_trait_item(trait_item); placeholder_type_error(tcx, None, &[], visitor.0, false, None, "constant"); } @@ -871,7 +873,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { tcx.ensure().item_bounds(trait_item_id.def_id); tcx.ensure().type_of(trait_item_id.def_id); // Account for `type T = _;`. - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_trait_item(trait_item); placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type"); } @@ -880,7 +882,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { tcx.ensure().item_bounds(trait_item_id.def_id); // #74612: Visit and try to find bad placeholders // even if there is no concrete type. - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_trait_item(trait_item); placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type"); @@ -902,7 +904,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { } hir::ImplItemKind::TyAlias(_) => { // Account for `type T = _;` - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_impl_item(impl_item); placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type"); @@ -1822,10 +1824,14 @@ fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool { /// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to /// use inference to provide suggestions for the appropriate type if possible. fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { + debug!(?ty); use hir::TyKind::*; match &ty.kind { Infer => true, - Slice(ty) | Array(ty, _) => is_suggestable_infer_ty(ty), + Slice(ty) => is_suggestable_infer_ty(ty), + Array(ty, length) => { + is_suggestable_infer_ty(ty) || matches!(length, hir::ArrayLen::Infer(_, _)) + } Tup(tys) => tys.iter().any(is_suggestable_infer_ty), Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty), OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args), @@ -1877,9 +1883,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { }); let fn_sig = ty::Binder::dummy(fn_sig); - let mut visitor = PlaceholderHirTyCollector::default(); + let mut visitor = HirPlaceholderCollector::default(); visitor.visit_ty(ty); - let mut diag = bad_placeholder(tcx, "type", visitor.0, "return type"); + let mut diag = bad_placeholder(tcx, visitor.0, "return type"); let ret_ty = fn_sig.skip_binder().output(); if !ret_ty.references_error() { if !ret_ty.is_closure() { diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index bc7507bcc500f..63020b7f90f0a 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -20,9 +20,6 @@ use super::{bad_placeholder, is_suggestable_infer_ty}; /// This should be called using the query `tcx.opt_const_param_of`. #[instrument(level = "debug", skip(tcx))] pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - // FIXME(generic_arg_infer): allow for returning DefIds of inference of - // GenericArg::Infer below. This may require a change where GenericArg::Infer has some flag - // for const or type. use hir::*; let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); @@ -753,7 +750,7 @@ fn infer_placeholder_type<'a>( err.emit(); } None => { - let mut diag = bad_placeholder(tcx, "type", vec![span], kind); + let mut diag = bad_placeholder(tcx, vec![span], kind); if !ty.references_error() { let mut mk_nameable = MakeNameable::new(tcx); diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 56bdc6beb902d..e38c0412a0afe 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1,8 +1,9 @@ use crate::any::type_name; use crate::fmt; use crate::intrinsics; -use crate::mem::ManuallyDrop; +use crate::mem::{self, ManuallyDrop}; use crate::ptr; +use crate::slice; /// A wrapper type to construct uninitialized instances of `T`. /// @@ -1160,4 +1161,126 @@ impl MaybeUninit { // SAFETY: Valid elements have just been written into `this` so it is initialized unsafe { MaybeUninit::slice_assume_init_mut(this) } } + + /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. + /// + /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still + /// contain padding bytes which are left uninitialized. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)] + /// use std::mem::MaybeUninit; + /// + /// let val = 0x12345678i32; + /// let uninit = MaybeUninit::new(val); + /// let uninit_bytes = uninit.as_bytes(); + /// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(uninit_bytes) }; + /// assert_eq!(bytes, val.to_ne_bytes()); + /// ``` + #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] + pub fn as_bytes(&self) -> &[MaybeUninit] { + // SAFETY: MaybeUninit is always valid, even for padding bytes + unsafe { + slice::from_raw_parts(self.as_ptr() as *const MaybeUninit, mem::size_of::()) + } + } + + /// Returns the contents of this `MaybeUninit` as a mutable slice of potentially uninitialized + /// bytes. + /// + /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still + /// contain padding bytes which are left uninitialized. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_as_bytes)] + /// use std::mem::MaybeUninit; + /// + /// let val = 0x12345678i32; + /// let mut uninit = MaybeUninit::new(val); + /// let uninit_bytes = uninit.as_bytes_mut(); + /// if cfg!(target_endian = "little") { + /// uninit_bytes[0].write(0xcd); + /// } else { + /// uninit_bytes[3].write(0xcd); + /// } + /// let val2 = unsafe { uninit.assume_init() }; + /// assert_eq!(val2, 0x123456cd); + /// ``` + #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] + pub fn as_bytes_mut(&mut self) -> &mut [MaybeUninit] { + // SAFETY: MaybeUninit is always valid, even for padding bytes + unsafe { + slice::from_raw_parts_mut( + self.as_mut_ptr() as *mut MaybeUninit, + mem::size_of::(), + ) + } + } + + /// Returns the contents of this slice of `MaybeUninit` as a slice of potentially uninitialized + /// bytes. + /// + /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still + /// contain padding bytes which are left uninitialized. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_as_bytes, maybe_uninit_write_slice, maybe_uninit_slice)] + /// use std::mem::MaybeUninit; + /// + /// let uninit = [MaybeUninit::new(0x1234u16), MaybeUninit::new(0x5678u16)]; + /// let uninit_bytes = MaybeUninit::slice_as_bytes(&uninit); + /// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(&uninit_bytes) }; + /// let val1 = u16::from_ne_bytes(bytes[0..2].try_into().unwrap()); + /// let val2 = u16::from_ne_bytes(bytes[2..4].try_into().unwrap()); + /// assert_eq!(&[val1, val2], &[0x1234u16, 0x5678u16]); + /// ``` + #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] + pub fn slice_as_bytes(this: &[MaybeUninit]) -> &[MaybeUninit] { + // SAFETY: MaybeUninit is always valid, even for padding bytes + unsafe { + slice::from_raw_parts( + this.as_ptr() as *const MaybeUninit, + this.len() * mem::size_of::(), + ) + } + } + + /// Returns the contents of this mutable slice of `MaybeUninit` as a mutable slice of + /// potentially uninitialized bytes. + /// + /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still + /// contain padding bytes which are left uninitialized. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_as_bytes, maybe_uninit_write_slice, maybe_uninit_slice)] + /// use std::mem::MaybeUninit; + /// + /// let mut uninit = [MaybeUninit::::uninit(), MaybeUninit::::uninit()]; + /// let uninit_bytes = MaybeUninit::slice_as_bytes_mut(&mut uninit); + /// MaybeUninit::write_slice(uninit_bytes, &[0x12, 0x34, 0x56, 0x78]); + /// let vals = unsafe { MaybeUninit::slice_assume_init_ref(&uninit) }; + /// if cfg!(target_endian = "little") { + /// assert_eq!(vals, &[0x3412u16, 0x7856u16]); + /// } else { + /// assert_eq!(vals, &[0x1234u16, 0x5678u16]); + /// } + /// ``` + #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] + pub fn slice_as_bytes_mut(this: &mut [MaybeUninit]) -> &mut [MaybeUninit] { + // SAFETY: MaybeUninit is always valid, even for padding bytes + unsafe { + slice::from_raw_parts_mut( + this.as_mut_ptr() as *mut MaybeUninit, + this.len() * mem::size_of::(), + ) + } + } } diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 5537ec18d34a9..9d6b2fe8c25d8 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2042,13 +2042,17 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// /// # Platform-specific behavior /// -/// This function currently corresponds to `opendir`, `lstat`, `rm` and `rmdir` functions on Unix -/// and the `FindFirstFile`, `GetFileAttributesEx`, `DeleteFile`, and `RemoveDirectory` functions -/// on Windows. -/// Note that, this [may change in the future][changes]. +/// This function currently corresponds to `openat`, `fdopendir`, `unlinkat` and `lstat` functions +/// on Unix (except for macOS before version 10.10 and REDOX) and the `CreateFileW`, +/// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtOpenFile` functions on +/// Windows. Note that, this [may change in the future][changes]. /// /// [changes]: io#platform-specific-behavior /// +/// On macOS before version 10.10 and REDOX this function is not protected against time-of-check to +/// time-of-use (TOCTOU) race conditions, and should not be used in security-sensitive code on +/// those platforms. All other platforms are protected. +/// /// # Errors /// /// See [`fs::remove_file`] and [`fs::remove_dir`]. diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 749d51d4981c3..a62c01ef29b27 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -4,8 +4,10 @@ use crate::fs::{self, File, OpenOptions}; use crate::io::{ErrorKind, SeekFrom}; use crate::path::Path; use crate::str; +use crate::sync::Arc; use crate::sys_common::io::test::{tmpdir, TempDir}; use crate::thread; +use crate::time::{Duration, Instant}; use rand::{rngs::StdRng, RngCore, SeedableRng}; @@ -601,6 +603,21 @@ fn recursive_rmdir_of_symlink() { assert!(canary.exists()); } +#[test] +fn recursive_rmdir_of_file_fails() { + // test we do not delete a directly specified file. + let tmpdir = tmpdir(); + let canary = tmpdir.join("do_not_delete"); + check!(check!(File::create(&canary)).write(b"foo")); + let result = fs::remove_dir_all(&canary); + #[cfg(unix)] + error!(result, "Not a directory"); + #[cfg(windows)] + error!(result, 267); // ERROR_DIRECTORY - The directory name is invalid. + assert!(result.is_err()); + assert!(canary.exists()); +} + #[test] // only Windows makes a distinction between file and directory symlinks. #[cfg(windows)] @@ -620,6 +637,59 @@ fn recursive_rmdir_of_file_symlink() { } } +#[test] +#[ignore] // takes too much time +fn recursive_rmdir_toctou() { + // Test for time-of-check to time-of-use issues. + // + // Scenario: + // The attacker wants to get directory contents deleted, to which he does not have access. + // He has a way to get a privileged Rust binary call `std::fs::remove_dir_all()` on a + // directory he controls, e.g. in his home directory. + // + // The POC sets up the `attack_dest/attack_file` which the attacker wants to have deleted. + // The attacker repeatedly creates a directory and replaces it with a symlink from + // `victim_del` to `attack_dest` while the victim code calls `std::fs::remove_dir_all()` + // on `victim_del`. After a few seconds the attack has succeeded and + // `attack_dest/attack_file` is deleted. + let tmpdir = tmpdir(); + let victim_del_path = tmpdir.join("victim_del"); + let victim_del_path_clone = victim_del_path.clone(); + + // setup dest + let attack_dest_dir = tmpdir.join("attack_dest"); + let attack_dest_dir = attack_dest_dir.as_path(); + fs::create_dir(attack_dest_dir).unwrap(); + let attack_dest_file = tmpdir.join("attack_dest/attack_file"); + File::create(&attack_dest_file).unwrap(); + + let drop_canary_arc = Arc::new(()); + let drop_canary_weak = Arc::downgrade(&drop_canary_arc); + + eprintln!("x: {:?}", &victim_del_path); + + // victim just continuously removes `victim_del` + thread::spawn(move || { + while drop_canary_weak.upgrade().is_some() { + let _ = fs::remove_dir_all(&victim_del_path_clone); + } + }); + + // attacker (could of course be in a separate process) + let start_time = Instant::now(); + while Instant::now().duration_since(start_time) < Duration::from_secs(1000) { + if !attack_dest_file.exists() { + panic!( + "Victim deleted symlinked file outside of victim_del. Attack succeeded in {:?}.", + Instant::now().duration_since(start_time) + ); + } + let _ = fs::create_dir(&victim_del_path); + let _ = fs::remove_dir(&victim_del_path); + let _ = symlink_dir(attack_dest_dir, &victim_del_path); + } +} + #[test] fn unicode_path_is_dir() { assert!(Path::new(".").is_dir()); diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 44f573297eed1..d0f332fe5e810 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -263,7 +263,7 @@ fn default_hook(info: &PanicInfo<'_>) { // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. let backtrace_env = if panic_count::get_count() >= 2 { - RustBacktrace::Print(crate::backtrace_rs::PrintFmt::Full) + backtrace::rust_backtrace_print_full() } else { backtrace::rust_backtrace_env() }; diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index bcf2be0e95fb7..f8deda93fe2a7 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -64,7 +64,7 @@ use libc::{ dirent64, fstat64, ftruncate64, lseek64, lstat64, off64_t, open64, readdir64_r, stat64, }; -pub use crate::sys_common::fs::{remove_dir_all, try_exists}; +pub use crate::sys_common::fs::try_exists; pub struct File(FileDesc); @@ -228,7 +228,7 @@ pub struct DirEntry { target_os = "fuchsia", target_os = "redox" ))] - name: Box<[u8]>, + name: CString, } #[derive(Clone, Debug)] @@ -455,8 +455,6 @@ impl Iterator for ReadDir { target_os = "illumos" ))] fn next(&mut self) -> Option> { - use crate::slice; - unsafe { loop { // Although readdir_r(3) would be a correct function to use here because @@ -474,14 +472,10 @@ impl Iterator for ReadDir { }; } - let name = (*entry_ptr).d_name.as_ptr(); - let namelen = libc::strlen(name) as usize; - let ret = DirEntry { entry: *entry_ptr, - name: slice::from_raw_parts(name as *const u8, namelen as usize) - .to_owned() - .into_boxed_slice(), + // d_name is guaranteed to be null-terminated. + name: CStr::from_ptr((*entry_ptr).d_name.as_ptr()).to_owned(), dir: Arc::clone(&self.inner), }; if ret.name_bytes() != b"." && ret.name_bytes() != b".." { @@ -664,7 +658,21 @@ impl DirEntry { target_os = "redox" ))] fn name_bytes(&self) -> &[u8] { - &*self.name + self.name.as_bytes() + } + + #[cfg(not(any( + target_os = "solaris", + target_os = "illumos", + target_os = "fuchsia", + target_os = "redox" + )))] + fn name_cstr(&self) -> &CStr { + unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) } + } + #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "fuchsia"))] + fn name_cstr(&self) -> &CStr { + &self.name } pub fn file_name_os_str(&self) -> &OsStr { @@ -1437,3 +1445,258 @@ pub fn chroot(dir: &Path) -> io::Result<()> { cvt(unsafe { libc::chroot(dir.as_ptr()) })?; Ok(()) } + +pub use remove_dir_impl::remove_dir_all; + +// Fallback for REDOX +#[cfg(target_os = "redox")] +mod remove_dir_impl { + pub use crate::sys_common::fs::remove_dir_all; +} + +// Dynamically choose implementation Macos x86-64: modern for 10.10+, fallback for older versions +#[cfg(all(target_os = "macos", target_arch = "x86_64"))] +mod remove_dir_impl { + use super::{cstr, lstat, Dir, InnerReadDir, ReadDir}; + use crate::ffi::CStr; + use crate::io; + use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; + use crate::os::unix::prelude::{OwnedFd, RawFd}; + use crate::path::{Path, PathBuf}; + use crate::sync::Arc; + use crate::sys::weak::weak; + use crate::sys::{cvt, cvt_r}; + use libc::{c_char, c_int, DIR}; + + pub fn openat_nofollow_dironly(parent_fd: Option, p: &CStr) -> io::Result { + weak!(fn openat(c_int, *const c_char, c_int) -> c_int); + let fd = cvt_r(|| unsafe { + openat.get().unwrap()( + parent_fd.unwrap_or(libc::AT_FDCWD), + p.as_ptr(), + libc::O_CLOEXEC | libc::O_RDONLY | libc::O_NOFOLLOW | libc::O_DIRECTORY, + ) + })?; + Ok(unsafe { OwnedFd::from_raw_fd(fd) }) + } + + fn fdreaddir(dir_fd: OwnedFd) -> io::Result<(ReadDir, RawFd)> { + weak!(fn fdopendir(c_int) -> *mut DIR, "fdopendir$INODE64"); + let ptr = unsafe { fdopendir.get().unwrap()(dir_fd.as_raw_fd()) }; + if ptr.is_null() { + return Err(io::Error::last_os_error()); + } + let dirp = Dir(ptr); + // file descriptor is automatically closed by libc::closedir() now, so give up ownership + let new_parent_fd = dir_fd.into_raw_fd(); + // a valid root is not needed because we do not call any functions involving the full path + // of the DirEntrys. + let dummy_root = PathBuf::new(); + Ok(( + ReadDir { + inner: Arc::new(InnerReadDir { dirp, root: dummy_root }), + end_of_stream: false, + }, + new_parent_fd, + )) + } + + fn remove_dir_all_recursive(parent_fd: Option, p: &Path) -> io::Result<()> { + weak!(fn unlinkat(c_int, *const c_char, c_int) -> c_int); + + let pcstr = cstr(p)?; + + // entry is expected to be a directory, open as such + let fd = openat_nofollow_dironly(parent_fd, &pcstr)?; + + // open the directory passing ownership of the fd + let (dir, fd) = fdreaddir(fd)?; + for child in dir { + let child = child?; + match child.entry.d_type { + libc::DT_DIR => { + remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?; + } + libc::DT_UNKNOWN => { + match cvt(unsafe { unlinkat.get().unwrap()(fd, child.name_cstr().as_ptr(), 0) }) + { + // type unknown - try to unlink + Err(err) if err.raw_os_error() == Some(libc::EPERM) => { + // if the file is a directory unlink fails with EPERM + remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?; + } + result => { + result?; + } + } + } + _ => { + // not a directory -> unlink + cvt(unsafe { unlinkat.get().unwrap()(fd, child.name_cstr().as_ptr(), 0) })?; + } + } + } + + // unlink the directory after removing its contents + cvt(unsafe { + unlinkat.get().unwrap()( + parent_fd.unwrap_or(libc::AT_FDCWD), + pcstr.as_ptr(), + libc::AT_REMOVEDIR, + ) + })?; + Ok(()) + } + + fn remove_dir_all_modern(p: &Path) -> io::Result<()> { + // We cannot just call remove_dir_all_recursive() here because that would not delete a passed + // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse + // into symlinks. + let attr = lstat(p)?; + if attr.file_type().is_symlink() { + crate::fs::remove_file(p) + } else { + remove_dir_all_recursive(None, p) + } + } + + pub fn remove_dir_all(p: &Path) -> io::Result<()> { + weak!(fn openat(c_int, *const c_char, c_int) -> c_int); + if openat.get().is_some() { + // openat() is available with macOS 10.10+, just like unlinkat() and fdopendir() + remove_dir_all_modern(p) + } else { + // fall back to classic implementation + crate::sys_common::fs::remove_dir_all(p) + } + } +} + +// Modern implementation using openat(), unlinkat() and fdopendir() +#[cfg(not(any(all(target_os = "macos", target_arch = "x86_64"), target_os = "redox")))] +mod remove_dir_impl { + use super::{cstr, lstat, Dir, DirEntry, InnerReadDir, ReadDir}; + use crate::ffi::CStr; + use crate::io; + use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; + use crate::os::unix::prelude::{OwnedFd, RawFd}; + use crate::path::{Path, PathBuf}; + use crate::sync::Arc; + use crate::sys::{cvt, cvt_r}; + use libc::{fdopendir, openat, unlinkat}; + + pub fn openat_nofollow_dironly(parent_fd: Option, p: &CStr) -> io::Result { + let fd = cvt_r(|| unsafe { + openat( + parent_fd.unwrap_or(libc::AT_FDCWD), + p.as_ptr(), + libc::O_CLOEXEC | libc::O_RDONLY | libc::O_NOFOLLOW | libc::O_DIRECTORY, + ) + })?; + Ok(unsafe { OwnedFd::from_raw_fd(fd) }) + } + + fn fdreaddir(dir_fd: OwnedFd) -> io::Result<(ReadDir, RawFd)> { + let ptr = unsafe { fdopendir(dir_fd.as_raw_fd()) }; + if ptr.is_null() { + return Err(io::Error::last_os_error()); + } + let dirp = Dir(ptr); + // file descriptor is automatically closed by libc::closedir() now, so give up ownership + let new_parent_fd = dir_fd.into_raw_fd(); + // a valid root is not needed because we do not call any functions involving the full path + // of the DirEntrys. + let dummy_root = PathBuf::new(); + Ok(( + ReadDir { + inner: Arc::new(InnerReadDir { dirp, root: dummy_root }), + #[cfg(not(any( + target_os = "solaris", + target_os = "illumos", + target_os = "fuchsia", + target_os = "redox", + )))] + end_of_stream: false, + }, + new_parent_fd, + )) + } + + #[cfg(any( + target_os = "solaris", + target_os = "illumos", + target_os = "haiku", + target_os = "vxworks", + target_os = "fuchsia" + ))] + fn is_dir(_ent: &DirEntry) -> Option { + None + } + + #[cfg(not(any( + target_os = "solaris", + target_os = "illumos", + target_os = "haiku", + target_os = "vxworks", + target_os = "fuchsia" + )))] + fn is_dir(ent: &DirEntry) -> Option { + match ent.entry.d_type { + libc::DT_UNKNOWN => None, + libc::DT_DIR => Some(true), + _ => Some(false), + } + } + + fn remove_dir_all_recursive(parent_fd: Option, p: &Path) -> io::Result<()> { + let pcstr = cstr(p)?; + + // entry is expected to be a directory, open as such + let fd = openat_nofollow_dironly(parent_fd, &pcstr)?; + + // open the directory passing ownership of the fd + let (dir, fd) = fdreaddir(fd)?; + for child in dir { + let child = child?; + match is_dir(&child) { + Some(true) => { + remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?; + } + Some(false) => { + cvt(unsafe { unlinkat(fd, child.name_cstr().as_ptr(), 0) })?; + } + None => match cvt(unsafe { unlinkat(fd, child.name_cstr().as_ptr(), 0) }) { + // type unknown - try to unlink + Err(err) + if err.raw_os_error() == Some(libc::EISDIR) + || err.raw_os_error() == Some(libc::EPERM) => + { + // if the file is a directory unlink fails with EISDIR on Linux and EPERM everyhwere else + remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?; + } + result => { + result?; + } + }, + } + } + + // unlink the directory after removing its contents + cvt(unsafe { + unlinkat(parent_fd.unwrap_or(libc::AT_FDCWD), pcstr.as_ptr(), libc::AT_REMOVEDIR) + })?; + Ok(()) + } + + pub fn remove_dir_all(p: &Path) -> io::Result<()> { + // We cannot just call remove_dir_all_recursive() here because that would not delete a passed + // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse + // into symlinks. + let attr = lstat(p)?; + if attr.file_type().is_symlink() { + crate::fs::remove_file(p) + } else { + remove_dir_all_recursive(None, p) + } + } +} diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs index 55719b87c7e06..da63c068384a2 100644 --- a/library/std/src/sys/unix/weak.rs +++ b/library/std/src/sys/unix/weak.rs @@ -73,12 +73,14 @@ impl ExternWeak { pub(crate) macro dlsym { (fn $name:ident($($t:ty),*) -> $ret:ty) => ( + dlsym!(fn $name($($t),*) -> $ret, stringify!($name)); + ), + (fn $name:ident($($t:ty),*) -> $ret:ty, $sym:expr) => ( static DLSYM: DlsymWeak $ret> = - DlsymWeak::new(concat!(stringify!($name), '\0')); + DlsymWeak::new(concat!($sym, '\0')); let $name = &DLSYM; ) } - pub(crate) struct DlsymWeak { name: &'static str, addr: AtomicUsize, diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 1a3da3746ac61..5924789d12ba4 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -16,7 +16,7 @@ use crate::sys::time::SystemTime; use crate::sys::unsupported; use crate::sys_common::{AsInner, FromInner, IntoInner}; -pub use crate::sys_common::fs::{remove_dir_all, try_exists}; +pub use crate::sys_common::fs::try_exists; pub struct File { fd: WasiFd, @@ -130,6 +130,18 @@ impl FileType { } } +impl ReadDir { + fn new(dir: File, root: PathBuf) -> ReadDir { + ReadDir { + cookie: Some(0), + buf: vec![0; 128], + offset: 0, + cap: 0, + inner: Arc::new(ReadDirInner { dir, root }), + } + } +} + impl fmt::Debug for ReadDir { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ReadDir").finish_non_exhaustive() @@ -516,13 +528,7 @@ pub fn readdir(p: &Path) -> io::Result { opts.directory(true); opts.read(true); let dir = File::open(p, &opts)?; - Ok(ReadDir { - cookie: Some(0), - buf: vec![0; 128], - offset: 0, - cap: 0, - inner: Arc::new(ReadDirInner { dir, root: p.to_path_buf() }), - }) + Ok(ReadDir::new(dir, p.to_path_buf())) } pub fn unlink(p: &Path) -> io::Result<()> { @@ -716,3 +722,52 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { io::copy(&mut reader, &mut writer) } + +pub fn remove_dir_all(path: &Path) -> io::Result<()> { + let (parent, path) = open_parent(path)?; + remove_dir_all_recursive(&parent, &path) +} + +fn remove_dir_all_recursive(parent: &WasiFd, path: &Path) -> io::Result<()> { + // Open up a file descriptor for the directory itself. Note that we don't + // follow symlinks here and we specifically open directories. + // + // At the root invocation of this function this will correctly handle + // symlinks passed to the top-level `remove_dir_all`. At the recursive + // level this will double-check that after the `readdir` call deduced this + // was a directory it's still a directory by the time we open it up. + // + // If the opened file was actually a symlink then the symlink is deleted, + // not the directory recursively. + let mut opts = OpenOptions::new(); + opts.lookup_flags(0); + opts.directory(true); + opts.read(true); + let fd = open_at(parent, path, &opts)?; + if fd.file_attr()?.file_type().is_symlink() { + return parent.unlink_file(osstr2str(path.as_ref())?); + } + + // this "root" is only used by `DirEntry::path` which we don't use below so + // it's ok for this to be a bogus value + let dummy_root = PathBuf::new(); + + // Iterate over all the entries in this directory, and travel recursively if + // necessary + for entry in ReadDir::new(fd, dummy_root) { + let entry = entry?; + let path = crate::str::from_utf8(&entry.name).map_err(|_| { + io::Error::new_const(io::ErrorKind::Uncategorized, &"invalid utf-8 file name found") + })?; + + if entry.file_type()?.is_dir() { + remove_dir_all_recursive(&entry.inner.dir.fd, path.as_ref())?; + } else { + entry.inner.dir.fd.unlink_file(path)?; + } + } + + // Once all this directory's contents are deleted it should be safe to + // delete the directory tiself. + parent.remove_directory(osstr2str(path.as_ref())?) +} diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index b87b6b5d88e4a..09d3661e4fd52 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -4,6 +4,7 @@ #![cfg_attr(test, allow(dead_code))] #![unstable(issue = "none", feature = "windows_c")] +use crate::mem; use crate::os::raw::NonZero_c_ulong; use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort}; use crate::ptr; @@ -36,6 +37,7 @@ pub type USHORT = c_ushort; pub type SIZE_T = usize; pub type WORD = u16; pub type CHAR = c_char; +pub type CCHAR = c_char; pub type ULONG_PTR = usize; pub type ULONG = c_ulong; pub type NTSTATUS = LONG; @@ -86,16 +88,21 @@ pub const FILE_SHARE_DELETE: DWORD = 0x4; pub const FILE_SHARE_READ: DWORD = 0x1; pub const FILE_SHARE_WRITE: DWORD = 0x2; +pub const FILE_OPEN_REPARSE_POINT: ULONG = 0x200000; +pub const OBJ_DONT_REPARSE: ULONG = 0x1000; + pub const CREATE_ALWAYS: DWORD = 2; pub const CREATE_NEW: DWORD = 1; pub const OPEN_ALWAYS: DWORD = 4; pub const OPEN_EXISTING: DWORD = 3; pub const TRUNCATE_EXISTING: DWORD = 5; +pub const FILE_LIST_DIRECTORY: DWORD = 0x1; pub const FILE_WRITE_DATA: DWORD = 0x00000002; pub const FILE_APPEND_DATA: DWORD = 0x00000004; pub const FILE_WRITE_EA: DWORD = 0x00000010; pub const FILE_WRITE_ATTRIBUTES: DWORD = 0x00000100; +pub const DELETE: DWORD = 0x10000; pub const READ_CONTROL: DWORD = 0x00020000; pub const SYNCHRONIZE: DWORD = 0x00100000; pub const GENERIC_READ: DWORD = 0x80000000; @@ -261,9 +268,61 @@ pub const FD_SETSIZE: usize = 64; pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000; pub const STATUS_SUCCESS: NTSTATUS = 0x00000000; +pub const STATUS_DELETE_PENDING: NTSTATUS = 0xc0000056_u32 as _; +pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xc000000d_u32 as _; + +// Equivalent to the `NT_SUCCESS` C preprocessor macro. +// See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values +pub fn nt_success(status: NTSTATUS) -> bool { + status >= 0 +} pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002; +#[repr(C)] +pub struct UNICODE_STRING { + pub Length: u16, + pub MaximumLength: u16, + pub Buffer: *mut u16, +} +impl UNICODE_STRING { + pub fn from_ref(slice: &[u16]) -> Self { + let len = slice.len() * mem::size_of::(); + Self { Length: len as _, MaximumLength: len as _, Buffer: slice.as_ptr() as _ } + } +} +#[repr(C)] +pub struct OBJECT_ATTRIBUTES { + pub Length: ULONG, + pub RootDirectory: HANDLE, + pub ObjectName: *const UNICODE_STRING, + pub Attributes: ULONG, + pub SecurityDescriptor: *mut c_void, + pub SecurityQualityOfService: *mut c_void, +} +impl Default for OBJECT_ATTRIBUTES { + fn default() -> Self { + Self { + Length: mem::size_of::() as _, + RootDirectory: ptr::null_mut(), + ObjectName: ptr::null_mut(), + Attributes: 0, + SecurityDescriptor: ptr::null_mut(), + SecurityQualityOfService: ptr::null_mut(), + } + } +} +#[repr(C)] +pub struct IO_STATUS_BLOCK { + pub Pointer: *mut c_void, + pub Information: usize, +} +impl Default for IO_STATUS_BLOCK { + fn default() -> Self { + Self { Pointer: ptr::null_mut(), Information: 0 } + } +} + #[repr(C)] #[cfg(not(target_pointer_width = "64"))] pub struct WSADATA { @@ -353,9 +412,43 @@ pub enum FILE_INFO_BY_HANDLE_CLASS { FileIdInfo = 18, // 0x12 FileIdExtdDirectoryInfo = 19, // 0x13 FileIdExtdDirectoryRestartInfo = 20, // 0x14 + FileDispositionInfoEx = 21, // 0x15, Windows 10 version 1607 MaximumFileInfoByHandlesClass, } +#[repr(C)] +pub struct FILE_DISPOSITION_INFO { + pub DeleteFile: BOOLEAN, +} + +pub const FILE_DISPOSITION_DELETE: DWORD = 0x1; +pub const FILE_DISPOSITION_POSIX_SEMANTICS: DWORD = 0x2; +pub const FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE: DWORD = 0x10; + +#[repr(C)] +pub struct FILE_DISPOSITION_INFO_EX { + pub Flags: DWORD, +} + +#[repr(C)] +#[derive(Default)] +pub struct FILE_ID_BOTH_DIR_INFO { + pub NextEntryOffset: DWORD, + pub FileIndex: DWORD, + pub CreationTime: LARGE_INTEGER, + pub LastAccessTime: LARGE_INTEGER, + pub LastWriteTime: LARGE_INTEGER, + pub ChangeTime: LARGE_INTEGER, + pub EndOfFile: LARGE_INTEGER, + pub AllocationSize: LARGE_INTEGER, + pub FileAttributes: DWORD, + pub FileNameLength: DWORD, + pub EaSize: DWORD, + pub ShortNameLength: CCHAR, + pub ShortName: [WCHAR; 12], + pub FileId: LARGE_INTEGER, + pub FileName: [WCHAR; 1], +} #[repr(C)] pub struct FILE_BASIC_INFO { pub CreationTime: LARGE_INTEGER, @@ -750,16 +843,6 @@ if #[cfg(target_vendor = "uwp")] { pub DeletePending: BOOLEAN, pub Directory: BOOLEAN, } - - #[link(name = "kernel32")] - extern "system" { - pub fn GetFileInformationByHandleEx( - hFile: HANDLE, - fileInfoClass: FILE_INFO_BY_HANDLE_CLASS, - lpFileInformation: LPVOID, - dwBufferSize: DWORD, - ) -> BOOL; - } } } @@ -949,6 +1032,12 @@ extern "system" { cchFilePath: DWORD, dwFlags: DWORD, ) -> DWORD; + pub fn GetFileInformationByHandleEx( + hFile: HANDLE, + fileInfoClass: FILE_INFO_BY_HANDLE_CLASS, + lpFileInformation: LPVOID, + dwBufferSize: DWORD, + ) -> BOOL; pub fn SetFileInformationByHandle( hFile: HANDLE, FileInformationClass: FILE_INFO_BY_HANDLE_CLASS, @@ -1139,6 +1228,21 @@ compat_fn! { compat_fn! { "ntdll": + pub fn NtOpenFile( + FileHandle: *mut HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: *const OBJECT_ATTRIBUTES, + IoStatusBlock: *mut IO_STATUS_BLOCK, + ShareAccess: ULONG, + OpenOptions: ULONG + ) -> NTSTATUS { + panic!("`NtOpenFile` not available"); + } + pub fn RtlNtStatusToDosError( + Status: NTSTATUS + ) -> ULONG { + panic!("`RtlNtStatusToDosError` not available"); + } pub fn NtCreateKeyedEvent( KeyedEventHandle: LPHANDLE, DesiredAccess: ACCESS_MASK, diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index b258fc0478bdc..dd21c6b43891f 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -547,6 +547,218 @@ impl File { })?; Ok(()) } + /// Get only basic file information such as attributes and file times. + fn basic_info(&self) -> io::Result { + unsafe { + let mut info: c::FILE_BASIC_INFO = mem::zeroed(); + let size = mem::size_of_val(&info); + cvt(c::GetFileInformationByHandleEx( + self.handle.as_raw_handle(), + c::FileBasicInfo, + &mut info as *mut _ as *mut libc::c_void, + size as c::DWORD, + ))?; + Ok(info) + } + } + /// Delete using POSIX semantics. + /// + /// Files will be deleted as soon as the handle is closed. This is supported + /// for Windows 10 1607 (aka RS1) and later. However some filesystem + /// drivers will not support it even then, e.g. FAT32. + /// + /// If the operation is not supported for this filesystem or OS version + /// then errors will be `ERROR_NOT_SUPPORTED` or `ERROR_INVALID_PARAMETER`. + fn posix_delete(&self) -> io::Result<()> { + let mut info = c::FILE_DISPOSITION_INFO_EX { + Flags: c::FILE_DISPOSITION_DELETE + | c::FILE_DISPOSITION_POSIX_SEMANTICS + | c::FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE, + }; + let size = mem::size_of_val(&info); + cvt(unsafe { + c::SetFileInformationByHandle( + self.handle.as_raw_handle(), + c::FileDispositionInfoEx, + &mut info as *mut _ as *mut _, + size as c::DWORD, + ) + })?; + Ok(()) + } + + /// Delete a file using win32 semantics. The file won't actually be deleted + /// until all file handles are closed. However, marking a file for deletion + /// will prevent anyone from opening a new handle to the file. + fn win32_delete(&self) -> io::Result<()> { + let mut info = c::FILE_DISPOSITION_INFO { DeleteFile: c::TRUE as _ }; + let size = mem::size_of_val(&info); + cvt(unsafe { + c::SetFileInformationByHandle( + self.handle.as_raw_handle(), + c::FileDispositionInfo, + &mut info as *mut _ as *mut _, + size as c::DWORD, + ) + })?; + Ok(()) + } + + /// Fill the given buffer with as many directory entries as will fit. + /// This will remember its position and continue from the last call unless + /// `restart` is set to `true`. + /// + /// The returned bool indicates if there are more entries or not. + /// It is an error if `self` is not a directory. + /// + /// # Symlinks and other reparse points + /// + /// On Windows a file is either a directory or a non-directory. + /// A symlink directory is simply an empty directory with some "reparse" metadata attached. + /// So if you open a link (not its target) and iterate the directory, + /// you will always iterate an empty directory regardless of the target. + fn fill_dir_buff(&self, buffer: &mut DirBuff, restart: bool) -> io::Result { + let class = + if restart { c::FileIdBothDirectoryRestartInfo } else { c::FileIdBothDirectoryInfo }; + + unsafe { + let result = cvt(c::GetFileInformationByHandleEx( + self.handle.as_raw_handle(), + class, + buffer.as_mut_ptr().cast(), + buffer.capacity() as _, + )); + match result { + Ok(_) => Ok(true), + Err(e) if e.raw_os_error() == Some(c::ERROR_NO_MORE_FILES as _) => Ok(false), + Err(e) => Err(e), + } + } + } +} + +/// A buffer for holding directory entries. +struct DirBuff { + buffer: Vec, +} +impl DirBuff { + fn new() -> Self { + const BUFFER_SIZE: usize = 1024; + Self { buffer: vec![0_u8; BUFFER_SIZE] } + } + fn capacity(&self) -> usize { + self.buffer.len() + } + fn as_mut_ptr(&mut self) -> *mut u8 { + self.buffer.as_mut_ptr().cast() + } + /// Returns a `DirBuffIter`. + fn iter(&self) -> DirBuffIter<'_> { + DirBuffIter::new(self) + } +} +impl AsRef<[u8]> for DirBuff { + fn as_ref(&self) -> &[u8] { + &self.buffer + } +} + +/// An iterator over entries stored in a `DirBuff`. +/// +/// Currently only returns file names (UTF-16 encoded). +struct DirBuffIter<'a> { + buffer: Option<&'a [u8]>, + cursor: usize, +} +impl<'a> DirBuffIter<'a> { + fn new(buffer: &'a DirBuff) -> Self { + Self { buffer: Some(buffer.as_ref()), cursor: 0 } + } +} +impl<'a> Iterator for DirBuffIter<'a> { + type Item = &'a [u16]; + fn next(&mut self) -> Option { + use crate::mem::size_of; + let buffer = &self.buffer?[self.cursor..]; + + // Get the name and next entry from the buffer. + // SAFETY: The buffer contains a `FILE_ID_BOTH_DIR_INFO` struct but the + // last field (the file name) is unsized. So an offset has to be + // used to get the file name slice. + let (name, next_entry) = unsafe { + let info = buffer.as_ptr().cast::(); + let next_entry = (*info).NextEntryOffset as usize; + let name = crate::slice::from_raw_parts( + (*info).FileName.as_ptr().cast::(), + (*info).FileNameLength as usize / size_of::(), + ); + (name, next_entry) + }; + + if next_entry == 0 { + self.buffer = None + } else { + self.cursor += next_entry + } + + // Skip `.` and `..` pseudo entries. + const DOT: u16 = b'.' as u16; + match name { + [DOT] | [DOT, DOT] => self.next(), + _ => Some(name), + } + } +} + +/// Open a link relative to the parent directory, ensure no symlinks are followed. +fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result { + // This is implemented using the lower level `NtOpenFile` function as + // unfortunately opening a file relative to a parent is not supported by + // win32 functions. It is however a fundamental feature of the NT kernel. + // + // See https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntopenfile + unsafe { + let mut handle = ptr::null_mut(); + let mut io_status = c::IO_STATUS_BLOCK::default(); + let name_str = c::UNICODE_STRING::from_ref(name); + use crate::sync::atomic::{AtomicU32, Ordering}; + // The `OBJ_DONT_REPARSE` attribute ensures that we haven't been + // tricked into following a symlink. However, it may not be available in + // earlier versions of Windows. + static ATTRIBUTES: AtomicU32 = AtomicU32::new(c::OBJ_DONT_REPARSE); + let object = c::OBJECT_ATTRIBUTES { + ObjectName: &name_str, + RootDirectory: parent.as_raw_handle(), + Attributes: ATTRIBUTES.load(Ordering::Relaxed), + ..c::OBJECT_ATTRIBUTES::default() + }; + let status = c::NtOpenFile( + &mut handle, + access, + &object, + &mut io_status, + c::FILE_SHARE_DELETE | c::FILE_SHARE_READ | c::FILE_SHARE_WRITE, + // If `name` is a symlink then open the link rather than the target. + c::FILE_OPEN_REPARSE_POINT, + ); + // Convert an NTSTATUS to the more familiar Win32 error codes (aka "DosError") + if c::nt_success(status) { + Ok(File::from_raw_handle(handle)) + } else if status == c::STATUS_DELETE_PENDING { + // We make a special exception for `STATUS_DELETE_PENDING` because + // otherwise this will be mapped to `ERROR_ACCESS_DENIED` which is + // very unhelpful. + Err(io::Error::from_raw_os_error(c::ERROR_DELETE_PENDING as _)) + } else if status == c::STATUS_INVALID_PARAMETER + && ATTRIBUTES.load(Ordering::Relaxed) == c::OBJ_DONT_REPARSE + { + // Try without `OBJ_DONT_REPARSE`. See above. + ATTRIBUTES.store(0, Ordering::Relaxed); + open_link_no_reparse(parent, name, access) + } else { + Err(io::Error::from_raw_os_error(c::RtlNtStatusToDosError(status) as _)) + } + } } impl AsInner for File { @@ -756,30 +968,106 @@ pub fn rmdir(p: &Path) -> io::Result<()> { Ok(()) } +/// Open a file or directory without following symlinks. +fn open_link(path: &Path, access_mode: u32) -> io::Result { + let mut opts = OpenOptions::new(); + opts.access_mode(access_mode); + // `FILE_FLAG_BACKUP_SEMANTICS` allows opening directories. + // `FILE_FLAG_OPEN_REPARSE_POINT` opens a link instead of its target. + opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT); + File::open(path, &opts) +} + pub fn remove_dir_all(path: &Path) -> io::Result<()> { - let filetype = lstat(path)?.file_type(); - if filetype.is_symlink() { - // On Windows symlinks to files and directories are removed differently. - // rmdir only deletes dir symlinks and junctions, not file symlinks. - rmdir(path) + let file = open_link(path, c::DELETE | c::FILE_LIST_DIRECTORY)?; + + // Test if the file is not a directory or a symlink to a directory. + if (file.basic_info()?.FileAttributes & c::FILE_ATTRIBUTE_DIRECTORY) == 0 { + return Err(io::Error::from_raw_os_error(c::ERROR_DIRECTORY as _)); + } + let mut delete: fn(&File) -> io::Result<()> = File::posix_delete; + let result = match delete(&file) { + Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => { + match remove_dir_all_recursive(&file, delete) { + // Return unexpected errors. + Err(e) if e.kind() != io::ErrorKind::DirectoryNotEmpty => return Err(e), + result => result, + } + } + // If POSIX delete is not supported for this filesystem then fallback to win32 delete. + Err(e) + if e.raw_os_error() == Some(c::ERROR_NOT_SUPPORTED as i32) + || e.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as i32) => + { + delete = File::win32_delete; + Err(e) + } + result => result, + }; + if result.is_ok() { + Ok(()) } else { - remove_dir_all_recursive(path) + // This is a fallback to make sure the directory is actually deleted. + // Otherwise this function is prone to failing with `DirectoryNotEmpty` + // due to possible delays between marking a file for deletion and the + // file actually being deleted from the filesystem. + // + // So we retry a few times before giving up. + for _ in 0..5 { + match remove_dir_all_recursive(&file, delete) { + Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => {} + result => return result, + } + } + // Try one last time. + delete(&file) } } -fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { - for child in readdir(path)? { - let child = child?; - let child_type = child.file_type()?; - if child_type.is_dir() { - remove_dir_all_recursive(&child.path())?; - } else if child_type.is_symlink_dir() { - rmdir(&child.path())?; - } else { - unlink(&child.path())?; +fn remove_dir_all_recursive(f: &File, delete: fn(&File) -> io::Result<()>) -> io::Result<()> { + let mut buffer = DirBuff::new(); + let mut restart = true; + // Fill the buffer and iterate the entries. + while f.fill_dir_buff(&mut buffer, restart)? { + for name in buffer.iter() { + // Open the file without following symlinks and try deleting it. + // We try opening will all needed permissions and if that is denied + // fallback to opening without `FILE_LIST_DIRECTORY` permission. + // Note `SYNCHRONIZE` permission is needed for synchronous access. + let mut result = + open_link_no_reparse(&f, name, c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY); + if matches!(&result, Err(e) if e.kind() == io::ErrorKind::PermissionDenied) { + result = open_link_no_reparse(&f, name, c::SYNCHRONIZE | c::DELETE); + } + match result { + Ok(file) => match delete(&file) { + Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => { + // Iterate the directory's files. + // Ignore `DirectoryNotEmpty` errors here. They will be + // caught when `remove_dir_all` tries to delete the top + // level directory. It can then decide if to retry or not. + match remove_dir_all_recursive(&file, delete) { + Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => {} + result => result?, + } + } + result => result?, + }, + // Ignore error if a delete is already in progress or the file + // has already been deleted. It also ignores sharing violations + // (where a file is locked by another process) as these are + // usually temporary. + Err(e) + if e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _) + || e.kind() == io::ErrorKind::NotFound + || e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _) => {} + Err(e) => return Err(e), + } } + // Continue reading directory entries without restarting from the beginning, + restart = false; } - rmdir(path) + delete(&f) } pub fn readlink(path: &Path) -> io::Result { diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index d5e8f12414ff2..dc581a0675b38 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -150,16 +150,18 @@ pub enum RustBacktrace { RuntimeDisabled, } +// If the `backtrace` feature of this crate isn't enabled quickly return +// `Disabled` so this can be constant propagated all over the place to +// optimize away callers. +#[cfg(not(feature = "backtrace"))] +pub fn rust_backtrace_env() -> RustBacktrace { + RustBacktrace::Disabled +} + // For now logging is turned off by default, and this function checks to see // whether the magical environment variable is present to see if it's turned on. +#[cfg(feature = "backtrace")] pub fn rust_backtrace_env() -> RustBacktrace { - // If the `backtrace` feature of this crate isn't enabled quickly return - // `None` so this can be constant propagated all over the place to turn - // optimize away callers. - if !cfg!(feature = "backtrace") { - return RustBacktrace::Disabled; - } - // Setting environment variables for Fuchsia components isn't a standard // or easily supported workflow. For now, always display backtraces. if cfg!(target_os = "fuchsia") { @@ -189,6 +191,15 @@ pub fn rust_backtrace_env() -> RustBacktrace { format } +/// Setting for printing the full backtrace, unless backtraces are completely disabled +pub(crate) fn rust_backtrace_print_full() -> RustBacktrace { + if cfg!(feature = "backtrace") { + RustBacktrace::Print(PrintFmt::Full) + } else { + RustBacktrace::Disabled + } +} + /// Prints the filename of the backtrace frame. /// /// See also `output`. diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 7f482f0f2b1a0..11925ab978588 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -170,6 +170,12 @@ The valid types of print values are: include a diagnostic note that indicates the linker flags to use when linking the resulting static library. The note starts with the text `native-static-libs:` to make it easier to fetch the output. +- `link-args` — This flag does not disable the `--emit` step. When linking, + this flag causes `rustc` to print the full linker invocation in a + human-readable form. This can be useful when debugging linker options. The + exact format of this debugging output is not a stable guarantee, other than + that it will include the linker executable and the text of each command-line + argument passed to the linker. [conditional compilation]: ../reference/conditional-compilation.html diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index fac1a0817e033..920dd202ee9e4 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1040,9 +1040,9 @@ impl Attributes { ) -> Attributes { let mut doc_strings: Vec = vec![]; let clean_attr = |(attr, parent_module): (&ast::Attribute, Option)| { - if let Some(value) = attr.doc_str() { + if let Some((value, kind)) = attr.doc_str_and_comment_kind() { trace!("got doc_str={:?}", value); - let value = beautify_doc_string(value); + let value = beautify_doc_string(value, kind); let kind = if attr.is_doc_comment() { DocFragmentKind::SugaredDoc } else { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 29a793f3110b1..8badce8226fd9 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -799,6 +799,20 @@ fn assoc_type( } } +/// Writes a span containing the versions at which an item became stable and/or const-stable. For +/// example, if the item became stable at 1.0.0, and const-stable at 1.45.0, this function would +/// write a span containing "1.0.0 (const: 1.45.0)". +/// +/// Returns `true` if a stability annotation was rendered. +/// +/// Stability and const-stability are considered separately. If the item is unstable, no version +/// will be written. If the item is const-unstable, "const: unstable" will be appended to the +/// span, with a link to the tracking issue if present. If an item's stability or const-stability +/// version matches the version of its enclosing item, that version will be omitted. +/// +/// Note that it is possible for an unstable function to be const-stable. In that case, the span +/// will include the const-stable version, but no stable version will be emitted, as a natural +/// consequence of the above rules. fn render_stability_since_raw( w: &mut Buffer, ver: Option, @@ -806,51 +820,56 @@ fn render_stability_since_raw( containing_ver: Option, containing_const_ver: Option, ) -> bool { - let ver = ver.filter(|inner| !inner.is_empty()); + let stable_version = ver.filter(|inner| !inner.is_empty() && Some(*inner) != containing_ver); - match (ver, const_stability) { - // stable and const stable - (Some(v), Some(ConstStability { level: StabilityLevel::Stable { since }, .. })) + let mut title = String::new(); + let mut stability = String::new(); + + if let Some(ver) = stable_version { + stability.push_str(&ver.as_str()); + title.push_str(&format!("Stable since Rust version {}", ver)); + } + + let const_title_and_stability = match const_stability { + Some(ConstStability { level: StabilityLevel::Stable { since }, .. }) if Some(since) != containing_const_ver => { - write!( - w, - "{0} (const: {1})", - v, since - ); + Some((format!("const since {}", since), format!("const: {}", since))) } - // stable and const unstable - ( - Some(v), - Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }), - ) => { - write!( - w, - "{0} (const: ", - v - ); - if let Some(n) = issue { - write!( - w, - "unstable", + Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }) => { + let unstable = if let Some(n) = issue { + format!( + r#"unstable"#, n, feature - ); + ) } else { - write!(w, "unstable"); - } - write!(w, ")"); + String::from("unstable") + }; + + Some((String::from("const unstable"), format!("const: {}", unstable))) } - // stable - (Some(v), _) if ver != containing_ver => { - write!( - w, - "{0}", - v - ); + _ => None, + }; + + if let Some((const_title, const_stability)) = const_title_and_stability { + if !title.is_empty() { + title.push_str(&format!(", {}", const_title)); + } else { + title.push_str(&const_title); + } + + if !stability.is_empty() { + stability.push_str(&format!(" ({})", const_stability)); + } else { + stability.push_str(&const_stability); } - _ => return false, } - true + + if !stability.is_empty() { + write!(w, r#"{}"#, title, stability); + } + + !stability.is_empty() } fn render_assoc_item( diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 44a9a571fa1f8..d0244351b5973 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -148,11 +148,11 @@ h1.fqn { } .main-heading { display: flex; + flex-wrap: wrap; + justify-content: space-between; + border-bottom: 1px dashed #DDDDDD; + padding-bottom: 6px; margin-bottom: 15px; - - /* workaround to keep flex from breaking below 700 px width due to the float: right on the nav - above the h1 */ - padding-left: 1px; } .main-heading a:hover { text-decoration: underline; @@ -623,11 +623,7 @@ nav.sub { .content .out-of-band { flex-grow: 0; - text-align: right; - margin-left: auto; - margin-right: 0; font-size: 1.15rem; - padding: 0 0 0 12px; font-weight: normal; float: right; } @@ -1748,10 +1744,25 @@ details.rustdoc-toggle[open] > summary.hideme::after { padding-top: 0px; } - .rustdoc { + .rustdoc, + .main-heading { flex-direction: column; } + .content .out-of-band { + text-align: left; + margin-left: initial; + padding: initial; + } + + .content .out-of-band .since::before { + content: "Since "; + } + + #copy-path { + display: none; + } + /* Hide the logo and item name from the sidebar. Those are displayed in the mobile-topbar instead. */ .sidebar .sidebar-logo, diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 1a9794e75bc06..7dbf00420de12 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -305,16 +305,15 @@ crate enum FragmentKind { impl ItemFragment { /// Create a fragment for an associated item. - /// - /// `is_prototype` is whether this associated item is a trait method - /// without a default definition. - fn from_assoc_item(def_id: DefId, kind: ty::AssocKind, is_prototype: bool) -> Self { - match kind { + #[instrument(level = "debug")] + fn from_assoc_item(item: &ty::AssocItem) -> Self { + let def_id = item.def_id; + match item.kind { ty::AssocKind::Fn => { - if is_prototype { - ItemFragment(FragmentKind::TyMethod, def_id) - } else { + if item.defaultness.has_value() { ItemFragment(FragmentKind::Method, def_id) + } else { + ItemFragment(FragmentKind::TyMethod, def_id) } } ty::AssocKind::Const => ItemFragment(FragmentKind::AssociatedConstant, def_id), @@ -473,8 +472,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { tcx.associated_items(impl_) .find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, impl_) .map(|item| { - let kind = item.kind; - let fragment = ItemFragment::from_assoc_item(item.def_id, kind, false); + let fragment = ItemFragment::from_assoc_item(item); (Res::Primitive(prim_ty), fragment) }) }) @@ -726,8 +724,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { .flatten(); assoc_item.map(|item| { - let kind = item.kind; - let fragment = ItemFragment::from_assoc_item(item.def_id, kind, false); + let fragment = ItemFragment::from_assoc_item(&item); (root_res, fragment) }) }) @@ -765,20 +762,19 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // To handle that properly resolve() would have to support // something like [`ambi_fn`](::ambi_fn) .or_else(|| { - let item = resolve_associated_trait_item( + resolve_associated_trait_item( tcx.type_of(did), module_id, item_name, ns, self.cx, - ); - debug!("got associated item {:?}", item); - item + ) }); + debug!("got associated item {:?}", assoc_item); + if let Some(item) = assoc_item { - let kind = item.kind; - let fragment = ItemFragment::from_assoc_item(item.def_id, kind, false); + let fragment = ItemFragment::from_assoc_item(&item); return Some((root_res, fragment)); } @@ -813,11 +809,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { .associated_items(did) .find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, did) .map(|item| { - let fragment = ItemFragment::from_assoc_item( - item.def_id, - item.kind, - !item.defaultness.has_value(), - ); + let fragment = ItemFragment::from_assoc_item(item); let res = Res::Def(item.kind.as_def_kind(), item.def_id); (res, fragment) }), @@ -883,30 +875,56 @@ fn resolve_associated_trait_item<'a>( // Next consider explicit impls: `impl MyTrait for MyType` // Give precedence to inherent impls. - let traits = traits_implemented_by(cx, ty, module); + let traits = trait_impls_for(cx, ty, module); debug!("considering traits {:?}", traits); - let mut candidates = traits.iter().filter_map(|&trait_| { - cx.tcx.associated_items(trait_).find_by_name_and_namespace( - cx.tcx, - Ident::with_dummy_span(item_name), - ns, - trait_, - ) + let mut candidates = traits.iter().filter_map(|&(impl_, trait_)| { + cx.tcx + .associated_items(trait_) + .find_by_name_and_namespace(cx.tcx, Ident::with_dummy_span(item_name), ns, trait_) + .map(|trait_assoc| { + trait_assoc_to_impl_assoc_item(cx.tcx, impl_, trait_assoc.def_id) + .unwrap_or(trait_assoc) + }) }); // FIXME(#74563): warn about ambiguity debug!("the candidates were {:?}", candidates.clone().collect::>()); candidates.next().copied() } -/// Given a type, return all traits in scope in `module` implemented by that type. +/// Find the associated item in the impl `impl_id` that corresponds to the +/// trait associated item `trait_assoc_id`. +/// +/// This function returns `None` if no associated item was found in the impl. +/// This can occur when the trait associated item has a default value that is +/// not overriden in the impl. +/// +/// This is just a wrapper around [`TyCtxt::impl_item_implementor_ids()`] and +/// [`TyCtxt::associated_item()`] (with some helpful logging added). +#[instrument(level = "debug", skip(tcx))] +fn trait_assoc_to_impl_assoc_item<'tcx>( + tcx: TyCtxt<'tcx>, + impl_id: DefId, + trait_assoc_id: DefId, +) -> Option<&'tcx ty::AssocItem> { + let trait_to_impl_assoc_map = tcx.impl_item_implementor_ids(impl_id); + debug!(?trait_to_impl_assoc_map); + let impl_assoc_id = *trait_to_impl_assoc_map.get(&trait_assoc_id)?; + debug!(?impl_assoc_id); + let impl_assoc = tcx.associated_item(impl_assoc_id); + debug!(?impl_assoc); + Some(impl_assoc) +} + +/// Given a type, return all trait impls in scope in `module` for that type. +/// Returns a set of pairs of `(impl_id, trait_id)`. /// /// NOTE: this cannot be a query because more traits could be available when more crates are compiled! /// So it is not stable to serialize cross-crate. -fn traits_implemented_by<'a>( +fn trait_impls_for<'a>( cx: &mut DocContext<'a>, ty: Ty<'a>, module: DefId, -) -> FxHashSet { +) -> FxHashSet<(DefId, DefId)> { let mut resolver = cx.resolver.borrow_mut(); let in_scope_traits = cx.module_trait_cache.entry(module).or_insert_with(|| { resolver.access(|resolver| { @@ -948,7 +966,7 @@ fn traits_implemented_by<'a>( _ => false, }; - if saw_impl { Some(trait_) } else { None } + if saw_impl { Some((impl_, trait_)) } else { None } }) }); iter.collect() diff --git a/src/test/run-make-fulldeps/codegen-options-parsing/Makefile b/src/test/run-make-fulldeps/codegen-options-parsing/Makefile index 39e9a9bdd6b68..f1410b69b3fce 100644 --- a/src/test/run-make-fulldeps/codegen-options-parsing/Makefile +++ b/src/test/run-make-fulldeps/codegen-options-parsing/Makefile @@ -24,8 +24,8 @@ all: $(RUSTC) -C lto dummy.rs # Should not link dead code... - $(RUSTC) -Z print-link-args dummy.rs 2>&1 | \ + $(RUSTC) --print link-args dummy.rs 2>&1 | \ $(CGREP) -e '--gc-sections|-z[^ ]* [^ ]*|-dead_strip|/OPT:REF' # ... unless you specifically ask to keep it - $(RUSTC) -Z print-link-args -C link-dead-code dummy.rs 2>&1 | \ + $(RUSTC) --print link-args -C link-dead-code dummy.rs 2>&1 | \ $(CGREP) -ve '--gc-sections|-z[^ ]* [^ ]*|-dead_strip|/OPT:REF' diff --git a/src/test/run-make-fulldeps/interdependent-c-libraries/Makefile b/src/test/run-make-fulldeps/interdependent-c-libraries/Makefile index 1268022e37b74..0a50859cdaa4d 100644 --- a/src/test/run-make-fulldeps/interdependent-c-libraries/Makefile +++ b/src/test/run-make-fulldeps/interdependent-c-libraries/Makefile @@ -11,4 +11,4 @@ all: $(call NATIVE_STATICLIB,foo) $(call NATIVE_STATICLIB,bar) $(RUSTC) foo.rs $(RUSTC) bar.rs - $(RUSTC) main.rs -Z print-link-args + $(RUSTC) main.rs --print link-args diff --git a/src/test/run-make-fulldeps/link-arg/Makefile b/src/test/run-make-fulldeps/link-arg/Makefile index d7c9fd2711285..0360ede762551 100644 --- a/src/test/run-make-fulldeps/link-arg/Makefile +++ b/src/test/run-make-fulldeps/link-arg/Makefile @@ -1,5 +1,5 @@ -include ../tools.mk -RUSTC_FLAGS = -C link-arg="-lfoo" -C link-arg="-lbar" -Z print-link-args +RUSTC_FLAGS = -C link-arg="-lfoo" -C link-arg="-lbar" --print link-args all: $(RUSTC) $(RUSTC_FLAGS) empty.rs | $(CGREP) lfoo lbar diff --git a/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/Makefile b/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/Makefile index 09e6ae0bbf7cd..3ffbba9444bc2 100644 --- a/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/Makefile +++ b/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/Makefile @@ -6,5 +6,5 @@ all: $(RUSTC) bar.rs \ --extern foo1=$(TMPDIR)/libfoo-a.rlib \ --extern foo2=$(TMPDIR)/libfoo-b.rlib \ - -Z print-link-args + --print link-args $(call RUN,bar) diff --git a/src/test/run-make-fulldeps/no-builtins-lto/Makefile b/src/test/run-make-fulldeps/no-builtins-lto/Makefile index b9688f16c6464..2e41be39d5d00 100644 --- a/src/test/run-make-fulldeps/no-builtins-lto/Makefile +++ b/src/test/run-make-fulldeps/no-builtins-lto/Makefile @@ -6,4 +6,4 @@ all: # Build an executable that depends on that crate using LTO. The no_builtins crate doesn't # participate in LTO, so its rlib must be explicitly linked into the final binary. Verify this by # grepping the linker arguments. - $(RUSTC) main.rs -C lto -Z print-link-args | $(CGREP) 'libno_builtins.rlib' + $(RUSTC) main.rs -C lto --print link-args | $(CGREP) 'libno_builtins.rlib' diff --git a/src/test/run-make-fulldeps/redundant-libs/Makefile b/src/test/run-make-fulldeps/redundant-libs/Makefile index 8468d102bec83..e09841fb42e18 100644 --- a/src/test/run-make-fulldeps/redundant-libs/Makefile +++ b/src/test/run-make-fulldeps/redundant-libs/Makefile @@ -16,7 +16,7 @@ RUSTC_FLAGS = \ -l foo \ -l static=baz \ -l foo \ - -Z print-link-args + --print link-args all: $(call DYLIB,foo) $(call STATICLIB,bar) $(call STATICLIB,baz) $(RUSTC) $(RUSTC_FLAGS) main.rs diff --git a/src/test/run-make-fulldeps/static-nobundle/Makefile b/src/test/run-make-fulldeps/static-nobundle/Makefile index abc32d4423b05..8f78c401a1141 100644 --- a/src/test/run-make-fulldeps/static-nobundle/Makefile +++ b/src/test/run-make-fulldeps/static-nobundle/Makefile @@ -13,9 +13,9 @@ all: $(call NATIVE_STATICLIB,aaa) nm $(TMPDIR)/libbbb.rlib | $(CGREP) -e "U _*native_func" # Check that aaa gets linked (either as `-l aaa` or `aaa.lib`) when building ccc. - $(RUSTC) ccc.rs -C prefer-dynamic --crate-type=dylib -Z print-link-args | $(CGREP) -e '-l[" ]*aaa|aaa\.lib' + $(RUSTC) ccc.rs -C prefer-dynamic --crate-type=dylib --print link-args | $(CGREP) -e '-l[" ]*aaa|aaa\.lib' # Check that aaa does NOT get linked when building ddd. - $(RUSTC) ddd.rs -Z print-link-args | $(CGREP) -ve '-l[" ]*aaa|aaa\.lib' + $(RUSTC) ddd.rs --print link-args | $(CGREP) -ve '-l[" ]*aaa|aaa\.lib' $(call RUN,ddd) diff --git a/src/test/rustdoc-gui/mobile.goml b/src/test/rustdoc-gui/mobile.goml new file mode 100644 index 0000000000000..acde112392521 --- /dev/null +++ b/src/test/rustdoc-gui/mobile.goml @@ -0,0 +1,17 @@ +// Test various properties of the mobile UI +goto: file://|DOC_PATH|/staged_api/struct.Foo.html +size: (400, 600) + +// The out-of-band info (source, stable version, collapse) should be below the +// h1 when the screen gets narrow enough. +assert-css: (".main-heading", { + "display": "flex", + "flex-direction": "column" +}) + +// Note: We can't use assert-text here because the 'Since' is set by CSS and +// is therefore not part of the DOM. +assert-css: (".content .out-of-band .since::before", { "content": "\"Since \"" }) + +size: (1000, 1000) +assert-css-false: (".content .out-of-band .since::before", { "content": "\"Since \"" }) diff --git a/src/test/rustdoc-gui/toggle-docs-mobile.goml b/src/test/rustdoc-gui/toggle-docs-mobile.goml index 4c83fd6c0e31c..e7a75b43c5a02 100644 --- a/src/test/rustdoc-gui/toggle-docs-mobile.goml +++ b/src/test/rustdoc-gui/toggle-docs-mobile.goml @@ -1,12 +1,12 @@ goto: file://|DOC_PATH|/test_docs/struct.Foo.html size: (433, 600) assert-attribute: (".top-doc", {"open": ""}) -click: (4, 250) // This is the position of the top doc comment toggle +click: (4, 270) // This is the position of the top doc comment toggle assert-attribute-false: (".top-doc", {"open": ""}) -click: (4, 250) +click: (4, 270) assert-attribute: (".top-doc", {"open": ""}) // To ensure that the toggle isn't over the text, we check that the toggle isn't clicked. -click: (3, 250) +click: (3, 270) assert-attribute: (".top-doc", {"open": ""}) // Assert the position of the toggle on the top doc block. @@ -22,10 +22,10 @@ assert-position: ( // Now we do the same but with a little bigger width size: (600, 600) assert-attribute: (".top-doc", {"open": ""}) -click: (4, 250) // New Y position since all search elements are back on one line. +click: (4, 270) // New Y position since all search elements are back on one line. assert-attribute-false: (".top-doc", {"open": ""}) -click: (4, 250) +click: (4, 270) assert-attribute: (".top-doc", {"open": ""}) // To ensure that the toggle isn't over the text, we check that the toggle isn't clicked. -click: (3, 250) +click: (3, 270) assert-attribute: (".top-doc", {"open": ""}) diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs index fb8ea7e33c28c..b8e101038f8f1 100644 --- a/src/test/rustdoc/const-display.rs +++ b/src/test/rustdoc/const-display.rs @@ -67,3 +67,20 @@ impl Foo { #[rustc_const_stable(feature = "rust1", since = "1.2.0")] pub const fn stable_impl() -> u32 { 42 } } + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Bar; + +impl Bar { + // Do not show non-const stabilities that are the same as the enclosing item. + // @matches 'foo/struct.Bar.html' '//span[@class="since"]' '^const: 1.2.0$' + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "rust1", since = "1.2.0")] + pub const fn stable_impl() -> u32 { 42 } + + // Show const-stability even for unstable functions. + // @matches 'foo/struct.Bar.html' '//span[@class="since"]' '^const: 1.3.0$' + #[unstable(feature = "foo2", issue = "none")] + #[rustc_const_stable(feature = "rust1", since = "1.3.0")] + pub const fn const_stable_unstable() -> u32 { 42 } +} diff --git a/src/test/rustdoc/deref-const-fn.rs b/src/test/rustdoc/deref-const-fn.rs index ca51f3c7b5af0..8ecca6d12d24a 100644 --- a/src/test/rustdoc/deref-const-fn.rs +++ b/src/test/rustdoc/deref-const-fn.rs @@ -13,7 +13,7 @@ pub struct Bar; impl Bar { // @has - '//*[@id="method.len"]' 'pub const fn len(&self) -> usize' - // @has - '//*[@id="method.len"]//span[@class="since"]' '1.0.0 (const: 1.0.0)' + // @has - '//*[@id="method.len"]//span[@class="since"]' 'const: 1.0.0' #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rust1", since = "1.0.0")] pub const fn len(&self) -> usize { 0 } diff --git a/src/test/rustdoc/strip-block-doc-comments-stars.docblock.html b/src/test/rustdoc/strip-block-doc-comments-stars.docblock.html new file mode 100644 index 0000000000000..22b0b5dc47e28 --- /dev/null +++ b/src/test/rustdoc/strip-block-doc-comments-stars.docblock.html @@ -0,0 +1,2 @@ +

a

+
\ No newline at end of file diff --git a/src/test/rustdoc/strip-block-doc-comments-stars.rs b/src/test/rustdoc/strip-block-doc-comments-stars.rs new file mode 100644 index 0000000000000..ed2297b4fac5d --- /dev/null +++ b/src/test/rustdoc/strip-block-doc-comments-stars.rs @@ -0,0 +1,11 @@ +#![crate_name = "foo"] + +// The goal of this test is to answer that it won't be generated as a list because +// block doc comments can have their lines starting with a star. + +// @has foo/fn.foo.html +// @snapshot docblock - '//*[@class="rustdoc-toggle top-doc"]//*[@class="docblock"]' +/** + * a + */ +pub fn foo() {} diff --git a/src/test/ui/async-await/issue-76547.stderr b/src/test/ui/async-await/issue-76547.stderr index 9bfb0f28028cb..ac5f99970c814 100644 --- a/src/test/ui/async-await/issue-76547.stderr +++ b/src/test/ui/async-await/issue-76547.stderr @@ -2,23 +2,17 @@ error[E0623]: lifetime mismatch --> $DIR/issue-76547.rs:20:13 | LL | async fn fut(bufs: &mut [&mut [u8]]) { - | --------- - - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---------------- these two types are declared with different lifetimes... LL | ListFut(bufs).await - | ^^^^ ...but data from `bufs` is held across an await point here + | ^^^^ ...but data from `bufs` flows into `bufs` here error[E0623]: lifetime mismatch --> $DIR/issue-76547.rs:34:14 | LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 { - | --------- --- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---------------- these two types are declared with different lifetimes... LL | ListFut2(bufs).await - | ^^^^ ...but data from `bufs` is held across an await point here + | ^^^^ ...but data from `bufs` flows into `bufs` here error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/issues/issue-63388-1.stderr b/src/test/ui/async-await/issues/issue-63388-1.stderr index ac29cca9d3f60..8f602a1492ad2 100644 --- a/src/test/ui/async-await/issues/issue-63388-1.stderr +++ b/src/test/ui/async-await/issues/issue-63388-1.stderr @@ -2,14 +2,12 @@ error[E0623]: lifetime mismatch --> $DIR/issue-63388-1.rs:14:9 | LL | &'a self, foo: &dyn Foo - | -------- this parameter and the returned future are declared with different lifetimes... + | -------- this parameter and the return type are declared with different lifetimes... LL | ) -> &dyn Foo | -------- - | | - | this `async fn` implicitly returns an `impl Future` LL | { LL | foo - | ^^^ ...but data from `foo` is held across an await point here + | ^^^ ...but data from `foo` is returned here error: aborting due to previous error diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr index 464f283095dad..149692a2c6998 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr @@ -4,9 +4,8 @@ error[E0623]: lifetime mismatch LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { | ------ ^^^^^^^^^^^^^^^^^^^ | | | - | | ...but data from `a` is held across an await point here - | | this `async fn` implicitly returns an `impl Future + 'b>` - | this parameter and the returned future are declared with different lifetimes... + | | ...but data from `a` is returned here + | this parameter and the return type are declared with different lifetimes... error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds --> $DIR/ret-impl-trait-one.rs:16:65 diff --git a/src/test/ui/const-generics/generic_arg_infer/array-in-sig.rs b/src/test/ui/const-generics/generic_arg_infer/array-in-sig.rs deleted file mode 100644 index 56b88a426a1a8..0000000000000 --- a/src/test/ui/const-generics/generic_arg_infer/array-in-sig.rs +++ /dev/null @@ -1,12 +0,0 @@ -// To avoid having to `or` gate `_` as an expr. -#![feature(generic_arg_infer)] - -fn foo() -> [u8; _] { - //~^ ERROR the const placeholder `_` is not allowed within types on item signatures for generics - // FIXME(generic_arg_infer): this error message should say in the return type or sth like that. - [0; 3] -} - -fn main() { - foo(); -} diff --git a/src/test/ui/const-generics/generic_arg_infer/array-in-sig.stderr b/src/test/ui/const-generics/generic_arg_infer/array-in-sig.stderr deleted file mode 100644 index eaa12b4192dc6..0000000000000 --- a/src/test/ui/const-generics/generic_arg_infer/array-in-sig.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0121]: the const placeholder `_` is not allowed within types on item signatures for generics - --> $DIR/array-in-sig.rs:4:18 - | -LL | fn foo() -> [u8; _] { - | ^ not allowed in type signatures - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/const-generics/generic_arg_infer/in-signature.rs b/src/test/ui/const-generics/generic_arg_infer/in-signature.rs new file mode 100644 index 0000000000000..1f60b2242411d --- /dev/null +++ b/src/test/ui/const-generics/generic_arg_infer/in-signature.rs @@ -0,0 +1,61 @@ +#![crate_type = "rlib"] +#![feature(generic_arg_infer)] + +struct Foo; +struct Bar(T); + +fn arr_fn() -> [u8; _] { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + [0; 3] +} + +fn ty_fn() -> Bar { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + Bar::(0) +} + +fn ty_fn_mixed() -> Bar<_, _> { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + Bar::(0) +} + +const ARR_CT: [u8; _] = [0; 3]; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +static ARR_STATIC: [u8; _] = [0; 3]; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables +const TY_CT: Bar = Bar::(0); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +static TY_STATIC: Bar = Bar::(0); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables +const TY_CT_MIXED: Bar<_, _> = Bar::(0); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +static TY_STATIC_MIXED: Bar<_, _> = Bar::(0); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables +trait ArrAssocConst { + const ARR: [u8; _]; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +} +trait TyAssocConst { + const ARR: Bar; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +} +trait TyAssocConstMixed { + const ARR: Bar<_, _>; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +} + +trait AssocTy { + type Assoc; +} +impl AssocTy for i8 { + type Assoc = [u8; _]; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types +} +impl AssocTy for i16 { + type Assoc = Bar; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types +} +impl AssocTy for i32 { + type Assoc = Bar<_, _>; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types +} diff --git a/src/test/ui/const-generics/generic_arg_infer/in-signature.stderr b/src/test/ui/const-generics/generic_arg_infer/in-signature.stderr new file mode 100644 index 0000000000000..7581cf4120ecf --- /dev/null +++ b/src/test/ui/const-generics/generic_arg_infer/in-signature.stderr @@ -0,0 +1,119 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/in-signature.rs:7:21 + | +LL | fn arr_fn() -> [u8; _] { + | -----^- + | | | + | | not allowed in type signatures + | help: replace with the correct return type: `[u8; 3]` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/in-signature.rs:12:24 + | +LL | fn ty_fn() -> Bar { + | ---------^- + | | | + | | not allowed in type signatures + | help: replace with the correct return type: `Bar` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/in-signature.rs:17:25 + | +LL | fn ty_fn_mixed() -> Bar<_, _> { + | ----^--^- + | | | | + | | | not allowed in type signatures + | | not allowed in type signatures + | help: replace with the correct return type: `Bar` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:22:15 + | +LL | const ARR_CT: [u8; _] = [0; 3]; + | ^^^^^^^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/in-signature.rs:24:20 + | +LL | static ARR_STATIC: [u8; _] = [0; 3]; + | ^^^^^^^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:26:14 + | +LL | const TY_CT: Bar = Bar::(0); + | ^^^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Bar` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/in-signature.rs:28:19 + | +LL | static TY_STATIC: Bar = Bar::(0); + | ^^^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Bar` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:30:20 + | +LL | const TY_CT_MIXED: Bar<_, _> = Bar::(0); + | ^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Bar` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/in-signature.rs:32:25 + | +LL | static TY_STATIC_MIXED: Bar<_, _> = Bar::(0); + | ^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Bar` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:35:21 + | +LL | const ARR: [u8; _]; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:39:25 + | +LL | const ARR: Bar; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:43:20 + | +LL | const ARR: Bar<_, _>; + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/in-signature.rs:51:23 + | +LL | type Assoc = [u8; _]; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/in-signature.rs:55:27 + | +LL | type Assoc = Bar; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/in-signature.rs:59:22 + | +LL | type Assoc = Bar<_, _>; + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.rs b/src/test/ui/did_you_mean/bad-assoc-ty.rs index 609a5b0de6b7e..f787c416c2d63 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.rs +++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs @@ -16,7 +16,7 @@ type D = (u8, u8)::AssocTy; type E = _::AssocTy; //~^ ERROR missing angle brackets in associated item path -//~| ERROR the type placeholder `_` is not allowed within types on item signatures for type aliases +//~| ERROR the placeholder `_` is not allowed within types on item signatures for type aliases type F = &'static (u8)::AssocTy; //~^ ERROR missing angle brackets in associated item path @@ -49,37 +49,37 @@ type I = ty!()::AssocTy; trait K {} fn foo>(x: X) {} -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn bar(_: F) where F: Fn() -> _ {} -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn baz _>(_: F) {} -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions struct L(F) where F: Fn() -> _; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for structs struct M where F: Fn() -> _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for structs a: F, } enum N where F: Fn() -> _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for enums +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for enums Foo(F), } union O where F: Fn() -> _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for unions +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for unions foo: F, } trait P where F: Fn() -> _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for traits +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for traits } trait Q { fn foo(_: F) where F: Fn() -> _ {} - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions } fn main() {} diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr index 11514a28b2ca5..2326af934d014 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr @@ -81,7 +81,7 @@ error[E0223]: ambiguous associated type LL | type D = (u8, u8)::AssocTy; | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(u8, u8) as Trait>::AssocTy` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for type aliases +error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases --> $DIR/bad-assoc-ty.rs:17:10 | LL | type E = _::AssocTy; @@ -136,7 +136,7 @@ error[E0223]: ambiguous associated type LL | type I = ty!()::AssocTy; | ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/bad-assoc-ty.rs:51:13 | LL | fn foo>(x: X) {} @@ -149,7 +149,7 @@ help: use type parameters instead LL | fn foo, T>(x: X) {} | ~ ~ +++ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/bad-assoc-ty.rs:54:34 | LL | fn bar(_: F) where F: Fn() -> _ {} @@ -160,7 +160,7 @@ help: use type parameters instead LL | fn bar(_: F) where F: Fn() -> T {} | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/bad-assoc-ty.rs:57:19 | LL | fn baz _>(_: F) {} @@ -171,7 +171,7 @@ help: use type parameters instead LL | fn baz T, T>(_: F) {} | ~+++ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/bad-assoc-ty.rs:60:33 | LL | struct L(F) where F: Fn() -> _; @@ -182,7 +182,7 @@ help: use type parameters instead LL | struct L(F) where F: Fn() -> T; | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/bad-assoc-ty.rs:62:30 | LL | struct M where F: Fn() -> _ { @@ -193,7 +193,7 @@ help: use type parameters instead LL | struct M where F: Fn() -> T { | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for enums +error[E0121]: the placeholder `_` is not allowed within types on item signatures for enums --> $DIR/bad-assoc-ty.rs:66:28 | LL | enum N where F: Fn() -> _ { @@ -204,7 +204,7 @@ help: use type parameters instead LL | enum N where F: Fn() -> T { | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for unions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for unions --> $DIR/bad-assoc-ty.rs:71:29 | LL | union O where F: Fn() -> _ { @@ -215,7 +215,7 @@ help: use type parameters instead LL | union O where F: Fn() -> T { | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for traits +error[E0121]: the placeholder `_` is not allowed within types on item signatures for traits --> $DIR/bad-assoc-ty.rs:76:29 | LL | trait P where F: Fn() -> _ { @@ -226,7 +226,7 @@ help: use type parameters instead LL | trait P where F: Fn() -> T { | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/bad-assoc-ty.rs:81:38 | LL | fn foo(_: F) where F: Fn() -> _ {} diff --git a/src/test/ui/error-codes/E0121.stderr b/src/test/ui/error-codes/E0121.stderr index cc0c2df72ea7c..023d7e011bf3a 100644 --- a/src/test/ui/error-codes/E0121.stderr +++ b/src/test/ui/error-codes/E0121.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/E0121.rs:1:13 | LL | fn foo() -> _ { 5 } @@ -7,7 +7,7 @@ LL | fn foo() -> _ { 5 } | not allowed in type signatures | help: replace with the correct return type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/E0121.rs:3:13 | LL | static BAR: _ = "test"; diff --git a/src/test/ui/fn/issue-80179.rs b/src/test/ui/fn/issue-80179.rs index 550974bf77881..fcef6f1b60ecf 100644 --- a/src/test/ui/fn/issue-80179.rs +++ b/src/test/ui/fn/issue-80179.rs @@ -8,7 +8,7 @@ fn returns_i32() -> i32 { } fn returns_fn_ptr() -> _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types [E0121] +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] //~| NOTE not allowed in type signatures //~| HELP replace with the correct return type //~| SUGGESTION fn() -> i32 @@ -16,7 +16,7 @@ fn returns_fn_ptr() -> _ { } fn returns_closure() -> _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types [E0121] +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] //~| NOTE not allowed in type signatures //~| HELP consider using an `Fn`, `FnMut`, or `FnOnce` trait bound //~| NOTE for more information on `Fn` traits and closure types, see diff --git a/src/test/ui/fn/issue-80179.stderr b/src/test/ui/fn/issue-80179.stderr index 96d0f02b01af4..2ca4ae982d96f 100644 --- a/src/test/ui/fn/issue-80179.stderr +++ b/src/test/ui/fn/issue-80179.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-80179.rs:10:24 | LL | fn returns_fn_ptr() -> _ { @@ -7,7 +7,7 @@ LL | fn returns_fn_ptr() -> _ { | not allowed in type signatures | help: replace with the correct return type: `fn() -> i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-80179.rs:18:25 | LL | fn returns_closure() -> _ { diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.rs b/src/test/ui/issues/issue-69396-const-no-type-in-macro.rs index 6880e1a46293f..45a30857413b9 100644 --- a/src/test/ui/issues/issue-69396-const-no-type-in-macro.rs +++ b/src/test/ui/issues/issue-69396-const-no-type-in-macro.rs @@ -4,7 +4,7 @@ macro_rules! suite { const A = "A".$fn(); //~^ ERROR the name `A` is defined multiple times //~| ERROR missing type for `const` item - //~| ERROR the type placeholder `_` is not allowed within types on item signatures for constants + //~| ERROR the placeholder `_` is not allowed within types on item signatures for constants )* } } diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr index 34c2073db0485..e5ab65169ce3b 100644 --- a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr +++ b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr @@ -30,7 +30,7 @@ LL | | } | = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/issue-69396-const-no-type-in-macro.rs:4:19 | LL | const A = "A".$fn(); diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr index e6846fb40494f..299a2d2f2d3de 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr @@ -2,28 +2,25 @@ error[E0623]: lifetime mismatch --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52 | LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } - | ---- ---- ^ ...but data from `f` is held across an await point here - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- ^ ...but data from `f` is returned here + | | + | this parameter and the return type are declared with different lifetimes... error[E0623]: lifetime mismatch --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:82 | LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } - | ----- ----------------- ^ ...but data from `f` is held across an await point here - | | | - | | this `async fn` implicitly returns an `impl Future, &Foo)>` - | this parameter and the returned future are declared with different lifetimes... + | ---- ----------------- ^ ...but data from `f` is returned here + | | + | this parameter and the return type are declared with different lifetimes... error[E0623]: lifetime mismatch --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64 | LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } - | ----- --- ^^^ ...but data from `arg` is held across an await point here - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ------ --- ^^^ ...but data from `arg` is returned here + | | + | this parameter and the return type are declared with different lifetimes... error: aborting due to 3 previous errors diff --git a/src/test/ui/self/elision/lt-ref-self-async.stderr b/src/test/ui/self/elision/lt-ref-self-async.stderr index 3221d27085096..7448e8484b47a 100644 --- a/src/test/ui/self/elision/lt-ref-self-async.stderr +++ b/src/test/ui/self/elision/lt-ref-self-async.stderr @@ -2,67 +2,61 @@ error[E0623]: lifetime mismatch --> $DIR/lt-ref-self-async.rs:13:9 | LL | async fn ref_self(&self, f: &u32) -> &u32 { - | ----- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/lt-ref-self-async.rs:19:9 | LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { - | ----- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/lt-ref-self-async.rs:23:9 | LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { - | ----- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/lt-ref-self-async.rs:27:9 | LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { - | ----- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/lt-ref-self-async.rs:31:9 | LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { - | ----- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/lt-ref-self-async.rs:35:9 | LL | async fn box_pin_Self(self: Box>, f: &u32) -> &u32 { - | ----- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error: aborting due to 6 previous errors diff --git a/src/test/ui/self/elision/ref-mut-self-async.stderr b/src/test/ui/self/elision/ref-mut-self-async.stderr index b6ca986923d2e..6056cc46d3d8a 100644 --- a/src/test/ui/self/elision/ref-mut-self-async.stderr +++ b/src/test/ui/self/elision/ref-mut-self-async.stderr @@ -2,67 +2,61 @@ error[E0623]: lifetime mismatch --> $DIR/ref-mut-self-async.rs:13:9 | LL | async fn ref_self(&mut self, f: &u32) -> &u32 { - | --------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-mut-self-async.rs:19:9 | LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { - | --------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-mut-self-async.rs:23:9 | LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { - | --------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-mut-self-async.rs:27:9 | LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { - | --------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-mut-self-async.rs:31:9 | LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { - | --------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-mut-self-async.rs:35:9 | LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { - | --------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error: aborting due to 6 previous errors diff --git a/src/test/ui/self/elision/ref-mut-struct-async.stderr b/src/test/ui/self/elision/ref-mut-struct-async.stderr index eda15d76390b6..61034ae4d47b6 100644 --- a/src/test/ui/self/elision/ref-mut-struct-async.stderr +++ b/src/test/ui/self/elision/ref-mut-struct-async.stderr @@ -2,56 +2,51 @@ error[E0623]: lifetime mismatch --> $DIR/ref-mut-struct-async.rs:13:9 | LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { - | ----------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-mut-struct-async.rs:17:9 | LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { - | ----------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-mut-struct-async.rs:21:9 | LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { - | ----------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-mut-struct-async.rs:25:9 | LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { - | ----------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-mut-struct-async.rs:29:9 | LL | async fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u32 { - | ----------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error: aborting due to 5 previous errors diff --git a/src/test/ui/self/elision/ref-self-async.stderr b/src/test/ui/self/elision/ref-self-async.stderr index b42caa88c6fef..0eab16e685d4c 100644 --- a/src/test/ui/self/elision/ref-self-async.stderr +++ b/src/test/ui/self/elision/ref-self-async.stderr @@ -2,78 +2,71 @@ error[E0623]: lifetime mismatch --> $DIR/ref-self-async.rs:23:9 | LL | async fn ref_self(&self, f: &u32) -> &u32 { - | ----- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-self-async.rs:29:9 | LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { - | ----- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-self-async.rs:33:9 | LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { - | ----- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-self-async.rs:37:9 | LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { - | ----- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-self-async.rs:41:9 | LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { - | ----- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-self-async.rs:45:9 | LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { - | ----- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-self-async.rs:49:9 | LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { - | ----- --- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | --- --- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error: aborting due to 7 previous errors diff --git a/src/test/ui/self/elision/ref-struct-async.stderr b/src/test/ui/self/elision/ref-struct-async.stderr index 599becd308062..aa1d7453e83e1 100644 --- a/src/test/ui/self/elision/ref-struct-async.stderr +++ b/src/test/ui/self/elision/ref-struct-async.stderr @@ -2,56 +2,51 @@ error[E0623]: lifetime mismatch --> $DIR/ref-struct-async.rs:13:9 | LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { - | ------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-struct-async.rs:17:9 | LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { - | ------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-struct-async.rs:21:9 | LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { - | ------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-struct-async.rs:25:9 | LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { - | ------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch --> $DIR/ref-struct-async.rs:29:9 | LL | async fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { - | ------- ---- - | | | - | | this `async fn` implicitly returns an `impl Future` - | this parameter and the returned future are declared with different lifetimes... + | ---- ---- + | | + | this parameter and the return type are declared with different lifetimes... LL | f - | ^ ...but data from `f` is held across an await point here + | ^ ...but data from `f` is returned here error: aborting due to 5 previous errors diff --git a/src/test/ui/self/self-infer.rs b/src/test/ui/self/self-infer.rs index cc17d8f8e3962..9839b8880e9e1 100644 --- a/src/test/ui/self/self-infer.rs +++ b/src/test/ui/self/self-infer.rs @@ -1,8 +1,8 @@ struct S; impl S { - fn f(self: _) {} //~ERROR the type placeholder `_` is not allowed within types on item signatures for functions - fn g(self: &_) {} //~ERROR the type placeholder `_` is not allowed within types on item signatures for functions + fn f(self: _) {} //~ERROR the placeholder `_` is not allowed within types on item signatures for functions + fn g(self: &_) {} //~ERROR the placeholder `_` is not allowed within types on item signatures for functions } fn main() {} diff --git a/src/test/ui/self/self-infer.stderr b/src/test/ui/self/self-infer.stderr index d3bf63efa40d8..4f9e3f21dca52 100644 --- a/src/test/ui/self/self-infer.stderr +++ b/src/test/ui/self/self-infer.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/self-infer.rs:4:16 | LL | fn f(self: _) {} @@ -9,7 +9,7 @@ help: use type parameters instead LL | fn f(self: T) {} | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/self-infer.rs:5:17 | LL | fn g(self: &_) {} diff --git a/src/test/ui/suggestions/unnamable-types.rs b/src/test/ui/suggestions/unnamable-types.rs index 483f9bbb48cc6..f2485041d9ba2 100644 --- a/src/test/ui/suggestions/unnamable-types.rs +++ b/src/test/ui/suggestions/unnamable-types.rs @@ -8,14 +8,14 @@ const A = 5; //~| HELP: provide a type for the constant static B: _ = "abc"; -//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for static variables +//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for static variables //~| NOTE: not allowed in type signatures //~| HELP: replace with the correct type // FIXME: this should also suggest a function pointer, as the closure is non-capturing const C: _ = || 42; -//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for constants +//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for constants //~| NOTE: not allowed in type signatures //~| NOTE: however, the inferred type diff --git a/src/test/ui/suggestions/unnamable-types.stderr b/src/test/ui/suggestions/unnamable-types.stderr index 3a489a6e94313..6127446c83e3b 100644 --- a/src/test/ui/suggestions/unnamable-types.stderr +++ b/src/test/ui/suggestions/unnamable-types.stderr @@ -4,7 +4,7 @@ error: missing type for `const` item LL | const A = 5; | ^ help: provide a type for the constant: `A: i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/unnamable-types.rs:10:11 | LL | static B: _ = "abc"; @@ -13,7 +13,7 @@ LL | static B: _ = "abc"; | not allowed in type signatures | help: replace with the correct type: `&str` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/unnamable-types.rs:17:10 | LL | const C: _ = || 42; diff --git a/src/test/ui/transmute/transmute-imut-to-mut.rs b/src/test/ui/transmute/transmute-imut-to-mut.rs index 8e34e0ae8c74d..9f3f76c1ef3e0 100644 --- a/src/test/ui/transmute/transmute-imut-to-mut.rs +++ b/src/test/ui/transmute/transmute-imut-to-mut.rs @@ -4,5 +4,5 @@ use std::mem::transmute; fn main() { let _a: &mut u8 = unsafe { transmute(&1u8) }; - //~^ ERROR mutating transmuted &mut T from &T may cause undefined behavior + //~^ ERROR transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell } diff --git a/src/test/ui/transmute/transmute-imut-to-mut.stderr b/src/test/ui/transmute/transmute-imut-to-mut.stderr index d323c1a73b772..1e9dff3ce89b2 100644 --- a/src/test/ui/transmute/transmute-imut-to-mut.stderr +++ b/src/test/ui/transmute/transmute-imut-to-mut.stderr @@ -1,4 +1,4 @@ -error: mutating transmuted &mut T from &T may cause undefined behavior, consider instead using an UnsafeCell +error: transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell --> $DIR/transmute-imut-to-mut.rs:6:32 | LL | let _a: &mut u8 = unsafe { transmute(&1u8) }; diff --git a/src/test/ui/type-alias-impl-trait/issue-77179.rs b/src/test/ui/type-alias-impl-trait/issue-77179.rs index 31c45a2093a04..8d818d4a387a6 100644 --- a/src/test/ui/type-alias-impl-trait/issue-77179.rs +++ b/src/test/ui/type-alias-impl-trait/issue-77179.rs @@ -5,7 +5,7 @@ type Pointer = impl std::ops::Deref; fn test() -> Pointer<_> { - //~^ ERROR: the type placeholder `_` is not allowed within types + //~^ ERROR: the placeholder `_` is not allowed within types Box::new(1) } diff --git a/src/test/ui/type-alias-impl-trait/issue-77179.stderr b/src/test/ui/type-alias-impl-trait/issue-77179.stderr index 593aeeacb83aa..15205ba9b419e 100644 --- a/src/test/ui/type-alias-impl-trait/issue-77179.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-77179.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-77179.rs:7:22 | LL | fn test() -> Pointer<_> { diff --git a/src/test/ui/typeck/issue-74086.rs b/src/test/ui/typeck/issue-74086.rs index 1de9cd8007cff..44ca256b05163 100644 --- a/src/test/ui/typeck/issue-74086.rs +++ b/src/test/ui/typeck/issue-74086.rs @@ -1,4 +1,4 @@ fn main() { static BUG: fn(_) -> u8 = |_| 8; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions [E0121] + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions [E0121] } diff --git a/src/test/ui/typeck/issue-74086.stderr b/src/test/ui/typeck/issue-74086.stderr index ac1752e17dfb9..e7aea33758cb2 100644 --- a/src/test/ui/typeck/issue-74086.stderr +++ b/src/test/ui/typeck/issue-74086.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/issue-74086.rs:2:20 | LL | static BUG: fn(_) -> u8 = |_| 8; diff --git a/src/test/ui/typeck/issue-75883.rs b/src/test/ui/typeck/issue-75883.rs index 0d1534df091fa..885acc48231b2 100644 --- a/src/test/ui/typeck/issue-75883.rs +++ b/src/test/ui/typeck/issue-75883.rs @@ -5,7 +5,7 @@ pub struct UI {} impl UI { pub fn run() -> Result<_> { //~^ ERROR: this enum takes 2 generic arguments but 1 generic argument was supplied - //~| ERROR: the type placeholder `_` is not allowed within types on item signatures for return types + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for return types let mut ui = UI {}; ui.interact(); @@ -14,7 +14,7 @@ impl UI { pub fn interact(&mut self) -> Result<_> { //~^ ERROR: this enum takes 2 generic arguments but 1 generic argument was supplied - //~| ERROR: the type placeholder `_` is not allowed within types on item signatures for return types + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for return types unimplemented!(); } } diff --git a/src/test/ui/typeck/issue-75883.stderr b/src/test/ui/typeck/issue-75883.stderr index 5e42c817e030b..3861e0507f6dd 100644 --- a/src/test/ui/typeck/issue-75883.stderr +++ b/src/test/ui/typeck/issue-75883.stderr @@ -34,13 +34,13 @@ help: add missing generic argument LL | pub fn interact(&mut self) -> Result<_, E> { | +++ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-75883.rs:15:42 | LL | pub fn interact(&mut self) -> Result<_> { | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-75883.rs:6:28 | LL | pub fn run() -> Result<_> { diff --git a/src/test/ui/typeck/issue-75889.stderr b/src/test/ui/typeck/issue-75889.stderr index de4bdf4e6d9de..1438f481ec7e1 100644 --- a/src/test/ui/typeck/issue-75889.stderr +++ b/src/test/ui/typeck/issue-75889.stderr @@ -1,10 +1,10 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constant items +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constant items --> $DIR/issue-75889.rs:3:24 | LL | const FOO: dyn Fn() -> _ = ""; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static items +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static items --> $DIR/issue-75889.rs:4:25 | LL | static BOO: dyn Fn() -> _ = ""; diff --git a/src/test/ui/typeck/issue-80779.rs b/src/test/ui/typeck/issue-80779.rs index 99a93b1863d6e..1624f6b7742b0 100644 --- a/src/test/ui/typeck/issue-80779.rs +++ b/src/test/ui/typeck/issue-80779.rs @@ -3,11 +3,11 @@ pub struct T<'a>(&'a str); pub fn f<'a>(val: T<'a>) -> _ { - //~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for return types + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for return types g(val) } pub fn g(_: T<'static>) -> _ {} -//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for return types +//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for return types fn main() {} diff --git a/src/test/ui/typeck/issue-80779.stderr b/src/test/ui/typeck/issue-80779.stderr index 5a695fecc29dc..2261ba616545f 100644 --- a/src/test/ui/typeck/issue-80779.stderr +++ b/src/test/ui/typeck/issue-80779.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-80779.rs:10:28 | LL | pub fn g(_: T<'static>) -> _ {} @@ -7,7 +7,7 @@ LL | pub fn g(_: T<'static>) -> _ {} | not allowed in type signatures | help: replace with the correct return type: `()` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-80779.rs:5:29 | LL | pub fn f<'a>(val: T<'a>) -> _ { diff --git a/src/test/ui/typeck/issue-81885.rs b/src/test/ui/typeck/issue-81885.rs index 5117f250fe5ea..8935535fb7eb8 100644 --- a/src/test/ui/typeck/issue-81885.rs +++ b/src/test/ui/typeck/issue-81885.rs @@ -1,8 +1,8 @@ const TEST4: fn() -> _ = 42; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn main() { const TEST5: fn() -> _ = 42; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions } diff --git a/src/test/ui/typeck/issue-81885.stderr b/src/test/ui/typeck/issue-81885.stderr index 8206156a6180a..3ff4375cd8d3f 100644 --- a/src/test/ui/typeck/issue-81885.stderr +++ b/src/test/ui/typeck/issue-81885.stderr @@ -1,10 +1,10 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/issue-81885.rs:1:22 | LL | const TEST4: fn() -> _ = 42; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/issue-81885.rs:5:26 | LL | const TEST5: fn() -> _ = 42; diff --git a/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.stderr b/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.stderr index 7c5cf1082be09..9376e8bcf80bc 100644 --- a/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.stderr +++ b/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/issue-83621-placeholder-static-in-extern.rs:4:15 | LL | static x: _; diff --git a/src/test/ui/typeck/issue-91450-inner-ty-error.rs b/src/test/ui/typeck/issue-91450-inner-ty-error.rs index 0b942d6d94f84..3c7c990d4e27c 100644 --- a/src/test/ui/typeck/issue-91450-inner-ty-error.rs +++ b/src/test/ui/typeck/issue-91450-inner-ty-error.rs @@ -2,6 +2,6 @@ // This test ensures that the compiler does not suggest `Foo<[type error]>` in diagnostic messages. fn foo() -> Option<_> {} //~ ERROR: [E0308] -//~^ ERROR: the type placeholder `_` is not allowed +//~^ ERROR: the placeholder `_` is not allowed fn main() {} diff --git a/src/test/ui/typeck/issue-91450-inner-ty-error.stderr b/src/test/ui/typeck/issue-91450-inner-ty-error.stderr index 314fe56180368..32f4c8f6fdf82 100644 --- a/src/test/ui/typeck/issue-91450-inner-ty-error.stderr +++ b/src/test/ui/typeck/issue-91450-inner-ty-error.stderr @@ -9,7 +9,7 @@ LL | fn foo() -> Option<_> {} = note: expected enum `Option<_>` found unit type `()` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-91450-inner-ty-error.rs:4:20 | LL | fn foo() -> Option<_> {} diff --git a/src/test/ui/typeck/type-placeholder-fn-in-const.rs b/src/test/ui/typeck/type-placeholder-fn-in-const.rs index f657bea164872..ab2e2d8c53aa3 100644 --- a/src/test/ui/typeck/type-placeholder-fn-in-const.rs +++ b/src/test/ui/typeck/type-placeholder-fn-in-const.rs @@ -2,13 +2,13 @@ struct MyStruct; trait Test { const TEST: fn() -> _; - //~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for functions [E0121] - //~| ERROR: the type placeholder `_` is not allowed within types on item signatures for constants [E0121] + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for constants [E0121] } impl Test for MyStruct { const TEST: fn() -> _ = 42; - //~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for functions [E0121] + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] } fn main() {} diff --git a/src/test/ui/typeck/type-placeholder-fn-in-const.stderr b/src/test/ui/typeck/type-placeholder-fn-in-const.stderr index 62f4db8638f3c..e7b2e554a8d42 100644 --- a/src/test/ui/typeck/type-placeholder-fn-in-const.stderr +++ b/src/test/ui/typeck/type-placeholder-fn-in-const.stderr @@ -1,16 +1,16 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/type-placeholder-fn-in-const.rs:4:25 | LL | const TEST: fn() -> _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/type-placeholder-fn-in-const.rs:4:25 | LL | const TEST: fn() -> _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/type-placeholder-fn-in-const.rs:10:25 | LL | const TEST: fn() -> _ = 42; diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index a3b75543510ae..ca0876be58df9 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -5,67 +5,67 @@ // inference by using the `_` type placeholder. fn test() -> _ { 5 } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types fn test2() -> (_, _) { (5, 5) } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types static TEST3: _ = "test"; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables static TEST4: _ = 145; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables static TEST5: (_, _) = (1, 2); -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables fn test6(_: _) { } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn test6_b(_: _, _: T) { } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn test6_c(_: _, _: (T, K, L, A, B)) { } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn test7(x: _) { let _x: usize = x; } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn test8(_f: fn() -> _) { } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions -//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions +//~^^ ERROR the placeholder `_` is not allowed within types on item signatures for functions struct Test9; impl Test9 { fn test9(&self) -> _ { () } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types fn test10(&self, _x : _) { } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions } fn test11(x: &usize) -> &_ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types &x } unsafe fn test12(x: *const usize) -> *const *const _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types &x } impl Clone for Test9 { fn clone(&self) -> _ { Test9 } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types fn clone_from(&mut self, other: _) { *self = Test9; } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions } struct Test10 { a: _, - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for structs b: (_, _), } @@ -73,94 +73,94 @@ pub fn main() { static A = 42; //~^ ERROR missing type for `static` item static B: _ = 42; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables static C: Option<_> = Some(42); - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables fn fn_test() -> _ { 5 } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types fn fn_test2() -> (_, _) { (5, 5) } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types static FN_TEST3: _ = "test"; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables static FN_TEST4: _ = 145; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables static FN_TEST5: (_, _) = (1, 2); - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables fn fn_test6(_: _) { } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn fn_test7(x: _) { let _x: usize = x; } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn fn_test8(_f: fn() -> _) { } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions - //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + //~^^ ERROR the placeholder `_` is not allowed within types on item signatures for functions struct FnTest9; impl FnTest9 { fn fn_test9(&self) -> _ { () } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types fn fn_test10(&self, _x : _) { } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions } impl Clone for FnTest9 { fn clone(&self) -> _ { FnTest9 } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types fn clone_from(&mut self, other: _) { *self = FnTest9; } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions } struct FnTest10 { a: _, - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for structs b: (_, _), } fn fn_test11(_: _) -> (_, _) { panic!() } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types //~| ERROR type annotations needed fn fn_test12(x: i32) -> (_, _) { (x, x) } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types fn fn_test13(x: _) -> (i32, _) { (x, x) } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types } trait T { fn method_test1(&self, x: _); - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn method_test2(&self, x: _) -> _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn method_test3(&self) -> _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn assoc_fn_test1(x: _); - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn assoc_fn_test2(x: _) -> _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions fn assoc_fn_test3() -> _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions } struct BadStruct<_>(_); //~^ ERROR expected identifier, found reserved identifier `_` -//~| ERROR the type placeholder `_` is not allowed within types on item signatures for structs +//~| ERROR the placeholder `_` is not allowed within types on item signatures for structs trait BadTrait<_> {} //~^ ERROR expected identifier, found reserved identifier `_` impl BadTrait<_> for BadStruct<_> {} -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for implementations +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for implementations fn impl_trait() -> impl BadTrait<_> { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for opaque types +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for opaque types unimplemented!() } @@ -168,19 +168,19 @@ struct BadStruct1<_, _>(_); //~^ ERROR expected identifier, found reserved identifier `_` //~| ERROR expected identifier, found reserved identifier `_` //~| ERROR the name `_` is already used -//~| ERROR the type placeholder `_` is not allowed within types on item signatures for structs +//~| ERROR the placeholder `_` is not allowed within types on item signatures for structs struct BadStruct2<_, T>(_, T); //~^ ERROR expected identifier, found reserved identifier `_` -//~| ERROR the type placeholder `_` is not allowed within types on item signatures for structs +//~| ERROR the placeholder `_` is not allowed within types on item signatures for structs type X = Box<_>; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for type aliases +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for type aliases struct Struct; trait Trait {} impl Trait for Struct {} type Y = impl Trait<_>; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for opaque types +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for opaque types fn foo() -> Y { Struct } @@ -188,25 +188,25 @@ fn foo() -> Y { trait Qux { type A; type B = _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types const C: _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants const D: _ = 42; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants // type E: _; // FIXME: make the parser propagate the existence of `B` type F: std::ops::Fn(_); - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types } impl Qux for Struct { type A = _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types type B = _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types const C: _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants //~| ERROR associated constant in `impl` without body const D: _ = 42; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants } fn map(_: fn() -> Option<&'static T>) -> Option { @@ -214,9 +214,9 @@ fn map(_: fn() -> Option<&'static T>) -> Option { } fn value() -> Option<&'static _> { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types Option::<&'static u8>::None } const _: Option<_> = map(value); -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index e1f66afdacc11..c07b96f9a977a 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -44,7 +44,7 @@ LL | struct BadStruct1<_, _>(_); | | | first use of `_` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:7:14 | LL | fn test() -> _ { 5 } @@ -53,7 +53,7 @@ LL | fn test() -> _ { 5 } | not allowed in type signatures | help: replace with the correct return type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:10:16 | LL | fn test2() -> (_, _) { (5, 5) } @@ -63,7 +63,7 @@ LL | fn test2() -> (_, _) { (5, 5) } | |not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:13:15 | LL | static TEST3: _ = "test"; @@ -72,7 +72,7 @@ LL | static TEST3: _ = "test"; | not allowed in type signatures | help: replace with the correct type: `&str` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:16:15 | LL | static TEST4: _ = 145; @@ -81,13 +81,13 @@ LL | static TEST4: _ = 145; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:19:15 | LL | static TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:22:13 | LL | fn test6(_: _) { } @@ -98,7 +98,7 @@ help: use type parameters instead LL | fn test6(_: T) { } | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:25:18 | LL | fn test6_b(_: _, _: T) { } @@ -109,7 +109,7 @@ help: use type parameters instead LL | fn test6_b(_: U, _: T) { } | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:28:30 | LL | fn test6_c(_: _, _: (T, K, L, A, B)) { } @@ -120,7 +120,7 @@ help: use type parameters instead LL | fn test6_c(_: U, _: (T, K, L, A, B)) { } | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:31:13 | LL | fn test7(x: _) { let _x: usize = x; } @@ -131,7 +131,7 @@ help: use type parameters instead LL | fn test7(x: T) { let _x: usize = x; } | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:34:22 | LL | fn test8(_f: fn() -> _) { } @@ -140,7 +140,7 @@ LL | fn test8(_f: fn() -> _) { } | not allowed in type signatures | help: use type parameters instead: `T` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:34:22 | LL | fn test8(_f: fn() -> _) { } @@ -151,7 +151,7 @@ help: use type parameters instead LL | fn test8(_f: fn() -> T) { } | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:48:26 | LL | fn test11(x: &usize) -> &_ { @@ -160,7 +160,7 @@ LL | fn test11(x: &usize) -> &_ { | |not allowed in type signatures | help: replace with the correct return type: `&'static &'static usize` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:53:52 | LL | unsafe fn test12(x: *const usize) -> *const *const _ { @@ -169,7 +169,7 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ { | | not allowed in type signatures | help: replace with the correct return type: `*const *const usize` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/typeck_type_placeholder_item.rs:67:8 | LL | a: _, @@ -194,7 +194,7 @@ error: missing type for `static` item LL | static A = 42; | ^ help: provide a type for the static variable: `A: i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:75:15 | LL | static B: _ = 42; @@ -203,13 +203,13 @@ LL | static B: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:77:15 | LL | static C: Option<_> = Some(42); | ^^^^^^^^^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:79:21 | LL | fn fn_test() -> _ { 5 } @@ -218,7 +218,7 @@ LL | fn fn_test() -> _ { 5 } | not allowed in type signatures | help: replace with the correct return type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:82:23 | LL | fn fn_test2() -> (_, _) { (5, 5) } @@ -228,7 +228,7 @@ LL | fn fn_test2() -> (_, _) { (5, 5) } | |not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:85:22 | LL | static FN_TEST3: _ = "test"; @@ -237,7 +237,7 @@ LL | static FN_TEST3: _ = "test"; | not allowed in type signatures | help: replace with the correct type: `&str` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:88:22 | LL | static FN_TEST4: _ = 145; @@ -246,13 +246,13 @@ LL | static FN_TEST4: _ = 145; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:91:22 | LL | static FN_TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:94:20 | LL | fn fn_test6(_: _) { } @@ -263,7 +263,7 @@ help: use type parameters instead LL | fn fn_test6(_: T) { } | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:97:20 | LL | fn fn_test7(x: _) { let _x: usize = x; } @@ -274,7 +274,7 @@ help: use type parameters instead LL | fn fn_test7(x: T) { let _x: usize = x; } | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:100:29 | LL | fn fn_test8(_f: fn() -> _) { } @@ -283,7 +283,7 @@ LL | fn fn_test8(_f: fn() -> _) { } | not allowed in type signatures | help: use type parameters instead: `T` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:100:29 | LL | fn fn_test8(_f: fn() -> _) { } @@ -294,7 +294,7 @@ help: use type parameters instead LL | fn fn_test8(_f: fn() -> T) { } | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/typeck_type_placeholder_item.rs:123:12 | LL | a: _, @@ -319,7 +319,7 @@ error[E0282]: type annotations needed LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ cannot infer type -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:128:28 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } @@ -327,7 +327,7 @@ LL | fn fn_test11(_: _) -> (_, _) { panic!() } | | | not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:132:30 | LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } @@ -337,7 +337,7 @@ LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | |not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:135:33 | LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } @@ -346,7 +346,7 @@ LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | | not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/typeck_type_placeholder_item.rs:154:21 | LL | struct BadStruct<_>(_); @@ -357,7 +357,7 @@ help: use type parameters instead LL | struct BadStruct(T); | ~ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for implementations +error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations --> $DIR/typeck_type_placeholder_item.rs:159:15 | LL | impl BadTrait<_> for BadStruct<_> {} @@ -370,13 +370,13 @@ help: use type parameters instead LL | impl BadTrait for BadStruct {} | +++ ~ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for opaque types --> $DIR/typeck_type_placeholder_item.rs:162:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/typeck_type_placeholder_item.rs:167:25 | LL | struct BadStruct1<_, _>(_); @@ -387,7 +387,7 @@ help: use type parameters instead LL | struct BadStruct1(T); | ~ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/typeck_type_placeholder_item.rs:172:25 | LL | struct BadStruct2<_, T>(_, T); @@ -398,19 +398,19 @@ help: use type parameters instead LL | struct BadStruct2(U, T); | ~ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for type aliases +error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases --> $DIR/typeck_type_placeholder_item.rs:176:14 | LL | type X = Box<_>; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for opaque types --> $DIR/typeck_type_placeholder_item.rs:182:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:216:31 | LL | fn value() -> Option<&'static _> { @@ -419,7 +419,7 @@ LL | fn value() -> Option<&'static _> { | | not allowed in type signatures | help: replace with the correct return type: `Option<&'static u8>` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item.rs:221:10 | LL | const _: Option<_> = map(value); @@ -428,7 +428,7 @@ LL | const _: Option<_> = map(value); | not allowed in type signatures | help: replace with the correct type: `Option` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:140:31 | LL | fn method_test1(&self, x: _); @@ -439,7 +439,7 @@ help: use type parameters instead LL | fn method_test1(&self, x: T); | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:142:31 | LL | fn method_test2(&self, x: _) -> _; @@ -452,7 +452,7 @@ help: use type parameters instead LL | fn method_test2(&self, x: T) -> T; | +++ ~ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:144:31 | LL | fn method_test3(&self) -> _; @@ -463,7 +463,7 @@ help: use type parameters instead LL | fn method_test3(&self) -> T; | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:146:26 | LL | fn assoc_fn_test1(x: _); @@ -474,7 +474,7 @@ help: use type parameters instead LL | fn assoc_fn_test1(x: T); | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:148:26 | LL | fn assoc_fn_test2(x: _) -> _; @@ -487,7 +487,7 @@ help: use type parameters instead LL | fn assoc_fn_test2(x: T) -> T; | +++ ~ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:150:28 | LL | fn assoc_fn_test3() -> _; @@ -498,19 +498,19 @@ help: use type parameters instead LL | fn assoc_fn_test3() -> T; | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types --> $DIR/typeck_type_placeholder_item.rs:190:14 | LL | type B = _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item.rs:192:14 | LL | const C: _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item.rs:194:14 | LL | const D: _ = 42; @@ -519,13 +519,13 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types --> $DIR/typeck_type_placeholder_item.rs:197:26 | LL | type F: std::ops::Fn(_); | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:41:24 | LL | fn test9(&self) -> _ { () } @@ -534,7 +534,7 @@ LL | fn test9(&self) -> _ { () } | not allowed in type signatures | help: replace with the correct return type: `()` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:44:27 | LL | fn test10(&self, _x : _) { } @@ -545,7 +545,7 @@ help: use type parameters instead LL | fn test10(&self, _x : T) { } | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:59:24 | LL | fn clone(&self) -> _ { Test9 } @@ -554,7 +554,7 @@ LL | fn clone(&self) -> _ { Test9 } | not allowed in type signatures | help: replace with the correct return type: `Test9` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:62:37 | LL | fn clone_from(&mut self, other: _) { *self = Test9; } @@ -565,7 +565,7 @@ help: use type parameters instead LL | fn clone_from(&mut self, other: T) { *self = Test9; } | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:107:31 | LL | fn fn_test9(&self) -> _ { () } @@ -574,7 +574,7 @@ LL | fn fn_test9(&self) -> _ { () } | not allowed in type signatures | help: replace with the correct return type: `()` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:110:34 | LL | fn fn_test10(&self, _x : _) { } @@ -585,7 +585,7 @@ help: use type parameters instead LL | fn fn_test10(&self, _x : T) { } | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:115:28 | LL | fn clone(&self) -> _ { FnTest9 } @@ -594,7 +594,7 @@ LL | fn clone(&self) -> _ { FnTest9 } | not allowed in type signatures | help: replace with the correct return type: `FnTest9` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:118:41 | LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } @@ -605,25 +605,25 @@ help: use type parameters instead LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | +++ ~ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types --> $DIR/typeck_type_placeholder_item.rs:201:14 | LL | type A = _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types --> $DIR/typeck_type_placeholder_item.rs:203:14 | LL | type B = _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item.rs:205:14 | LL | const C: _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item.rs:208:14 | LL | const D: _ = 42; diff --git a/src/test/ui/typeck/typeck_type_placeholder_item_help.rs b/src/test/ui/typeck/typeck_type_placeholder_item_help.rs index 3af5cf926abf0..53f31b683c1a4 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item_help.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item_help.rs @@ -2,27 +2,27 @@ // using the `_` type placeholder. fn test1() -> _ { Some(42) } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types const TEST2: _ = 42u32; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants const TEST3: _ = Some(42); -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants const TEST4: fn() -> _ = 42; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions trait Test5 { const TEST5: _ = 42; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants } struct Test6; impl Test6 { const TEST6: _ = 13; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants } pub fn main() { diff --git a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr index 1b56b1033a8c1..e8191832318e5 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item_help.rs:4:15 | LL | fn test1() -> _ { Some(42) } @@ -7,7 +7,7 @@ LL | fn test1() -> _ { Some(42) } | not allowed in type signatures | help: replace with the correct return type: `Option` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item_help.rs:7:14 | LL | const TEST2: _ = 42u32; @@ -16,7 +16,7 @@ LL | const TEST2: _ = 42u32; | not allowed in type signatures | help: replace with the correct type: `u32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item_help.rs:10:14 | LL | const TEST3: _ = Some(42); @@ -25,13 +25,13 @@ LL | const TEST3: _ = Some(42); | not allowed in type signatures | help: replace with the correct type: `Option` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item_help.rs:13:22 | LL | const TEST4: fn() -> _ = 42; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item_help.rs:17:18 | LL | const TEST5: _ = 42; @@ -40,7 +40,7 @@ LL | const TEST5: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item_help.rs:24:18 | LL | const TEST6: _ = 13; diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 8e9ccbf97a702..9700addc82111 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 8e9ccbf97a70259b6c6576e8fd7d77d28238737e +Subproject commit 9700addc82111200a2150b9a796f62dd8e600ddf