1
Fork 0

Auto merge of #78270 - JohnTitor:rollup-bldrjh5, r=JohnTitor

Rollup of 17 pull requests

Successful merges:

 - #77268 (Link to "Contributing to Rust" rather than "Getting Started".)
 - #77339 (Implement TryFrom between NonZero types.)
 - #77488 (Mark `repr128` as `incomplete_features`)
 - #77890 (Fixing escaping to ensure generation of welformed json.)
 - #77918 (Cleanup network tests)
 - #77920 (Avoid extraneous space between visibility kw and ident for statics)
 - #77969 (Doc formating consistency between slice sort and sort_unstable, and big O notation consistency)
 - #78098 (Clean up and improve some docs)
 - #78116 (Make inline const work in range patterns)
 - #78153 (Sync LLVM submodule if it has been initialized)
 - #78163 (Clean up lib docs)
 - #78169 (Update cargo)
 - #78231 (Make closures inherit the parent function's target features)
 - #78235 (Explain where the closure return type was inferred)
 - #78255 (Reduce diagram mess in 'match arms have incompatible types' error)
 - #78263 (Add regression test of issue-77668)
 - #78265 (Add some inference-related regression tests about incorrect diagnostics)

Failed merges:

r? `@ghost`
This commit is contained in:
bors 2020-10-23 09:31:44 +00:00
commit 07a63e6d1f
53 changed files with 523 additions and 111 deletions

View file

@ -2,14 +2,14 @@
Thank you for your interest in contributing to Rust! Thank you for your interest in contributing to Rust!
To get started, read the [Getting Started] guide in the [rustc-dev-guide]. To get started, read the [Contributing to Rust] chapter of the [rustc-dev-guide].
## Bug reports ## Bug reports
Did a compiler error message tell you to come here? If you want to create an ICE report, Did a compiler error message tell you to come here? If you want to create an ICE report,
refer to [this section][contributing-bug-reports] and [open an issue][issue template]. refer to [this section][contributing-bug-reports] and [open an issue][issue template].
[Getting Started]: https://rustc-dev-guide.rust-lang.org/getting-started.html [Contributing to Rust]: https://rustc-dev-guide.rust-lang.org/contributing.html#contributing-to-rust
[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/
[contributing-bug-reports]: https://rustc-dev-guide.rust-lang.org/contributing.html#bug-reports [contributing-bug-reports]: https://rustc-dev-guide.rust-lang.org/contributing.html#bug-reports
[issue template]: https://github.com/rust-lang/rust/issues/new/choose [issue template]: https://github.com/rust-lang/rust/issues/new/choose

View file

@ -310,7 +310,7 @@ dependencies = [
"crypto-hash", "crypto-hash",
"curl", "curl",
"curl-sys", "curl-sys",
"env_logger 0.7.1", "env_logger 0.8.1",
"filetime", "filetime",
"flate2", "flate2",
"fwdansi", "fwdansi",
@ -1035,6 +1035,19 @@ dependencies = [
"termcolor", "termcolor",
] ]
[[package]]
name = "env_logger"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54532e3223c5af90a6a757c90b5c5521564b07e5e7a958681bcd2afad421cdcd"
dependencies = [
"atty",
"humantime 2.0.1",
"log",
"regex",
"termcolor",
]
[[package]] [[package]]
name = "error_index_generator" name = "error_index_generator"
version = "0.0.0" version = "0.0.0"

View file

@ -622,6 +622,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
sym::lazy_normalization_consts, sym::lazy_normalization_consts,
sym::specialization, sym::specialization,
sym::inline_const, sym::inline_const,
sym::repr128,
]; ];
/// Some features are not allowed to be used together at the same time, if /// Some features are not allowed to be used together at the same time, if

View file

@ -619,6 +619,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
scrut_hir_id, scrut_hir_id,
opt_suggest_box_span, opt_suggest_box_span,
arm_span, arm_span,
scrut_span,
.. ..
}) => match source { }) => match source {
hir::MatchSource::IfLetDesugar { .. } => { hir::MatchSource::IfLetDesugar { .. } => {
@ -664,18 +665,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
Some(ty::error::ExpectedFound { expected, .. }) => expected, Some(ty::error::ExpectedFound { expected, .. }) => expected,
_ => last_ty, _ => last_ty,
}); });
let msg = "`match` arms have incompatible types"; let source_map = self.tcx.sess.source_map();
err.span_label(cause.span, msg); let mut any_multiline_arm = source_map.is_multiline(arm_span);
if prior_arms.len() <= 4 { if prior_arms.len() <= 4 {
for sp in prior_arms { for sp in prior_arms {
any_multiline_arm |= source_map.is_multiline(*sp);
err.span_label(*sp, format!("this is found to be of type `{}`", t)); err.span_label(*sp, format!("this is found to be of type `{}`", t));
} }
} else if let Some(sp) = prior_arms.last() { } else if let Some(sp) = prior_arms.last() {
any_multiline_arm |= source_map.is_multiline(*sp);
err.span_label( err.span_label(
*sp, *sp,
format!("this and all prior arms are found to be of type `{}`", t), format!("this and all prior arms are found to be of type `{}`", t),
); );
} }
let outer_error_span = if any_multiline_arm {
// Cover just `match` and the scrutinee expression, not
// the entire match body, to reduce diagram noise.
cause.span.shrink_to_lo().to(scrut_span)
} else {
cause.span
};
let msg = "`match` arms have incompatible types";
err.span_label(outer_error_span, msg);
if let Some(sp) = semi_span { if let Some(sp) = semi_span {
err.span_suggestion_short( err.span_suggestion_short(
sp, sp,

View file

@ -292,20 +292,20 @@ pub struct ScopeTree {
/// ///
/// Then: /// Then:
/// ///
/// 1. From the ordering guarantee of HIR visitors (see /// 1. From the ordering guarantee of HIR visitors (see
/// `rustc_hir::intravisit`), `D` does not dominate `U`. /// `rustc_hir::intravisit`), `D` does not dominate `U`.
/// ///
/// 2. Therefore, `D` is *potentially* storage-dead at `U` (because /// 2. Therefore, `D` is *potentially* storage-dead at `U` (because
/// we might visit `U` without ever getting to `D`). /// we might visit `U` without ever getting to `D`).
/// ///
/// 3. However, we guarantee that at each HIR point, each /// 3. However, we guarantee that at each HIR point, each
/// binding/temporary is always either always storage-live /// binding/temporary is always either always storage-live
/// or always storage-dead. This is what is being guaranteed /// or always storage-dead. This is what is being guaranteed
/// by `terminating_scopes` including all blocks where the /// by `terminating_scopes` including all blocks where the
/// count of executions is not guaranteed. /// count of executions is not guaranteed.
/// ///
/// 4. By `2.` and `3.`, `D` is *statically* storage-dead at `U`, /// 4. By `2.` and `3.`, `D` is *statically* storage-dead at `U`,
/// QED. /// QED.
/// ///
/// This property ought to not on (3) in an essential way -- it /// This property ought to not on (3) in an essential way -- it
/// is probably still correct even if we have "unrestricted" terminating /// is probably still correct even if we have "unrestricted" terminating

View file

@ -343,6 +343,7 @@ static_assert_size!(ObligationCauseCode<'_>, 32);
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
pub struct MatchExpressionArmCause<'tcx> { pub struct MatchExpressionArmCause<'tcx> {
pub arm_span: Span, pub arm_span: Span,
pub scrut_span: Span,
pub semi_span: Option<Span>, pub semi_span: Option<Span>,
pub source: hir::MatchSource, pub source: hir::MatchSource,
pub prior_arms: Vec<Span>, pub prior_arms: Vec<Span>,

View file

@ -78,20 +78,26 @@
//! new pattern `p`. //! new pattern `p`.
//! //!
//! For example, say we have the following: //! For example, say we have the following:
//!
//! ``` //! ```
//! // x: (Option<bool>, Result<()>) //! // x: (Option<bool>, Result<()>)
//! match x { //! match x {
//! (Some(true), _) => {} //! (Some(true), _) => {}
//! (None, Err(())) => {} //! (None, Err(())) => {}
//! (None, Err(_)) => {} //! (None, Err(_)) => {}
//! } //! }
//! ``` //! ```
//!
//! Here, the matrix `P` starts as: //! Here, the matrix `P` starts as:
//!
//! ```
//! [ //! [
//! [(Some(true), _)], //! [(Some(true), _)],
//! [(None, Err(()))], //! [(None, Err(()))],
//! [(None, Err(_))], //! [(None, Err(_))],
//! ] //! ]
//! ```
//!
//! We can tell it's not exhaustive, because `U(P, _)` is true (we're not covering //! We can tell it's not exhaustive, because `U(P, _)` is true (we're not covering
//! `[(Some(false), _)]`, for instance). In addition, row 3 is not useful, because //! `[(Some(false), _)]`, for instance). In addition, row 3 is not useful, because
//! all the values it covers are already covered by row 2. //! all the values it covers are already covered by row 2.
@ -178,10 +184,14 @@
//! This special case is handled in `is_useful_specialized`. //! This special case is handled in `is_useful_specialized`.
//! //!
//! For example, if `P` is: //! For example, if `P` is:
//!
//! ```
//! [ //! [
//! [Some(true), _], //! [Some(true), _],
//! [None, 0], //! [None, 0],
//! ] //! ]
//! ```
//!
//! and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only //! and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only
//! matches values that row 2 doesn't. For row 1 however, we need to dig into the //! matches values that row 2 doesn't. For row 1 however, we need to dig into the
//! arguments of `Some` to know whether some new value is covered. So we compute //! arguments of `Some` to know whether some new value is covered. So we compute
@ -198,10 +208,14 @@
//! `U(P, p) := U(D(P), D(p))` //! `U(P, p) := U(D(P), D(p))`
//! //!
//! For example, if `P` is: //! For example, if `P` is:
//!
//! ```
//! [ //! [
//! [_, true, _], //! [_, true, _],
//! [None, false, 1], //! [None, false, 1],
//! ] //! ]
//! ```
//!
//! and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we //! and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we
//! only had row 2, we'd know that `p` is useful. However row 1 starts with a //! only had row 2, we'd know that `p` is useful. However row 1 starts with a
//! wildcard, so we need to check whether `U([[true, _]], [false, 1])`. //! wildcard, so we need to check whether `U([[true, _]], [false, 1])`.
@ -215,10 +229,14 @@
//! `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))` //! `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))`
//! //!
//! For example, if `P` is: //! For example, if `P` is:
//!
//! ```
//! [ //! [
//! [Some(true), _], //! [Some(true), _],
//! [None, false], //! [None, false],
//! ] //! ]
//! ```
//!
//! and `p` is [_, false], both `None` and `Some` constructors appear in the first //! and `p` is [_, false], both `None` and `Some` constructors appear in the first
//! components of `P`. We will therefore try popping both constructors in turn: we //! components of `P`. We will therefore try popping both constructors in turn: we
//! compute `U([[true, _]], [_, false])` for the `Some` constructor, and `U([[false]], //! compute `U([[true, _]], [_, false])` for the `Some` constructor, and `U([[false]],
@ -1496,6 +1514,7 @@ struct PatCtxt<'tcx> {
/// multiple patterns. /// multiple patterns.
/// ///
/// For example, if we are constructing a witness for the match against /// For example, if we are constructing a witness for the match against
///
/// ``` /// ```
/// struct Pair(Option<(u32, u32)>, bool); /// struct Pair(Option<(u32, u32)>, bool);
/// ///
@ -1619,12 +1638,14 @@ fn all_constructors<'a, 'tcx>(
// actually match against them all themselves. So we always return only the fictitious // actually match against them all themselves. So we always return only the fictitious
// constructor. // constructor.
// E.g., in an example like: // E.g., in an example like:
//
// ``` // ```
// let err: io::ErrorKind = ...; // let err: io::ErrorKind = ...;
// match err { // match err {
// io::ErrorKind::NotFound => {}, // io::ErrorKind::NotFound => {},
// } // }
// ``` // ```
//
// we don't want to show every possible IO error, but instead have only `_` as the // we don't want to show every possible IO error, but instead have only `_` as the
// witness. // witness.
let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty); let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty);
@ -2017,6 +2038,7 @@ crate fn is_useful<'p, 'tcx>(
let mut unreachable_branches = Vec::new(); let mut unreachable_branches = Vec::new();
// Subpatterns that are unreachable from all branches. E.g. in the following case, the last // Subpatterns that are unreachable from all branches. E.g. in the following case, the last
// `true` is unreachable only from one branch, so it is overall reachable. // `true` is unreachable only from one branch, so it is overall reachable.
//
// ``` // ```
// match (true, true) { // match (true, true) {
// (true, true) => {} // (true, true) => {}
@ -2161,10 +2183,12 @@ crate fn is_useful<'p, 'tcx>(
// to do this and instead report a single `_` witness: // to do this and instead report a single `_` witness:
// if the user didn't actually specify a constructor // if the user didn't actually specify a constructor
// in this arm, e.g., in // in this arm, e.g., in
//
// ``` // ```
// let x: (Direction, Direction, bool) = ...; // let x: (Direction, Direction, bool) = ...;
// let (_, _, false) = x; // let (_, _, false) = x;
// ``` // ```
//
// we don't want to show all 16 possible witnesses // we don't want to show all 16 possible witnesses
// `(<direction-1>, <direction-2>, true)` - we are // `(<direction-1>, <direction-2>, true)` - we are
// satisfied with `(_, _, true)`. In this case, // satisfied with `(_, _, true)`. In this case,

View file

@ -1062,8 +1062,8 @@ impl<'a> Parser<'a> {
}) })
} else if self.eat_keyword(kw::Unsafe) { } else if self.eat_keyword(kw::Unsafe) {
self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs) self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs)
} else if self.check_inline_const() { } else if self.check_inline_const(0) {
self.parse_const_expr(lo.to(self.token.span)) self.parse_const_block(lo.to(self.token.span))
} else if self.is_do_catch_block() { } else if self.is_do_catch_block() {
self.recover_do_catch(attrs) self.recover_do_catch(attrs)
} else if self.is_try_block() { } else if self.is_try_block() {

View file

@ -522,9 +522,9 @@ impl<'a> Parser<'a> {
self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const) self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const)
} }
fn check_inline_const(&mut self) -> bool { fn check_inline_const(&self, dist: usize) -> bool {
self.check_keyword(kw::Const) self.is_keyword_ahead(dist, &[kw::Const])
&& self.look_ahead(1, |t| match t.kind { && self.look_ahead(dist + 1, |t| match t.kind {
token::Interpolated(ref nt) => matches!(**nt, token::NtBlock(..)), token::Interpolated(ref nt) => matches!(**nt, token::NtBlock(..)),
token::OpenDelim(DelimToken::Brace) => true, token::OpenDelim(DelimToken::Brace) => true,
_ => false, _ => false,
@ -864,7 +864,7 @@ impl<'a> Parser<'a> {
} }
/// Parses inline const expressions. /// Parses inline const expressions.
fn parse_const_expr(&mut self, span: Span) -> PResult<'a, P<Expr>> { fn parse_const_block(&mut self, span: Span) -> PResult<'a, P<Expr>> {
self.sess.gated_spans.gate(sym::inline_const, span); self.sess.gated_spans.gate(sym::inline_const, span);
self.eat_keyword(kw::Const); self.eat_keyword(kw::Const);
let blk = self.parse_block()?; let blk = self.parse_block()?;

View file

@ -313,9 +313,15 @@ impl<'a> Parser<'a> {
let pat = self.parse_pat_with_range_pat(false, None)?; let pat = self.parse_pat_with_range_pat(false, None)?;
self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_token.span)); self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_token.span));
PatKind::Box(pat) PatKind::Box(pat)
} else if self.check_inline_const() { } else if self.check_inline_const(0) {
// Parse `const pat` // Parse `const pat`
PatKind::Lit(self.parse_const_expr(lo.to(self.token.span))?) let const_expr = self.parse_const_block(lo.to(self.token.span))?;
if let Some(re) = self.parse_range_end() {
self.parse_pat_range_begin_with(const_expr, re)?
} else {
PatKind::Lit(const_expr)
}
} else if self.can_be_ident_pat() { } else if self.can_be_ident_pat() {
// Parse `ident @ pat` // Parse `ident @ pat`
// This can give false positives and parse nullary enums, // This can give false positives and parse nullary enums,
@ -717,16 +723,19 @@ impl<'a> Parser<'a> {
/// Is the token `dist` away from the current suitable as the start of a range patterns end? /// Is the token `dist` away from the current suitable as the start of a range patterns end?
fn is_pat_range_end_start(&self, dist: usize) -> bool { fn is_pat_range_end_start(&self, dist: usize) -> bool {
self.look_ahead(dist, |t| { self.check_inline_const(dist)
t.is_path_start() // e.g. `MY_CONST`; || self.look_ahead(dist, |t| {
t.is_path_start() // e.g. `MY_CONST`;
|| t.kind == token::Dot // e.g. `.5` for recovery; || t.kind == token::Dot // e.g. `.5` for recovery;
|| t.can_begin_literal_maybe_minus() // e.g. `42`. || t.can_begin_literal_maybe_minus() // e.g. `42`.
|| t.is_whole_expr() || t.is_whole_expr()
}) })
} }
fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> { fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
if self.check_path() { if self.check_inline_const(0) {
self.parse_const_block(self.token.span)
} else if self.check_path() {
let lo = self.token.span; let lo = self.token.span;
let (qself, path) = if self.eat_lt() { let (qself, path) = if self.eat_lt() {
// Parse a qualified path // Parse a qualified path

View file

@ -201,6 +201,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr.span, expr.span,
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
arm_span, arm_span,
scrut_span: scrut.span,
semi_span, semi_span,
source: match_src, source: match_src,
prior_arms: other_arms.clone(), prior_arms: other_arms.clone(),

View file

@ -1475,6 +1475,28 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.borrow().as_ref(), fn_output) { if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.borrow().as_ref(), fn_output) {
self.add_impl_trait_explanation(&mut err, cause, fcx, expected, *sp, fn_output); self.add_impl_trait_explanation(&mut err, cause, fcx, expected, *sp, fn_output);
} }
if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
// If the closure has an explicit return type annotation,
// then a type error may occur at the first return expression we
// see in the closure (if it conflicts with the declared
// return type). Skip adding a note in this case, since it
// would be incorrect.
if !err.span.primary_spans().iter().any(|span| span == sp) {
let hir = fcx.tcx.hir();
let body_owner = hir.body_owned_by(hir.enclosing_body_owner(fcx.body_id));
if fcx.tcx.is_closure(hir.body_owner_def_id(body_owner).to_def_id()) {
err.span_note(
*sp,
&format!(
"return type inferred to be `{}` here",
fcx.resolve_vars_if_possible(&expected)
),
);
}
}
}
err err
} }

View file

@ -40,7 +40,7 @@ use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::Discr; use rustc_middle::ty::util::Discr;
use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt}; use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt};
use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness}; use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness};
use rustc_session::config::SanitizerSet; use rustc_session::config::SanitizerSet;
use rustc_session::lint; use rustc_session::lint;
@ -2786,6 +2786,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
} }
}); });
// #73631: closures inherit `#[target_feature]` annotations
if tcx.features().target_feature_11 && tcx.is_closure(id) {
let owner_id = tcx.parent(id).expect("closure should have a parent");
codegen_fn_attrs
.target_features
.extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied())
}
// If a function uses #[target_feature] it can't be inlined into general // If a function uses #[target_feature] it can't be inlined into general
// purpose functions as they wouldn't have the right target features // purpose functions as they wouldn't have the right target features
// enabled. For that reason we also forbid #[inline(always)] as it can't be // enabled. For that reason we also forbid #[inline(always)] as it can't be

View file

@ -259,7 +259,7 @@ impl<T, A: AllocRef> RawVec<T, A> {
/// Ensures that the buffer contains at least enough space to hold `len + /// Ensures that the buffer contains at least enough space to hold `len +
/// additional` elements. If it doesn't already have enough capacity, will /// additional` elements. If it doesn't already have enough capacity, will
/// reallocate enough space plus comfortable slack space to get amortized /// reallocate enough space plus comfortable slack space to get amortized
/// `O(1)` behavior. Will limit this behavior if it would needlessly cause /// *O*(1) behavior. Will limit this behavior if it would needlessly cause
/// itself to panic. /// itself to panic.
/// ///
/// If `len` exceeds `self.capacity()`, this may fail to actually allocate /// If `len` exceeds `self.capacity()`, this may fail to actually allocate

View file

@ -167,7 +167,7 @@ mod hack {
impl<T> [T] { impl<T> [T] {
/// Sorts the slice. /// Sorts the slice.
/// ///
/// This sort is stable (i.e., does not reorder equal elements) and `O(n * log(n))` worst-case. /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*)) worst-case.
/// ///
/// When applicable, unstable sorting is preferred because it is generally faster than stable /// When applicable, unstable sorting is preferred because it is generally faster than stable
/// sorting and it doesn't allocate auxiliary memory. /// sorting and it doesn't allocate auxiliary memory.
@ -202,7 +202,7 @@ impl<T> [T] {
/// Sorts the slice with a comparator function. /// Sorts the slice with a comparator function.
/// ///
/// This sort is stable (i.e., does not reorder equal elements) and `O(n * log(n))` worst-case. /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*)) worst-case.
/// ///
/// The comparator function must define a total ordering for the elements in the slice. If /// The comparator function must define a total ordering for the elements in the slice. If
/// the ordering is not total, the order of the elements is unspecified. An order is a /// the ordering is not total, the order of the elements is unspecified. An order is a
@ -256,8 +256,8 @@ impl<T> [T] {
/// Sorts the slice with a key extraction function. /// Sorts the slice with a key extraction function.
/// ///
/// This sort is stable (i.e., does not reorder equal elements) and `O(m * n * log(n))` /// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* \* log(*n*))
/// worst-case, where the key function is `O(m)`. /// worst-case, where the key function is *O*(*m*).
/// ///
/// For expensive key functions (e.g. functions that are not simple property accesses or /// For expensive key functions (e.g. functions that are not simple property accesses or
/// basic operations), [`sort_by_cached_key`](#method.sort_by_cached_key) is likely to be /// basic operations), [`sort_by_cached_key`](#method.sort_by_cached_key) is likely to be
@ -299,8 +299,8 @@ impl<T> [T] {
/// ///
/// During sorting, the key function is called only once per element. /// During sorting, the key function is called only once per element.
/// ///
/// This sort is stable (i.e., does not reorder equal elements) and `O(m * n + n * log(n))` /// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* + *n* \* log(*n*))
/// worst-case, where the key function is `O(m)`. /// worst-case, where the key function is *O*(*m*).
/// ///
/// For simple key functions (e.g., functions that are property accesses or /// For simple key functions (e.g., functions that are property accesses or
/// basic operations), [`sort_by_key`](#method.sort_by_key) is likely to be /// basic operations), [`sort_by_key`](#method.sort_by_key) is likely to be
@ -944,7 +944,7 @@ where
/// 1. for every `i` in `1..runs.len()`: `runs[i - 1].len > runs[i].len` /// 1. for every `i` in `1..runs.len()`: `runs[i - 1].len > runs[i].len`
/// 2. for every `i` in `2..runs.len()`: `runs[i - 2].len > runs[i - 1].len + runs[i].len` /// 2. for every `i` in `2..runs.len()`: `runs[i - 2].len > runs[i - 1].len + runs[i].len`
/// ///
/// The invariants ensure that the total running time is `O(n * log(n))` worst-case. /// The invariants ensure that the total running time is *O*(*n* \* log(*n*)) worst-case.
fn merge_sort<T, F>(v: &mut [T], mut is_less: F) fn merge_sort<T, F>(v: &mut [T], mut is_less: F)
where where
F: FnMut(&T, &T) -> bool, F: FnMut(&T, &T) -> bool,

View file

@ -1,8 +1,8 @@
//! A UTF-8 encoded, growable string. //! A UTF-8encoded, growable string.
//! //!
//! This module contains the [`String`] type, a trait for converting //! This module contains the [`String`] type, the [`ToString`] trait for
//! [`ToString`]s, and several error types that may result from working with //! converting to strings, and several error types that may result from
//! [`String`]s. //! working with [`String`]s.
//! //!
//! # Examples //! # Examples
//! //!
@ -57,7 +57,7 @@ use crate::collections::TryReserveError;
use crate::str::{self, from_boxed_utf8_unchecked, Chars, FromStr, Utf8Error}; use crate::str::{self, from_boxed_utf8_unchecked, Chars, FromStr, Utf8Error};
use crate::vec::Vec; use crate::vec::Vec;
/// A UTF-8 encoded, growable string. /// A UTF-8encoded, growable string.
/// ///
/// The `String` type is the most common string type that has ownership over the /// The `String` type is the most common string type that has ownership over the
/// contents of the string. It has a close relationship with its borrowed /// contents of the string. It has a close relationship with its borrowed
@ -565,7 +565,7 @@ impl String {
Cow::Owned(res) Cow::Owned(res)
} }
/// Decode a UTF-16 encoded vector `v` into a `String`, returning [`Err`] /// Decode a UTF-16encoded vector `v` into a `String`, returning [`Err`]
/// if `v` contains any invalid data. /// if `v` contains any invalid data.
/// ///
/// # Examples /// # Examples
@ -599,7 +599,7 @@ impl String {
Ok(ret) Ok(ret)
} }
/// Decode a UTF-16 encoded slice `v` into a `String`, replacing /// Decode a UTF-16encoded slice `v` into a `String`, replacing
/// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD].
/// ///
/// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`],
@ -2191,8 +2191,9 @@ pub trait ToString {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Display + ?Sized> ToString for T { impl<T: fmt::Display + ?Sized> ToString for T {
// A common guideline is to not inline generic functions. However, // A common guideline is to not inline generic functions. However,
// remove `#[inline]` from this method causes non-negligible regression. // removing `#[inline]` from this method causes non-negligible regressions.
// See <https://github.com/rust-lang/rust/pull/74852> as last attempt try to remove it. // See <https://github.com/rust-lang/rust/pull/74852>, the last attempt
// to try to remove it.
#[inline] #[inline]
default fn to_string(&self) -> String { default fn to_string(&self) -> String {
use fmt::Write; use fmt::Write;

View file

@ -259,7 +259,7 @@ use crate::raw_vec::RawVec;
/// `Vec` does not guarantee any particular growth strategy when reallocating /// `Vec` does not guarantee any particular growth strategy when reallocating
/// when full, nor when [`reserve`] is called. The current strategy is basic /// when full, nor when [`reserve`] is called. The current strategy is basic
/// and it may prove desirable to use a non-constant growth factor. Whatever /// and it may prove desirable to use a non-constant growth factor. Whatever
/// strategy is used will of course guarantee `O(1)` amortized [`push`]. /// strategy is used will of course guarantee *O*(1) amortized [`push`].
/// ///
/// `vec![x; n]`, `vec![a, b, c, d]`, and /// `vec![x; n]`, `vec![a, b, c, d]`, and
/// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec` /// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec`

View file

@ -485,3 +485,49 @@ nzint_impl_try_from_int! { i32, NonZeroI32, #[stable(feature = "nzint_try_from_i
nzint_impl_try_from_int! { i64, NonZeroI64, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] } nzint_impl_try_from_int! { i64, NonZeroI64, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
nzint_impl_try_from_int! { i128, NonZeroI128, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] } nzint_impl_try_from_int! { i128, NonZeroI128, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
nzint_impl_try_from_int! { isize, NonZeroIsize, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] } nzint_impl_try_from_int! { isize, NonZeroIsize, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
macro_rules! nzint_impl_try_from_nzint {
($From:ty => $To:ty, $doc: expr) => {
#[stable(feature = "nzint_try_from_nzint_conv", since = "1.49.0")]
#[doc = $doc]
impl TryFrom<$From> for $To {
type Error = TryFromIntError;
#[inline]
fn try_from(value: $From) -> Result<Self, Self::Error> {
TryFrom::try_from(value.get()).map(|v| {
// SAFETY: $From is a NonZero type, so v is not zero.
unsafe { Self::new_unchecked(v) }
})
}
}
};
($To:ty: $($From: ty),*) => {$(
nzint_impl_try_from_nzint!(
$From => $To,
concat!(
"Attempts to convert `",
stringify!($From),
"` to `",
stringify!($To),
"`.",
)
);
)*};
}
// Non-zero int -> non-zero unsigned int
nzint_impl_try_from_nzint! { NonZeroU8: NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
nzint_impl_try_from_nzint! { NonZeroU16: NonZeroI8, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
nzint_impl_try_from_nzint! { NonZeroU32: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
nzint_impl_try_from_nzint! { NonZeroU64: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
nzint_impl_try_from_nzint! { NonZeroU128: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroUsize, NonZeroIsize }
nzint_impl_try_from_nzint! { NonZeroUsize: NonZeroI8, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroIsize }
// Non-zero int -> non-zero signed int
nzint_impl_try_from_nzint! { NonZeroI8: NonZeroU8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
nzint_impl_try_from_nzint! { NonZeroI16: NonZeroU16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
nzint_impl_try_from_nzint! { NonZeroI32: NonZeroU32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
nzint_impl_try_from_nzint! { NonZeroI64: NonZeroU64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
nzint_impl_try_from_nzint! { NonZeroI128: NonZeroU128, NonZeroUsize, NonZeroIsize }
nzint_impl_try_from_nzint! { NonZeroIsize: NonZeroU16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize }

View file

@ -1945,10 +1945,10 @@ impl<T> [T] {
/// ///
/// The comparator function must define a total ordering for the elements in the slice. If /// The comparator function must define a total ordering for the elements in the slice. If
/// the ordering is not total, the order of the elements is unspecified. An order is a /// the ordering is not total, the order of the elements is unspecified. An order is a
/// total order if it is (for all a, b and c): /// total order if it is (for all `a`, `b` and `c`):
/// ///
/// * total and antisymmetric: exactly one of a < b, a == b or a > b is true; and /// * total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true, and
/// * transitive, a < b and b < c implies a < c. The same must hold for both == and >. /// * transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
/// ///
/// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use /// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use
/// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`. /// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`.

View file

@ -89,7 +89,7 @@ fn str_index_overflow_fail() -> ! {
/// self`. Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. Unlike /// self`. Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. Unlike
/// other indexing operations, this can never panic. /// other indexing operations, this can never panic.
/// ///
/// This operation is `O(1)`. /// This operation is *O*(1).
/// ///
/// Prior to 1.20.0, these indexing operations were still supported by /// Prior to 1.20.0, these indexing operations were still supported by
/// direct implementation of `Index` and `IndexMut`. /// direct implementation of `Index` and `IndexMut`.
@ -130,7 +130,7 @@ unsafe impl SliceIndex<str> for ops::RangeFull {
/// Returns a slice of the given string from the byte range /// Returns a slice of the given string from the byte range
/// [`begin`, `end`). /// [`begin`, `end`).
/// ///
/// This operation is `O(1)`. /// This operation is *O*(1).
/// ///
/// Prior to 1.20.0, these indexing operations were still supported by /// Prior to 1.20.0, these indexing operations were still supported by
/// direct implementation of `Index` and `IndexMut`. /// direct implementation of `Index` and `IndexMut`.
@ -237,7 +237,7 @@ unsafe impl SliceIndex<str> for ops::Range<usize> {
/// Returns a slice of the given string from the byte range [`0`, `end`). /// Returns a slice of the given string from the byte range [`0`, `end`).
/// Equivalent to `&self[0 .. end]` or `&mut self[0 .. end]`. /// Equivalent to `&self[0 .. end]` or `&mut self[0 .. end]`.
/// ///
/// This operation is `O(1)`. /// This operation is *O*(1).
/// ///
/// Prior to 1.20.0, these indexing operations were still supported by /// Prior to 1.20.0, these indexing operations were still supported by
/// direct implementation of `Index` and `IndexMut`. /// direct implementation of `Index` and `IndexMut`.
@ -308,7 +308,7 @@ unsafe impl SliceIndex<str> for ops::RangeTo<usize> {
/// `len`). Equivalent to `&self[begin .. len]` or `&mut self[begin .. /// `len`). Equivalent to `&self[begin .. len]` or `&mut self[begin ..
/// len]`. /// len]`.
/// ///
/// This operation is `O(1)`. /// This operation is *O*(1).
/// ///
/// Prior to 1.20.0, these indexing operations were still supported by /// Prior to 1.20.0, these indexing operations were still supported by
/// direct implementation of `Index` and `IndexMut`. /// direct implementation of `Index` and `IndexMut`.
@ -385,7 +385,7 @@ unsafe impl SliceIndex<str> for ops::RangeFrom<usize> {
/// self[begin .. end + 1]`, except if `end` has the maximum value for /// self[begin .. end + 1]`, except if `end` has the maximum value for
/// `usize`. /// `usize`.
/// ///
/// This operation is `O(1)`. /// This operation is *O*(1).
/// ///
/// # Panics /// # Panics
/// ///
@ -441,7 +441,7 @@ unsafe impl SliceIndex<str> for ops::RangeInclusive<usize> {
/// Equivalent to `&self [0 .. end + 1]`, except if `end` has the maximum /// Equivalent to `&self [0 .. end + 1]`, except if `end` has the maximum
/// value for `usize`. /// value for `usize`.
/// ///
/// This operation is `O(1)`. /// This operation is *O*(1).
/// ///
/// # Panics /// # Panics
/// ///

View file

@ -73,10 +73,9 @@ pub fn got_symlink_permission(tmpdir: &TempDir) -> bool {
let link = tmpdir.join("some_hopefully_unique_link_name"); let link = tmpdir.join("some_hopefully_unique_link_name");
match symlink_file(r"nonexisting_target", link) { match symlink_file(r"nonexisting_target", link) {
Ok(_) => true,
// ERROR_PRIVILEGE_NOT_HELD = 1314 // ERROR_PRIVILEGE_NOT_HELD = 1314
Err(ref err) if err.raw_os_error() == Some(1314) => false, Err(ref err) if err.raw_os_error() == Some(1314) => false,
Err(_) => true, Ok(_) | Err(_) => true,
} }
} }

View file

@ -152,19 +152,13 @@ fn udp_clone_two_write() {
let (done, rx) = channel(); let (done, rx) = channel();
let tx2 = tx.clone(); let tx2 = tx.clone();
let _t = thread::spawn(move || { let _t = thread::spawn(move || {
match sock3.send_to(&[1], &addr2) { if sock3.send_to(&[1], &addr2).is_ok() {
Ok(..) => { let _ = tx2.send(());
let _ = tx2.send(());
}
Err(..) => {}
} }
done.send(()).unwrap(); done.send(()).unwrap();
}); });
match sock1.send_to(&[2], &addr2) { if sock1.send_to(&[2], &addr2).is_ok() {
Ok(..) => { let _ = tx.send(());
let _ = tx.send(());
}
Err(..) => {}
} }
drop(tx); drop(tx);

View file

@ -39,9 +39,12 @@ impl<T: Write> JsonFormatter<T> {
stdout: Option<Cow<'_, str>>, stdout: Option<Cow<'_, str>>,
extra: Option<&str>, extra: Option<&str>,
) -> io::Result<()> { ) -> io::Result<()> {
// A doc test's name includes a filename which must be escaped for correct json.
self.write_message(&*format!( self.write_message(&*format!(
r#"{{ "type": "{}", "name": "{}", "event": "{}""#, r#"{{ "type": "{}", "name": "{}", "event": "{}""#,
ty, name, evt ty,
EscapedString(name),
evt
))?; ))?;
if let Some(exec_time) = exec_time { if let Some(exec_time) = exec_time {
self.write_message(&*format!(r#", "exec_time": "{}""#, exec_time))?; self.write_message(&*format!(r#", "exec_time": "{}""#, exec_time))?;
@ -67,7 +70,7 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> { fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
self.writeln_message(&*format!( self.writeln_message(&*format!(
r#"{{ "type": "test", "event": "started", "name": "{}" }}"#, r#"{{ "type": "test", "event": "started", "name": "{}" }}"#,
desc.name EscapedString(desc.name.as_slice())
)) ))
} }
@ -140,7 +143,10 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
\"name\": \"{}\", \ \"name\": \"{}\", \
\"median\": {}, \ \"median\": {}, \
\"deviation\": {}{} }}", \"deviation\": {}{} }}",
desc.name, median, deviation, mbps EscapedString(desc.name.as_slice()),
median,
deviation,
mbps
); );
self.writeln_message(&*line) self.writeln_message(&*line)
@ -151,7 +157,7 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> { fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
self.writeln_message(&*format!( self.writeln_message(&*format!(
r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#, r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#,
desc.name EscapedString(desc.name.as_slice())
)) ))
} }

View file

@ -893,10 +893,15 @@ class RustBuild(object):
).decode(default_encoding).splitlines()] ).decode(default_encoding).splitlines()]
filtered_submodules = [] filtered_submodules = []
submodules_names = [] submodules_names = []
llvm_checked_out = os.path.exists(os.path.join(self.rust_root, "src/llvm-project/.git"))
for module in submodules: for module in submodules:
if module.endswith("llvm-project"): if module.endswith("llvm-project"):
# Don't sync the llvm-project submodule either if an external LLVM
# was provided, or if we are downloading LLVM. Also, if the
# submodule has been initialized already, sync it anyways so that
# it doesn't mess up contributor pull requests.
if self.get_toml('llvm-config') or self.downloading_llvm(): if self.get_toml('llvm-config') or self.downloading_llvm():
if self.get_toml('lld') != 'true': if self.get_toml('lld') != 'true' and not llvm_checked_out:
continue continue
check = self.check_submodule(module, slow_submodules) check = self.check_submodule(module, slow_submodules)
filtered_submodules.append((module, check)) filtered_submodules.append((module, check))

View file

@ -16,8 +16,8 @@ The basic idea is this:
The triple backticks start and end code blocks. If this were in a file named `foo.rs`, The triple backticks start and end code blocks. If this were in a file named `foo.rs`,
running `rustdoc --test foo.rs` will extract this example, and then run it as a test. running `rustdoc --test foo.rs` will extract this example, and then run it as a test.
Please note that by default, if no language is set for the block code, `rustdoc` Please note that by default, if no language is set for the block code, rustdoc
assumes it is `Rust` code. So the following: assumes it is Rust code. So the following:
``````markdown ``````markdown
```rust ```rust
@ -44,7 +44,6 @@ the `assert!` family of macros works the same as other Rust code:
```rust ```rust
let foo = "foo"; let foo = "foo";
assert_eq!(foo, "foo"); assert_eq!(foo, "foo");
``` ```
@ -55,8 +54,9 @@ the code panics and the doctest fails.
In the example above, you'll note something strange: there's no `main` In the example above, you'll note something strange: there's no `main`
function! Forcing you to write `main` for every example, no matter how small, function! Forcing you to write `main` for every example, no matter how small,
adds friction. So `rustdoc` processes your examples slightly before adds friction and clutters the output. So `rustdoc` processes your examples
running them. Here's the full algorithm rustdoc uses to preprocess examples: slightly before running them. Here's the full algorithm `rustdoc` uses to
preprocess examples:
1. Some common `allow` attributes are inserted, including 1. Some common `allow` attributes are inserted, including
`unused_variables`, `unused_assignments`, `unused_mut`, `unused_variables`, `unused_assignments`, `unused_mut`,
@ -78,10 +78,12 @@ Sometimes, you need some setup code, or other things that would distract
from your example, but are important to make the tests work. Consider from your example, but are important to make the tests work. Consider
an example block that looks like this: an example block that looks like this:
```text ```ignore
/// ```
/// /// Some documentation. /// /// Some documentation.
/// # fn foo() {} // this function will be hidden /// # fn foo() {} // this function will be hidden
/// println!("Hello, World!"); /// println!("Hello, World!");
/// ```
``` ```
It will render like this: It will render like this:
@ -251,7 +253,7 @@ disambiguate the error type:
This is an unfortunate consequence of the `?` operator adding an implicit This is an unfortunate consequence of the `?` operator adding an implicit
conversion, so type inference fails because the type is not unique. Please note conversion, so type inference fails because the type is not unique. Please note
that you must write the `(())` in one sequence without intermediate whitespace that you must write the `(())` in one sequence without intermediate whitespace
so that rustdoc understands you want an implicit `Result`-returning function. so that `rustdoc` understands you want an implicit `Result`-returning function.
## Documenting macros ## Documenting macros
@ -359,7 +361,7 @@ the code with the 2015 edition.
## Syntax reference ## Syntax reference
The *exact* syntax for code blocks, including the edge cases, can be found The *exact* syntax for code blocks, including the edge cases, can be found
in the [Fenced Code Blocks](https://spec.commonmark.org/0.28/#fenced-code-blocks) in the [Fenced Code Blocks](https://spec.commonmark.org/0.29/#fenced-code-blocks)
section of the CommonMark specification. section of the CommonMark specification.
Rustdoc also accepts *indented* code blocks as an alternative to fenced Rustdoc also accepts *indented* code blocks as an alternative to fenced
@ -372,7 +374,7 @@ can indent each line by four or more spaces.
`````` ``````
These, too, are documented in the CommonMark specification, in the These, too, are documented in the CommonMark specification, in the
[Indented Code Blocks](https://spec.commonmark.org/0.28/#indented-code-blocks) [Indented Code Blocks](https://spec.commonmark.org/0.29/#indented-code-blocks)
section. section.
However, it's preferable to use fenced code blocks over indented code blocks. However, it's preferable to use fenced code blocks over indented code blocks.
@ -388,7 +390,7 @@ documentation. To this end, Rustdoc allows you to have certain items only appear
collecting doctests, so you can utilize doctest functionality without forcing the test to appear in collecting doctests, so you can utilize doctest functionality without forcing the test to appear in
docs, or to find an arbitrary private item to include it on. docs, or to find an arbitrary private item to include it on.
When compiling a crate for use in doctests (with `--test` option), rustdoc will set `cfg(doctest)`. When compiling a crate for use in doctests (with `--test` option), `rustdoc` will set `#[cfg(doctest)]`.
Note that they will still link against only the public items of your crate; if you need to test Note that they will still link against only the public items of your crate; if you need to test
private items, you need to write a unit test. private items, you need to write a unit test.
@ -407,18 +409,18 @@ pub struct MyStructOnlyTakesUsize;
``` ```
Note that the struct `MyStructOnlyTakesUsize` here isn't actually part of your public crate Note that the struct `MyStructOnlyTakesUsize` here isn't actually part of your public crate
API. The use of `#[cfg(doctest)]` makes sure that this struct only exists while rustdoc is API. The use of `#[cfg(doctest)]` makes sure that this struct only exists while `rustdoc` is
collecting doctests. This means that its doctest is executed when `--test` is passed to rustdoc, collecting doctests. This means that its doctest is executed when `--test` is passed to rustdoc,
but is hidden from the public documentation. but is hidden from the public documentation.
Another possible use of `cfg(doctest)` is to test doctests that are included in your README file Another possible use of `#[cfg(doctest)]` is to test doctests that are included in your README file
without including it in your main documentation. For example, you could write this into your without including it in your main documentation. For example, you could write this into your
`lib.rs` to test your README as part of your doctests: `lib.rs` to test your README as part of your doctests:
```rust,ignore ```rust,ignore
#![feature(external_doc)] #![feature(external_doc)]
#[doc(include="../README.md")] #[doc(include = "../README.md")]
#[cfg(doctest)] #[cfg(doctest)]
pub struct ReadmeDoctests; pub struct ReadmeDoctests;
``` ```

View file

@ -2384,7 +2384,7 @@ fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static
render_attributes(w, it, false); render_attributes(w, it, false);
write!( write!(
w, w,
"{vis}static {mutability} {name}: {typ}</pre>", "{vis}static {mutability}{name}: {typ}</pre>",
vis = it.visibility.print_with_space(), vis = it.visibility.print_with_space(),
mutability = s.mutability.print_with_space(), mutability = s.mutability.print_with_space(),
name = it.name.as_ref().unwrap(), name = it.name.as_ref().unwrap(),

View file

@ -0,0 +1,12 @@
// compile-flags: --document-private-items
#![crate_type = "lib"]
// @has static/static.FOO.html '//pre' 'static FOO: usize'
static FOO: usize = 1;
// @has static/static.BAR.html '//pre' 'pub static BAR: usize'
pub static BAR: usize = 1;
// @has static/static.BAZ.html '//pre' 'pub static mut BAZ: usize'
pub static mut BAZ: usize = 1;

View file

@ -0,0 +1,17 @@
fn main() {
|| {
if false {
return "test";
}
let a = true;
a //~ ERROR mismatched types
};
|| -> bool {
if false {
return "hello" //~ ERROR mismatched types
};
let b = true;
b
};
}

View file

@ -0,0 +1,21 @@
error[E0308]: mismatched types
--> $DIR/closure-return-type-mismatch.rs:7:9
|
LL | a
| ^ expected `&str`, found `bool`
|
note: return type inferred to be `&str` here
--> $DIR/closure-return-type-mismatch.rs:4:20
|
LL | return "test";
| ^^^^^^
error[E0308]: mismatched types
--> $DIR/closure-return-type-mismatch.rs:12:20
|
LL | return "hello"
| ^^^^^^^ expected `bool`, found `&str`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,5 +1,6 @@
// run-pass // run-pass
#![feature(core_intrinsics, repr128)] #![feature(core_intrinsics, repr128)]
//~^ WARN the feature `repr128` is incomplete
use std::intrinsics::discriminant_value; use std::intrinsics::discriminant_value;

View file

@ -0,0 +1,11 @@
warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/discriminant_size.rs:2:29
|
LL | #![feature(core_intrinsics, repr128)]
| ^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
warning: 1 warning emitted

View file

@ -1,5 +1,6 @@
// run-pass // run-pass
#![feature(repr128, arbitrary_enum_discriminant)] #![feature(repr128, arbitrary_enum_discriminant)]
//~^ WARN the feature `repr128` is incomplete
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
#[repr(i128)] #[repr(i128)]

View file

@ -0,0 +1,11 @@
warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-70509-partial_eq.rs:2:12
|
LL | #![feature(repr128, arbitrary_enum_discriminant)]
| ^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
warning: 1 warning emitted

View file

@ -1,5 +1,6 @@
// run-pass // run-pass
#![feature(repr128, core_intrinsics, discriminant_kind)] #![feature(repr128, core_intrinsics, discriminant_kind)]
//~^ WARN the feature `repr128` is incomplete
use std::intrinsics::discriminant_value; use std::intrinsics::discriminant_value;
use std::marker::DiscriminantKind; use std::marker::DiscriminantKind;

View file

@ -0,0 +1,11 @@
warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/repr128.rs:2:12
|
LL | #![feature(repr128, core_intrinsics, discriminant_kind)]
| ^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
warning: 1 warning emitted

View file

@ -6,6 +6,11 @@ LL | 5
| |
= note: expected type `std::result::Result<{integer}, _>` = note: expected type `std::result::Result<{integer}, _>`
found type `{integer}` found type `{integer}`
note: return type inferred to be `std::result::Result<{integer}, _>` here
--> $DIR/type-mismatch-signature-deduction.rs:8:20
|
LL | return Ok(6);
| ^^^^^
error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:6:5: 14:6] as Generator>::Return == i32` error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:6:5: 14:6] as Generator>::Return == i32`
--> $DIR/type-mismatch-signature-deduction.rs:5:13 --> $DIR/type-mismatch-signature-deduction.rs:5:13

View file

@ -0,0 +1,23 @@
// Regression test for #71732, it used to emit incorrect diagnostics, like:
// error[E0283]: type annotations needed
// --> src/main.rs:5:10
// |
// 5 | .get(&"key".into())
// | ^^^ cannot infer type for struct `String`
// |
// = note: cannot satisfy `String: Borrow<_>`
// help: consider specifying the type argument in the method call
// |
// 5 | .get::<Q>(&"key".into())
// |
use std::collections::hash_map::HashMap;
fn foo(parameters: &HashMap<String, String>) -> bool {
parameters
.get(&"key".into()) //~ ERROR: type annotations needed
.and_then(|found: &String| Some(false))
.unwrap_or(false)
}
fn main() {}

View file

@ -0,0 +1,13 @@
error[E0283]: type annotations needed
--> $DIR/issue-71732.rs:18:10
|
LL | .get(&"key".into())
| ^^^ ------------ this method call resolves to `T`
| |
| cannot infer type for type parameter `Q` declared on the associated function `get`
|
= note: cannot satisfy `String: Borrow<_>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0283`.

View file

@ -0,0 +1,29 @@
// Regression test for #72616, it used to emit incorrect diagnostics, like:
// error[E0283]: type annotations needed for `String`
// --> src/main.rs:8:30
// |
// 5 | let _: String = "".to_owned().try_into().unwrap();
// | - consider giving this pattern a type
// ...
// 8 | if String::from("a") == "a".try_into().unwrap() {}
// | ^^ cannot infer type for struct `String`
// |
// = note: cannot satisfy `String: PartialEq<_>`
use std::convert::TryInto;
pub fn main() {
{
let _: String = "".to_owned().try_into().unwrap();
}
{
if String::from("a") == "a".try_into().unwrap() {}
//~^ ERROR: type annotations needed
}
{
let _: String = match "_".try_into() {
Ok(a) => a,
Err(_) => "".into(),
};
}
}

View file

@ -0,0 +1,13 @@
error[E0283]: type annotations needed
--> $DIR/issue-72616.rs:20:30
|
LL | if String::from("a") == "a".try_into().unwrap() {}
| ^^ -------------- this method call resolves to `std::result::Result<T, <Self as TryInto<T>>::Error>`
| |
| cannot infer type
|
= note: cannot satisfy `String: PartialEq<_>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0283`.

View file

@ -0,0 +1,38 @@
// build-pass
#![allow(incomplete_features)]
#![feature(inline_const, half_open_range_patterns, exclusive_range_pattern)]
fn main() {
const N: u32 = 10;
let x: u32 = 3;
match x {
1 ..= const { N + 1 } => {},
_ => {},
}
match x {
const { N - 1 } ..= 10 => {},
_ => {},
}
match x {
const { N - 1 } ..= const { N + 1 } => {},
_ => {},
}
match x {
.. const { N + 1 } => {},
_ => {},
}
match x {
const { N - 1 } .. => {},
_ => {},
}
match x {
..= const { N + 1 } => {},
_ => {}
}
}

View file

@ -2,6 +2,7 @@
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
#![feature(repr128)] #![feature(repr128)]
//~^ WARN the feature `repr128` is incomplete
#[repr(i128)] #[repr(i128)]
enum Big { A, B } enum Big { A, B }

View file

@ -0,0 +1,11 @@
warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-43398.rs:4:12
|
LL | #![feature(repr128)]
| ^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
warning: 1 warning emitted

View file

@ -1,3 +1,7 @@
// revisions: default miropt
//[miropt]compile-flags: -Z mir-opt-level=2
// ~^ This flag is for #77668, it used to be ICE.
#![crate_type = "lib"] #![crate_type = "lib"]
pub fn bar<P>( // Error won't happen if "bar" is not generic pub fn bar<P>( // Error won't happen if "bar" is not generic

View file

@ -39,4 +39,14 @@ fn main() {
None => { //~ ERROR incompatible types None => { //~ ERROR incompatible types
}, },
}; };
let _ = match Some(42) {
Some(x) => "rust-lang.org"
.chars()
.skip(1)
.chain(Some(x as u8 as char))
.take(10)
.any(char::is_alphanumeric),
None => {} //~ ERROR incompatible types
};
} }

View file

@ -56,19 +56,33 @@ LL | | };
error[E0308]: `match` arms have incompatible types error[E0308]: `match` arms have incompatible types
--> $DIR/match-incompat-type-semi.rs:39:17 --> $DIR/match-incompat-type-semi.rs:39:17
| |
LL | let _ = match Some(42) { LL | let _ = match Some(42) {
| _____________- | -------------- `match` arms have incompatible types
LL | | Some(x) => { LL | Some(x) => {
LL | | x LL | x
| | - this is found to be of type `{integer}` | - this is found to be of type `{integer}`
LL | | }, LL | },
LL | | None => { LL | None => {
| |_________________^ | _________________^
LL | || }, LL | | },
| ||_________^ expected integer, found `()` | |_________^ expected integer, found `()`
LL | | };
| |_____- `match` arms have incompatible types
error: aborting due to 4 previous errors error[E0308]: `match` arms have incompatible types
--> $DIR/match-incompat-type-semi.rs:50:17
|
LL | let _ = match Some(42) {
| -------------- `match` arms have incompatible types
LL | Some(x) => "rust-lang.org"
| ____________________-
LL | | .chars()
LL | | .skip(1)
LL | | .chain(Some(x as u8 as char))
LL | | .take(10)
LL | | .any(char::is_alphanumeric),
| |_______________________________________- this is found to be of type `bool`
LL | None => {}
| ^^ expected `bool`, found `()`
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0308`. For more information about this error, try `rustc --explain E0308`.

View file

@ -13,4 +13,4 @@
fn f() { |[](* } fn f() { |[](* }
//~^ ERROR expected one of `,` or `:`, found `(` //~^ ERROR expected one of `,` or `:`, found `(`
//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `const`, `mut`, `ref`, `|`, identifier, or path, found `*` //~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`

View file

@ -4,7 +4,7 @@ error: expected one of `,` or `:`, found `(`
LL | fn f() { |[](* } LL | fn f() { |[](* }
| ^ expected one of `,` or `:` | ^ expected one of `,` or `:`
error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `const`, `mut`, `ref`, `|`, identifier, or path, found `*` error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
--> $DIR/issue-66357-unexpected-unreachable.rs:14:14 --> $DIR/issue-66357-unexpected-unreachable.rs:14:14
| |
LL | fn f() { |[](* } LL | fn f() { |[](* }

View file

@ -0,0 +1,18 @@
// Tests #73631: closures inherit `#[target_feature]` annotations
// check-pass
// only-x86_64
#![feature(target_feature_11)]
#[target_feature(enable="avx")]
fn also_use_avx() {
println!("Hello from AVX")
}
#[target_feature(enable="avx")]
fn use_avx() -> Box<dyn Fn()> {
Box::new(|| also_use_avx())
}
fn main() {}

@ -1 +1 @@
Subproject commit 79b397d72c557eb6444a2ba0dc00a211a226a35a Subproject commit dd83ae55c871d94f060524656abab62ec40b4c40

View file

@ -3,6 +3,7 @@
#![crate_type = "proc-macro"] #![crate_type = "proc-macro"]
#![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)] #![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)]
#![allow(incomplete_features)]
#![allow(clippy::useless_conversion)] #![allow(clippy::useless_conversion)]
extern crate proc_macro; extern crate proc_macro;

View file

@ -3,6 +3,7 @@
#![crate_type = "proc-macro"] #![crate_type = "proc-macro"]
#![feature(repr128, proc_macro_quote)] #![feature(repr128, proc_macro_quote)]
#![allow(incomplete_features)]
extern crate proc_macro; extern crate proc_macro;

View file

@ -6,6 +6,7 @@
// contain a proc-macro. // contain a proc-macro.
#![feature(repr128)] #![feature(repr128)]
#![allow(incomplete_features)]
#![crate_type = "proc-macro"] #![crate_type = "proc-macro"]
extern crate proc_macro; extern crate proc_macro;