diff --git a/Cargo.lock b/Cargo.lock index 85a9f239ab581..18b85103202e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4443,6 +4443,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "askama", + "atty", "expect-test", "itertools 0.9.0", "minifier", diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs index ea298d28e72c6..20954a322a578 100644 --- a/compiler/rustc_ast_pretty/src/pp.rs +++ b/compiler/rustc_ast_pretty/src/pp.rs @@ -222,29 +222,6 @@ struct PrintStackElem { const SIZE_INFINITY: isize = 0xffff; -pub fn mk_printer() -> Printer { - let linewidth = 78; - // Yes 55, it makes the ring buffers big enough to never fall behind. - let n: usize = 55 * linewidth; - debug!("mk_printer {}", linewidth); - Printer { - out: String::new(), - buf_max_len: n, - margin: linewidth as isize, - space: linewidth as isize, - left: 0, - right: 0, - // Initialize a single entry; advance_right() will extend it on demand - // up to `buf_max_len` elements. - buf: vec![BufEntry::default()], - left_total: 0, - right_total: 0, - scan_stack: VecDeque::new(), - print_stack: Vec::new(), - pending_indentation: 0, - } -} - pub struct Printer { out: String, buf_max_len: usize, @@ -288,6 +265,29 @@ impl Default for BufEntry { } impl Printer { + pub fn new() -> Self { + let linewidth = 78; + // Yes 55, it makes the ring buffers big enough to never fall behind. + let n: usize = 55 * linewidth; + debug!("Printer::new {}", linewidth); + Printer { + out: String::new(), + buf_max_len: n, + margin: linewidth as isize, + space: linewidth as isize, + left: 0, + right: 0, + // Initialize a single entry; advance_right() will extend it on demand + // up to `buf_max_len` elements. + buf: vec![BufEntry::default()], + left_total: 0, + right_total: 0, + scan_stack: VecDeque::new(), + print_stack: Vec::new(), + pending_indentation: 0, + } + } + pub fn last_token(&self) -> Token { self.buf[self.right].token.clone() } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 32a4a0751d8d2..015cd431deb6b 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -103,7 +103,7 @@ pub fn print_crate<'a>( edition: Edition, ) -> String { let mut s = - State { s: pp::mk_printer(), comments: Some(Comments::new(sm, filename, input)), ann }; + State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann }; if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) { // We need to print `#![no_std]` (and its feature gate) so that @@ -910,7 +910,7 @@ impl<'a> PrintState<'a> for State<'a> { impl<'a> State<'a> { pub fn new() -> State<'a> { - State { s: pp::mk_printer(), comments: None, ann: &NoAnn } + State { s: pp::Printer::new(), comments: None, ann: &NoAnn } } crate fn commasep_cmnt(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 1fd226291d12a..dabab073551c3 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -170,7 +170,7 @@ impl<'a> State<'a> { ann: &'a dyn PpAnn, ) -> State<'a> { State { - s: pp::mk_printer(), + s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), attrs, ann, @@ -186,7 +186,7 @@ pub fn to_string(ann: &dyn PpAnn, f: F) -> String where F: FnOnce(&mut State<'_>), { - let mut printer = State { s: pp::mk_printer(), comments: None, attrs: &|_| &[], ann }; + let mut printer = State { s: pp::Printer::new(), comments: None, attrs: &|_| &[], ann }; f(&mut printer); printer.s.eof() } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 612d450856512..c41f2d3299bf7 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -27,7 +27,7 @@ use std::mem::take; use tracing::{debug, trace}; const TURBOFISH_SUGGESTION_STR: &str = - "use `::<...>` instead of `<...>` to specify type or const arguments"; + "use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments"; /// Creates a placeholder argument. pub(super) fn dummy_arg(ident: Ident) -> Param { @@ -731,21 +731,28 @@ impl<'a> Parser<'a> { match x { Ok((_, _, false)) => { if self.eat(&token::Gt) { - match self.parse_expr() { - Ok(_) => { - e.span_suggestion_verbose( - binop.span.shrink_to_lo(), - TURBOFISH_SUGGESTION_STR, - "::".to_string(), - Applicability::MaybeIncorrect, - ); - e.emit(); - *expr = - self.mk_expr_err(expr.span.to(self.prev_token.span)); - return Ok(()); - } - Err(mut err) => { - err.cancel(); + let turbo_err = e.span_suggestion_verbose( + binop.span.shrink_to_lo(), + TURBOFISH_SUGGESTION_STR, + "::".to_string(), + Applicability::MaybeIncorrect, + ); + if self.check(&TokenKind::Semi) { + turbo_err.emit(); + *expr = self.mk_expr_err(expr.span); + return Ok(()); + } else { + match self.parse_expr() { + Ok(_) => { + turbo_err.emit(); + *expr = self + .mk_expr_err(expr.span.to(self.prev_token.span)); + return Ok(()); + } + Err(mut err) => { + turbo_err.cancel(); + err.cancel(); + } } } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index cd3846d5a224e..192e87b4c01f7 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1443,7 +1443,7 @@ impl<'a> Parser<'a> { &mut self, label: Label, attrs: AttrVec, - consume_colon: bool, + mut consume_colon: bool, ) -> PResult<'a, P> { let lo = label.ident.span; let label = Some(label); @@ -1456,6 +1456,12 @@ impl<'a> Parser<'a> { self.parse_loop_expr(label, lo, attrs) } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() { self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs) + } else if !ate_colon && (self.check(&TokenKind::Comma) || self.check(&TokenKind::Gt)) { + // We're probably inside of a `Path<'a>` that needs a turbofish, so suppress the + // "must be followed by a colon" error. + self.diagnostic().delay_span_bug(lo, "this label wasn't parsed correctly"); + consume_colon = false; + Ok(self.mk_expr_err(lo)) } else { let msg = "expected `while`, `for`, `loop` or `{` after a label"; self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit(); diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index c351a9f70404a..241dcbc64a676 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; -use rustc_span::symbol::sym; +use rustc_span::symbol::{sym, Symbol}; use rustc_span::{BytePos, Span}; use super::method::probe; @@ -24,7 +24,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn emit_coerce_suggestions( &self, err: &mut DiagnosticBuilder<'_>, - expr: &hir::Expr<'_>, + expr: &hir::Expr<'tcx>, expr_ty: Ty<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, @@ -109,7 +109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn demand_coerce( &self, - expr: &hir::Expr<'_>, + expr: &hir::Expr<'tcx>, checked_ty: Ty<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, @@ -129,7 +129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// will be permitted if the diverges flag is currently "always". pub fn demand_coerce_diag( &self, - expr: &hir::Expr<'_>, + expr: &hir::Expr<'tcx>, checked_ty: Ty<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, @@ -338,31 +338,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .collect(); - if let [variant] = &compatible_variants[..] { - // Just a single matching variant. - err.multipart_suggestion( - &format!("try wrapping the expression in `{}`", variant), - vec![ - (expr.span.shrink_to_lo(), format!("{}(", variant)), - (expr.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MaybeIncorrect, - ); - } else if compatible_variants.len() > 1 { - // More than one matching variant. - err.multipart_suggestions( - &format!( - "try wrapping the expression in a variant of `{}`", - self.tcx.def_path_str(expected_adt.did) - ), - compatible_variants.into_iter().map(|variant| { + let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { + Some(ident) => format!("{}: ", ident), + None => format!(""), + }; + + match &compatible_variants[..] { + [] => { /* No variants to format */ } + [variant] => { + // Just a single matching variant. + err.multipart_suggestion_verbose( + &format!("try wrapping the expression in `{}`", variant), vec![ - (expr.span.shrink_to_lo(), format!("{}(", variant)), + (expr.span.shrink_to_lo(), format!("{}{}(", prefix, variant)), (expr.span.shrink_to_hi(), ")".to_string()), - ] - }), - Applicability::MaybeIncorrect, - ); + ], + Applicability::MaybeIncorrect, + ); + } + _ => { + // More than one matching variant. + err.multipart_suggestions( + &format!( + "try wrapping the expression in a variant of `{}`", + self.tcx.def_path_str(expected_adt.did) + ), + compatible_variants.into_iter().map(|variant| { + vec![ + (expr.span.shrink_to_lo(), format!("{}{}(", prefix, variant)), + (expr.span.shrink_to_hi(), ")".to_string()), + ] + }), + Applicability::MaybeIncorrect, + ); + } } } } @@ -483,33 +492,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - crate fn is_hir_id_from_struct_pattern_shorthand_field( + crate fn maybe_get_struct_pattern_shorthand_field( &self, - hir_id: hir::HirId, - sp: Span, - ) -> bool { - let sm = self.sess().source_map(); - let parent_id = self.tcx.hir().get_parent_node(hir_id); - if let Some(parent) = self.tcx.hir().find(parent_id) { - // Account for fields - if let Node::Expr(hir::Expr { kind: hir::ExprKind::Struct(_, fields, ..), .. }) = parent - { - if let Ok(src) = sm.span_to_snippet(sp) { - for field in *fields { - if field.ident.as_str() == src && field.is_shorthand { - return true; - } + expr: &hir::Expr<'_>, + ) -> Option { + let hir = self.tcx.hir(); + let local = match expr { + hir::Expr { + kind: + hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { + res: hir::def::Res::Local(_), + segments: [hir::PathSegment { ident, .. }], + .. + }, + )), + .. + } => Some(ident), + _ => None, + }?; + + match hir.find(hir.get_parent_node(expr.hir_id))? { + Node::Expr(hir::Expr { kind: hir::ExprKind::Struct(_, fields, ..), .. }) => { + for field in *fields { + if field.ident.name == local.name && field.is_shorthand { + return Some(local.name); } } } + _ => {} } - false + + None } /// If the given `HirId` corresponds to a block with a trailing expression, return that expression - crate fn maybe_get_block_expr(&self, hir_id: hir::HirId) -> Option<&'tcx hir::Expr<'tcx>> { - match self.tcx.hir().find(hir_id)? { - Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, ..), .. }) => block.expr, + crate fn maybe_get_block_expr(&self, expr: &hir::Expr<'tcx>) -> Option<&'tcx hir::Expr<'tcx>> { + match expr { + hir::Expr { kind: hir::ExprKind::Block(block, ..), .. } => block.expr, _ => None, } } @@ -547,7 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// `&mut`!". pub fn check_ref( &self, - expr: &hir::Expr<'_>, + expr: &hir::Expr<'tcx>, checked_ty: Ty<'tcx>, expected: Ty<'tcx>, ) -> Option<(Span, &'static str, String, Applicability, bool /* verbose */)> { @@ -565,9 +586,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { s.strip_prefix(old).map(|stripped| new.to_string() + stripped) }; - let is_struct_pat_shorthand_field = - self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, sp); - // `ExprKind::DropTemps` is semantically irrelevant for these suggestions. let expr = expr.peel_drop_temps(); @@ -661,11 +679,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false, )); } - let field_name = if is_struct_pat_shorthand_field { - format!("{}: ", sugg_expr) - } else { - String::new() + + let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { + Some(ident) => format!("{}: ", ident), + None => format!(""), }; + if let Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(left_expr, ..), .. @@ -695,14 +714,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::Mutability::Mut => ( sp, "consider mutably borrowing here", - format!("{}&mut {}", field_name, sugg_expr), + format!("{}&mut {}", prefix, sugg_expr), Applicability::MachineApplicable, false, ), hir::Mutability::Not => ( sp, "consider borrowing here", - format!("{}&{}", field_name, sugg_expr), + format!("{}&{}", prefix, sugg_expr), Applicability::MachineApplicable, false, ), @@ -846,32 +865,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp) || checked_ty.is_box() { - if let Ok(code) = sm.span_to_snippet(expr.span) { - let message = if checked_ty.is_box() { - "consider unboxing the value" - } else if checked_ty.is_region_ptr() { - "consider dereferencing the borrow" - } else { - "consider dereferencing the type" - }; - let (span, suggestion) = if is_struct_pat_shorthand_field { - (expr.span, format!("{}: *{}", code, code)) - } else if self.is_else_if_block(expr) { - // Don't suggest nonsense like `else *if` - return None; - } else if let Some(expr) = self.maybe_get_block_expr(expr.hir_id) { - (expr.span.shrink_to_lo(), "*".to_string()) - } else { - (expr.span.shrink_to_lo(), "*".to_string()) - }; - return Some(( - span, - message, - suggestion, - Applicability::MachineApplicable, - true, - )); - } + let message = if checked_ty.is_box() { + "consider unboxing the value" + } else if checked_ty.is_region_ptr() { + "consider dereferencing the borrow" + } else { + "consider dereferencing the type" + }; + let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { + Some(ident) => format!("{}: ", ident), + None => format!(""), + }; + let (span, suggestion) = if self.is_else_if_block(expr) { + // Don't suggest nonsense like `else *if` + return None; + } else if let Some(expr) = self.maybe_get_block_expr(expr) { + // prefix should be empty here.. + (expr.span.shrink_to_lo(), "*".to_string()) + } else { + (expr.span.shrink_to_lo(), format!("{}*", prefix)) + }; + return Some(( + span, + message, + suggestion, + Applicability::MachineApplicable, + true, + )); } } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index e8a0cc946b5e1..473c848ad8f13 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -208,7 +208,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn suggest_deref_ref_or_into( &self, err: &mut DiagnosticBuilder<'_>, - expr: &hir::Expr<'_>, + expr: &hir::Expr<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, @@ -231,7 +231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } else if !self.check_for_cast(err, expr, found, expected, expected_ty_expr) { let is_struct_pat_shorthand_field = - self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, expr.span); + self.maybe_get_struct_pattern_shorthand_field(expr).is_some(); let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id); if !methods.is_empty() { if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 78f989e730d24..16ba5c008cd27 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1372,9 +1372,12 @@ impl Vec { /// /// Note: Because this shifts over the remaining elements, it has a /// worst-case performance of *O*(*n*). If you don't need the order of elements - /// to be preserved, use [`swap_remove`] instead. + /// to be preserved, use [`swap_remove`] instead. If you'd like to remove + /// elements from the beginning of the `Vec`, consider using + /// [`VecDeque::pop_front`] instead. /// /// [`swap_remove`]: Vec::swap_remove + /// [`VecDeque::pop_front`]: crate::collections::VecDeque::pop_front /// /// # Panics /// @@ -1735,6 +1738,11 @@ impl Vec { /// Removes the last element from a vector and returns it, or [`None`] if it /// is empty. /// + /// If you'd like to pop the first element, consider using + /// [`VecDeque::pop_front`] instead. + /// + /// [`VecDeque::pop_front`]: crate::collections::VecDeque::pop_front + /// /// # Examples /// /// ``` diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index deed9901cc9e4..f89cf812e970a 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -661,20 +661,37 @@ impl Clone for Reverse { /// /// ## Derivable /// -/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a -/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering based on the top-to-bottom declaration order of the struct's members. -/// When `derive`d on enums, variants are ordered by their top-to-bottom discriminant order. -/// This means variants at the top are less than variants at the bottom. -/// Here's an example: +/// This trait can be used with `#[derive]`. +/// +/// When `derive`d on structs, it will produce a +/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering +/// based on the top-to-bottom declaration order of the struct's members. +/// +/// When `derive`d on enums, variants are ordered by their discriminants. +/// By default, the discriminant is smallest for variants at the top, and +/// largest for variants at the bottom. Here's an example: /// /// ``` -/// #[derive(PartialEq, PartialOrd)] -/// enum Size { -/// Small, -/// Large, +/// #[derive(PartialEq, Eq, PartialOrd, Ord)] +/// enum E { +/// Top, +/// Bottom, /// } /// -/// assert!(Size::Small < Size::Large); +/// assert!(E::Top < E::Bottom); +/// ``` +/// +/// However, manually setting the discriminants can override this default +/// behavior: +/// +/// ``` +/// #[derive(PartialEq, Eq, PartialOrd, Ord)] +/// enum E { +/// Top = 2, +/// Bottom = 1, +/// } +/// +/// assert!(E::Bottom < E::Top); /// ``` /// /// ## Lexicographical comparison @@ -895,9 +912,38 @@ impl PartialOrd for Ordering { /// /// ## Derivable /// -/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a -/// lexicographic ordering based on the top-to-bottom declaration order of the struct's members. -/// When `derive`d on enums, variants are ordered by their top-to-bottom discriminant order. +/// This trait can be used with `#[derive]`. +/// +/// When `derive`d on structs, it will produce a +/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering +/// based on the top-to-bottom declaration order of the struct's members. +/// +/// When `derive`d on enums, variants are ordered by their discriminants. +/// By default, the discriminant is smallest for variants at the top, and +/// largest for variants at the bottom. Here's an example: +/// +/// ``` +/// #[derive(PartialEq, PartialOrd)] +/// enum E { +/// Top, +/// Bottom, +/// } +/// +/// assert!(E::Top < E::Bottom); +/// ``` +/// +/// However, manually setting the discriminants can override this default +/// behavior: +/// +/// ``` +/// #[derive(PartialEq, PartialOrd)] +/// enum E { +/// Top = 2, +/// Bottom = 1, +/// } +/// +/// assert!(E::Bottom < E::Top); +/// ``` /// /// ## How can I implement `PartialOrd`? /// @@ -970,8 +1016,8 @@ impl PartialOrd for Ordering { /// # Examples /// /// ``` -/// let x : u32 = 0; -/// let y : u32 = 1; +/// let x: u32 = 0; +/// let y: u32 = 1; /// /// assert_eq!(x < y, true); /// assert_eq!(x.lt(&y), true); diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index acbb612352b36..9781dc320edde 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1893,7 +1893,7 @@ extern "rust-intrinsic" { pub fn nontemporal_store(ptr: *mut T, val: T); /// See documentation of `<*const T>::offset_from` for details. - #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")] + #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "92980")] pub fn ptr_offset_from(ptr: *const T, base: *const T) -> isize; /// See documentation of `<*const T>::guaranteed_eq` for details. diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 7b826f921ca87..485a5965f4cf7 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -439,7 +439,7 @@ impl *const T { /// } /// ``` #[stable(feature = "ptr_offset_from", since = "1.47.0")] - #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")] + #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "92980")] #[inline] pub const unsafe fn offset_from(self, origin: *const T) -> isize where diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 6c50d4052976f..1412e836ebfc2 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -617,7 +617,7 @@ impl *mut T { /// } /// ``` #[stable(feature = "ptr_offset_from", since = "1.47.0")] - #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")] + #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "92980")] #[inline(always)] pub const unsafe fn offset_from(self, origin: *const T) -> isize where diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index bdf756df6fd79..ccb844cd10b25 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -9,6 +9,7 @@ path = "lib.rs" [dependencies] arrayvec = { version = "0.7", default-features = false } askama = { version = "0.11", default-features = false } +atty = "0.2" pulldown-cmark = { version = "0.9", default-features = false } minifier = "0.0.41" rayon = "1.5.1" diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f0cbe79bd065e..7f3e5d15de192 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1736,7 +1736,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { { write!( buffer, - "

{}{}

", + "

{}{}

", match *it.kind { clean::StructItem(..) => "Struct ", clean::TraitItem(..) => "Trait ", diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 67821f19a23f6..f2c111495edfb 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -670,7 +670,11 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra } write!(w, "
", id); write!(w, "
"); - render_stability_since(w, m, t, cx.tcx()); + + let has_stability = render_stability_since(w, m, t, cx.tcx()); + if has_stability { + w.write_str(" · "); + } write_srclink(cx, m, w); write!(w, "
"); write!(w, "

"); @@ -1457,14 +1461,14 @@ fn render_stability_since( item: &clean::Item, containing_item: &clean::Item, tcx: TyCtxt<'_>, -) { +) -> bool { render_stability_since_raw( w, item.stable_since(tcx), item.const_stability(tcx), containing_item.stable_since(tcx), containing_item.const_stable_since(tcx), - ); + ) } fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl, cx: &Context<'_>) -> Ordering { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index a647a0fbfa55d..d854aa86b3afd 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -71,7 +71,8 @@ extern crate tikv_jemalloc_sys; use tikv_jemalloc_sys as jemalloc_sys; use std::default::Default; -use std::env; +use std::env::{self, VarError}; +use std::io; use std::process; use rustc_driver::{abort_on_err, describe_lints}; @@ -179,47 +180,20 @@ pub fn main() { } fn init_logging() { - use std::io; - - // FIXME remove these and use winapi 0.3 instead - // Duplicates: bootstrap/compile.rs, librustc_errors/emitter.rs, rustc_driver/lib.rs - #[cfg(unix)] - fn stdout_isatty() -> bool { - extern crate libc; - unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } - } - - #[cfg(windows)] - fn stdout_isatty() -> bool { - extern crate winapi; - use winapi::um::consoleapi::GetConsoleMode; - use winapi::um::processenv::GetStdHandle; - use winapi::um::winbase::STD_OUTPUT_HANDLE; - - unsafe { - let handle = GetStdHandle(STD_OUTPUT_HANDLE); - let mut out = 0; - GetConsoleMode(handle, &mut out) != 0 - } - } - - let color_logs = match std::env::var("RUSTDOC_LOG_COLOR") { - Ok(value) => match value.as_ref() { - "always" => true, - "never" => false, - "auto" => stdout_isatty(), - _ => early_error( - ErrorOutputType::default(), - &format!( - "invalid log color value '{}': expected one of always, never, or auto", - value - ), - ), - }, - Err(std::env::VarError::NotPresent) => stdout_isatty(), - Err(std::env::VarError::NotUnicode(_value)) => early_error( + let color_logs = match std::env::var("RUSTDOC_LOG_COLOR").as_deref() { + Ok("always") => true, + Ok("never") => false, + Ok("auto") | Err(VarError::NotPresent) => atty::is(atty::Stream::Stdout), + Ok(value) => early_error( + ErrorOutputType::default(), + &format!("invalid log color value '{}': expected one of always, never, or auto", value), + ), + Err(VarError::NotUnicode(value)) => early_error( ErrorOutputType::default(), - "non-Unicode log color value: expected one of always, never, or auto", + &format!( + "invalid log color value '{}': expected one of always, never, or auto", + value.to_string_lossy() + ), ), }; let filter = tracing_subscriber::EnvFilter::from_env("RUSTDOC_LOG"); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 1544fae962cb4..1a9794e75bc06 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -436,8 +436,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } match tcx.type_of(did).kind() { ty::Adt(def, _) if def.is_enum() => { - if let Some(field) = - def.all_fields().find(|f| f.ident(tcx).name == variant_field_name) + if let Some(field) = def.all_fields().find(|f| f.name == variant_field_name) { Ok((ty_res, Some(ItemFragment(FragmentKind::VariantField, field.did)))) } else { @@ -806,11 +805,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { ty::Adt(def, _) if !def.is_enum() => def, _ => return None, }; - let field = def - .non_enum_variant() - .fields - .iter() - .find(|item| item.ident(tcx).name == item_name)?; + let field = + def.non_enum_variant().fields.iter().find(|item| item.name == item_name)?; Some((root_res, ItemFragment(FragmentKind::StructField, field.did))) } Res::Def(DefKind::Trait, did) => tcx diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml index f9c707f81e79c..9289244f6f8bb 100644 --- a/src/test/rustdoc-gui/sidebar.goml +++ b/src/test/rustdoc-gui/sidebar.goml @@ -22,6 +22,13 @@ click: "#structs + .item-table .item-left > a" assert-count: (".sidebar .location", 2) // We check that there is no crate listed outside of the top level. assert-false: ".sidebar-elems > .crate" + +click: ".sidebar-links a" +assert-property: ("html", {"scrollTop": "389"}) + +click: ".sidebar h2.location" +assert-property: ("html", {"scrollTop": "0"}) + // We now go back to the crate page to click on the "lib2" crate link. goto: file://|DOC_PATH|/test_docs/index.html click: ".sidebar-elems .crate > ul > li:first-child > a" diff --git a/src/test/rustdoc/source-version-separator.rs b/src/test/rustdoc/source-version-separator.rs new file mode 100644 index 0000000000000..45a555eaa1563 --- /dev/null +++ b/src/test/rustdoc/source-version-separator.rs @@ -0,0 +1,31 @@ +#![stable(feature = "bar", since = "1.0")] +#![crate_name = "foo"] + +#![feature(staged_api)] + +// @has foo/trait.Bar.html +// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0· source · ' +#[stable(feature = "bar", since = "1.0")] +pub trait Bar { + // @has - '//div[@id="tymethod.foo"]/*[@class="rightside"]' '3.0 · source' + #[stable(feature = "foobar", since = "3.0")] + fn foo(); +} + +// @has - '//div[@id="implementors-list"]//*[@class="rightside"]' '4.0 · source' + +// @has foo/struct.Foo.html +// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0· source · ' +#[stable(feature = "baz", since = "1.0")] +pub struct Foo; + +impl Foo { + // @has - '//div[@id="method.foofoo"]/*[@class="rightside"]' '3.0 · source' + #[stable(feature = "foobar", since = "3.0")] + pub fn foofoo() {} +} + +#[stable(feature = "yolo", since = "4.0")] +impl Bar for Foo { + fn foo() {} +} diff --git a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr index 11c3481f15afa..a6825b8458943 100644 --- a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr +++ b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr @@ -4,7 +4,7 @@ error: comparison operators cannot be chained LL | foo(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | foo::(); | ++ @@ -15,7 +15,7 @@ error: comparison operators cannot be chained LL | foo(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | foo::(); | ++ @@ -26,7 +26,7 @@ error: comparison operators cannot be chained LL | foo<3 + 3>(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | foo::<3 + 3>(); | ++ @@ -37,7 +37,7 @@ error: comparison operators cannot be chained LL | foo(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | foo::(); | ++ @@ -48,7 +48,7 @@ error: comparison operators cannot be chained LL | foo(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | foo::(); | ++ @@ -59,7 +59,7 @@ error: comparison operators cannot be chained LL | foo<100 - BAR>(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | foo::<100 - BAR>(); | ++ @@ -70,7 +70,7 @@ error: comparison operators cannot be chained LL | foo()>(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | foo::()>(); | ++ @@ -87,7 +87,7 @@ error: comparison operators cannot be chained LL | foo()>(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | foo::()>(); | ++ @@ -98,7 +98,7 @@ error: comparison operators cannot be chained LL | foo() + BAR>(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | foo::() + BAR>(); | ++ @@ -109,7 +109,7 @@ error: comparison operators cannot be chained LL | foo() - BAR>(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | foo::() - BAR>(); | ++ @@ -120,7 +120,7 @@ error: comparison operators cannot be chained LL | foo()>(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | foo::()>(); | ++ @@ -131,7 +131,7 @@ error: comparison operators cannot be chained LL | foo()>(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | foo::()>(); | ++ diff --git a/src/test/ui/did_you_mean/compatible-variants.rs b/src/test/ui/did_you_mean/compatible-variants.rs index fb6b6a5673d90..a70dda8386f08 100644 --- a/src/test/ui/did_you_mean/compatible-variants.rs +++ b/src/test/ui/did_you_mean/compatible-variants.rs @@ -3,6 +3,10 @@ enum Hey { B(B), } +struct Foo { + bar: Option, +} + fn f() {} fn a() -> Option<()> { @@ -40,4 +44,8 @@ fn main() { let _: Hey = false; //~^ ERROR mismatched types //~| HELP try wrapping + let bar = 1i32; + let _ = Foo { bar }; + //~^ ERROR mismatched types + //~| HELP try wrapping } diff --git a/src/test/ui/did_you_mean/compatible-variants.stderr b/src/test/ui/did_you_mean/compatible-variants.stderr index e77949687fcb2..0dfd8f5c128f6 100644 --- a/src/test/ui/did_you_mean/compatible-variants.stderr +++ b/src/test/ui/did_you_mean/compatible-variants.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:9:5 + --> $DIR/compatible-variants.rs:13:5 | LL | fn a() -> Option<()> { | ---------- expected `Option<()>` because of return type @@ -21,7 +21,7 @@ LL + Some(()) | error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:17:5 + --> $DIR/compatible-variants.rs:21:5 | LL | fn b() -> Result<(), ()> { | -------------- expected `Result<(), ()>` because of return type @@ -37,7 +37,7 @@ LL + Ok(()) | error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:23:25 + --> $DIR/compatible-variants.rs:27:25 | LL | let _: Option<()> = while false {}; | ---------- ^^^^^^^^^^^^^^ expected enum `Option`, found `()` @@ -52,7 +52,7 @@ LL | let _: Option<()> = Some(while false {}); | +++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:27:9 + --> $DIR/compatible-variants.rs:31:9 | LL | while false {} | ^^^^^^^^^^^^^^ expected enum `Option`, found `()` @@ -69,7 +69,7 @@ LL + Some(()) | error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:31:31 + --> $DIR/compatible-variants.rs:35:31 | LL | let _: Result = 1; | ---------------- ^ expected enum `Result`, found integer @@ -86,7 +86,7 @@ LL | let _: Result = Err(1); | ++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:34:26 + --> $DIR/compatible-variants.rs:38:26 | LL | let _: Option = 1; | ----------- ^ expected enum `Option`, found integer @@ -101,7 +101,7 @@ LL | let _: Option = Some(1); | +++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:37:28 + --> $DIR/compatible-variants.rs:41:28 | LL | let _: Hey = 1; | ------------- ^ expected enum `Hey`, found integer @@ -118,7 +118,7 @@ LL | let _: Hey = Hey::B(1); | +++++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:40:29 + --> $DIR/compatible-variants.rs:44:29 | LL | let _: Hey = false; | -------------- ^^^^^ expected enum `Hey`, found `bool` @@ -132,6 +132,19 @@ help: try wrapping the expression in `Hey::B` LL | let _: Hey = Hey::B(false); | +++++++ + -error: aborting due to 8 previous errors +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:48:19 + | +LL | let _ = Foo { bar }; + | ^^^ expected enum `Option`, found `i32` + | + = note: expected enum `Option` + found type `i32` +help: try wrapping the expression in `Some` + | +LL | let _ = Foo { bar: Some(bar) }; + | ++++++++++ + + +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index d2938435ece31..d0249efd094ff 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -4,7 +4,7 @@ error: comparison operators cannot be chained LL | (0..13).collect>(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | (0..13).collect::>(); | ++ @@ -15,7 +15,7 @@ error: comparison operators cannot be chained LL | Vec::new(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | Vec::::new(); | ++ @@ -26,7 +26,7 @@ error: comparison operators cannot be chained LL | (0..13).collect(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | (0..13).collect::(); | ++ @@ -37,7 +37,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, fo LL | let x = std::collections::HashMap::new(); | ^ expected one of 8 possible tokens | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | let x = std::collections::HashMap::::new(); | ++ @@ -48,7 +48,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found LL | std::collections::HashMap::new() | ^ expected one of 8 possible tokens | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | std::collections::HashMap::::new() | ++ @@ -59,7 +59,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found LL | std::collections::HashMap::new(); | ^ expected one of 8 possible tokens | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | std::collections::HashMap::::new(); | ++ @@ -70,7 +70,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found LL | std::collections::HashMap::new(1, 2); | ^ expected one of 8 possible tokens | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | std::collections::HashMap::::new(1, 2); | ++ diff --git a/src/test/ui/inference/deref-suggestion.stderr b/src/test/ui/inference/deref-suggestion.stderr index da11ba204cb53..28c9afaa52c22 100644 --- a/src/test/ui/inference/deref-suggestion.stderr +++ b/src/test/ui/inference/deref-suggestion.stderr @@ -87,7 +87,7 @@ LL | let r = R { i }; help: consider dereferencing the borrow | LL | let r = R { i: *i }; - | ~~~~~ + | ++++ error[E0308]: mismatched types --> $DIR/deref-suggestion.rs:46:20 diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index e3ce6cd39bc24..68636f6b907ef 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -1,6 +1,3 @@ -fn f() {} -struct X; - fn main() { false == false == false; //~^ ERROR comparison operators cannot be chained @@ -12,15 +9,26 @@ fn main() { f(); //~^ ERROR comparison operators cannot be chained - //~| HELP use `::<...>` instead of `<...>` to specify type or const arguments + //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments f, Option>>(1, 2); //~^ ERROR comparison operators cannot be chained - //~| HELP use `::<...>` instead of `<...>` to specify type or const arguments + //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + + let _ = f(); + //~^ ERROR expected one of + //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + + let _ = f<'_, i8>(); + //~^ ERROR expected one of + //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + + f<'_>(); + //~^ comparison operators cannot be chained + //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments - use std::convert::identity; - let _ = identity; + let _ = f; //~^ ERROR comparison operators cannot be chained - //~| HELP use `::<...>` instead of `<...>` to specify type or const arguments + //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments //~| HELP or use `(...)` if you meant to specify fn arguments } diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index 74429cb438c73..cde6f8c674f4b 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -1,5 +1,5 @@ error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:5:11 + --> $DIR/require-parens-for-chained-comparison.rs:2:11 | LL | false == false == false; | ^^ ^^ @@ -10,7 +10,7 @@ LL | false == false && false == false; | ++++++++ error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:9:11 + --> $DIR/require-parens-for-chained-comparison.rs:6:11 | LL | false == 0 < 2; | ^^ ^ @@ -21,35 +21,68 @@ LL | false == (0 < 2); | + + error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:13:6 + --> $DIR/require-parens-for-chained-comparison.rs:10:6 | LL | f(); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | f::(); | ++ error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:17:6 + --> $DIR/require-parens-for-chained-comparison.rs:14:6 | LL | f, Option>>(1, 2); | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | f::, Option>>(1, 2); | ++ +error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,` + --> $DIR/require-parens-for-chained-comparison.rs:18:17 + | +LL | let _ = f(); + | ^ expected one of 8 possible tokens + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | let _ = f::(); + | ++ + +error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, `{`, or an operator, found `,` + --> $DIR/require-parens-for-chained-comparison.rs:22:17 + | +LL | let _ = f<'_, i8>(); + | ^ expected one of 10 possible tokens + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | let _ = f::<'_, i8>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/require-parens-for-chained-comparison.rs:26:6 + | +LL | f<'_>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | f::<'_>(); + | ++ + error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:22:21 + --> $DIR/require-parens-for-chained-comparison.rs:30:14 | -LL | let _ = identity; - | ^ ^ +LL | let _ = f; + | ^ ^ | - = help: use `::<...>` instead of `<...>` to specify type or const arguments + = help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments = help: or use `(...)` if you meant to specify fn arguments -error: aborting due to 5 previous errors +error: aborting due to 8 previous errors diff --git a/src/test/ui/suggestions/issue-82566-1.stderr b/src/test/ui/suggestions/issue-82566-1.stderr index a05c59c786b0a..72f0f45fb8380 100644 --- a/src/test/ui/suggestions/issue-82566-1.stderr +++ b/src/test/ui/suggestions/issue-82566-1.stderr @@ -4,7 +4,7 @@ error: comparison operators cannot be chained LL | T1<1>::C; | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | T1::<1>::C; | ++ @@ -15,7 +15,7 @@ error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` LL | T2<1, 2>::C; | ^ expected one of `.`, `;`, `?`, `}`, or an operator | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | T2::<1, 2>::C; | ++ @@ -26,7 +26,7 @@ error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` LL | T3<1, 2, 3>::C; | ^ expected one of `.`, `;`, `?`, `}`, or an operator | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | T3::<1, 2, 3>::C; | ++ diff --git a/src/test/ui/suggestions/issue-82566-2.stderr b/src/test/ui/suggestions/issue-82566-2.stderr index 8f30a301bb82f..ef9a414307cc9 100644 --- a/src/test/ui/suggestions/issue-82566-2.stderr +++ b/src/test/ui/suggestions/issue-82566-2.stderr @@ -4,7 +4,7 @@ error: comparison operators cannot be chained LL | fn foo1() -> [(); Foo1<10>::SUM] { | ^ ^ | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | fn foo1() -> [(); Foo1::<10>::SUM] { | ++ @@ -15,7 +15,7 @@ error: expected one of `.`, `?`, `]`, or an operator, found `,` LL | fn foo2() -> [(); Foo2<10, 20>::SUM] { | ^ expected one of `.`, `?`, `]`, or an operator | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | fn foo2() -> [(); Foo2::<10, 20>::SUM] { | ++ @@ -26,7 +26,7 @@ error: expected one of `.`, `?`, `]`, or an operator, found `,` LL | fn foo3() -> [(); Foo3<10, 20, 30>::SUM] { | ^ expected one of `.`, `?`, `]`, or an operator | -help: use `::<...>` instead of `<...>` to specify type or const arguments +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | LL | fn foo3() -> [(); Foo3::<10, 20, 30>::SUM] { | ++