Auto merge of #89545 - workingjubilee:rollup-ooxf3p2, r=workingjubilee

Rollup of 15 pull requests

Successful merges:

 - #87993 (Stabilize try_reserve)
 - #88090 (Perform type inference in range pattern)
 - #88780 (Added abs_diff for integer types.)
 - #89270 (path.push() should work as expected on windows verbatim paths)
 - #89413 (Correctly handle supertraits for min_specialization)
 - #89456 (Update to the final LLVM 13.0.0 release)
 - #89466 (Fix bug with query modifier parsing)
 - #89473 (Fix extra `non_snake_case` warning for shorthand field bindings)
 - #89474 (rustdoc: Improve doctest pass's name and module's name)
 - #89478 (Fixed numerus of error message)
 - #89480 (Add test for issue 89118.)
 - #89487 (Try to recover from a `=>` -> `=` or `->` typo in a match arm)
 - #89494 (Deny `where` clauses on `auto` traits)
 - #89511 (⬆️ rust-analyzer)
 - #89536 (update Miri)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-10-05 04:13:35 +00:00
commit a804c4b112
81 changed files with 787 additions and 297 deletions

2
.gitmodules vendored
View File

@ -34,7 +34,7 @@
[submodule "src/llvm-project"]
path = src/llvm-project
url = https://github.com/rust-lang/llvm-project.git
branch = rustc/13.0-2021-08-08
branch = rustc/13.0-2021-09-30
[submodule "src/doc/embedded-book"]
path = src/doc/embedded-book
url = https://github.com/rust-embedded/book.git

View File

@ -360,7 +360,7 @@ version = "0.1.0"
dependencies = [
"directories",
"rustc-workspace-hack",
"rustc_version",
"rustc_version 0.3.3",
"serde",
"serde_json",
"vergen",
@ -1092,19 +1092,6 @@ dependencies = [
"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]]
name = "env_logger"
version = "0.9.0"
@ -2250,7 +2237,7 @@ version = "0.1.0"
dependencies = [
"colored",
"compiletest_rs",
"env_logger 0.8.1",
"env_logger 0.9.0",
"getrandom 0.2.0",
"hex 0.4.2",
"libc",
@ -2258,7 +2245,7 @@ dependencies = [
"measureme",
"rand 0.8.4",
"rustc-workspace-hack",
"rustc_version",
"rustc_version 0.4.0",
"shell-escape",
"smallvec",
]
@ -4548,6 +4535,15 @@ dependencies = [
"semver 0.11.0",
]
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver 1.0.3",
]
[[package]]
name = "rustdoc"
version = "0.0.0"
@ -4908,9 +4904,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
name = "smallvec"
version = "1.6.1"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "snap"

View File

@ -295,6 +295,7 @@ impl TokenKind {
match *self {
Comma => Some(vec![Dot, Lt, Semi]),
Semi => Some(vec![Colon, Comma]),
FatArrow => Some(vec![Eq, RArrow]),
_ => None,
}
}

View File

@ -683,31 +683,53 @@ impl<'a> AstValidator<'a> {
}
}
fn emit_e0568(&self, span: Span, ident_span: Span) {
struct_span_err!(
self.session,
span,
E0568,
"auto traits cannot have super traits or lifetime bounds"
)
.span_label(ident_span, "auto trait cannot have super traits or lifetime bounds")
.span_suggestion(
span,
"remove the super traits or lifetime bounds",
String::new(),
Applicability::MachineApplicable,
)
.emit();
}
fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) {
if let [first @ last] | [first, .., last] = &bounds[..] {
let span = first.span().to(last.span());
struct_span_err!(self.session, span, E0568, "auto traits cannot have super traits")
.span_label(ident_span, "auto trait cannot have super traits")
.span_suggestion(
span,
"remove the super traits",
String::new(),
Applicability::MachineApplicable,
)
.emit();
if let [.., last] = &bounds[..] {
let span = ident_span.shrink_to_hi().to(last.span());
self.emit_e0568(span, ident_span);
}
}
fn deny_where_clause(&self, where_clause: &WhereClause, ident_span: Span) {
if !where_clause.predicates.is_empty() {
self.emit_e0568(where_clause.span, ident_span);
}
}
fn deny_items(&self, trait_items: &[P<AssocItem>], ident_span: Span) {
if !trait_items.is_empty() {
let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
let total_span = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span);
struct_span_err!(
self.session,
spans,
E0380,
"auto traits cannot have methods or associated items"
"auto traits cannot have associated items"
)
.span_label(ident_span, "auto trait cannot have items")
.span_suggestion(
total_span,
"remove these associated items",
String::new(),
Applicability::MachineApplicable,
)
.span_label(ident_span, "auto trait cannot have associated items")
.emit();
}
}
@ -1184,6 +1206,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
// Auto traits cannot have generics, super traits nor contain items.
self.deny_generic_params(generics, item.ident.span);
self.deny_super_traits(bounds, item.ident.span);
self.deny_where_clause(&generics.where_clause, item.ident.span);
self.deny_items(trait_items, item.ident.span);
}
self.no_questions_in_bounds(bounds, "supertraits", true);

View File

@ -31,7 +31,7 @@ const SSO_ARRAY_SIZE: usize = 8;
//
// Missing HashMap API:
// all hasher-related
// try_reserve (unstable)
// try_reserve
// shrink_to (unstable)
// drain_filter (unstable)
// into_keys/into_values (unstable)

View File

@ -13,7 +13,7 @@ use super::map::SsoHashMap;
//
// Missing HashSet API:
// all hasher-related
// try_reserve (unstable)
// try_reserve
// shrink_to (unstable)
// drain_filter (unstable)
// replace

View File

@ -437,12 +437,13 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
if let hir::Node::Pat(parent_pat) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid))
{
if let PatKind::Struct(_, field_pats, _) = &parent_pat.kind {
for field in field_pats.iter() {
if field.ident != ident {
// Only check if a new name has been introduced, to avoid warning
// on both the struct definition and this pattern.
self.check_snake_case(cx, "variable", &ident);
}
if field_pats
.iter()
.any(|field| !field.is_shorthand && field.pat.hir_id == p.hir_id)
{
// Only check if a new name has been introduced, to avoid warning
// on both the struct definition and this pattern.
self.check_snake_case(cx, "variable", &ident);
}
return;
}

View File

@ -455,28 +455,28 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
// Pass on the fatal_cycle modifier
if let Some(fatal_cycle) = &modifiers.fatal_cycle {
attributes.push(quote! { #fatal_cycle });
attributes.push(quote! { (#fatal_cycle) });
};
// Pass on the storage modifier
if let Some(ref ty) = modifiers.storage {
let span = ty.span();
attributes.push(quote_spanned! {span=> storage(#ty) });
attributes.push(quote_spanned! {span=> (storage #ty) });
};
// Pass on the cycle_delay_bug modifier
if let Some(cycle_delay_bug) = &modifiers.cycle_delay_bug {
attributes.push(quote! { #cycle_delay_bug });
attributes.push(quote! { (#cycle_delay_bug) });
};
// Pass on the no_hash modifier
if let Some(no_hash) = &modifiers.no_hash {
attributes.push(quote! { #no_hash });
attributes.push(quote! { (#no_hash) });
};
// Pass on the anon modifier
if let Some(anon) = &modifiers.anon {
attributes.push(quote! { #anon });
attributes.push(quote! { (#anon) });
};
// Pass on the eval_always modifier
if let Some(eval_always) = &modifiers.eval_always {
attributes.push(quote! { #eval_always });
attributes.push(quote! { (#eval_always) });
};
// This uses the span of the query definition for the commas,

View File

@ -140,11 +140,11 @@ macro_rules! is_eval_always_attr {
}
macro_rules! contains_anon_attr {
($($attr:ident $(($($attr_args:tt)*))* ),*) => ({$(is_anon_attr!($attr) | )* false});
($(($attr:ident $($attr_args:tt)* )),*) => ({$(is_anon_attr!($attr) | )* false});
}
macro_rules! contains_eval_always_attr {
($($attr:ident $(($($attr_args:tt)*))* ),*) => ({$(is_eval_always_attr!($attr) | )* false});
($(($attr:ident $($attr_args:tt)* )),*) => ({$(is_eval_always_attr!($attr) | )* false});
}
#[allow(non_upper_case_globals)]

View File

@ -52,7 +52,6 @@
#![feature(thread_local_const_init)]
#![feature(trusted_step)]
#![feature(try_blocks)]
#![feature(try_reserve)]
#![feature(try_reserve_kind)]
#![feature(nonzero_ops)]
#![recursion_limit = "512"]

View File

@ -111,11 +111,11 @@ macro_rules! query_storage {
([][$K:ty, $V:ty]) => {
<DefaultCacheSelector as CacheSelector<$K, $V>>::Cache
};
([storage($ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => {
([(storage $ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => {
<$ty as CacheSelector<$K, $V>>::Cache
};
([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => {
query_storage!([$($($modifiers)*)*][$($args)*])
([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
query_storage!([$($modifiers)*][$($args)*])
};
}

View File

@ -2322,7 +2322,24 @@ impl<'a> Parser<'a> {
None
};
let arrow_span = this.token.span;
this.expect(&token::FatArrow)?;
if let Err(mut err) = this.expect(&token::FatArrow) {
// We might have a `=>` -> `=` or `->` typo (issue #89396).
if TokenKind::FatArrow
.similar_tokens()
.map_or(false, |similar_tokens| similar_tokens.contains(&this.token.kind))
{
err.span_suggestion(
this.token.span,
"try using a fat arrow here",
"=>".to_string(),
Applicability::MaybeIncorrect,
);
err.emit();
this.bump();
} else {
return Err(err);
}
}
let arm_start_span = this.token.span;
let expr = this.parse_expr_res(Restrictions::STMT_EXPR, None).map_err(|mut err| {

View File

@ -253,17 +253,17 @@ macro_rules! handle_cycle_error {
$error.emit();
Value::from_cycle_error($tcx)
}};
([fatal_cycle $($rest:tt)*][$tcx:expr, $error:expr]) => {{
([(fatal_cycle) $($rest:tt)*][$tcx:expr, $error:expr]) => {{
$error.emit();
$tcx.sess.abort_if_errors();
unreachable!()
}};
([cycle_delay_bug $($rest:tt)*][$tcx:expr, $error:expr]) => {{
([(cycle_delay_bug) $($rest:tt)*][$tcx:expr, $error:expr]) => {{
$error.delay_as_bug();
Value::from_cycle_error($tcx)
}};
([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => {
handle_cycle_error!([$($($modifiers)*)*][$($args)*])
([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
handle_cycle_error!([$($modifiers)*][$($args)*])
};
}
@ -271,11 +271,11 @@ macro_rules! is_anon {
([]) => {{
false
}};
([anon $($rest:tt)*]) => {{
([(anon) $($rest:tt)*]) => {{
true
}};
([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*]) => {
is_anon!([$($($modifiers)*)*])
([$other:tt $($modifiers:tt)*]) => {
is_anon!([$($modifiers)*])
};
}
@ -283,11 +283,11 @@ macro_rules! is_eval_always {
([]) => {{
false
}};
([eval_always $($rest:tt)*]) => {{
([(eval_always) $($rest:tt)*]) => {{
true
}};
([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*]) => {
is_eval_always!([$($($modifiers)*)*])
([$other:tt $($modifiers:tt)*]) => {
is_eval_always!([$($modifiers)*])
};
}
@ -295,11 +295,11 @@ macro_rules! hash_result {
([][$hcx:expr, $result:expr]) => {{
dep_graph::hash_result($hcx, &$result)
}};
([no_hash $($rest:tt)*][$hcx:expr, $result:expr]) => {{
([(no_hash) $($rest:tt)*][$hcx:expr, $result:expr]) => {{
None
}};
([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => {
hash_result!([$($($modifiers)*)*][$($args)*])
([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
hash_result!([$($modifiers)*][$($args)*])
};
}

View File

@ -10,7 +10,9 @@ use crate::traits::normalize_projection_type;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style};
use rustc_errors::{
error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
@ -2273,7 +2275,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
parent_trait_ref = child_trait_ref;
}
if count > 0 {
err.note(&format!("{} redundant requirements hidden", count));
err.note(&format!(
"{} redundant requirement{} hidden",
count,
pluralize!(count)
));
err.note(&format!(
"required because of the requirements on the impl of `{}` for `{}`",
parent_trait_ref.print_only_trait_path(),

View File

@ -64,7 +64,9 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
pub use self::structural_match::search_for_structural_match_violation;
pub use self::structural_match::NonStructuralMatchTy;
pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
pub use self::util::{
elaborate_obligations, elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs,
};
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
pub use self::util::{
get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices,

View File

@ -449,16 +449,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ti: TopInfo<'tcx>,
) -> Ty<'tcx> {
let calc_side = |opt_expr: Option<&'tcx hir::Expr<'tcx>>| match opt_expr {
None => (None, None),
None => None,
Some(expr) => {
let ty = self.check_expr(expr);
// Check that the end-point is of numeric or char type.
let fail = !(ty.is_numeric() || ty.is_char() || ty.references_error());
(Some(ty), Some((fail, ty, expr.span)))
// Check that the end-point is possibly of numeric or char type.
// The early check here is not for correctness, but rather better
// diagnostics (e.g. when `&str` is being matched, `expected` will
// be peeled to `str` while ty here is still `&str`, if we don't
// err ealy here, a rather confusing unification error will be
// emitted instead).
let fail =
!(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error());
Some((fail, ty, expr.span))
}
};
let (lhs_ty, lhs) = calc_side(lhs);
let (rhs_ty, rhs) = calc_side(rhs);
let mut lhs = calc_side(lhs);
let mut rhs = calc_side(rhs);
if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
// There exists a side that didn't meet our criteria that the end-point
@ -467,25 +473,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return self.tcx.ty_error();
}
// Now that we know the types can be unified we find the unified type
// and use it to type the entire expression.
let common_type = self.resolve_vars_if_possible(lhs_ty.or(rhs_ty).unwrap_or(expected));
// Unify each side with `expected`.
// Subtyping doesn't matter here, as the value is some kind of scalar.
let demand_eqtype = |x, y| {
if let Some((_, x_ty, x_span)) = x {
let demand_eqtype = |x: &mut _, y| {
if let Some((ref mut fail, x_ty, x_span)) = *x {
if let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti) {
if let Some((_, y_ty, y_span)) = y {
self.endpoint_has_type(&mut err, y_span, y_ty);
}
err.emit();
*fail = true;
};
}
};
demand_eqtype(lhs, rhs);
demand_eqtype(rhs, lhs);
demand_eqtype(&mut lhs, rhs);
demand_eqtype(&mut rhs, lhs);
common_type
if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
return self.tcx.ty_error();
}
// Find the unified type and check if it's of numeric or char type again.
// This check is needed if both sides are inference variables.
// We require types to be resolved here so that we emit inference failure
// rather than "_ is not a char or numeric".
let ty = self.structurally_resolved_type(span, expected);
if !(ty.is_numeric() || ty.is_char() || ty.references_error()) {
if let Some((ref mut fail, _, _)) = lhs {
*fail = true;
}
if let Some((ref mut fail, _, _)) = rhs {
*fail = true;
}
self.emit_err_pat_range(span, lhs, rhs);
return self.tcx.ty_error();
}
ty
}
fn endpoint_has_type(&self, err: &mut DiagnosticBuilder<'_>, span: Span, ty: Ty<'_>) {
@ -512,10 +535,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
E0029,
"only `char` and numeric types are allowed in range patterns"
);
let msg = |ty| format!("this is of type `{}` but it should be `char` or numeric", ty);
let msg = |ty| {
let ty = self.resolve_vars_if_possible(ty);
format!("this is of type `{}` but it should be `char` or numeric", ty)
};
let mut one_side_err = |first_span, first_ty, second: Option<(bool, Ty<'tcx>, Span)>| {
err.span_label(first_span, &msg(first_ty));
if let Some((_, ty, sp)) = second {
let ty = self.resolve_vars_if_possible(ty);
self.endpoint_has_type(&mut err, sp, ty);
}
};

View File

@ -74,7 +74,7 @@ use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
use rustc_infer::traits::specialization_graph::Node;
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{self, InstantiatedPredicates, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
use rustc_span::Span;
use rustc_trait_selection::traits::{self, translate_substs, wf};
@ -294,13 +294,27 @@ fn check_predicates<'tcx>(
span: Span,
) {
let tcx = infcx.tcx;
let impl1_predicates = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
let impl1_predicates: Vec<_> = traits::elaborate_predicates(
tcx,
tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).predicates.into_iter(),
)
.map(|obligation| obligation.predicate)
.collect();
let mut impl2_predicates = if impl2_node.is_from_trait() {
// Always applicable traits have to be always applicable without any
// assumptions.
InstantiatedPredicates::empty()
Vec::new()
} else {
tcx.predicates_of(impl2_node.def_id()).instantiate(tcx, impl2_substs)
traits::elaborate_predicates(
tcx,
tcx.predicates_of(impl2_node.def_id())
.instantiate(tcx, impl2_substs)
.predicates
.into_iter(),
)
.map(|obligation| obligation.predicate)
.collect()
};
debug!(
"check_always_applicable(\nimpl1_predicates={:?},\nimpl2_predicates={:?}\n)",
@ -322,13 +336,12 @@ fn check_predicates<'tcx>(
// which is sound because we forbid impls like the following
//
// impl<D: Debug> AlwaysApplicable for D { }
let always_applicable_traits =
impl1_predicates.predicates.iter().copied().filter(|&predicate| {
matches!(
trait_predicate_kind(tcx, predicate),
Some(TraitSpecializationKind::AlwaysApplicable)
)
});
let always_applicable_traits = impl1_predicates.iter().copied().filter(|&predicate| {
matches!(
trait_predicate_kind(tcx, predicate),
Some(TraitSpecializationKind::AlwaysApplicable)
)
});
// Include the well-formed predicates of the type parameters of the impl.
for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().substs {
@ -340,18 +353,19 @@ fn check_predicates<'tcx>(
arg,
span,
) {
impl2_predicates
.predicates
.extend(obligations.into_iter().map(|obligation| obligation.predicate))
impl2_predicates.extend(
traits::elaborate_obligations(tcx, obligations)
.map(|obligation| obligation.predicate),
)
}
}
impl2_predicates.predicates.extend(
impl2_predicates.extend(
traits::elaborate_predicates(tcx, always_applicable_traits)
.map(|obligation| obligation.predicate),
);
for predicate in impl1_predicates.predicates {
if !impl2_predicates.predicates.contains(&predicate) {
for predicate in impl1_predicates {
if !impl2_predicates.contains(&predicate) {
check_specialization_on(tcx, predicate, span)
}
}

View File

@ -57,7 +57,7 @@ use core::fmt::Display;
/// The error type for `try_reserve` methods.
#[derive(Clone, PartialEq, Eq, Debug)]
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
#[stable(feature = "try_reserve", since = "1.57.0")]
pub struct TryReserveError {
kind: TryReserveErrorKind,
}
@ -126,7 +126,7 @@ impl From<LayoutError> for TryReserveErrorKind {
}
}
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
#[stable(feature = "try_reserve", since = "1.57.0")]
impl Display for TryReserveError {
fn fmt(
&self,

View File

@ -711,7 +711,6 @@ impl<T, A: Allocator> VecDeque<T, A> {
/// # Examples
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::TryReserveError;
/// use std::collections::VecDeque;
///
@ -730,7 +729,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
/// }
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
/// ```
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
#[stable(feature = "try_reserve", since = "1.57.0")]
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.try_reserve(additional)
}
@ -749,7 +748,6 @@ impl<T, A: Allocator> VecDeque<T, A> {
/// # Examples
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::TryReserveError;
/// use std::collections::VecDeque;
///
@ -768,7 +766,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
/// }
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
/// ```
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
#[stable(feature = "try_reserve", since = "1.57.0")]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
let old_cap = self.cap();
let used_cap = self.len() + 1;

View File

@ -1009,7 +1009,6 @@ impl String {
/// # Examples
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::TryReserveError;
///
/// fn process_data(data: &str) -> Result<String, TryReserveError> {
@ -1025,7 +1024,7 @@ impl String {
/// }
/// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?");
/// ```
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
#[stable(feature = "try_reserve", since = "1.57.0")]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.vec.try_reserve(additional)
}
@ -1049,7 +1048,6 @@ impl String {
/// # Examples
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::TryReserveError;
///
/// fn process_data(data: &str) -> Result<String, TryReserveError> {
@ -1065,7 +1063,7 @@ impl String {
/// }
/// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?");
/// ```
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
#[stable(feature = "try_reserve", since = "1.57.0")]
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.vec.try_reserve_exact(additional)
}

View File

@ -266,14 +266,21 @@ unsafe impl<T, A: Allocator> TrustedLen for IntoIter<T, A> {}
#[doc(hidden)]
#[unstable(issue = "none", feature = "std_internals")]
#[rustc_unsafe_specialization_marker]
pub trait NonDrop {}
// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr
// and thus we can't implement drop-handling
//
#[unstable(issue = "none", feature = "std_internals")]
impl<T: Copy> NonDrop for T {}
#[doc(hidden)]
#[unstable(issue = "none", feature = "std_internals")]
// TrustedRandomAccess (without NoCoerce) must not be implemented because
// subtypes/supertypes of `T` might not be `Copy`
// subtypes/supertypes of `T` might not be `NonDrop`
unsafe impl<T, A: Allocator> TrustedRandomAccessNoCoerce for IntoIter<T, A>
where
T: Copy,
T: NonDrop,
{
const MAY_HAVE_SIDE_EFFECT: bool = false;
}

View File

@ -849,7 +849,6 @@ impl<T, A: Allocator> Vec<T, A> {
/// # Examples
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::TryReserveError;
///
/// fn process_data(data: &[u32]) -> Result<Vec<u32>, TryReserveError> {
@ -867,7 +866,7 @@ impl<T, A: Allocator> Vec<T, A> {
/// }
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
/// ```
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
#[stable(feature = "try_reserve", since = "1.57.0")]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.buf.try_reserve(self.len, additional)
}
@ -892,7 +891,6 @@ impl<T, A: Allocator> Vec<T, A> {
/// # Examples
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::TryReserveError;
///
/// fn process_data(data: &[u32]) -> Result<Vec<u32>, TryReserveError> {
@ -910,7 +908,7 @@ impl<T, A: Allocator> Vec<T, A> {
/// }
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
/// ```
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
#[stable(feature = "try_reserve", since = "1.57.0")]
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.buf.try_reserve_exact(self.len, additional)
}

View File

@ -6,24 +6,14 @@ use super::{AsIntoIter, InPlaceDrop, SpecFromIter, SpecFromIterNested, Vec};
/// Specialization marker for collecting an iterator pipeline into a Vec while reusing the
/// source allocation, i.e. executing the pipeline in place.
///
/// The SourceIter parent trait is necessary for the specializing function to access the allocation
/// which is to be reused. But it is not sufficient for the specialization to be valid. See
/// additional bounds on the impl.
#[rustc_unsafe_specialization_marker]
pub(super) trait SourceIterMarker: SourceIter<Source: AsIntoIter> {}
pub(super) trait InPlaceIterableMarker {}
// The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of
// Adapter<Adapter<Adapter<IntoIter>>> (all owned by core/std). Additional bounds
// on the adapter implementations (beyond `impl<I: Trait> Trait for Adapter<I>`) only depend on other
// traits already marked as specialization traits (Copy, TrustedRandomAccess, FusedIterator).
// I.e. the marker does not depend on lifetimes of user-supplied types. Modulo the Copy hole, which
// several other specializations already depend on.
impl<T> SourceIterMarker for T where T: SourceIter<Source: AsIntoIter> + InPlaceIterable {}
impl<T> InPlaceIterableMarker for T where T: InPlaceIterable {}
impl<T, I> SpecFromIter<T, I> for Vec<T>
where
I: Iterator<Item = T> + SourceIterMarker,
I: Iterator<Item = T> + SourceIter<Source: AsIntoIter> + InPlaceIterableMarker,
{
default fn from_iter(mut iterator: I) -> Self {
// Additional requirements which cannot expressed via trait bounds. We rely on const eval

View File

@ -8,7 +8,6 @@
#![feature(new_uninit)]
#![feature(pattern)]
#![feature(trusted_len)]
#![feature(try_reserve)]
#![feature(try_reserve_kind)]
#![feature(unboxed_closures)]
#![feature(associated_type_bounds)]

View File

@ -249,14 +249,14 @@ impl<I> FusedIterator for Enumerate<I> where I: FusedIterator {}
unsafe impl<I> TrustedLen for Enumerate<I> where I: TrustedLen {}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, I: Iterator> SourceIter for Enumerate<I>
unsafe impl<I> SourceIter for Enumerate<I>
where
I: SourceIter<Source = S>,
I: SourceIter,
{
type Source = S;
type Source = I::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut I::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.iter) }
}

View File

@ -135,15 +135,14 @@ where
impl<I: FusedIterator, P> FusedIterator for Filter<I, P> where P: FnMut(&I::Item) -> bool {}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, P, I: Iterator> SourceIter for Filter<I, P>
unsafe impl<P, I> SourceIter for Filter<I, P>
where
P: FnMut(&I::Item) -> bool,
I: SourceIter<Source = S>,
I: SourceIter,
{
type Source = S;
type Source = I::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut I::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.iter) }
}

View File

@ -129,15 +129,14 @@ where
impl<B, I: FusedIterator, F> FusedIterator for FilterMap<I, F> where F: FnMut(I::Item) -> Option<B> {}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for FilterMap<I, F>
unsafe impl<I, F> SourceIter for FilterMap<I, F>
where
F: FnMut(I::Item) -> Option<B>,
I: SourceIter<Source = S>,
I: SourceIter,
{
type Source = S;
type Source = I::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut I::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.iter) }
}

View File

@ -149,15 +149,14 @@ where
impl<I: FusedIterator, F> FusedIterator for Inspect<I, F> where F: FnMut(&I::Item) {}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, I: Iterator, F> SourceIter for Inspect<I, F>
unsafe impl<I, F> SourceIter for Inspect<I, F>
where
F: FnMut(&I::Item),
I: SourceIter<Source = S>,
I: SourceIter,
{
type Source = S;
type Source = I::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut I::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.iter) }
}

View File

@ -201,15 +201,14 @@ where
}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for Map<I, F>
unsafe impl<I, F> SourceIter for Map<I, F>
where
F: FnMut(I::Item) -> B,
I: SourceIter<Source = S>,
I: SourceIter,
{
type Source = S;
type Source = I::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut I::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.iter) }
}

View File

@ -80,15 +80,14 @@ where
}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, B, I: Iterator, P> SourceIter for MapWhile<I, P>
unsafe impl<I, P> SourceIter for MapWhile<I, P>
where
P: FnMut(I::Item) -> Option<B>,
I: SourceIter<Source = S>,
I: SourceIter,
{
type Source = S;
type Source = I::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut I::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.iter) }
}

View File

@ -92,9 +92,10 @@ pub use self::zip::zip;
/// [`as_inner`]: SourceIter::as_inner
#[unstable(issue = "none", feature = "inplace_iteration")]
#[doc(hidden)]
#[rustc_specialization_trait]
pub unsafe trait SourceIter {
/// A source stage in an iterator pipeline.
type Source: Iterator;
type Source;
/// Retrieve the source of an iterator pipeline.
///
@ -200,14 +201,14 @@ where
}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, I, E> SourceIter for ResultShunt<'_, I, E>
unsafe impl<I, E> SourceIter for ResultShunt<'_, I, E>
where
I: SourceIter<Source = S>,
I: SourceIter,
{
type Source = S;
type Source = I::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut Self::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.iter) }
}

View File

@ -321,14 +321,14 @@ impl<I: Iterator> Peekable<I> {
unsafe impl<I> TrustedLen for Peekable<I> where I: TrustedLen {}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, I: Iterator> SourceIter for Peekable<I>
unsafe impl<I: Iterator> SourceIter for Peekable<I>
where
I: SourceIter<Source = S>,
I: SourceIter,
{
type Source = S;
type Source = I::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut I::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.iter) }
}

View File

@ -90,15 +90,14 @@ where
}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<St, F, B, S: Iterator, I: Iterator> SourceIter for Scan<I, St, F>
unsafe impl<St, F, I> SourceIter for Scan<I, St, F>
where
I: SourceIter<Source = S>,
F: FnMut(&mut St, I::Item) -> Option<B>,
I: SourceIter,
{
type Source = S;
type Source = I::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut I::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.iter) }
}

View File

@ -222,14 +222,14 @@ where
impl<I> FusedIterator for Skip<I> where I: FusedIterator {}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, I: Iterator> SourceIter for Skip<I>
unsafe impl<I> SourceIter for Skip<I>
where
I: SourceIter<Source = S>,
I: SourceIter,
{
type Source = S;
type Source = I::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut I::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.iter) }
}

View File

@ -105,15 +105,14 @@ where
}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, P, I: Iterator> SourceIter for SkipWhile<I, P>
unsafe impl<P, I> SourceIter for SkipWhile<I, P>
where
P: FnMut(&I::Item) -> bool,
I: SourceIter<Source = S>,
I: SourceIter,
{
type Source = S;
type Source = I::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut I::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.iter) }
}

View File

@ -130,14 +130,14 @@ where
}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, I: Iterator> SourceIter for Take<I>
unsafe impl<I> SourceIter for Take<I>
where
I: SourceIter<Source = S>,
I: SourceIter,
{
type Source = S;
type Source = I::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut I::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.iter) }
}

View File

@ -118,15 +118,14 @@ where
}
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S: Iterator, P, I: Iterator> SourceIter for TakeWhile<I, P>
unsafe impl<P, I> SourceIter for TakeWhile<I, P>
where
P: FnMut(&I::Item) -> bool,
I: SourceIter<Source = S>,
I: SourceIter,
{
type Source = S;
type Source = I::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut I::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.iter) }
}

View File

@ -414,16 +414,14 @@ where
// Arbitrarily selects the left side of the zip iteration as extractable "source"
// it would require negative trait bounds to be able to try both
#[unstable(issue = "none", feature = "inplace_iteration")]
unsafe impl<S, A, B> SourceIter for Zip<A, B>
unsafe impl<A, B> SourceIter for Zip<A, B>
where
A: SourceIter<Source = S>,
B: Iterator,
S: Iterator,
A: SourceIter,
{
type Source = S;
type Source = A::Source;
#[inline]
unsafe fn as_inner(&mut self) -> &mut S {
unsafe fn as_inner(&mut self) -> &mut A::Source {
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
unsafe { SourceIter::as_inner(&mut self.a) }
}

View File

@ -2235,6 +2235,46 @@ macro_rules! int_impl {
}
}
/// Computes the absolute difference between `self` and `other`.
///
/// This function always returns the correct answer without overflow or
/// panics by returning an unsigned integer.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(int_abs_diff)]
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(80), 20", stringify!($UnsignedT), ");")]
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(110), 10", stringify!($UnsignedT), ");")]
#[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").abs_diff(80), 180", stringify!($UnsignedT), ");")]
#[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").abs_diff(-120), 20", stringify!($UnsignedT), ");")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.abs_diff(", stringify!($SelfT), "::MAX), ", stringify!($UnsignedT), "::MAX);")]
/// ```
#[unstable(feature = "int_abs_diff", issue = "89492")]
#[inline]
pub const fn abs_diff(self, other: Self) -> $UnsignedT {
if self < other {
// Converting a non-negative x from signed to unsigned by using
// `x as U` is left unchanged, but a negative x is converted
// to value x + 2^N. Thus if `s` and `o` are binary variables
// respectively indicating whether `self` and `other` are
// negative, we are computing the mathematical value:
//
// (other + o*2^N) - (self + s*2^N) mod 2^N
// other - self + (o-s)*2^N mod 2^N
// other - self mod 2^N
//
// Finally, taking the mod 2^N of the mathematical value of
// `other - self` does not change it as it already is
// in the range [0, 2^N).
(other as $UnsignedT).wrapping_sub(self as $UnsignedT)
} else {
(self as $UnsignedT).wrapping_sub(other as $UnsignedT)
}
}
/// Returns a number representing sign of `self`.
///
/// - `0` if the number is zero

View File

@ -1490,6 +1490,33 @@ macro_rules! uint_impl {
(c, b | d)
}
/// Computes the absolute difference between `self` and `other`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(int_abs_diff)]
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(80), 20", stringify!($SelfT), ");")]
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(110), 10", stringify!($SelfT), ");")]
/// ```
#[unstable(feature = "int_abs_diff", issue = "89492")]
#[inline]
pub const fn abs_diff(self, other: Self) -> Self {
if mem::size_of::<Self>() == 1 {
// Trick LLVM into generating the psadbw instruction when SSE2
// is available and this function is autovectorized for u8's.
(self as i32).wrapping_sub(other as i32).abs() as Self
} else {
if self < other {
other - self
} else {
self - other
}
}
}
/// Calculates the multiplication of `self` and `rhs`.
///
/// Returns a tuple of the multiplication along with a boolean

View File

@ -625,14 +625,13 @@ where
/// # Examples
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::HashMap;
///
/// let mut map: HashMap<&str, isize> = HashMap::new();
/// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
/// ```
#[inline]
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
#[stable(feature = "try_reserve", since = "1.57.0")]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.base.try_reserve(additional).map_err(map_try_reserve_error)
}

View File

@ -423,13 +423,12 @@ where
/// # Examples
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::HashSet;
/// let mut set: HashSet<i32> = HashSet::new();
/// set.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
/// ```
#[inline]
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
#[stable(feature = "try_reserve", since = "1.57.0")]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.base.try_reserve(additional).map_err(map_try_reserve_error)
}

View File

@ -420,7 +420,7 @@ pub use self::hash_map::HashMap;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::hash_set::HashSet;
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
#[stable(feature = "try_reserve", since = "1.57.0")]
pub use alloc_crate::collections::TryReserveError;
#[unstable(
feature = "try_reserve_kind",

View File

@ -595,7 +595,7 @@ impl Error for char::ParseCharError {
}
}
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
#[stable(feature = "try_reserve", since = "1.57.0")]
impl Error for alloc::collections::TryReserveError {}
#[unstable(feature = "duration_checked_float", issue = "83400")]

View File

@ -331,7 +331,6 @@
#![feature(total_cmp)]
#![feature(trace_macros)]
#![feature(try_blocks)]
#![feature(try_reserve)]
#![feature(try_reserve_kind)]
#![feature(unboxed_closures)]
#![feature(unwrap_infallible)]

View File

@ -1231,20 +1231,59 @@ impl PathBuf {
let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false);
// in the special case of `C:` on Windows, do *not* add a separator
let comps = self.components();
if comps.prefix_len() > 0
&& comps.prefix_len() == comps.path.len()
&& comps.prefix.unwrap().is_drive()
{
let comps = self.components();
if comps.prefix_len() > 0
&& comps.prefix_len() == comps.path.len()
&& comps.prefix.unwrap().is_drive()
{
need_sep = false
}
need_sep = false
}
// absolute `path` replaces `self`
if path.is_absolute() || path.prefix().is_some() {
self.as_mut_vec().truncate(0);
// verbatim paths need . and .. removed
} else if comps.prefix_verbatim() {
let mut buf: Vec<_> = comps.collect();
for c in path.components() {
match c {
Component::RootDir => {
buf.truncate(1);
buf.push(c);
}
Component::CurDir => (),
Component::ParentDir => {
if let Some(Component::Normal(_)) = buf.last() {
buf.pop();
}
}
_ => buf.push(c),
}
}
let mut res = OsString::new();
let mut need_sep = false;
for c in buf {
if need_sep && c != Component::RootDir {
res.push(MAIN_SEP_STR);
}
res.push(c.as_os_str());
need_sep = match c {
Component::RootDir => false,
Component::Prefix(prefix) => {
!prefix.parsed.is_drive() && prefix.parsed.len() > 0
}
_ => true,
}
}
self.inner = res;
return;
// `path` has a root but no prefix, e.g., `\windows` (Windows only)
} else if path.has_root() {
let prefix_len = self.components().prefix_remaining();

View File

@ -1262,6 +1262,15 @@ pub fn test_push() {
tp!("\\\\.\\foo", "..\\bar", "\\\\.\\foo\\..\\bar");
tp!("\\\\?\\C:", "foo", "\\\\?\\C:\\foo"); // this is a weird one
tp!(r"\\?\C:\bar", "../foo", r"\\?\C:\foo");
tp!(r"\\?\C:\bar", "../../foo", r"\\?\C:\foo");
tp!(r"\\?\C:\", "../foo", r"\\?\C:\foo");
tp!(r"\\?\C:", r"D:\foo/./", r"D:\foo/./");
tp!(r"\\?\C:", r"\\?\D:\foo\.\", r"\\?\D:\foo\.\");
tp!(r"\\?\A:\x\y", "/foo", r"\\?\A:\foo");
tp!(r"\\?\A:", r"..\foo\.", r"\\?\A:\foo");
tp!(r"\\?\A:\x\y", r".\foo\.", r"\\?\A:\x\y\foo");
}
}

View File

@ -2,7 +2,7 @@ use crate::clean;
use crate::core::DocContext;
use crate::fold::{self, DocFolder};
use crate::html::markdown::{find_testable_code, ErrorCodes};
use crate::passes::doc_test_lints::{should_have_doc_example, Tests};
use crate::passes::check_doc_test_visibility::{should_have_doc_example, Tests};
use crate::passes::Pass;
use rustc_hir as hir;
use rustc_lint::builtin::MISSING_DOCS;

View File

@ -1,6 +1,6 @@
//! This pass is overloaded and runs two different lints.
//!
//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests
//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests.
//! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doctests.
use super::Pass;
@ -15,23 +15,23 @@ use rustc_middle::lint::LintLevelSource;
use rustc_session::lint;
use rustc_span::symbol::sym;
crate const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
name: "check-private-items-doc-tests",
run: check_private_items_doc_tests,
description: "check private items doc tests",
crate const CHECK_DOC_TEST_VISIBILITY: Pass = Pass {
name: "check_doc_test_visibility",
run: check_doc_test_visibility,
description: "run various visibility-related lints on doctests",
};
struct PrivateItemDocTestLinter<'a, 'tcx> {
struct DocTestVisibilityLinter<'a, 'tcx> {
cx: &'a mut DocContext<'tcx>,
}
crate fn check_private_items_doc_tests(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
let mut coll = PrivateItemDocTestLinter { cx };
crate fn check_doc_test_visibility(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
let mut coll = DocTestVisibilityLinter { cx };
coll.fold_crate(krate)
}
impl<'a, 'tcx> DocFolder for PrivateItemDocTestLinter<'a, 'tcx> {
impl<'a, 'tcx> DocFolder for DocTestVisibilityLinter<'a, 'tcx> {
fn fold_item(&mut self, item: Item) -> Option<Item> {
let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);

View File

@ -33,8 +33,8 @@ crate use self::propagate_doc_cfg::PROPAGATE_DOC_CFG;
crate mod collect_intra_doc_links;
crate use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS;
mod doc_test_lints;
crate use self::doc_test_lints::CHECK_PRIVATE_ITEMS_DOC_TESTS;
mod check_doc_test_visibility;
crate use self::check_doc_test_visibility::CHECK_DOC_TEST_VISIBILITY;
mod collect_trait_impls;
crate use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
@ -79,7 +79,7 @@ crate enum Condition {
/// The full list of passes.
crate const PASSES: &[Pass] = &[
CHECK_PRIVATE_ITEMS_DOC_TESTS,
CHECK_DOC_TEST_VISIBILITY,
STRIP_HIDDEN,
UNINDENT_COMMENTS,
STRIP_PRIVATE,
@ -97,7 +97,7 @@ crate const PASSES: &[Pass] = &[
crate const DEFAULT_PASSES: &[ConditionalPass] = &[
ConditionalPass::always(COLLECT_TRAIT_IMPLS),
ConditionalPass::always(UNINDENT_COMMENTS),
ConditionalPass::always(CHECK_PRIVATE_ITEMS_DOC_TESTS),
ConditionalPass::always(CHECK_DOC_TEST_VISIBILITY),
ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate),
ConditionalPass::new(STRIP_PRIV_IMPORTS, WhenDocumentPrivate),

@ -1 +1 @@
Subproject commit 522c3e3d9c097b53ede7682cc28544b461597b20
Subproject commit a7348ae0df3c71581dbe3d355fc0fb6ce6332dd0

View File

@ -15,7 +15,7 @@ note: required because of the requirements on the impl of `Grault` for `(T,)`
|
LL | impl<T: Grault> Grault for (T,)
| ^^^^^^ ^^^^
= note: 1 redundant requirements hidden
= note: 1 redundant requirement hidden
= note: required because of the requirements on the impl of `Grault` for `(T,)`
error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
@ -29,7 +29,7 @@ note: required because of the requirements on the impl of `Grault` for `(T,)`
|
LL | impl<T: Grault> Grault for (T,)
| ^^^^^^ ^^^^
= note: 1 redundant requirements hidden
= note: 1 redundant requirement hidden
= note: required because of the requirements on the impl of `Grault` for `(T,)`
error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
@ -43,7 +43,7 @@ note: required because of the requirements on the impl of `Grault` for `(T,)`
|
LL | impl<T: Grault> Grault for (T,)
| ^^^^^^ ^^^^
= note: 1 redundant requirements hidden
= note: 1 redundant requirement hidden
= note: required because of the requirements on the impl of `Grault` for `(T,)`
error: aborting due to 3 previous errors

View File

@ -0,0 +1,13 @@
#![feature(auto_traits)]
// run-rustfix
auto trait Generic {}
//~^ auto traits cannot have generic parameters [E0567]
auto trait Bound {}
//~^ auto traits cannot have super traits or lifetime bounds [E0568]
auto trait LifetimeBound {}
//~^ auto traits cannot have super traits or lifetime bounds [E0568]
auto trait MyTrait { }
//~^ auto traits cannot have associated items [E0380]
fn main() {}

View File

@ -1,9 +1,13 @@
#![feature(auto_traits)]
// run-rustfix
auto trait Generic<T> {}
//~^ auto traits cannot have generic parameters [E0567]
auto trait Bound : Copy {}
//~^ auto traits cannot have super traits [E0568]
//~^ auto traits cannot have super traits or lifetime bounds [E0568]
auto trait LifetimeBound : 'static {}
//~^ auto traits cannot have super traits or lifetime bounds [E0568]
auto trait MyTrait { fn foo() {} }
//~^ auto traits cannot have methods or associated items [E0380]
//~^ auto traits cannot have associated items [E0380]
fn main() {}

View File

@ -1,28 +1,37 @@
error[E0567]: auto traits cannot have generic parameters
--> $DIR/auto-trait-validation.rs:3:19
--> $DIR/auto-trait-validation.rs:5:19
|
LL | auto trait Generic<T> {}
| -------^^^ help: remove the parameters
| |
| auto trait cannot have generic parameters
error[E0568]: auto traits cannot have super traits
--> $DIR/auto-trait-validation.rs:5:20
error[E0568]: auto traits cannot have super traits or lifetime bounds
--> $DIR/auto-trait-validation.rs:7:17
|
LL | auto trait Bound : Copy {}
| ----- ^^^^ help: remove the super traits
| -----^^^^^^^ help: remove the super traits or lifetime bounds
| |
| auto trait cannot have super traits
| auto trait cannot have super traits or lifetime bounds
error[E0380]: auto traits cannot have methods or associated items
--> $DIR/auto-trait-validation.rs:7:25
error[E0568]: auto traits cannot have super traits or lifetime bounds
--> $DIR/auto-trait-validation.rs:9:25
|
LL | auto trait LifetimeBound : 'static {}
| -------------^^^^^^^^^^ help: remove the super traits or lifetime bounds
| |
| auto trait cannot have super traits or lifetime bounds
error[E0380]: auto traits cannot have associated items
--> $DIR/auto-trait-validation.rs:11:25
|
LL | auto trait MyTrait { fn foo() {} }
| ------- ^^^
| |
| auto trait cannot have items
| ------- ---^^^-----
| | |
| | help: remove these associated items
| auto trait cannot have associated items
error: aborting due to 3 previous errors
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0380, E0567, E0568.
For more information about an error, try `rustc --explain E0380`.

View File

@ -1,10 +1,10 @@
error[E0380]: auto traits cannot have methods or associated items
error[E0380]: auto traits cannot have associated items
--> $DIR/issue-23080-2.rs:5:10
|
LL | unsafe auto trait Trait {
| ----- auto trait cannot have items
| ----- auto trait cannot have associated items
LL | type Output;
| ^^^^^^
| -----^^^^^^- help: remove these associated items
error: aborting due to previous error

View File

@ -1,10 +1,13 @@
error[E0380]: auto traits cannot have methods or associated items
error[E0380]: auto traits cannot have associated items
--> $DIR/issue-23080.rs:5:8
|
LL | unsafe auto trait Trait {
| ----- auto trait cannot have items
LL | fn method(&self) {
| ^^^^^^
LL | unsafe auto trait Trait {
| ----- auto trait cannot have associated items
LL | fn method(&self) {
| _____- ^^^^^^
LL | | println!("Hello");
LL | | }
| |_____- help: remove these associated items
error: aborting due to previous error

View File

@ -0,0 +1,16 @@
// Regression test for issue #84075.
#![feature(auto_traits)]
auto trait Magic where Self: Copy {} //~ ERROR E0568
impl<T: Magic> Magic for T {}
fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
#[derive(Debug)]
struct NoClone;
fn main() {
let (a, b) = copy(NoClone);
println!("{:?} {:?}", a, b);
}

View File

@ -0,0 +1,11 @@
error[E0568]: auto traits cannot have super traits or lifetime bounds
--> $DIR/issue-84075.rs:5:18
|
LL | auto trait Magic where Self: Copy {}
| ----- ^^^^^^^^^^^^^^^^ help: remove the super traits or lifetime bounds
| |
| auto trait cannot have super traits or lifetime bounds
error: aborting due to previous error
For more information about this error, try `rustc --explain E0568`.

View File

@ -2,6 +2,7 @@
#![feature(negative_impls)]
auto trait Magic : Sized where Option<Self> : Magic {} //~ ERROR E0568
//~^ ERROR E0568
impl<T:Magic> Magic for T {}
fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }

View File

@ -1,11 +1,19 @@
error[E0568]: auto traits cannot have super traits
--> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:20
error[E0568]: auto traits cannot have super traits or lifetime bounds
--> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:17
|
LL | auto trait Magic : Sized where Option<Self> : Magic {}
| ----- ^^^^^ help: remove the super traits
| -----^^^^^^^^ help: remove the super traits or lifetime bounds
| |
| auto trait cannot have super traits
| auto trait cannot have super traits or lifetime bounds
error: aborting due to previous error
error[E0568]: auto traits cannot have super traits or lifetime bounds
--> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:26
|
LL | auto trait Magic : Sized where Option<Self> : Magic {}
| ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the super traits or lifetime bounds
| |
| auto trait cannot have super traits or lifetime bounds
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0568`.

View File

@ -1,10 +1,10 @@
error[E0568]: auto traits cannot have super traits
--> $DIR/typeck-auto-trait-no-supertraits.rs:28:19
error[E0568]: auto traits cannot have super traits or lifetime bounds
--> $DIR/typeck-auto-trait-no-supertraits.rs:28:17
|
LL | auto trait Magic: Copy {}
| ----- ^^^^ help: remove the super traits
| -----^^^^^^ help: remove the super traits or lifetime bounds
| |
| auto trait cannot have super traits
| auto trait cannot have super traits or lifetime bounds
error: aborting due to previous error

View File

@ -1,5 +1,4 @@
// check-pass
#![feature(try_reserve)]
fn main() {
let mut schema_all: (Vec<String>, Vec<String>) = (vec![], vec![]);

View File

@ -1,4 +0,0 @@
fn main() {
let v = Vec::new();
v.try_reserve(10); //~ ERROR: use of unstable library feature 'try_reserve'
}

View File

@ -1,12 +0,0 @@
error[E0658]: use of unstable library feature 'try_reserve': new API
--> $DIR/feature-gate-try_reserve.rs:3:7
|
LL | v.try_reserve(10);
| ^^^^^^^^^^^
|
= note: see issue #48043 <https://github.com/rust-lang/rust/issues/48043> for more information
= help: add `#![feature(try_reserve)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,32 @@
trait BufferMut {}
struct Ctx<D>(D);
trait BufferUdpStateContext<B> {}
impl<B: BufferMut, C> BufferUdpStateContext<B> for C {}
trait StackContext
where
Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>,
{
type Dispatcher;
}
trait TimerContext {
type Handler;
}
impl<C> TimerContext for C
where
C: StackContext,
//~^ ERROR: is not satisfied [E0277]
{
type Handler = Ctx<C::Dispatcher>;
//~^ ERROR: is not satisfied [E0277]
}
struct EthernetWorker<C>(C)
where
Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>;
impl<C> EthernetWorker<C> {}
//~^ ERROR: is not satisfied [E0277]
fn main() {}

View File

@ -0,0 +1,63 @@
error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
--> $DIR/issue-89118.rs:19:8
|
LL | C: StackContext,
| ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
|
note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>`
--> $DIR/issue-89118.rs:5:23
|
LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ ^
note: required by a bound in `StackContext`
--> $DIR/issue-89118.rs:9:14
|
LL | trait StackContext
| ------------ required by a bound in this
LL | where
LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext`
error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
--> $DIR/issue-89118.rs:22:20
|
LL | type Handler = Ctx<C::Dispatcher>;
| ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
|
note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>`
--> $DIR/issue-89118.rs:5:23
|
LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ ^
note: required by a bound in `StackContext`
--> $DIR/issue-89118.rs:9:14
|
LL | trait StackContext
| ------------ required by a bound in this
LL | where
LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext`
error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
--> $DIR/issue-89118.rs:29:9
|
LL | impl<C> EthernetWorker<C> {}
| ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
|
note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>`
--> $DIR/issue-89118.rs:5:23
|
LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ ^
note: required by a bound in `EthernetWorker`
--> $DIR/issue-89118.rs:28:14
|
LL | struct EthernetWorker<C>(C)
| -------------- required by a bound in this
LL | where
LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EthernetWorker`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,20 @@
// Regression test for #89469, where an extra non_snake_case warning was
// reported for a shorthand field binding.
// check-pass
#![deny(non_snake_case)]
#[allow(non_snake_case)]
struct Entry {
A: u16,
a: u16
}
fn foo() -> Entry {todo!()}
pub fn f() {
let Entry { A, a } = foo();
let _ = (A, a);
}
fn main() {}

View File

@ -0,0 +1,16 @@
// Regression test for issue #89396: Try to recover from a
// `=>` -> `=` or `->` typo in a match arm.
// run-rustfix
fn main() {
let opt = Some(42);
let _ = match opt {
Some(_) => true,
//~^ ERROR: expected one of
//~| HELP: try using a fat arrow here
None => false,
//~^ ERROR: expected one of
//~| HELP: try using a fat arrow here
};
}

View File

@ -0,0 +1,16 @@
// Regression test for issue #89396: Try to recover from a
// `=>` -> `=` or `->` typo in a match arm.
// run-rustfix
fn main() {
let opt = Some(42);
let _ = match opt {
Some(_) = true,
//~^ ERROR: expected one of
//~| HELP: try using a fat arrow here
None -> false,
//~^ ERROR: expected one of
//~| HELP: try using a fat arrow here
};
}

View File

@ -0,0 +1,20 @@
error: expected one of `=>`, `if`, or `|`, found `=`
--> $DIR/issue-89396.rs:9:17
|
LL | Some(_) = true,
| ^
| |
| expected one of `=>`, `if`, or `|`
| help: try using a fat arrow here: `=>`
error: expected one of `=>`, `@`, `if`, or `|`, found `->`
--> $DIR/issue-89396.rs:12:14
|
LL | None -> false,
| ^^
| |
| expected one of `=>`, `@`, `if`, or `|`
| help: try using a fat arrow here: `=>`
error: aborting due to 2 previous errors

View File

@ -0,0 +1,28 @@
trait Zero {
const ZERO: Self;
}
impl Zero for String {
const ZERO: Self = String::new();
}
fn foo() {
match String::new() {
Zero::ZERO ..= Zero::ZERO => {},
//~^ ERROR only `char` and numeric types are allowed in range patterns
_ => {},
}
}
fn bar() {
match Zero::ZERO {
Zero::ZERO ..= Zero::ZERO => {},
//~^ ERROR type annotations needed [E0282]
_ => {},
}
}
fn main() {
foo();
bar();
}

View File

@ -0,0 +1,21 @@
error[E0029]: only `char` and numeric types are allowed in range patterns
--> $DIR/issue-88074-pat-range-type-inference-err.rs:11:9
|
LL | Zero::ZERO ..= Zero::ZERO => {},
| ----------^^^^^----------
| | |
| | this is of type `String` but it should be `char` or numeric
| this is of type `String` but it should be `char` or numeric
error[E0282]: type annotations needed
--> $DIR/issue-88074-pat-range-type-inference-err.rs:19:9
|
LL | Zero::ZERO ..= Zero::ZERO => {},
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
|
= note: type must be known at this point
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0029, E0282.
For more information about an error, try `rustc --explain E0029`.

View File

@ -0,0 +1,16 @@
// check-pass
trait Zero {
const ZERO: Self;
}
impl Zero for i32 {
const ZERO: Self = 0;
}
fn main() {
match 1 {
Zero::ZERO ..= 1 => {},
_ => {},
}
}

View File

@ -19,7 +19,6 @@ enum_number!(Change {
Neg = -1,
Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns
//~| ERROR arbitrary expressions aren't allowed in patterns
//~| ERROR only `char` and numeric types are allowed in range patterns
});
fn main() {}

View File

@ -10,15 +10,5 @@ error: arbitrary expressions aren't allowed in patterns
LL | Arith = 1 + 1,
| ^^^^^
error[E0029]: only `char` and numeric types are allowed in range patterns
--> $DIR/patkind-litrange-no-expr.rs:20:13
|
LL | $( $value ..= 42 => Some($name::$variant), )* // PatKind::Range
| -- this is of type `{integer}`
...
LL | Arith = 1 + 1,
| ^^^^^ this is of type `_` but it should be `char` or numeric
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0029`.

View File

@ -0,0 +1,29 @@
// Check that supertraits cannot be used to work around min_specialization
// limitations.
#![feature(min_specialization)]
#![feature(rustc_attrs)]
trait HasMethod {
fn method(&self);
}
#[rustc_unsafe_specialization_marker]
trait Marker: HasMethod {}
trait Spec {
fn spec_me(&self);
}
impl<T> Spec for T {
default fn spec_me(&self) {}
}
impl<T: Marker> Spec for T {
//~^ ERROR cannot specialize on trait `HasMethod`
fn spec_me(&self) {
self.method();
}
}
fn main() {}

View File

@ -0,0 +1,13 @@
error: cannot specialize on trait `HasMethod`
--> $DIR/spec-marker-supertraits.rs:22:1
|
LL | / impl<T: Marker> Spec for T {
LL | |
LL | | fn spec_me(&self) {
LL | | self.method();
LL | | }
LL | | }
| |_^
error: aborting due to previous error

View File

@ -1,10 +1,10 @@
error[E0568]: auto traits cannot have super traits
--> $DIR/supertrait-auto-trait.rs:8:19
error[E0568]: auto traits cannot have super traits or lifetime bounds
--> $DIR/supertrait-auto-trait.rs:8:17
|
LL | auto trait Magic: Copy {}
| ----- ^^^^ help: remove the super traits
| -----^^^^^^ help: remove the super traits or lifetime bounds
| |
| auto trait cannot have super traits
| auto trait cannot have super traits or lifetime bounds
error[E0277]: the trait bound `NoClone: Copy` is not satisfied
--> $DIR/supertrait-auto-trait.rs:16:23

@ -1 +1 @@
Subproject commit 035933186957cf81c488261fb48a98bf523e8006
Subproject commit 18667a856596713fc4479f99b96afc7f03aa995c

@ -1 +1 @@
Subproject commit 009e6ceb1ddcd27a9ced3bcb7d0ef823379185a1
Subproject commit 4b7675fcc30d3e2c05eafc68a5724db66b58142c