Skip to content

Rollup of 12 pull requests #88596

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Sep 2, 2021
Merged
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4046667
Stabilize std::os::unix::fs::chroot
joshtriplett Aug 20, 2021
b99038f
use `unwrap_unchecked` where possible
ibraheemdev Aug 30, 2021
422ad3b
Upgrade array_into_iter lint to include Deref-to-array types.
m-ou-se Aug 30, 2021
90080f4
Don't give invalid suggestions in array_into_iter.
m-ou-se Aug 30, 2021
96d4666
Update tests for array_into_iter lint upgrade.
m-ou-se Aug 30, 2021
99a3d64
Remove single use variables
ptrojahn Aug 31, 2021
ffc43b8
add safety annotation to `LinkedList::detach_all_nodes`
ibraheemdev Aug 31, 2021
7189c85
Improve closure dummy capture suggestion in macros.
m-ou-se Aug 31, 2021
7d18052
Add test for closure migration where body is a block fragment.
m-ou-se Aug 31, 2021
6c9e708
`fmt::Formatter::pad`: don't call chars().count() more than one time
klensy Sep 1, 2021
f5f489b
fix clippy lints
klensy Sep 1, 2021
a5fd955
add regression test for issue 83190
lqd Sep 1, 2021
4553a4b
Remove redundant `Span` in `QueryJobInfo`
camelid Sep 1, 2021
50983ba
rustdoc: Don't panic on ambiguous inherent associated types
camelid Sep 1, 2021
727a4fc
Implement #88581
jhpratt Sep 2, 2021
a079ae2
Correct doc comments inside `use_expr_visitor.rs`
xFrednet Sep 2, 2021
b5f680e
do not resolve instances for trait fn ids
b-naber Sep 2, 2021
f825d6c
add test
b-naber Sep 2, 2021
e50069f
Rollup merge of #88177 - joshtriplett:stabilize-chroot, r=m-ou-se
m-ou-se Sep 2, 2021
8fd1bf3
Rollup merge of #88505 - ibraheemdev:use-unwrap-unchecked, r=kennytm
m-ou-se Sep 2, 2021
ea82d06
Rollup merge of #88512 - m-ou-se:array-into-iter-deref-stuff, r=estebank
m-ou-se Sep 2, 2021
afdaa2e
Rollup merge of #88532 - ptrojahn:single_use, r=davidtwco
m-ou-se Sep 2, 2021
ffbce26
Rollup merge of #88543 - m-ou-se:closure-migration-macro-block-fragme…
m-ou-se Sep 2, 2021
0d105c0
Rollup merge of #88560 - klensy:formatter-pad-shrink, r=m-ou-se
m-ou-se Sep 2, 2021
e248c4d
Rollup merge of #88565 - lqd:issue-83190, r=spastorino
m-ou-se Sep 2, 2021
f419334
Rollup merge of #88567 - camelid:query-job-info, r=cjgillot
m-ou-se Sep 2, 2021
73162aa
Rollup merge of #88573 - camelid:rustdoc-assoc-panic, r=GuillaumeGomez
m-ou-se Sep 2, 2021
2159c5d
Rollup merge of #88582 - jhpratt:int_roundings, r=joshtriplett
m-ou-se Sep 2, 2021
8f88d44
Rollup merge of #88589 - xFrednet:00000-correct-comment-to-doc, r=pet…
m-ou-se Sep 2, 2021
c082e15
Rollup merge of #88592 - b-naber:region_substs, r=oli-obk
m-ou-se Sep 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 30 additions & 24 deletions compiler/rustc_lint/src/array_into_iter.rs
Original file line number Diff line number Diff line change
@@ -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,
};

// Make sure we found an array after peeling the boxes.
if !matches!(recv_ty.kind(), ty::Array(..)) {
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 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,
if !found_array {
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![
7 changes: 2 additions & 5 deletions compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
@@ -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]
36 changes: 19 additions & 17 deletions compiler/rustc_mir/src/transform/check_consts/check.rs
Original file line number Diff line number Diff line change
@@ -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
15 changes: 6 additions & 9 deletions compiler/rustc_query_system/src/query/job.rs
Original file line number Diff line number Diff line change
@@ -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;
4 changes: 2 additions & 2 deletions compiler/rustc_query_system/src/query/plumbing.rs
Original file line number Diff line number Diff line change
@@ -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() });
}
}
}
35 changes: 26 additions & 9 deletions compiler/rustc_typeck/src/check/upvar.rs
Original file line number Diff line number Diff line change
@@ -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();

78 changes: 39 additions & 39 deletions compiler/rustc_typeck/src/expr_use_visitor.rs
Original file line number Diff line number Diff line change
@@ -21,74 +21,74 @@ 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>,
diag_expr_id: hir::HirId,
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));
5 changes: 4 additions & 1 deletion library/alloc/src/collections/linked_list.rs
Original file line number Diff line number Diff line change
@@ -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
7 changes: 2 additions & 5 deletions library/core/src/array/mod.rs
Original file line number Diff line number Diff line change
@@ -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
29 changes: 17 additions & 12 deletions library/core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
}
167 changes: 167 additions & 0 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
@@ -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;
104 changes: 104 additions & 0 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
@@ -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
7 changes: 2 additions & 5 deletions library/core/src/option.rs
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
@@ -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)]
49 changes: 49 additions & 0 deletions library/core/tests/num/int_macros.rs
Original file line number Diff line number Diff line change
@@ -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));
}
}
};
}
25 changes: 25 additions & 0 deletions library/core/tests/num/uint_macros.rs
Original file line number Diff line number Diff line change
@@ -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);
}
}
};
}
3 changes: 1 addition & 2 deletions library/std/src/os/unix/fs.rs
Original file line number Diff line number Diff line change
@@ -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())
10 changes: 6 additions & 4 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
@@ -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),
}
17 changes: 17 additions & 0 deletions src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs
Original file line number Diff line number Diff line change
@@ -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
}
15 changes: 15 additions & 0 deletions src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
@@ -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);
});
}
Original file line number Diff line number Diff line change
@@ -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);
});
}
Original file line number Diff line number Diff line change
@@ -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

26 changes: 26 additions & 0 deletions src/test/ui/const-generics/const_trait_fn-issue-88433.rs
Original file line number Diff line number Diff line change
@@ -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() {}
49 changes: 49 additions & 0 deletions src/test/ui/issues/issue-83190.rs
Original file line number Diff line number Diff line change
@@ -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() {}
5 changes: 4 additions & 1 deletion src/test/ui/iterators/into-iter-on-arrays-2018.rs
Original file line number Diff line number Diff line change
@@ -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);
28 changes: 19 additions & 9 deletions src/test/ui/iterators/into-iter-on-arrays-2018.stderr
Original file line number Diff line number Diff line change
@@ -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

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:22:43
|
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> = 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> = IntoIterator::into_iter(Box::new(array));
| ++++++++++++++++++++++++ ~
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:29:24
--> $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

80 changes: 8 additions & 72 deletions src/test/ui/iterators/into-iter-on-arrays-lint.stderr
Original file line number Diff line number Diff line change
@@ -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