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
This commit is contained in:
bors 2022-01-17 05:46:53 +00:00
commit 128417f40f
29 changed files with 416 additions and 253 deletions

View File

@ -4443,6 +4443,7 @@ version = "0.0.0"
dependencies = [
"arrayvec",
"askama",
"atty",
"expect-test",
"itertools 0.9.0",
"minifier",

View File

@ -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 @@ fn default() -> Self {
}
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()
}

View File

@ -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 @@ fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params:
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<T, F, G>(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G)

View File

@ -170,7 +170,7 @@ pub fn new_from_input(
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<F>(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()
}

View File

@ -27,7 +27,7 @@
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 @@ pub(super) fn check_mistyped_turbofish_with_multiple_type_params(
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();
}
}
}
}

View File

@ -1443,7 +1443,7 @@ fn parse_labeled_expr(
&mut self,
label: Label,
attrs: AttrVec,
consume_colon: bool,
mut consume_colon: bool,
) -> PResult<'a, P<Expr>> {
let lo = label.ident.span;
let label = Some(label);
@ -1456,6 +1456,12 @@ fn parse_labeled_expr(
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();

View File

@ -13,7 +13,7 @@
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 @@ pub fn demand_eqtype_with_origin(
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 @@ pub fn demand_coerce(
/// 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 @@ fn suggest_compatible_variants(
})
.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 @@ fn can_use_as_ref(&self, expr: &hir::Expr<'_>) -> Option<(Span, &'static str, St
}
}
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<Symbol> {
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 @@ fn can_use_as_ref(&self, expr: &hir::Expr<'_>) -> Option<(Span, &'static str, St
/// `&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 @@ pub fn check_ref(
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 @@ pub fn check_ref(
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 @@ pub fn check_ref(
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 @@ pub fn check_ref(
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,
));
}
}
}

View File

@ -208,7 +208,7 @@ fn suggest_fn_call(
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 @@ pub fn suggest_deref_ref_or_into(
}
} 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) {

View File

@ -1372,9 +1372,12 @@ fn assert_failed(index: usize, len: usize) -> ! {
///
/// 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 @@ pub fn push(&mut self, value: T) {
/// 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
///
/// ```

View File

@ -661,20 +661,37 @@ fn clone_from(&mut self, other: &Self) {
///
/// ## 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 @@ fn partial_cmp(&self, other: &Ordering) -> Option<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 @@ fn partial_cmp(&self, other: &Ordering) -> Option<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);

View File

@ -1893,7 +1893,7 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
pub fn nontemporal_store<T>(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<T>(ptr: *const T, base: *const T) -> isize;
/// See documentation of `<*const T>::guaranteed_eq` for details.

View File

@ -439,7 +439,7 @@ pub const fn wrapping_offset(self, count: isize) -> *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

View File

@ -617,7 +617,7 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
/// }
/// ```
#[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

View File

@ -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"

View File

@ -1736,7 +1736,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
{
write!(
buffer,
"<h2 class=\"location\">{}{}</h2>",
"<h2 class=\"location\"><a href=\"#\">{}{}</a></h2>",
match *it.kind {
clean::StructItem(..) => "Struct ",
clean::TraitItem(..) => "Trait ",

View File

@ -670,7 +670,11 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
}
write!(w, "<div id=\"{}\" class=\"method has-srclink\">", id);
write!(w, "<div class=\"rightside\">");
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, "</div>");
write!(w, "<h4 class=\"code-header\">");
@ -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 {

View File

@ -71,7 +71,8 @@
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(),
"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),
),
Err(VarError::NotUnicode(value)) => early_error(
ErrorOutputType::default(),
&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");

View File

@ -436,8 +436,7 @@ fn variant_field<'path>(
}
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 @@ fn resolve_associated_item(
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

View File

@ -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"

View File

@ -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() {}
}

View File

@ -4,7 +4,7 @@ error: comparison operators cannot be chained
LL | foo<BAR + 3>();
| ^ ^
|
help: use `::<...>` instead of `<...>` to specify type or const arguments
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
LL | foo::<BAR + 3>();
| ++
@ -15,7 +15,7 @@ error: comparison operators cannot be chained
LL | foo<BAR + 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 + BAR>();
| ++
@ -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<BAR - 3>();
| ^ ^
|
help: use `::<...>` instead of `<...>` to specify type or const arguments
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
LL | foo::<BAR - 3>();
| ++
@ -48,7 +48,7 @@ error: comparison operators cannot be chained
LL | foo<BAR - 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 - BAR>();
| ++
@ -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<bar<i32>()>();
| ^ ^
|
help: use `::<...>` instead of `<...>` to specify type or const arguments
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
LL | foo::<bar<i32>()>();
| ++
@ -87,7 +87,7 @@ error: comparison operators cannot be chained
LL | foo<bar::<i32>()>();
| ^ ^
|
help: use `::<...>` instead of `<...>` to specify type or const arguments
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
LL | foo::<bar::<i32>()>();
| ++
@ -98,7 +98,7 @@ error: comparison operators cannot be chained
LL | foo<bar::<i32>() + 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::<i32>() + BAR>();
| ++
@ -109,7 +109,7 @@ error: comparison operators cannot be chained
LL | foo<bar::<i32>() - 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::<i32>() - BAR>();
| ++
@ -120,7 +120,7 @@ error: comparison operators cannot be chained
LL | foo<BAR - bar::<i32>()>();
| ^ ^
|
help: use `::<...>` instead of `<...>` to specify type or const arguments
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
LL | foo::<BAR - bar::<i32>()>();
| ++
@ -131,7 +131,7 @@ error: comparison operators cannot be chained
LL | foo<BAR - bar::<i32>()>();
| ^ ^
|
help: use `::<...>` instead of `<...>` to specify type or const arguments
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
LL | foo::<BAR - bar::<i32>()>();
| ++

View File

@ -3,6 +3,10 @@ enum Hey<A, B> {
B(B),
}
struct Foo {
bar: Option<i32>,
}
fn f() {}
fn a() -> Option<()> {
@ -40,4 +44,8 @@ fn main() {
let _: Hey<i32, bool> = false;
//~^ ERROR mismatched types
//~| HELP try wrapping
let bar = 1i32;
let _ = Foo { bar };
//~^ ERROR mismatched types
//~| HELP try wrapping
}

View File

@ -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<i32, i32> = 1;
| ---------------- ^ expected enum `Result`, found integer
@ -86,7 +86,7 @@ LL | let _: Result<i32, i32> = Err(1);
| ++++ +
error[E0308]: mismatched types
--> $DIR/compatible-variants.rs:34:26
--> $DIR/compatible-variants.rs:38:26
|
LL | let _: Option<i32> = 1;
| ----------- ^ expected enum `Option`, found integer
@ -101,7 +101,7 @@ LL | let _: Option<i32> = Some(1);
| +++++ +
error[E0308]: mismatched types
--> $DIR/compatible-variants.rs:37:28
--> $DIR/compatible-variants.rs:41:28
|
LL | let _: Hey<i32, i32> = 1;
| ------------- ^ expected enum `Hey`, found integer
@ -118,7 +118,7 @@ LL | let _: Hey<i32, i32> = Hey::B(1);
| +++++++ +
error[E0308]: mismatched types
--> $DIR/compatible-variants.rs:40:29
--> $DIR/compatible-variants.rs:44:29
|
LL | let _: Hey<i32, bool> = false;
| -------------- ^^^^^ expected enum `Hey`, found `bool`
@ -132,6 +132,19 @@ help: try wrapping the expression in `Hey::B`
LL | let _: Hey<i32, bool> = 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<i32>`
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`.

View File

@ -4,7 +4,7 @@ error: comparison operators cannot be chained
LL | (0..13).collect<Vec<i32>>();
| ^ ^
|
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::<Vec<i32>>();
| ++
@ -15,7 +15,7 @@ error: comparison operators cannot be chained
LL | Vec<i32>::new();
| ^ ^
|
help: use `::<...>` instead of `<...>` to specify type or const arguments
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
LL | Vec::<i32>::new();
| ++
@ -26,7 +26,7 @@ error: comparison operators cannot be chained
LL | (0..13).collect<Vec<i32>();
| ^ ^
|
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::<Vec<i32>();
| ++
@ -37,7 +37,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, fo
LL | let x = std::collections::HashMap<i128, i128>::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::<i128, i128>::new();
| ++
@ -48,7 +48,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found
LL | std::collections::HashMap<i128, i128>::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::<i128, i128>::new()
| ++
@ -59,7 +59,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found
LL | std::collections::HashMap<i128, i128>::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::<i128, i128>::new();
| ++
@ -70,7 +70,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found
LL | std::collections::HashMap<i128, i128>::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::<i128, i128>::new(1, 2);
| ++

View File

@ -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

View File

@ -1,6 +1,3 @@
fn f<T>() {}
struct X;
fn main() {
false == false == false;
//~^ ERROR comparison operators cannot be chained
@ -12,15 +9,26 @@ fn main() {
f<X>();
//~^ 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<Result<Option<X>, Option<Option<X>>>(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
use std::convert::identity;
let _ = identity<u8>;
let _ = f<u8, i8>();
//~^ 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
let _ = f<u8>;
//~^ 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
}

View File

@ -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<X>();
| ^ ^
|
help: use `::<...>` instead of `<...>` to specify type or const arguments
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
LL | f::<X>();
| ++
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<Result<Option<X>, Option<Option<X>>>(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::<Result<Option<X>, Option<Option<X>>>(1, 2);
| ++
error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
--> $DIR/require-parens-for-chained-comparison.rs:18:17
|
LL | let _ = f<u8, i8>();
| ^ expected one of 8 possible tokens
|
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
LL | let _ = f::<u8, i8>();
| ++
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:22:21
--> $DIR/require-parens-for-chained-comparison.rs:26:6
|
LL | let _ = identity<u8>;
| ^ ^
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:30:14
|
LL | let _ = f<u8>;
| ^ ^
|
= 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

View File

@ -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;
| ++

View File

@ -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] {
| ++