Auto merge of #88596 - m-ou-se:rollup-cidzt4v, r=m-ou-se

Rollup of 12 pull requests

Successful merges:

 - #88177 (Stabilize std::os::unix::fs::chroot)
 - #88505 (Use `unwrap_unchecked` where possible)
 - #88512 (Upgrade array_into_iter lint to include Deref-to-array types.)
 - #88532 (Remove single use variables)
 - #88543 (Improve closure dummy capture suggestion in macros.)
 - #88560 (`fmt::Formatter::pad`: don't call chars().count() more than one time)
 - #88565 (Add regression test for issue 83190)
 - #88567 (Remove redundant `Span` in `QueryJobInfo`)
 - #88573 (rustdoc: Don't panic on ambiguous inherent associated types)
 - #88582 (Implement #88581)
 - #88589 (Correct doc comments inside `use_expr_visitor.rs`)
 - #88592 (Fix ICE in const check)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-09-02 18:58:12 +00:00
commit b834c4c1ba
28 changed files with 728 additions and 218 deletions

View file

@ -74,39 +74,45 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
_ => return,
};
// As this is a method call expression, we have at least one
// argument.
// As this is a method call expression, we have at least one argument.
let receiver_arg = &args[0];
let receiver_ty = cx.typeck_results().expr_ty(receiver_arg);
let adjustments = cx.typeck_results().expr_adjustments(receiver_arg);
// Peel all `Box<_>` layers. We have to special case `Box` here as
// `Box` is the only thing that values can be moved out of via
// method call. `Box::new([1]).into_iter()` should trigger this
// lint.
let mut recv_ty = cx.typeck_results().expr_ty(receiver_arg);
let mut num_box_derefs = 0;
while recv_ty.is_box() {
num_box_derefs += 1;
recv_ty = recv_ty.boxed_ty();
let target = match adjustments.last() {
Some(Adjustment { kind: Adjust::Borrow(_), target }) => target,
_ => return,
};
let types =
std::iter::once(receiver_ty).chain(adjustments.iter().map(|adj| adj.target));
let mut found_array = false;
for ty in types {
match ty.kind() {
// If we run into a &[T; N] or &[T] first, there's nothing to warn about.
// It'll resolve to the reference version.
ty::Ref(_, inner_ty, _) if inner_ty.is_array() => return,
ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), ty::Slice(..)) => return,
// Found an actual array type without matching a &[T; N] first.
// This is the problematic case.
ty::Array(..) => {
found_array = true;
break;
}
_ => {}
}
}
// Make sure we found an array after peeling the boxes.
if !matches!(recv_ty.kind(), ty::Array(..)) {
if !found_array {
return;
}
// Make sure that there is an autoref coercion at the expected
// position. The first `num_box_derefs` adjustments are the derefs
// of the box.
match cx.typeck_results().expr_adjustments(receiver_arg).get(num_box_derefs) {
Some(Adjustment { kind: Adjust::Borrow(_), .. }) => {}
_ => return,
}
// Emit lint diagnostic.
let target = match *cx.typeck_results().expr_ty_adjusted(receiver_arg).kind() {
let target = match *target.kind() {
ty::Ref(_, inner_ty, _) if inner_ty.is_array() => "[T; N]",
ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), ty::Slice(..)) => "[T]",
// We know the original first argument type is an array type,
// we know that the first adjustment was an autoref coercion
// and we know that `IntoIterator` is the trait involved. The
@ -135,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
String::new(),
Applicability::MaybeIncorrect,
);
} else {
} else if receiver_ty.is_array() {
diag.multipart_suggestion(
"or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value",
vec![

View file

@ -411,8 +411,7 @@ impl<'tcx> Body<'tcx> {
/// Returns an iterator over all function arguments.
#[inline]
pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
let arg_count = self.arg_count;
(1..arg_count + 1).map(Local::new)
(1..self.arg_count + 1).map(Local::new)
}
/// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
@ -421,9 +420,7 @@ impl<'tcx> Body<'tcx> {
pub fn vars_and_temps_iter(
&self,
) -> impl DoubleEndedIterator<Item = Local> + ExactSizeIterator {
let arg_count = self.arg_count;
let local_count = self.local_decls.len();
(arg_count + 1..local_count).map(Local::new)
(self.arg_count + 1..self.local_decls.len()).map(Local::new)
}
#[inline]

View file

@ -9,7 +9,7 @@ use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
use rustc_span::{sym, Span, Symbol};
@ -793,7 +793,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
let fn_ty = func.ty(body, tcx);
let (mut callee, substs) = match *fn_ty.kind() {
let (mut callee, mut substs) = match *fn_ty.kind() {
ty::FnDef(def_id, substs) => (def_id, substs),
ty::FnPtr(_) => {
@ -846,29 +846,31 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
.iter()
.find(|did| tcx.item_name(**did) == callee_name)
{
// using internal substs is ok here, since this is only
// used for the `resolve` call below
substs = InternalSubsts::identity_for_item(tcx, did);
callee = did;
}
}
_ => {
if !tcx.is_const_fn_raw(callee) {
// At this point, it is only legal when the caller is marked with
// #[default_method_body_is_const], and the callee is in the same
// trait.
let callee_trait = tcx.trait_of_item(callee);
if callee_trait.is_some() {
if tcx.has_attr(caller, sym::default_method_body_is_const) {
if tcx.trait_of_item(caller) == callee_trait {
nonconst_call_permission = true;
}
_ if !tcx.is_const_fn_raw(callee) => {
// At this point, it is only legal when the caller is marked with
// #[default_method_body_is_const], and the callee is in the same
// trait.
let callee_trait = tcx.trait_of_item(callee);
if callee_trait.is_some() {
if tcx.has_attr(caller, sym::default_method_body_is_const) {
if tcx.trait_of_item(caller) == callee_trait {
nonconst_call_permission = true;
}
}
}
if !nonconst_call_permission {
self.check_op(ops::FnCallNonConst);
return;
}
if !nonconst_call_permission {
self.check_op(ops::FnCallNonConst);
return;
}
}
_ => {}
}
// Resolve a trait method call to its concrete implementation, which may be in a

View file

@ -61,7 +61,7 @@ where
}
fn query(self, map: &QueryMap<D>) -> QueryStackFrame {
map.get(&self).unwrap().info.query.clone()
map.get(&self).unwrap().query.clone()
}
#[cfg(parallel_compiler)]
@ -81,7 +81,7 @@ where
}
pub struct QueryJobInfo<D> {
pub info: QueryInfo,
pub query: QueryStackFrame,
pub job: QueryJob<D>,
}
@ -155,7 +155,7 @@ where
while let Some(job) = current_job {
let info = query_map.get(&job).unwrap();
cycle.push(info.info.clone());
cycle.push(QueryInfo { span: info.job.span, query: info.query.clone() });
if job == *self {
cycle.reverse();
@ -170,7 +170,7 @@ where
.job
.parent
.as_ref()
.map(|parent| (info.info.span, parent.query(&query_map)));
.map(|parent| (info.job.span, parent.query(&query_map)));
return CycleError { usage, cycle };
}
@ -649,13 +649,10 @@ pub fn print_query_stack<CTX: QueryContext>(
};
let mut diag = Diagnostic::new(
Level::FailureNote,
&format!(
"#{} [{}] {}",
i, query_info.info.query.name, query_info.info.query.description
),
&format!("#{} [{}] {}", i, query_info.query.name, query_info.query.description),
);
diag.span =
tcx.dep_context().sess().source_map().guess_head_span(query_info.info.span).into();
tcx.dep_context().sess().source_map().guess_head_span(query_info.job.span).into();
handler.force_print_diagnostic(diag);
current_query = query_info.job.parent;

View file

@ -130,8 +130,8 @@ where
for (k, v) in shard.active.iter() {
if let QueryResult::Started(ref job) = *v {
let id = QueryJobId::new(job.id, shard_id, kind);
let info = QueryInfo { span: job.span, query: make_query(tcx, k.clone()) };
jobs.insert(id, QueryJobInfo { info, job: job.clone() });
let query = make_query(tcx, k.clone());
jobs.insert(id, QueryJobInfo { query, job: job.clone() });
}
}
}

View file

@ -47,7 +47,7 @@ use rustc_middle::ty::{
};
use rustc_session::lint;
use rustc_span::sym;
use rustc_span::{BytePos, MultiSpan, Pos, Span, Symbol, DUMMY_SP};
use rustc_span::{BytePos, MultiSpan, Pos, Span, Symbol};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_data_structures::stable_map::FxHashMap;
@ -680,15 +680,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
migrated_variables_concat
);
// If the body was entirely expanded from a macro
// invocation, i.e. the body is not contained inside the
// closure span, then we walk up the expansion until we
// find the span before the expansion.
let closure_body_span = self.tcx.hir().span(body_id.hir_id)
.find_ancestor_inside(closure_span)
.unwrap_or(DUMMY_SP);
let mut closure_body_span = {
// If the body was entirely expanded from a macro
// invocation, i.e. the body is not contained inside the
// closure span, then we walk up the expansion until we
// find the span before the expansion.
let s = self.tcx.hir().span(body_id.hir_id);
s.find_ancestor_inside(closure_span).unwrap_or(s)
};
if let Ok(mut s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
if s.starts_with('$') {
// Looks like a macro fragment. Try to find the real block.
if let Some(hir::Node::Expr(&hir::Expr {
kind: hir::ExprKind::Block(block, ..), ..
})) = self.tcx.hir().find(body_id.hir_id) {
// If the body is a block (with `{..}`), we use the span of that block.
// E.g. with a `|| $body` expanded from a `m!({ .. })`, we use `{ .. }`, and not `$body`.
// Since we know it's a block, we know we can insert the `let _ = ..` without
// breaking the macro syntax.
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(block.span) {
closure_body_span = block.span;
s = snippet;
}
}
}
if let Ok(s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
let mut lines = s.lines();
let line1 = lines.next().unwrap_or_default();

View file

@ -21,29 +21,26 @@ use std::iter;
use crate::mem_categorization as mc;
///////////////////////////////////////////////////////////////////////////
// The Delegate trait
/// This trait defines the callbacks you can expect to receive when
/// employing the ExprUseVisitor.
pub trait Delegate<'tcx> {
// The value found at `place` is moved, depending
// on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`.
//
// Use of a `Copy` type in a ByValue context is considered a use
// by `ImmBorrow` and `borrow` is called instead. This is because
// a shared borrow is the "minimum access" that would be needed
// to perform a copy.
//
//
// The parameter `diag_expr_id` indicates the HIR id that ought to be used for
// diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
// id will be the id of the expression `expr` but the place itself will have
// the id of the binding in the pattern `pat`.
/// The value found at `place` is moved, depending
/// on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`.
///
/// Use of a `Copy` type in a ByValue context is considered a use
/// by `ImmBorrow` and `borrow` is called instead. This is because
/// a shared borrow is the "minimum access" that would be needed
/// to perform a copy.
///
///
/// The parameter `diag_expr_id` indicates the HIR id that ought to be used for
/// diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
/// id will be the id of the expression `expr` but the place itself will have
/// the id of the binding in the pattern `pat`.
fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId);
// The value found at `place` is being borrowed with kind `bk`.
// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
/// The value found at `place` is being borrowed with kind `bk`.
/// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
fn borrow(
&mut self,
place_with_id: &PlaceWithHirId<'tcx>,
@ -51,44 +48,47 @@ pub trait Delegate<'tcx> {
bk: ty::BorrowKind,
);
// The path at `assignee_place` is being assigned to.
// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
/// The path at `assignee_place` is being assigned to.
/// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId);
// The `place` should be a fake read because of specified `cause`.
/// The `place` should be a fake read because of specified `cause`.
fn fake_read(&mut self, place: Place<'tcx>, cause: FakeReadCause, diag_expr_id: hir::HirId);
}
#[derive(Copy, Clone, PartialEq, Debug)]
enum ConsumeMode {
Copy, // reference to x where x has a type that copies
Move, // reference to x where x has a type that moves
/// reference to x where x has a type that copies
Copy,
/// reference to x where x has a type that moves
Move,
}
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum MutateMode {
Init,
JustWrite, // x = y
WriteAndRead, // x += y
/// Example: `x = y`
JustWrite,
/// Example: `x += y`
WriteAndRead,
}
///////////////////////////////////////////////////////////////////////////
// The ExprUseVisitor type
//
// This is the code that actually walks the tree.
/// The ExprUseVisitor type
///
/// This is the code that actually walks the tree.
pub struct ExprUseVisitor<'a, 'tcx> {
mc: mc::MemCategorizationContext<'a, 'tcx>,
body_owner: LocalDefId,
delegate: &'a mut dyn Delegate<'tcx>,
}
// If the MC results in an error, it's because the type check
// failed (or will fail, when the error is uncovered and reported
// during writeback). In this case, we just ignore this part of the
// code.
//
// Note that this macro appears similar to try!(), but, unlike try!(),
// it does not propagate the error.
/// If the MC results in an error, it's because the type check
/// failed (or will fail, when the error is uncovered and reported
/// during writeback). In this case, we just ignore this part of the
/// code.
///
/// Note that this macro appears similar to try!(), but, unlike try!(),
/// it does not propagate the error.
macro_rules! return_if_err {
($inp: expr) => {
match $inp {
@ -537,9 +537,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
self.walk_expr(with_expr);
}
// Invoke the appropriate delegate calls for anything that gets
// consumed or borrowed as part of the automatic adjustment
// process.
/// Invoke the appropriate delegate calls for anything that gets
/// consumed or borrowed as part of the automatic adjustment
/// process.
fn walk_adjustment(&mut self, expr: &hir::Expr<'_>) {
let adjustments = self.mc.typeck_results.expr_adjustments(expr);
let mut place_with_id = return_if_err!(self.mc.cat_expr_unadjusted(expr));

View file

@ -300,7 +300,10 @@ impl<T> LinkedList<T> {
let tail = self.tail.take();
let len = mem::replace(&mut self.len, 0);
if let Some(head) = head {
let tail = tail.unwrap_or_else(|| unsafe { core::hint::unreachable_unchecked() });
// SAFETY: In a LinkedList, either both the head and tail are None because
// the list is empty, or both head and tail are Some because the list is populated.
// Since we have verified the head is Some, we are sure the tail is Some too.
let tail = unsafe { tail.unwrap_unchecked() };
Some((head, tail, len))
} else {
None

View file

@ -459,11 +459,8 @@ where
debug_assert!(N <= iter.size_hint().1.unwrap_or(usize::MAX));
debug_assert!(N <= iter.size_hint().0);
match collect_into_array(iter) {
Some(array) => array,
// SAFETY: covered by the function contract.
None => unsafe { crate::hint::unreachable_unchecked() },
}
// SAFETY: covered by the function contract.
unsafe { collect_into_array(iter).unwrap_unchecked() }
}
/// Pulls `N` items from `iter` and returns them as an array. If the iterator

View file

@ -402,7 +402,7 @@ impl<'a> Arguments<'a> {
if self.args.is_empty() {
pieces_length
} else if self.pieces[0] == "" && pieces_length < 16 {
} else if !self.pieces.is_empty() && self.pieces[0].is_empty() && pieces_length < 16 {
// If the format string starts with an argument,
// don't preallocate anything, unless length
// of pieces is significant.
@ -1163,7 +1163,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
}
// SAFETY: arg and args.args come from the same Arguments,
// which guarantees the indexes are always within bounds.
unsafe { run(&mut formatter, arg, &args.args) }?;
unsafe { run(&mut formatter, arg, args.args) }?;
idx += 1;
}
}
@ -1409,7 +1409,7 @@ impl<'a> Formatter<'a> {
// we know that it can't panic. Use `get` + `unwrap_or` to avoid
// `unsafe` and otherwise don't emit any panic-related code
// here.
s.get(..i).unwrap_or(&s)
s.get(..i).unwrap_or(s)
} else {
&s
}
@ -1421,16 +1421,21 @@ impl<'a> Formatter<'a> {
// If we're under the maximum length, and there's no minimum length
// requirements, then we can just emit the string
None => self.buf.write_str(s),
// If we're under the maximum width, check if we're over the minimum
// width, if so it's as easy as just emitting the string.
Some(width) if s.chars().count() >= width => self.buf.write_str(s),
// If we're under both the maximum and the minimum width, then fill
// up the minimum width with the specified string + some alignment.
Some(width) => {
let align = rt::v1::Alignment::Left;
let post_padding = self.padding(width - s.chars().count(), align)?;
self.buf.write_str(s)?;
post_padding.write(self.buf)
let chars_count = s.chars().count();
// If we're under the maximum width, check if we're over the minimum
// width, if so it's as easy as just emitting the string.
if chars_count >= width {
self.buf.write_str(s)
}
// If we're under both the maximum and the minimum width, then fill
// up the minimum width with the specified string + some alignment.
else {
let align = rt::v1::Alignment::Left;
let post_padding = self.padding(width - chars_count, align)?;
self.buf.write_str(s)?;
post_padding.write(self.buf)
}
}
}
}

View file

@ -1834,6 +1834,173 @@ macro_rules! int_impl {
}
}
/// Calculates the quotient of `self` and `rhs`, rounding the result towards negative infinity.
///
/// # Panics
///
/// This function will panic if `rhs` is 0 or the division results in overflow.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(int_roundings)]
#[doc = concat!("let a: ", stringify!($SelfT)," = 8;")]
/// let b = 3;
///
/// assert_eq!(a.div_floor(b), 2);
/// assert_eq!(a.div_floor(-b), -3);
/// assert_eq!((-a).div_floor(b), -3);
/// assert_eq!((-a).div_floor(-b), 2);
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[rustc_inherit_overflow_checks]
pub const fn div_floor(self, rhs: Self) -> Self {
let d = self / rhs;
let r = self % rhs;
if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {
d - 1
} else {
d
}
}
/// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity.
///
/// # Panics
///
/// This function will panic if `rhs` is 0 or the division results in overflow.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(int_roundings)]
#[doc = concat!("let a: ", stringify!($SelfT)," = 8;")]
/// let b = 3;
///
/// assert_eq!(a.div_ceil(b), 3);
/// assert_eq!(a.div_ceil(-b), -2);
/// assert_eq!((-a).div_ceil(b), -2);
/// assert_eq!((-a).div_ceil(-b), 3);
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[rustc_inherit_overflow_checks]
pub const fn div_ceil(self, rhs: Self) -> Self {
let d = self / rhs;
let r = self % rhs;
if (r > 0 && rhs > 0) || (r < 0 && rhs < 0) {
d + 1
} else {
d
}
}
/// If `rhs` is positive, calculates the smallest value greater than or
/// equal to `self` that is a multiple of `rhs`. If `rhs` is negative,
/// calculates the largest value less than or equal to `self` that is a
/// multiple of `rhs`.
///
/// # Panics
///
/// This function will panic if `rhs` is 0 or the operation results in overflow.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(int_roundings)]
#[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")]
#[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")]
#[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(-8), 16);")]
#[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(-8), 16);")]
#[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(8), -16);")]
#[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(8), -16);")]
#[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(-8), -16);")]
#[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(-8), -24);")]
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[rustc_inherit_overflow_checks]
pub const fn next_multiple_of(self, rhs: Self) -> Self {
// This would otherwise fail when calculating `r` when self == T::MIN.
if rhs == -1 {
return self;
}
let r = self % rhs;
let m = if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {
r + rhs
} else {
r
};
if m == 0 {
self
} else {
self + (rhs - m)
}
}
/// If `rhs` is positive, calculates the smallest value greater than or
/// equal to `self` that is a multiple of `rhs`. If `rhs` is negative,
/// calculates the largest value less than or equal to `self` that is a
/// multiple of `rhs`. Returns `None` if `rhs` is zero or the operation
/// would result in overflow.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(int_roundings)]
#[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(16));")]
#[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(24));")]
#[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".checked_next_multiple_of(-8), Some(16));")]
#[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".checked_next_multiple_of(-8), Some(16));")]
#[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").checked_next_multiple_of(8), Some(-16));")]
#[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").checked_next_multiple_of(8), Some(-16));")]
#[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").checked_next_multiple_of(-8), Some(-16));")]
#[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").checked_next_multiple_of(-8), Some(-24));")]
#[doc = concat!("assert_eq!(1_", stringify!($SelfT), ".checked_next_multiple_of(0), None);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_next_multiple_of(2), None);")]
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[rustc_inherit_overflow_checks]
pub const fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
// This would otherwise fail when calculating `r` when self == T::MIN.
if rhs == -1 {
return Some(self);
}
let r = try_opt!(self.checked_rem(rhs));
let m = if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {
try_opt!(r.checked_add(rhs))
} else {
r
};
if m == 0 {
Some(self)
} else {
self.checked_add(try_opt!(rhs.checked_sub(m)))
}
}
/// Returns the logarithm of the number with respect to an arbitrary base.
///
/// This method might not be optimized owing to implementation details;

View file

@ -1848,6 +1848,110 @@ macro_rules! uint_impl {
self % rhs
}
/// Calculates the quotient of `self` and `rhs`, rounding the result towards negative infinity.
///
/// This is the same as performing `self / rhs` for all unsigned integers.
///
/// # Panics
///
/// This function will panic if `rhs` is 0.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(int_roundings)]
#[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_floor(4), 1);")]
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[inline(always)]
#[rustc_inherit_overflow_checks]
pub const fn div_floor(self, rhs: Self) -> Self {
self / rhs
}
/// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity.
///
/// # Panics
///
/// This function will panic if `rhs` is 0.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(int_roundings)]
#[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_ceil(4), 2);")]
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[inline]
#[rustc_inherit_overflow_checks]
pub const fn div_ceil(self, rhs: Self) -> Self {
let d = self / rhs;
let r = self % rhs;
if r > 0 && rhs > 0 {
d + 1
} else {
d
}
}
/// Calculates the smallest value greater than or equal to `self` that
/// is a multiple of `rhs`.
///
/// # Panics
///
/// This function will panic if `rhs` is 0 or the operation results in overflow.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(int_roundings)]
#[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")]
#[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")]
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[rustc_inherit_overflow_checks]
pub const fn next_multiple_of(self, rhs: Self) -> Self {
match self % rhs {
0 => self,
r => self + (rhs - r)
}
}
/// Calculates the smallest value greater than or equal to `self` that
/// is a multiple of `rhs`. If `rhs` is negative,
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(int_roundings)]
#[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(16));")]
#[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(24));")]
#[doc = concat!("assert_eq!(1_", stringify!($SelfT), ".checked_next_multiple_of(0), None);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_next_multiple_of(2), None);")]
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[rustc_inherit_overflow_checks]
pub const fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
match try_opt!(self.checked_rem(rhs)) {
0 => Some(self),
r => self.checked_add(try_opt!(rhs.checked_sub(r)))
}
}
/// Returns `true` if and only if `self == 2^k` for some `k`.
///
/// # Examples

View file

@ -1198,11 +1198,8 @@ impl<T> Option<T> {
pub fn insert(&mut self, value: T) -> &mut T {
*self = Some(value);
match self {
Some(v) => v,
// SAFETY: the code above just filled the option
None => unsafe { hint::unreachable_unchecked() },
}
// SAFETY: the code above just filled the option
unsafe { self.as_mut().unwrap_unchecked() }
}
/// Inserts `value` into the option if it is [`None`], then

View file

@ -64,6 +64,7 @@
#![feature(unsized_tuple_coercion)]
#![feature(const_option)]
#![feature(integer_atomics)]
#![feature(int_roundings)]
#![feature(slice_group_by)]
#![feature(trusted_random_access)]
#![feature(unsize)]

View file

@ -289,6 +289,55 @@ macro_rules! int_module {
assert_eq!(r.saturating_pow(3), -8 as $T);
assert_eq!(r.saturating_pow(0), 1 as $T);
}
#[test]
fn test_div_floor() {
let a: $T = 8;
let b = 3;
assert_eq!(a.div_floor(b), 2);
assert_eq!(a.div_floor(-b), -3);
assert_eq!((-a).div_floor(b), -3);
assert_eq!((-a).div_floor(-b), 2);
}
#[test]
fn test_div_ceil() {
let a: $T = 8;
let b = 3;
assert_eq!(a.div_ceil(b), 3);
assert_eq!(a.div_ceil(-b), -2);
assert_eq!((-a).div_ceil(b), -2);
assert_eq!((-a).div_ceil(-b), 3);
}
#[test]
fn test_next_multiple_of() {
assert_eq!((16 as $T).next_multiple_of(8), 16);
assert_eq!((23 as $T).next_multiple_of(8), 24);
assert_eq!((16 as $T).next_multiple_of(-8), 16);
assert_eq!((23 as $T).next_multiple_of(-8), 16);
assert_eq!((-16 as $T).next_multiple_of(8), -16);
assert_eq!((-23 as $T).next_multiple_of(8), -16);
assert_eq!((-16 as $T).next_multiple_of(-8), -16);
assert_eq!((-23 as $T).next_multiple_of(-8), -24);
assert_eq!(MIN.next_multiple_of(-1), MIN);
}
#[test]
fn test_checked_next_multiple_of() {
assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16));
assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24));
assert_eq!((16 as $T).checked_next_multiple_of(-8), Some(16));
assert_eq!((23 as $T).checked_next_multiple_of(-8), Some(16));
assert_eq!((-16 as $T).checked_next_multiple_of(8), Some(-16));
assert_eq!((-23 as $T).checked_next_multiple_of(8), Some(-16));
assert_eq!((-16 as $T).checked_next_multiple_of(-8), Some(-16));
assert_eq!((-23 as $T).checked_next_multiple_of(-8), Some(-24));
assert_eq!((1 as $T).checked_next_multiple_of(0), None);
assert_eq!(MAX.checked_next_multiple_of(2), None);
assert_eq!(MIN.checked_next_multiple_of(-3), None);
assert_eq!(MIN.checked_next_multiple_of(-1), Some(MIN));
}
}
};
}

View file

@ -205,6 +205,31 @@ macro_rules! uint_module {
assert_eq!(r.overflowing_pow(2), (1 as $T, true));
assert_eq!(r.saturating_pow(2), MAX);
}
#[test]
fn test_div_floor() {
assert_eq!((8 as $T).div_floor(3), 2);
}
#[test]
fn test_div_ceil() {
assert_eq!((8 as $T).div_ceil(3), 3);
}
#[test]
fn test_next_multiple_of() {
assert_eq!((16 as $T).next_multiple_of(8), 16);
assert_eq!((23 as $T).next_multiple_of(8), 24);
assert_eq!(MAX.next_multiple_of(1), MAX);
}
#[test]
fn test_checked_next_multiple_of() {
assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16));
assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24));
assert_eq!((1 as $T).checked_next_multiple_of(0), None);
assert_eq!(MAX.checked_next_multiple_of(2), None);
}
}
};
}

View file

@ -934,7 +934,6 @@ impl DirBuilderExt for fs::DirBuilder {
/// # Examples
///
/// ```no_run
/// #![feature(unix_chroot)]
/// use std::os::unix::fs;
///
/// fn main() -> std::io::Result<()> {
@ -944,7 +943,7 @@ impl DirBuilderExt for fs::DirBuilder {
/// Ok(())
/// }
/// ```
#[unstable(feature = "unix_chroot", issue = "84715")]
#[stable(feature = "unix_chroot", since = "1.56.0")]
#[cfg(not(any(target_os = "fuchsia", target_os = "vxworks")))]
pub fn chroot<P: AsRef<Path>>(dir: P) -> io::Result<()> {
sys::fs::chroot(dir.as_ref())

View file

@ -1311,10 +1311,11 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
}
hir::QPath::TypeRelative(ref qself, ref segment) => {
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
let res = if let ty::Projection(proj) = ty.kind() {
Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id)
} else {
Res::Err
let res = match ty.kind() {
ty::Projection(proj) => Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id),
// Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s.
ty::Error(_) => return Type::Infer,
_ => bug!("clean: expected associated type, found `{:?}`", ty),
};
let trait_path = hir::Path { span, res, segments: &[] }.clean(cx);
Type::QPath {
@ -1379,6 +1380,7 @@ impl Clean<Type> for hir::Ty<'_> {
DynTrait(bounds, lifetime)
}
TyKind::BareFn(ref barefn) => BareFunction(Box::new(barefn.clean(cx))),
// Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
TyKind::Infer | TyKind::Err => Infer,
TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind),
}

View file

@ -0,0 +1,17 @@
// This test ensures that rustdoc does not panic on inherented associated types
// that are referred to without fully-qualified syntax.
#![feature(inherent_associated_types)]
#![allow(incomplete_features)]
pub struct Struct;
impl Struct {
pub type AssocTy = usize;
pub const AssocConst: Self::AssocTy = 42;
//~^ ERROR ambiguous associated type
//~| HELP use fully-qualified syntax
// FIXME: for some reason, the error is shown twice with rustdoc but only once with rustc
//~| ERROR ambiguous associated type
//~| HELP use fully-qualified syntax
}

View file

@ -0,0 +1,15 @@
error[E0223]: ambiguous associated type
--> $DIR/ambiguous-inherent-assoc-ty.rs:11:27
|
LL | pub const AssocConst: Self::AssocTy = 42;
| ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Struct as Trait>::AssocTy`
error[E0223]: ambiguous associated type
--> $DIR/ambiguous-inherent-assoc-ty.rs:11:27
|
LL | pub const AssocConst: Self::AssocTy = 42;
| ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Struct as Trait>::AssocTy`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0223`.

View file

@ -0,0 +1,25 @@
// run-rustfix
// edition:2018
// check-pass
#![warn(rust_2021_compatibility)]
macro_rules! m {
(@ $body:expr) => {{
let f = || $body;
//~^ WARNING: drop order
f();
}};
($body:block) => {{
m!(@ $body);
}};
}
fn main() {
let a = (1.to_string(), 2.to_string());
m!({
let _ = &a;
//~^ HELP: add a dummy
let x = a.0;
println!("{}", x);
});
}

View file

@ -0,0 +1,24 @@
// run-rustfix
// edition:2018
// check-pass
#![warn(rust_2021_compatibility)]
macro_rules! m {
(@ $body:expr) => {{
let f = || $body;
//~^ WARNING: drop order
f();
}};
($body:block) => {{
m!(@ $body);
}};
}
fn main() {
let a = (1.to_string(), 2.to_string());
m!({
//~^ HELP: add a dummy
let x = a.0;
println!("{}", x);
});
}

View file

@ -0,0 +1,37 @@
warning: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/closure-body-macro-fragment.rs:8:17
|
LL | let f = || $body;
| _________________^
LL | |
LL | | f();
LL | | }};
| | - in Rust 2018, `a` is dropped here, but in Rust 2021, only `a.0` will be dropped here as part of the closure
LL | | ($body:block) => {{
LL | | m!(@ $body);
| |__________________^
...
LL | / m!({
LL | |
LL | | let x = a.0;
| | --- in Rust 2018, this closure captures all of `a`, but in Rust 2021, it will only capture `a.0`
LL | | println!("{}", x);
LL | | });
| |_______- in this macro invocation
|
note: the lint level is defined here
--> $DIR/closure-body-macro-fragment.rs:4:9
|
LL | #![warn(rust_2021_compatibility)]
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: `#[warn(rust_2021_incompatible_closure_captures)]` implied by `#[warn(rust_2021_compatibility)]`
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
= note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
help: add a dummy let to cause `a` to be fully captured
|
LL ~ m!({
LL + let _ = &a;
|
warning: 1 warning emitted

View file

@ -0,0 +1,26 @@
// build-pass
#![feature(const_trait_impl)]
trait Func<T> {
type Output;
fn call_once(self, arg: T) -> Self::Output;
}
struct Closure;
impl const Func<&usize> for Closure {
type Output = usize;
fn call_once(self, arg: &usize) -> Self::Output {
*arg
}
}
enum Bug<T = [(); Closure.call_once(&0) ]> {
V(T),
}
fn main() {}

View file

@ -0,0 +1,49 @@
// check-pass
// Regression test for issue #83190, triggering an ICE in borrowck.
pub trait Any {}
impl<T> Any for T {}
pub trait StreamOnce {
type Range;
}
pub trait Parser<Input>: Sized {
type Output;
type PartialState;
fn map(self) -> Map<Self> {
todo!()
}
}
pub struct Map<P>(P);
impl<I, P: Parser<I, Output = ()>> Parser<I> for Map<P> {
type Output = ();
type PartialState = P::PartialState;
}
struct TakeWhile1<Input>(Input);
impl<I: StreamOnce> Parser<I> for TakeWhile1<I> {
type Output = I::Range;
type PartialState = ();
}
impl<I> TakeWhile1<I> {
fn new() -> Self {
todo!()
}
}
impl<I, A: Parser<I>> Parser<I> for (A,) {
type Output = ();
type PartialState = Map<A::Output>;
}
pub fn metric_stream_parser<'a, I>() -> impl Parser<I, Output = (), PartialState = impl Any + 'a>
where
I: StreamOnce<Range = &'a [()]>,
{
(TakeWhile1::new(),).map()
}
fn main() {}

View file

@ -19,9 +19,12 @@ fn main() {
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
//~| WARNING this changes meaning
// The `array_into_iter` lint doesn't cover other wrappers that deref to an array.
let _: Iter<'_, i32> = Rc::new(array).into_iter();
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
//~| WARNING this changes meaning
let _: Iter<'_, i32> = Array(array).into_iter();
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
//~| WARNING this changes meaning
// But you can always use the trait method explicitly as an array.
let _: IntoIter<i32, 10> = IntoIterator::into_iter(array);

View file

@ -20,21 +20,31 @@ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (du
--> $DIR/into-iter-on-arrays-2018.rs:18:44
|
LL | let _: Iter<'_, i32> = Box::new(array).into_iter();
| ^^^^^^^^^
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this changes meaning in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | let _: Iter<'_, i32> = Box::new(array).iter();
| ~~~~
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
|
LL | let _: Iter<'_, i32> = IntoIterator::into_iter(Box::new(array));
| ++++++++++++++++++++++++ ~
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
--> $DIR/into-iter-on-arrays-2018.rs:29:24
--> $DIR/into-iter-on-arrays-2018.rs:22:43
|
LL | let _: Iter<'_, i32> = Rc::new(array).into_iter();
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this changes meaning in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
--> $DIR/into-iter-on-arrays-2018.rs:25:41
|
LL | let _: Iter<'_, i32> = Array(array).into_iter();
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this changes meaning in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
--> $DIR/into-iter-on-arrays-2018.rs:32:24
|
LL | for _ in [1, 2, 3].into_iter() {}
| ^^^^^^^^^
@ -51,5 +61,5 @@ LL - for _ in [1, 2, 3].into_iter() {}
LL + for _ in [1, 2, 3] {}
|
warning: 3 warnings emitted
warning: 5 warnings emitted

View file

@ -71,137 +71,73 @@ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (du
--> $DIR/into-iter-on-arrays-lint.rs:23:21
|
LL | Box::new(small).into_iter();
| ^^^^^^^^^
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this changes meaning in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new(small).iter();
| ~~~~
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
|
LL | IntoIterator::into_iter(Box::new(small));
| ++++++++++++++++++++++++ ~
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
--> $DIR/into-iter-on-arrays-lint.rs:26:22
|
LL | Box::new([1, 2]).into_iter();
| ^^^^^^^^^
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this changes meaning in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new([1, 2]).iter();
| ~~~~
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
|
LL | IntoIterator::into_iter(Box::new([1, 2]));
| ++++++++++++++++++++++++ ~
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
--> $DIR/into-iter-on-arrays-lint.rs:29:19
|
LL | Box::new(big).into_iter();
| ^^^^^^^^^
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this changes meaning in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new(big).iter();
| ~~~~
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
|
LL | IntoIterator::into_iter(Box::new(big));
| ++++++++++++++++++++++++ ~
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
--> $DIR/into-iter-on-arrays-lint.rs:32:25
|
LL | Box::new([0u8; 33]).into_iter();
| ^^^^^^^^^
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this changes meaning in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new([0u8; 33]).iter();
| ~~~~
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
|
LL | IntoIterator::into_iter(Box::new([0u8; 33]));
| ++++++++++++++++++++++++ ~
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
--> $DIR/into-iter-on-arrays-lint.rs:36:31
|
LL | Box::new(Box::new(small)).into_iter();
| ^^^^^^^^^
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this changes meaning in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new(Box::new(small)).iter();
| ~~~~
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
|
LL | IntoIterator::into_iter(Box::new(Box::new(small)));
| ++++++++++++++++++++++++ ~
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
--> $DIR/into-iter-on-arrays-lint.rs:39:32
|
LL | Box::new(Box::new([1, 2])).into_iter();
| ^^^^^^^^^
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this changes meaning in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new(Box::new([1, 2])).iter();
| ~~~~
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
|
LL | IntoIterator::into_iter(Box::new(Box::new([1, 2])));
| ++++++++++++++++++++++++ ~
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
--> $DIR/into-iter-on-arrays-lint.rs:42:29
|
LL | Box::new(Box::new(big)).into_iter();
| ^^^^^^^^^
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this changes meaning in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new(Box::new(big)).iter();
| ~~~~
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
|
LL | IntoIterator::into_iter(Box::new(Box::new(big)));
| ++++++++++++++++++++++++ ~
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
--> $DIR/into-iter-on-arrays-lint.rs:45:35
|
LL | Box::new(Box::new([0u8; 33])).into_iter();
| ^^^^^^^^^
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this changes meaning in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new(Box::new([0u8; 33])).iter();
| ~~~~
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
|
LL | IntoIterator::into_iter(Box::new(Box::new([0u8; 33])));
| ++++++++++++++++++++++++ ~
warning: 12 warnings emitted