Skip to content

Commit 128417f

Browse files
committedJan 17, 2022
Auto merge of #92996 - matthiaskrgr:rollup-50wpzva, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #92795 (Link sidebar "location" heading to top of page) - #92799 (Remove some unnecessary uses of `FieldDef::ident`) - #92808 (Fix `try wrapping expression in variant` suggestion with struct field shorthand) - #92819 (rustdoc: remove hand-rolled isatty) - #92876 (Fix suggesting turbofish with lifetime arguments) - #92921 (Rename Printer constructor from mk_printer() to Printer::new()) - #92937 (rustdoc: Add missing dot separator) - #92953 (Copy an example to PartialOrd as well) - #92977 (Docs: recommend VecDeque instead of Vec::remove(0)) - #92981 (fix const_ptr_offset_from tracking issue) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents fd20513 + 9612038 commit 128417f

29 files changed

+416
-253
lines changed
 

‎Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4443,6 +4443,7 @@ version = "0.0.0"
44434443
dependencies = [
44444444
"arrayvec",
44454445
"askama",
4446+
"atty",
44464447
"expect-test",
44474448
"itertools 0.9.0",
44484449
"minifier",

‎compiler/rustc_ast_pretty/src/pp.rs

+23-23
Original file line numberDiff line numberDiff line change
@@ -222,29 +222,6 @@ struct PrintStackElem {
222222

223223
const SIZE_INFINITY: isize = 0xffff;
224224

225-
pub fn mk_printer() -> Printer {
226-
let linewidth = 78;
227-
// Yes 55, it makes the ring buffers big enough to never fall behind.
228-
let n: usize = 55 * linewidth;
229-
debug!("mk_printer {}", linewidth);
230-
Printer {
231-
out: String::new(),
232-
buf_max_len: n,
233-
margin: linewidth as isize,
234-
space: linewidth as isize,
235-
left: 0,
236-
right: 0,
237-
// Initialize a single entry; advance_right() will extend it on demand
238-
// up to `buf_max_len` elements.
239-
buf: vec![BufEntry::default()],
240-
left_total: 0,
241-
right_total: 0,
242-
scan_stack: VecDeque::new(),
243-
print_stack: Vec::new(),
244-
pending_indentation: 0,
245-
}
246-
}
247-
248225
pub struct Printer {
249226
out: String,
250227
buf_max_len: usize,
@@ -288,6 +265,29 @@ impl Default for BufEntry {
288265
}
289266

290267
impl Printer {
268+
pub fn new() -> Self {
269+
let linewidth = 78;
270+
// Yes 55, it makes the ring buffers big enough to never fall behind.
271+
let n: usize = 55 * linewidth;
272+
debug!("Printer::new {}", linewidth);
273+
Printer {
274+
out: String::new(),
275+
buf_max_len: n,
276+
margin: linewidth as isize,
277+
space: linewidth as isize,
278+
left: 0,
279+
right: 0,
280+
// Initialize a single entry; advance_right() will extend it on demand
281+
// up to `buf_max_len` elements.
282+
buf: vec![BufEntry::default()],
283+
left_total: 0,
284+
right_total: 0,
285+
scan_stack: VecDeque::new(),
286+
print_stack: Vec::new(),
287+
pending_indentation: 0,
288+
}
289+
}
290+
291291
pub fn last_token(&self) -> Token {
292292
self.buf[self.right].token.clone()
293293
}

‎compiler/rustc_ast_pretty/src/pprust/state.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ pub fn print_crate<'a>(
103103
edition: Edition,
104104
) -> String {
105105
let mut s =
106-
State { s: pp::mk_printer(), comments: Some(Comments::new(sm, filename, input)), ann };
106+
State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann };
107107

108108
if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) {
109109
// We need to print `#![no_std]` (and its feature gate) so that
@@ -910,7 +910,7 @@ impl<'a> PrintState<'a> for State<'a> {
910910

911911
impl<'a> State<'a> {
912912
pub fn new() -> State<'a> {
913-
State { s: pp::mk_printer(), comments: None, ann: &NoAnn }
913+
State { s: pp::Printer::new(), comments: None, ann: &NoAnn }
914914
}
915915

916916
crate fn commasep_cmnt<T, F, G>(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G)

‎compiler/rustc_hir_pretty/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ impl<'a> State<'a> {
170170
ann: &'a dyn PpAnn,
171171
) -> State<'a> {
172172
State {
173-
s: pp::mk_printer(),
173+
s: pp::Printer::new(),
174174
comments: Some(Comments::new(sm, filename, input)),
175175
attrs,
176176
ann,
@@ -186,7 +186,7 @@ pub fn to_string<F>(ann: &dyn PpAnn, f: F) -> String
186186
where
187187
F: FnOnce(&mut State<'_>),
188188
{
189-
let mut printer = State { s: pp::mk_printer(), comments: None, attrs: &|_| &[], ann };
189+
let mut printer = State { s: pp::Printer::new(), comments: None, attrs: &|_| &[], ann };
190190
f(&mut printer);
191191
printer.s.eof()
192192
}

‎compiler/rustc_parse/src/parser/diagnostics.rs

+23-16
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use std::mem::take;
2727
use tracing::{debug, trace};
2828

2929
const TURBOFISH_SUGGESTION_STR: &str =
30-
"use `::<...>` instead of `<...>` to specify type or const arguments";
30+
"use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments";
3131

3232
/// Creates a placeholder argument.
3333
pub(super) fn dummy_arg(ident: Ident) -> Param {
@@ -731,21 +731,28 @@ impl<'a> Parser<'a> {
731731
match x {
732732
Ok((_, _, false)) => {
733733
if self.eat(&token::Gt) {
734-
match self.parse_expr() {
735-
Ok(_) => {
736-
e.span_suggestion_verbose(
737-
binop.span.shrink_to_lo(),
738-
TURBOFISH_SUGGESTION_STR,
739-
"::".to_string(),
740-
Applicability::MaybeIncorrect,
741-
);
742-
e.emit();
743-
*expr =
744-
self.mk_expr_err(expr.span.to(self.prev_token.span));
745-
return Ok(());
746-
}
747-
Err(mut err) => {
748-
err.cancel();
734+
let turbo_err = e.span_suggestion_verbose(
735+
binop.span.shrink_to_lo(),
736+
TURBOFISH_SUGGESTION_STR,
737+
"::".to_string(),
738+
Applicability::MaybeIncorrect,
739+
);
740+
if self.check(&TokenKind::Semi) {
741+
turbo_err.emit();
742+
*expr = self.mk_expr_err(expr.span);
743+
return Ok(());
744+
} else {
745+
match self.parse_expr() {
746+
Ok(_) => {
747+
turbo_err.emit();
748+
*expr = self
749+
.mk_expr_err(expr.span.to(self.prev_token.span));
750+
return Ok(());
751+
}
752+
Err(mut err) => {
753+
turbo_err.cancel();
754+
err.cancel();
755+
}
749756
}
750757
}
751758
}

‎compiler/rustc_parse/src/parser/expr.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1443,7 +1443,7 @@ impl<'a> Parser<'a> {
14431443
&mut self,
14441444
label: Label,
14451445
attrs: AttrVec,
1446-
consume_colon: bool,
1446+
mut consume_colon: bool,
14471447
) -> PResult<'a, P<Expr>> {
14481448
let lo = label.ident.span;
14491449
let label = Some(label);
@@ -1456,6 +1456,12 @@ impl<'a> Parser<'a> {
14561456
self.parse_loop_expr(label, lo, attrs)
14571457
} else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {
14581458
self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs)
1459+
} else if !ate_colon && (self.check(&TokenKind::Comma) || self.check(&TokenKind::Gt)) {
1460+
// We're probably inside of a `Path<'a>` that needs a turbofish, so suppress the
1461+
// "must be followed by a colon" error.
1462+
self.diagnostic().delay_span_bug(lo, "this label wasn't parsed correctly");
1463+
consume_colon = false;
1464+
Ok(self.mk_expr_err(lo))
14591465
} else {
14601466
let msg = "expected `while`, `for`, `loop` or `{` after a label";
14611467
self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();

‎compiler/rustc_typeck/src/check/demand.rs

+102-82
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_middle::ty::adjustment::AllowTwoPhase;
1313
use rustc_middle::ty::error::{ExpectedFound, TypeError};
1414
use rustc_middle::ty::print::with_no_trimmed_paths;
1515
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
16-
use rustc_span::symbol::sym;
16+
use rustc_span::symbol::{sym, Symbol};
1717
use rustc_span::{BytePos, Span};
1818

1919
use super::method::probe;
@@ -24,7 +24,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2424
pub fn emit_coerce_suggestions(
2525
&self,
2626
err: &mut DiagnosticBuilder<'_>,
27-
expr: &hir::Expr<'_>,
27+
expr: &hir::Expr<'tcx>,
2828
expr_ty: Ty<'tcx>,
2929
expected: Ty<'tcx>,
3030
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
@@ -109,7 +109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
109109

110110
pub fn demand_coerce(
111111
&self,
112-
expr: &hir::Expr<'_>,
112+
expr: &hir::Expr<'tcx>,
113113
checked_ty: Ty<'tcx>,
114114
expected: Ty<'tcx>,
115115
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
@@ -129,7 +129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
129129
/// will be permitted if the diverges flag is currently "always".
130130
pub fn demand_coerce_diag(
131131
&self,
132-
expr: &hir::Expr<'_>,
132+
expr: &hir::Expr<'tcx>,
133133
checked_ty: Ty<'tcx>,
134134
expected: Ty<'tcx>,
135135
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
@@ -338,31 +338,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
338338
})
339339
.collect();
340340

341-
if let [variant] = &compatible_variants[..] {
342-
// Just a single matching variant.
343-
err.multipart_suggestion(
344-
&format!("try wrapping the expression in `{}`", variant),
345-
vec![
346-
(expr.span.shrink_to_lo(), format!("{}(", variant)),
347-
(expr.span.shrink_to_hi(), ")".to_string()),
348-
],
349-
Applicability::MaybeIncorrect,
350-
);
351-
} else if compatible_variants.len() > 1 {
352-
// More than one matching variant.
353-
err.multipart_suggestions(
354-
&format!(
355-
"try wrapping the expression in a variant of `{}`",
356-
self.tcx.def_path_str(expected_adt.did)
357-
),
358-
compatible_variants.into_iter().map(|variant| {
341+
let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
342+
Some(ident) => format!("{}: ", ident),
343+
None => format!(""),
344+
};
345+
346+
match &compatible_variants[..] {
347+
[] => { /* No variants to format */ }
348+
[variant] => {
349+
// Just a single matching variant.
350+
err.multipart_suggestion_verbose(
351+
&format!("try wrapping the expression in `{}`", variant),
359352
vec![
360-
(expr.span.shrink_to_lo(), format!("{}(", variant)),
353+
(expr.span.shrink_to_lo(), format!("{}{}(", prefix, variant)),
361354
(expr.span.shrink_to_hi(), ")".to_string()),
362-
]
363-
}),
364-
Applicability::MaybeIncorrect,
365-
);
355+
],
356+
Applicability::MaybeIncorrect,
357+
);
358+
}
359+
_ => {
360+
// More than one matching variant.
361+
err.multipart_suggestions(
362+
&format!(
363+
"try wrapping the expression in a variant of `{}`",
364+
self.tcx.def_path_str(expected_adt.did)
365+
),
366+
compatible_variants.into_iter().map(|variant| {
367+
vec![
368+
(expr.span.shrink_to_lo(), format!("{}{}(", prefix, variant)),
369+
(expr.span.shrink_to_hi(), ")".to_string()),
370+
]
371+
}),
372+
Applicability::MaybeIncorrect,
373+
);
374+
}
366375
}
367376
}
368377
}
@@ -483,33 +492,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
483492
}
484493
}
485494

486-
crate fn is_hir_id_from_struct_pattern_shorthand_field(
495+
crate fn maybe_get_struct_pattern_shorthand_field(
487496
&self,
488-
hir_id: hir::HirId,
489-
sp: Span,
490-
) -> bool {
491-
let sm = self.sess().source_map();
492-
let parent_id = self.tcx.hir().get_parent_node(hir_id);
493-
if let Some(parent) = self.tcx.hir().find(parent_id) {
494-
// Account for fields
495-
if let Node::Expr(hir::Expr { kind: hir::ExprKind::Struct(_, fields, ..), .. }) = parent
496-
{
497-
if let Ok(src) = sm.span_to_snippet(sp) {
498-
for field in *fields {
499-
if field.ident.as_str() == src && field.is_shorthand {
500-
return true;
501-
}
497+
expr: &hir::Expr<'_>,
498+
) -> Option<Symbol> {
499+
let hir = self.tcx.hir();
500+
let local = match expr {
501+
hir::Expr {
502+
kind:
503+
hir::ExprKind::Path(hir::QPath::Resolved(
504+
None,
505+
hir::Path {
506+
res: hir::def::Res::Local(_),
507+
segments: [hir::PathSegment { ident, .. }],
508+
..
509+
},
510+
)),
511+
..
512+
} => Some(ident),
513+
_ => None,
514+
}?;
515+
516+
match hir.find(hir.get_parent_node(expr.hir_id))? {
517+
Node::Expr(hir::Expr { kind: hir::ExprKind::Struct(_, fields, ..), .. }) => {
518+
for field in *fields {
519+
if field.ident.name == local.name && field.is_shorthand {
520+
return Some(local.name);
502521
}
503522
}
504523
}
524+
_ => {}
505525
}
506-
false
526+
527+
None
507528
}
508529

509530
/// If the given `HirId` corresponds to a block with a trailing expression, return that expression
510-
crate fn maybe_get_block_expr(&self, hir_id: hir::HirId) -> Option<&'tcx hir::Expr<'tcx>> {
511-
match self.tcx.hir().find(hir_id)? {
512-
Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, ..), .. }) => block.expr,
531+
crate fn maybe_get_block_expr(&self, expr: &hir::Expr<'tcx>) -> Option<&'tcx hir::Expr<'tcx>> {
532+
match expr {
533+
hir::Expr { kind: hir::ExprKind::Block(block, ..), .. } => block.expr,
513534
_ => None,
514535
}
515536
}
@@ -547,7 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
547568
/// `&mut`!".
548569
pub fn check_ref(
549570
&self,
550-
expr: &hir::Expr<'_>,
571+
expr: &hir::Expr<'tcx>,
551572
checked_ty: Ty<'tcx>,
552573
expected: Ty<'tcx>,
553574
) -> Option<(Span, &'static str, String, Applicability, bool /* verbose */)> {
@@ -565,9 +586,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
565586
s.strip_prefix(old).map(|stripped| new.to_string() + stripped)
566587
};
567588

568-
let is_struct_pat_shorthand_field =
569-
self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, sp);
570-
571589
// `ExprKind::DropTemps` is semantically irrelevant for these suggestions.
572590
let expr = expr.peel_drop_temps();
573591

@@ -661,11 +679,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
661679
false,
662680
));
663681
}
664-
let field_name = if is_struct_pat_shorthand_field {
665-
format!("{}: ", sugg_expr)
666-
} else {
667-
String::new()
682+
683+
let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
684+
Some(ident) => format!("{}: ", ident),
685+
None => format!(""),
668686
};
687+
669688
if let Some(hir::Node::Expr(hir::Expr {
670689
kind: hir::ExprKind::Assign(left_expr, ..),
671690
..
@@ -695,14 +714,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
695714
hir::Mutability::Mut => (
696715
sp,
697716
"consider mutably borrowing here",
698-
format!("{}&mut {}", field_name, sugg_expr),
717+
format!("{}&mut {}", prefix, sugg_expr),
699718
Applicability::MachineApplicable,
700719
false,
701720
),
702721
hir::Mutability::Not => (
703722
sp,
704723
"consider borrowing here",
705-
format!("{}&{}", field_name, sugg_expr),
724+
format!("{}&{}", prefix, sugg_expr),
706725
Applicability::MachineApplicable,
707726
false,
708727
),
@@ -846,32 +865,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
846865
if self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp)
847866
|| checked_ty.is_box()
848867
{
849-
if let Ok(code) = sm.span_to_snippet(expr.span) {
850-
let message = if checked_ty.is_box() {
851-
"consider unboxing the value"
852-
} else if checked_ty.is_region_ptr() {
853-
"consider dereferencing the borrow"
854-
} else {
855-
"consider dereferencing the type"
856-
};
857-
let (span, suggestion) = if is_struct_pat_shorthand_field {
858-
(expr.span, format!("{}: *{}", code, code))
859-
} else if self.is_else_if_block(expr) {
860-
// Don't suggest nonsense like `else *if`
861-
return None;
862-
} else if let Some(expr) = self.maybe_get_block_expr(expr.hir_id) {
863-
(expr.span.shrink_to_lo(), "*".to_string())
864-
} else {
865-
(expr.span.shrink_to_lo(), "*".to_string())
866-
};
867-
return Some((
868-
span,
869-
message,
870-
suggestion,
871-
Applicability::MachineApplicable,
872-
true,
873-
));
874-
}
868+
let message = if checked_ty.is_box() {
869+
"consider unboxing the value"
870+
} else if checked_ty.is_region_ptr() {
871+
"consider dereferencing the borrow"
872+
} else {
873+
"consider dereferencing the type"
874+
};
875+
let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
876+
Some(ident) => format!("{}: ", ident),
877+
None => format!(""),
878+
};
879+
let (span, suggestion) = if self.is_else_if_block(expr) {
880+
// Don't suggest nonsense like `else *if`
881+
return None;
882+
} else if let Some(expr) = self.maybe_get_block_expr(expr) {
883+
// prefix should be empty here..
884+
(expr.span.shrink_to_lo(), "*".to_string())
885+
} else {
886+
(expr.span.shrink_to_lo(), format!("{}*", prefix))
887+
};
888+
return Some((
889+
span,
890+
message,
891+
suggestion,
892+
Applicability::MachineApplicable,
893+
true,
894+
));
875895
}
876896
}
877897
}

‎compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
208208
pub fn suggest_deref_ref_or_into(
209209
&self,
210210
err: &mut DiagnosticBuilder<'_>,
211-
expr: &hir::Expr<'_>,
211+
expr: &hir::Expr<'tcx>,
212212
expected: Ty<'tcx>,
213213
found: Ty<'tcx>,
214214
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
@@ -231,7 +231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
231231
}
232232
} else if !self.check_for_cast(err, expr, found, expected, expected_ty_expr) {
233233
let is_struct_pat_shorthand_field =
234-
self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, expr.span);
234+
self.maybe_get_struct_pattern_shorthand_field(expr).is_some();
235235
let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id);
236236
if !methods.is_empty() {
237237
if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {

‎library/alloc/src/vec/mod.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -1372,9 +1372,12 @@ impl<T, A: Allocator> Vec<T, A> {
13721372
///
13731373
/// Note: Because this shifts over the remaining elements, it has a
13741374
/// worst-case performance of *O*(*n*). If you don't need the order of elements
1375-
/// to be preserved, use [`swap_remove`] instead.
1375+
/// to be preserved, use [`swap_remove`] instead. If you'd like to remove
1376+
/// elements from the beginning of the `Vec`, consider using
1377+
/// [`VecDeque::pop_front`] instead.
13761378
///
13771379
/// [`swap_remove`]: Vec::swap_remove
1380+
/// [`VecDeque::pop_front`]: crate::collections::VecDeque::pop_front
13781381
///
13791382
/// # Panics
13801383
///
@@ -1735,6 +1738,11 @@ impl<T, A: Allocator> Vec<T, A> {
17351738
/// Removes the last element from a vector and returns it, or [`None`] if it
17361739
/// is empty.
17371740
///
1741+
/// If you'd like to pop the first element, consider using
1742+
/// [`VecDeque::pop_front`] instead.
1743+
///
1744+
/// [`VecDeque::pop_front`]: crate::collections::VecDeque::pop_front
1745+
///
17381746
/// # Examples
17391747
///
17401748
/// ```

‎library/core/src/cmp.rs

+61-15
Original file line numberDiff line numberDiff line change
@@ -661,20 +661,37 @@ impl<T: Clone> Clone for Reverse<T> {
661661
///
662662
/// ## Derivable
663663
///
664-
/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
665-
/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering based on the top-to-bottom declaration order of the struct's members.
666-
/// When `derive`d on enums, variants are ordered by their top-to-bottom discriminant order.
667-
/// This means variants at the top are less than variants at the bottom.
668-
/// Here's an example:
664+
/// This trait can be used with `#[derive]`.
665+
///
666+
/// When `derive`d on structs, it will produce a
667+
/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering
668+
/// based on the top-to-bottom declaration order of the struct's members.
669+
///
670+
/// When `derive`d on enums, variants are ordered by their discriminants.
671+
/// By default, the discriminant is smallest for variants at the top, and
672+
/// largest for variants at the bottom. Here's an example:
669673
///
670674
/// ```
671-
/// #[derive(PartialEq, PartialOrd)]
672-
/// enum Size {
673-
/// Small,
674-
/// Large,
675+
/// #[derive(PartialEq, Eq, PartialOrd, Ord)]
676+
/// enum E {
677+
/// Top,
678+
/// Bottom,
675679
/// }
676680
///
677-
/// assert!(Size::Small < Size::Large);
681+
/// assert!(E::Top < E::Bottom);
682+
/// ```
683+
///
684+
/// However, manually setting the discriminants can override this default
685+
/// behavior:
686+
///
687+
/// ```
688+
/// #[derive(PartialEq, Eq, PartialOrd, Ord)]
689+
/// enum E {
690+
/// Top = 2,
691+
/// Bottom = 1,
692+
/// }
693+
///
694+
/// assert!(E::Bottom < E::Top);
678695
/// ```
679696
///
680697
/// ## Lexicographical comparison
@@ -895,9 +912,38 @@ impl PartialOrd for Ordering {
895912
///
896913
/// ## Derivable
897914
///
898-
/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
899-
/// lexicographic ordering based on the top-to-bottom declaration order of the struct's members.
900-
/// When `derive`d on enums, variants are ordered by their top-to-bottom discriminant order.
915+
/// This trait can be used with `#[derive]`.
916+
///
917+
/// When `derive`d on structs, it will produce a
918+
/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering
919+
/// based on the top-to-bottom declaration order of the struct's members.
920+
///
921+
/// When `derive`d on enums, variants are ordered by their discriminants.
922+
/// By default, the discriminant is smallest for variants at the top, and
923+
/// largest for variants at the bottom. Here's an example:
924+
///
925+
/// ```
926+
/// #[derive(PartialEq, PartialOrd)]
927+
/// enum E {
928+
/// Top,
929+
/// Bottom,
930+
/// }
931+
///
932+
/// assert!(E::Top < E::Bottom);
933+
/// ```
934+
///
935+
/// However, manually setting the discriminants can override this default
936+
/// behavior:
937+
///
938+
/// ```
939+
/// #[derive(PartialEq, PartialOrd)]
940+
/// enum E {
941+
/// Top = 2,
942+
/// Bottom = 1,
943+
/// }
944+
///
945+
/// assert!(E::Bottom < E::Top);
946+
/// ```
901947
///
902948
/// ## How can I implement `PartialOrd`?
903949
///
@@ -970,8 +1016,8 @@ impl PartialOrd for Ordering {
9701016
/// # Examples
9711017
///
9721018
/// ```
973-
/// let x : u32 = 0;
974-
/// let y : u32 = 1;
1019+
/// let x: u32 = 0;
1020+
/// let y: u32 = 1;
9751021
///
9761022
/// assert_eq!(x < y, true);
9771023
/// assert_eq!(x.lt(&y), true);

‎library/core/src/intrinsics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1893,7 +1893,7 @@ extern "rust-intrinsic" {
18931893
pub fn nontemporal_store<T>(ptr: *mut T, val: T);
18941894

18951895
/// See documentation of `<*const T>::offset_from` for details.
1896-
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
1896+
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "92980")]
18971897
pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
18981898

18991899
/// See documentation of `<*const T>::guaranteed_eq` for details.

‎library/core/src/ptr/const_ptr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ impl<T: ?Sized> *const T {
439439
/// }
440440
/// ```
441441
#[stable(feature = "ptr_offset_from", since = "1.47.0")]
442-
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
442+
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "92980")]
443443
#[inline]
444444
pub const unsafe fn offset_from(self, origin: *const T) -> isize
445445
where

‎library/core/src/ptr/mut_ptr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ impl<T: ?Sized> *mut T {
617617
/// }
618618
/// ```
619619
#[stable(feature = "ptr_offset_from", since = "1.47.0")]
620-
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
620+
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "92980")]
621621
#[inline(always)]
622622
pub const unsafe fn offset_from(self, origin: *const T) -> isize
623623
where

‎src/librustdoc/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ path = "lib.rs"
99
[dependencies]
1010
arrayvec = { version = "0.7", default-features = false }
1111
askama = { version = "0.11", default-features = false }
12+
atty = "0.2"
1213
pulldown-cmark = { version = "0.9", default-features = false }
1314
minifier = "0.0.41"
1415
rayon = "1.5.1"

‎src/librustdoc/html/render/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1736,7 +1736,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
17361736
{
17371737
write!(
17381738
buffer,
1739-
"<h2 class=\"location\">{}{}</h2>",
1739+
"<h2 class=\"location\"><a href=\"#\">{}{}</a></h2>",
17401740
match *it.kind {
17411741
clean::StructItem(..) => "Struct ",
17421742
clean::TraitItem(..) => "Trait ",

‎src/librustdoc/html/render/print_item.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,11 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
670670
}
671671
write!(w, "<div id=\"{}\" class=\"method has-srclink\">", id);
672672
write!(w, "<div class=\"rightside\">");
673-
render_stability_since(w, m, t, cx.tcx());
673+
674+
let has_stability = render_stability_since(w, m, t, cx.tcx());
675+
if has_stability {
676+
w.write_str(" · ");
677+
}
674678
write_srclink(cx, m, w);
675679
write!(w, "</div>");
676680
write!(w, "<h4 class=\"code-header\">");
@@ -1457,14 +1461,14 @@ fn render_stability_since(
14571461
item: &clean::Item,
14581462
containing_item: &clean::Item,
14591463
tcx: TyCtxt<'_>,
1460-
) {
1464+
) -> bool {
14611465
render_stability_since_raw(
14621466
w,
14631467
item.stable_since(tcx),
14641468
item.const_stability(tcx),
14651469
containing_item.stable_since(tcx),
14661470
containing_item.const_stable_since(tcx),
1467-
);
1471+
)
14681472
}
14691473

14701474
fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl, cx: &Context<'_>) -> Ordering {

‎src/librustdoc/lib.rs

+15-41
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ extern crate tikv_jemalloc_sys;
7171
use tikv_jemalloc_sys as jemalloc_sys;
7272

7373
use std::default::Default;
74-
use std::env;
74+
use std::env::{self, VarError};
75+
use std::io;
7576
use std::process;
7677

7778
use rustc_driver::{abort_on_err, describe_lints};
@@ -179,47 +180,20 @@ pub fn main() {
179180
}
180181

181182
fn init_logging() {
182-
use std::io;
183-
184-
// FIXME remove these and use winapi 0.3 instead
185-
// Duplicates: bootstrap/compile.rs, librustc_errors/emitter.rs, rustc_driver/lib.rs
186-
#[cfg(unix)]
187-
fn stdout_isatty() -> bool {
188-
extern crate libc;
189-
unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
190-
}
191-
192-
#[cfg(windows)]
193-
fn stdout_isatty() -> bool {
194-
extern crate winapi;
195-
use winapi::um::consoleapi::GetConsoleMode;
196-
use winapi::um::processenv::GetStdHandle;
197-
use winapi::um::winbase::STD_OUTPUT_HANDLE;
198-
199-
unsafe {
200-
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
201-
let mut out = 0;
202-
GetConsoleMode(handle, &mut out) != 0
203-
}
204-
}
205-
206-
let color_logs = match std::env::var("RUSTDOC_LOG_COLOR") {
207-
Ok(value) => match value.as_ref() {
208-
"always" => true,
209-
"never" => false,
210-
"auto" => stdout_isatty(),
211-
_ => early_error(
212-
ErrorOutputType::default(),
213-
&format!(
214-
"invalid log color value '{}': expected one of always, never, or auto",
215-
value
216-
),
217-
),
218-
},
219-
Err(std::env::VarError::NotPresent) => stdout_isatty(),
220-
Err(std::env::VarError::NotUnicode(_value)) => early_error(
183+
let color_logs = match std::env::var("RUSTDOC_LOG_COLOR").as_deref() {
184+
Ok("always") => true,
185+
Ok("never") => false,
186+
Ok("auto") | Err(VarError::NotPresent) => atty::is(atty::Stream::Stdout),
187+
Ok(value) => early_error(
188+
ErrorOutputType::default(),
189+
&format!("invalid log color value '{}': expected one of always, never, or auto", value),
190+
),
191+
Err(VarError::NotUnicode(value)) => early_error(
221192
ErrorOutputType::default(),
222-
"non-Unicode log color value: expected one of always, never, or auto",
193+
&format!(
194+
"invalid log color value '{}': expected one of always, never, or auto",
195+
value.to_string_lossy()
196+
),
223197
),
224198
};
225199
let filter = tracing_subscriber::EnvFilter::from_env("RUSTDOC_LOG");

‎src/librustdoc/passes/collect_intra_doc_links.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
436436
}
437437
match tcx.type_of(did).kind() {
438438
ty::Adt(def, _) if def.is_enum() => {
439-
if let Some(field) =
440-
def.all_fields().find(|f| f.ident(tcx).name == variant_field_name)
439+
if let Some(field) = def.all_fields().find(|f| f.name == variant_field_name)
441440
{
442441
Ok((ty_res, Some(ItemFragment(FragmentKind::VariantField, field.did))))
443442
} else {
@@ -806,11 +805,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
806805
ty::Adt(def, _) if !def.is_enum() => def,
807806
_ => return None,
808807
};
809-
let field = def
810-
.non_enum_variant()
811-
.fields
812-
.iter()
813-
.find(|item| item.ident(tcx).name == item_name)?;
808+
let field =
809+
def.non_enum_variant().fields.iter().find(|item| item.name == item_name)?;
814810
Some((root_res, ItemFragment(FragmentKind::StructField, field.did)))
815811
}
816812
Res::Def(DefKind::Trait, did) => tcx

‎src/test/rustdoc-gui/sidebar.goml

+7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ click: "#structs + .item-table .item-left > a"
2222
assert-count: (".sidebar .location", 2)
2323
// We check that there is no crate listed outside of the top level.
2424
assert-false: ".sidebar-elems > .crate"
25+
26+
click: ".sidebar-links a"
27+
assert-property: ("html", {"scrollTop": "389"})
28+
29+
click: ".sidebar h2.location"
30+
assert-property: ("html", {"scrollTop": "0"})
31+
2532
// We now go back to the crate page to click on the "lib2" crate link.
2633
goto: file://|DOC_PATH|/test_docs/index.html
2734
click: ".sidebar-elems .crate > ul > li:first-child > a"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#![stable(feature = "bar", since = "1.0")]
2+
#![crate_name = "foo"]
3+
4+
#![feature(staged_api)]
5+
6+
// @has foo/trait.Bar.html
7+
// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0· source · '
8+
#[stable(feature = "bar", since = "1.0")]
9+
pub trait Bar {
10+
// @has - '//div[@id="tymethod.foo"]/*[@class="rightside"]' '3.0 · source'
11+
#[stable(feature = "foobar", since = "3.0")]
12+
fn foo();
13+
}
14+
15+
// @has - '//div[@id="implementors-list"]//*[@class="rightside"]' '4.0 · source'
16+
17+
// @has foo/struct.Foo.html
18+
// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0· source · '
19+
#[stable(feature = "baz", since = "1.0")]
20+
pub struct Foo;
21+
22+
impl Foo {
23+
// @has - '//div[@id="method.foofoo"]/*[@class="rightside"]' '3.0 · source'
24+
#[stable(feature = "foobar", since = "3.0")]
25+
pub fn foofoo() {}
26+
}
27+
28+
#[stable(feature = "yolo", since = "4.0")]
29+
impl Bar for Foo {
30+
fn foo() {}
31+
}

‎src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr

+12-12
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: comparison operators cannot be chained
44
LL | foo<BAR + 3>();
55
| ^ ^
66
|
7-
help: use `::<...>` instead of `<...>` to specify type or const arguments
7+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
88
|
99
LL | foo::<BAR + 3>();
1010
| ++
@@ -15,7 +15,7 @@ error: comparison operators cannot be chained
1515
LL | foo<BAR + BAR>();
1616
| ^ ^
1717
|
18-
help: use `::<...>` instead of `<...>` to specify type or const arguments
18+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
1919
|
2020
LL | foo::<BAR + BAR>();
2121
| ++
@@ -26,7 +26,7 @@ error: comparison operators cannot be chained
2626
LL | foo<3 + 3>();
2727
| ^ ^
2828
|
29-
help: use `::<...>` instead of `<...>` to specify type or const arguments
29+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
3030
|
3131
LL | foo::<3 + 3>();
3232
| ++
@@ -37,7 +37,7 @@ error: comparison operators cannot be chained
3737
LL | foo<BAR - 3>();
3838
| ^ ^
3939
|
40-
help: use `::<...>` instead of `<...>` to specify type or const arguments
40+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
4141
|
4242
LL | foo::<BAR - 3>();
4343
| ++
@@ -48,7 +48,7 @@ error: comparison operators cannot be chained
4848
LL | foo<BAR - BAR>();
4949
| ^ ^
5050
|
51-
help: use `::<...>` instead of `<...>` to specify type or const arguments
51+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
5252
|
5353
LL | foo::<BAR - BAR>();
5454
| ++
@@ -59,7 +59,7 @@ error: comparison operators cannot be chained
5959
LL | foo<100 - BAR>();
6060
| ^ ^
6161
|
62-
help: use `::<...>` instead of `<...>` to specify type or const arguments
62+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
6363
|
6464
LL | foo::<100 - BAR>();
6565
| ++
@@ -70,7 +70,7 @@ error: comparison operators cannot be chained
7070
LL | foo<bar<i32>()>();
7171
| ^ ^
7272
|
73-
help: use `::<...>` instead of `<...>` to specify type or const arguments
73+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
7474
|
7575
LL | foo::<bar<i32>()>();
7676
| ++
@@ -87,7 +87,7 @@ error: comparison operators cannot be chained
8787
LL | foo<bar::<i32>()>();
8888
| ^ ^
8989
|
90-
help: use `::<...>` instead of `<...>` to specify type or const arguments
90+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
9191
|
9292
LL | foo::<bar::<i32>()>();
9393
| ++
@@ -98,7 +98,7 @@ error: comparison operators cannot be chained
9898
LL | foo<bar::<i32>() + BAR>();
9999
| ^ ^
100100
|
101-
help: use `::<...>` instead of `<...>` to specify type or const arguments
101+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
102102
|
103103
LL | foo::<bar::<i32>() + BAR>();
104104
| ++
@@ -109,7 +109,7 @@ error: comparison operators cannot be chained
109109
LL | foo<bar::<i32>() - BAR>();
110110
| ^ ^
111111
|
112-
help: use `::<...>` instead of `<...>` to specify type or const arguments
112+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
113113
|
114114
LL | foo::<bar::<i32>() - BAR>();
115115
| ++
@@ -120,7 +120,7 @@ error: comparison operators cannot be chained
120120
LL | foo<BAR - bar::<i32>()>();
121121
| ^ ^
122122
|
123-
help: use `::<...>` instead of `<...>` to specify type or const arguments
123+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
124124
|
125125
LL | foo::<BAR - bar::<i32>()>();
126126
| ++
@@ -131,7 +131,7 @@ error: comparison operators cannot be chained
131131
LL | foo<BAR - bar::<i32>()>();
132132
| ^ ^
133133
|
134-
help: use `::<...>` instead of `<...>` to specify type or const arguments
134+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
135135
|
136136
LL | foo::<BAR - bar::<i32>()>();
137137
| ++

‎src/test/ui/did_you_mean/compatible-variants.rs

+8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ enum Hey<A, B> {
33
B(B),
44
}
55

6+
struct Foo {
7+
bar: Option<i32>,
8+
}
9+
610
fn f() {}
711

812
fn a() -> Option<()> {
@@ -40,4 +44,8 @@ fn main() {
4044
let _: Hey<i32, bool> = false;
4145
//~^ ERROR mismatched types
4246
//~| HELP try wrapping
47+
let bar = 1i32;
48+
let _ = Foo { bar };
49+
//~^ ERROR mismatched types
50+
//~| HELP try wrapping
4351
}

‎src/test/ui/did_you_mean/compatible-variants.stderr

+22-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/compatible-variants.rs:9:5
2+
--> $DIR/compatible-variants.rs:13:5
33
|
44
LL | fn a() -> Option<()> {
55
| ---------- expected `Option<()>` because of return type
@@ -21,7 +21,7 @@ LL + Some(())
2121
|
2222

2323
error[E0308]: mismatched types
24-
--> $DIR/compatible-variants.rs:17:5
24+
--> $DIR/compatible-variants.rs:21:5
2525
|
2626
LL | fn b() -> Result<(), ()> {
2727
| -------------- expected `Result<(), ()>` because of return type
@@ -37,7 +37,7 @@ LL + Ok(())
3737
|
3838

3939
error[E0308]: mismatched types
40-
--> $DIR/compatible-variants.rs:23:25
40+
--> $DIR/compatible-variants.rs:27:25
4141
|
4242
LL | let _: Option<()> = while false {};
4343
| ---------- ^^^^^^^^^^^^^^ expected enum `Option`, found `()`
@@ -52,7 +52,7 @@ LL | let _: Option<()> = Some(while false {});
5252
| +++++ +
5353

5454
error[E0308]: mismatched types
55-
--> $DIR/compatible-variants.rs:27:9
55+
--> $DIR/compatible-variants.rs:31:9
5656
|
5757
LL | while false {}
5858
| ^^^^^^^^^^^^^^ expected enum `Option`, found `()`
@@ -69,7 +69,7 @@ LL + Some(())
6969
|
7070

7171
error[E0308]: mismatched types
72-
--> $DIR/compatible-variants.rs:31:31
72+
--> $DIR/compatible-variants.rs:35:31
7373
|
7474
LL | let _: Result<i32, i32> = 1;
7575
| ---------------- ^ expected enum `Result`, found integer
@@ -86,7 +86,7 @@ LL | let _: Result<i32, i32> = Err(1);
8686
| ++++ +
8787

8888
error[E0308]: mismatched types
89-
--> $DIR/compatible-variants.rs:34:26
89+
--> $DIR/compatible-variants.rs:38:26
9090
|
9191
LL | let _: Option<i32> = 1;
9292
| ----------- ^ expected enum `Option`, found integer
@@ -101,7 +101,7 @@ LL | let _: Option<i32> = Some(1);
101101
| +++++ +
102102

103103
error[E0308]: mismatched types
104-
--> $DIR/compatible-variants.rs:37:28
104+
--> $DIR/compatible-variants.rs:41:28
105105
|
106106
LL | let _: Hey<i32, i32> = 1;
107107
| ------------- ^ expected enum `Hey`, found integer
@@ -118,7 +118,7 @@ LL | let _: Hey<i32, i32> = Hey::B(1);
118118
| +++++++ +
119119

120120
error[E0308]: mismatched types
121-
--> $DIR/compatible-variants.rs:40:29
121+
--> $DIR/compatible-variants.rs:44:29
122122
|
123123
LL | let _: Hey<i32, bool> = false;
124124
| -------------- ^^^^^ expected enum `Hey`, found `bool`
@@ -132,6 +132,19 @@ help: try wrapping the expression in `Hey::B`
132132
LL | let _: Hey<i32, bool> = Hey::B(false);
133133
| +++++++ +
134134

135-
error: aborting due to 8 previous errors
135+
error[E0308]: mismatched types
136+
--> $DIR/compatible-variants.rs:48:19
137+
|
138+
LL | let _ = Foo { bar };
139+
| ^^^ expected enum `Option`, found `i32`
140+
|
141+
= note: expected enum `Option<i32>`
142+
found type `i32`
143+
help: try wrapping the expression in `Some`
144+
|
145+
LL | let _ = Foo { bar: Some(bar) };
146+
| ++++++++++ +
147+
148+
error: aborting due to 9 previous errors
136149

137150
For more information about this error, try `rustc --explain E0308`.

‎src/test/ui/did_you_mean/issue-40396.stderr

+7-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: comparison operators cannot be chained
44
LL | (0..13).collect<Vec<i32>>();
55
| ^ ^
66
|
7-
help: use `::<...>` instead of `<...>` to specify type or const arguments
7+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
88
|
99
LL | (0..13).collect::<Vec<i32>>();
1010
| ++
@@ -15,7 +15,7 @@ error: comparison operators cannot be chained
1515
LL | Vec<i32>::new();
1616
| ^ ^
1717
|
18-
help: use `::<...>` instead of `<...>` to specify type or const arguments
18+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
1919
|
2020
LL | Vec::<i32>::new();
2121
| ++
@@ -26,7 +26,7 @@ error: comparison operators cannot be chained
2626
LL | (0..13).collect<Vec<i32>();
2727
| ^ ^
2828
|
29-
help: use `::<...>` instead of `<...>` to specify type or const arguments
29+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
3030
|
3131
LL | (0..13).collect::<Vec<i32>();
3232
| ++
@@ -37,7 +37,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, fo
3737
LL | let x = std::collections::HashMap<i128, i128>::new();
3838
| ^ expected one of 8 possible tokens
3939
|
40-
help: use `::<...>` instead of `<...>` to specify type or const arguments
40+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
4141
|
4242
LL | let x = std::collections::HashMap::<i128, i128>::new();
4343
| ++
@@ -48,7 +48,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found
4848
LL | std::collections::HashMap<i128, i128>::new()
4949
| ^ expected one of 8 possible tokens
5050
|
51-
help: use `::<...>` instead of `<...>` to specify type or const arguments
51+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
5252
|
5353
LL | std::collections::HashMap::<i128, i128>::new()
5454
| ++
@@ -59,7 +59,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found
5959
LL | std::collections::HashMap<i128, i128>::new();
6060
| ^ expected one of 8 possible tokens
6161
|
62-
help: use `::<...>` instead of `<...>` to specify type or const arguments
62+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
6363
|
6464
LL | std::collections::HashMap::<i128, i128>::new();
6565
| ++
@@ -70,7 +70,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found
7070
LL | std::collections::HashMap<i128, i128>::new(1, 2);
7171
| ^ expected one of 8 possible tokens
7272
|
73-
help: use `::<...>` instead of `<...>` to specify type or const arguments
73+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
7474
|
7575
LL | std::collections::HashMap::<i128, i128>::new(1, 2);
7676
| ++

‎src/test/ui/inference/deref-suggestion.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ LL | let r = R { i };
8787
help: consider dereferencing the borrow
8888
|
8989
LL | let r = R { i: *i };
90-
| ~~~~~
90+
| ++++
9191

9292
error[E0308]: mismatched types
9393
--> $DIR/deref-suggestion.rs:46:20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
fn f<T>() {}
2-
struct X;
3-
41
fn main() {
52
false == false == false;
63
//~^ ERROR comparison operators cannot be chained
@@ -12,15 +9,26 @@ fn main() {
129

1310
f<X>();
1411
//~^ ERROR comparison operators cannot be chained
15-
//~| HELP use `::<...>` instead of `<...>` to specify type or const arguments
12+
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
1613

1714
f<Result<Option<X>, Option<Option<X>>>(1, 2);
1815
//~^ ERROR comparison operators cannot be chained
19-
//~| HELP use `::<...>` instead of `<...>` to specify type or const arguments
16+
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
17+
18+
let _ = f<u8, i8>();
19+
//~^ ERROR expected one of
20+
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
21+
22+
let _ = f<'_, i8>();
23+
//~^ ERROR expected one of
24+
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
25+
26+
f<'_>();
27+
//~^ comparison operators cannot be chained
28+
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
2029

21-
use std::convert::identity;
22-
let _ = identity<u8>;
30+
let _ = f<u8>;
2331
//~^ ERROR comparison operators cannot be chained
24-
//~| HELP use `::<...>` instead of `<...>` to specify type or const arguments
32+
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
2533
//~| HELP or use `(...)` if you meant to specify fn arguments
2634
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: comparison operators cannot be chained
2-
--> $DIR/require-parens-for-chained-comparison.rs:5:11
2+
--> $DIR/require-parens-for-chained-comparison.rs:2:11
33
|
44
LL | false == false == false;
55
| ^^ ^^
@@ -10,7 +10,7 @@ LL | false == false && false == false;
1010
| ++++++++
1111

1212
error: comparison operators cannot be chained
13-
--> $DIR/require-parens-for-chained-comparison.rs:9:11
13+
--> $DIR/require-parens-for-chained-comparison.rs:6:11
1414
|
1515
LL | false == 0 < 2;
1616
| ^^ ^
@@ -21,35 +21,68 @@ LL | false == (0 < 2);
2121
| + +
2222

2323
error: comparison operators cannot be chained
24-
--> $DIR/require-parens-for-chained-comparison.rs:13:6
24+
--> $DIR/require-parens-for-chained-comparison.rs:10:6
2525
|
2626
LL | f<X>();
2727
| ^ ^
2828
|
29-
help: use `::<...>` instead of `<...>` to specify type or const arguments
29+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
3030
|
3131
LL | f::<X>();
3232
| ++
3333

3434
error: comparison operators cannot be chained
35-
--> $DIR/require-parens-for-chained-comparison.rs:17:6
35+
--> $DIR/require-parens-for-chained-comparison.rs:14:6
3636
|
3737
LL | f<Result<Option<X>, Option<Option<X>>>(1, 2);
3838
| ^ ^
3939
|
40-
help: use `::<...>` instead of `<...>` to specify type or const arguments
40+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
4141
|
4242
LL | f::<Result<Option<X>, Option<Option<X>>>(1, 2);
4343
| ++
4444

45+
error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
46+
--> $DIR/require-parens-for-chained-comparison.rs:18:17
47+
|
48+
LL | let _ = f<u8, i8>();
49+
| ^ expected one of 8 possible tokens
50+
|
51+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
52+
|
53+
LL | let _ = f::<u8, i8>();
54+
| ++
55+
56+
error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, `{`, or an operator, found `,`
57+
--> $DIR/require-parens-for-chained-comparison.rs:22:17
58+
|
59+
LL | let _ = f<'_, i8>();
60+
| ^ expected one of 10 possible tokens
61+
|
62+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
63+
|
64+
LL | let _ = f::<'_, i8>();
65+
| ++
66+
67+
error: comparison operators cannot be chained
68+
--> $DIR/require-parens-for-chained-comparison.rs:26:6
69+
|
70+
LL | f<'_>();
71+
| ^ ^
72+
|
73+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
74+
|
75+
LL | f::<'_>();
76+
| ++
77+
4578
error: comparison operators cannot be chained
46-
--> $DIR/require-parens-for-chained-comparison.rs:22:21
79+
--> $DIR/require-parens-for-chained-comparison.rs:30:14
4780
|
48-
LL | let _ = identity<u8>;
49-
| ^ ^
81+
LL | let _ = f<u8>;
82+
| ^ ^
5083
|
51-
= help: use `::<...>` instead of `<...>` to specify type or const arguments
84+
= help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
5285
= help: or use `(...)` if you meant to specify fn arguments
5386

54-
error: aborting due to 5 previous errors
87+
error: aborting due to 8 previous errors
5588

‎src/test/ui/suggestions/issue-82566-1.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: comparison operators cannot be chained
44
LL | T1<1>::C;
55
| ^ ^
66
|
7-
help: use `::<...>` instead of `<...>` to specify type or const arguments
7+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
88
|
99
LL | T1::<1>::C;
1010
| ++
@@ -15,7 +15,7 @@ error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
1515
LL | T2<1, 2>::C;
1616
| ^ expected one of `.`, `;`, `?`, `}`, or an operator
1717
|
18-
help: use `::<...>` instead of `<...>` to specify type or const arguments
18+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
1919
|
2020
LL | T2::<1, 2>::C;
2121
| ++
@@ -26,7 +26,7 @@ error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
2626
LL | T3<1, 2, 3>::C;
2727
| ^ expected one of `.`, `;`, `?`, `}`, or an operator
2828
|
29-
help: use `::<...>` instead of `<...>` to specify type or const arguments
29+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
3030
|
3131
LL | T3::<1, 2, 3>::C;
3232
| ++

‎src/test/ui/suggestions/issue-82566-2.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: comparison operators cannot be chained
44
LL | fn foo1() -> [(); Foo1<10>::SUM] {
55
| ^ ^
66
|
7-
help: use `::<...>` instead of `<...>` to specify type or const arguments
7+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
88
|
99
LL | fn foo1() -> [(); Foo1::<10>::SUM] {
1010
| ++
@@ -15,7 +15,7 @@ error: expected one of `.`, `?`, `]`, or an operator, found `,`
1515
LL | fn foo2() -> [(); Foo2<10, 20>::SUM] {
1616
| ^ expected one of `.`, `?`, `]`, or an operator
1717
|
18-
help: use `::<...>` instead of `<...>` to specify type or const arguments
18+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
1919
|
2020
LL | fn foo2() -> [(); Foo2::<10, 20>::SUM] {
2121
| ++
@@ -26,7 +26,7 @@ error: expected one of `.`, `?`, `]`, or an operator, found `,`
2626
LL | fn foo3() -> [(); Foo3<10, 20, 30>::SUM] {
2727
| ^ expected one of `.`, `?`, `]`, or an operator
2828
|
29-
help: use `::<...>` instead of `<...>` to specify type or const arguments
29+
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
3030
|
3131
LL | fn foo3() -> [(); Foo3::<10, 20, 30>::SUM] {
3232
| ++

0 commit comments

Comments
 (0)
Please sign in to comment.