diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index 21fad5f9af683..5ac42c50c7240 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -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![ diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 346a9e8021731..83f6e79d5fcf6 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -411,8 +411,7 @@ impl<'tcx> Body<'tcx> { /// Returns an iterator over all function arguments. #[inline] pub fn args_iter(&self) -> impl Iterator + 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 + 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] diff --git a/compiler/rustc_mir/src/transform/check_consts/check.rs b/compiler/rustc_mir/src/transform/check_consts/check.rs index 2b748062cdf23..0c38127682359 100644 --- a/compiler/rustc_mir/src/transform/check_consts/check.rs +++ b/compiler/rustc_mir/src/transform/check_consts/check.rs @@ -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 diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 63a8f0624759c..c3fdf4fc22851 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -61,7 +61,7 @@ where } fn query(self, map: &QueryMap) -> 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 { - pub info: QueryInfo, + pub query: QueryStackFrame, pub job: QueryJob, } @@ -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( }; 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; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index a7511846cadb6..3f22de6fba407 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -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() }); } } } diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index a25d0f8064404..702f69a9fcf0b 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -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(); diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 3d483e322a851..ba70006fe96b3 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -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)); diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 7aa24ff4afaee..9d45c5082db43 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -300,7 +300,10 @@ impl LinkedList { 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 diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 3c638e655dc91..70cccd31b92de 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -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 diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 1d75ac3d254bd..aff789f2afa14 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -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) + } } } } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 1a310917fdfc4..780d6c34c9197 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -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 { + // 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; diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 9366efb32bcf9..02a5ed4ca800e 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -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 { + 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 diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 47865240f6a6f..9d5e03dd0de79 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1198,11 +1198,8 @@ impl Option { 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 diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 7853b571be326..19bcc45108dfd 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -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)] diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs index 90c476567844e..d2d655ea2c750 100644 --- a/library/core/tests/num/int_macros.rs +++ b/library/core/tests/num/int_macros.rs @@ -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)); + } } }; } diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs index 445f8fb350eeb..49f8f1f13fad4 100644 --- a/library/core/tests/num/uint_macros.rs +++ b/library/core/tests/num/uint_macros.rs @@ -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); + } } }; } diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index e4ce788f74195..6cf37f23c574d 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -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>(dir: P) -> io::Result<()> { sys::fs::chroot(dir.as_ref()) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index bde821c5d9cd0..a9baa1c31aeb8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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 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), } diff --git a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs new file mode 100644 index 0000000000000..3ad56aebc21c5 --- /dev/null +++ b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs @@ -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 +} diff --git a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr new file mode 100644 index 0000000000000..b963b722f6620 --- /dev/null +++ b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr @@ -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: `::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: `::AssocTy` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0223`. diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.fixed new file mode 100644 index 0000000000000..f91454aa2111e --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.fixed @@ -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); + }); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.rs b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.rs new file mode 100644 index 0000000000000..5a1026d043319 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.rs @@ -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); + }); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr new file mode 100644 index 0000000000000..e6e5598f6d2a1 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr @@ -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 + = 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 + diff --git a/src/test/ui/const-generics/const_trait_fn-issue-88433.rs b/src/test/ui/const-generics/const_trait_fn-issue-88433.rs new file mode 100644 index 0000000000000..8724fa6982546 --- /dev/null +++ b/src/test/ui/const-generics/const_trait_fn-issue-88433.rs @@ -0,0 +1,26 @@ +// build-pass + +#![feature(const_trait_impl)] + +trait Func { + 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 { + V(T), +} + +fn main() {} diff --git a/src/test/ui/issues/issue-83190.rs b/src/test/ui/issues/issue-83190.rs new file mode 100644 index 0000000000000..da931c3edaf6f --- /dev/null +++ b/src/test/ui/issues/issue-83190.rs @@ -0,0 +1,49 @@ +// check-pass + +// Regression test for issue #83190, triggering an ICE in borrowck. + +pub trait Any {} +impl Any for T {} + +pub trait StreamOnce { + type Range; +} + +pub trait Parser: Sized { + type Output; + type PartialState; + fn map(self) -> Map { + todo!() + } +} + +pub struct Map

(P); +impl> Parser for Map

{ + type Output = (); + type PartialState = P::PartialState; +} + +struct TakeWhile1(Input); +impl Parser for TakeWhile1 { + type Output = I::Range; + type PartialState = (); +} +impl TakeWhile1 { + fn new() -> Self { + todo!() + } +} + +impl> Parser for (A,) { + type Output = (); + type PartialState = Map; +} + +pub fn metric_stream_parser<'a, I>() -> impl Parser +where + I: StreamOnce, +{ + (TakeWhile1::new(),).map() +} + +fn main() {} diff --git a/src/test/ui/iterators/into-iter-on-arrays-2018.rs b/src/test/ui/iterators/into-iter-on-arrays-2018.rs index e56c2956a697e..60995170a5164 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-2018.rs +++ b/src/test/ui/iterators/into-iter-on-arrays-2018.rs @@ -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 = IntoIterator::into_iter(array); diff --git a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr index e9780d9b165c7..bc08fdcafa08d 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr @@ -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 -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 + +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 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 diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr index 138becc4ffe1e..2df1a06df20ab 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr @@ -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 -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 -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 -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 -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 -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 -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 -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 -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