From 9d3e84432dae2e96a5e0f97be18ee09b5a2217b1 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Wed, 22 Jan 2020 20:28:28 +0000 Subject: Avoid overflow in `std::iter::Skip::count` The call to `count` on the inner iterator can overflow even if `Skip` itself would return less that `usize::max_value()` items. --- src/libcore/iter/adapters/mod.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/libcore') diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 6eb837ed0fe..5787b9174ed 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -1815,8 +1815,14 @@ where } #[inline] - fn count(self) -> usize { - self.iter.count().saturating_sub(self.n) + fn count(mut self) -> usize { + if self.n > 0 { + // nth(n) skips n+1 + if self.iter.nth(self.n - 1).is_none() { + return 0; + } + } + self.iter.count() } #[inline] -- cgit 1.4.1-3-g733a5 From 6eaf59dfc8be4ee5647f9c090c5a7668682f30c0 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Thu, 23 Jan 2020 11:51:56 -0800 Subject: use `diagnostic_item` and modify wording --- src/libcore/option.rs | 1 + src/libcore/result.rs | 1 + .../borrow_check/diagnostics/move_errors.rs | 22 ++++++++++++++++------ src/test/ui/suggestions/for-i-in-vec.stderr | 2 +- 4 files changed, 19 insertions(+), 7 deletions(-) (limited to 'src/libcore') diff --git a/src/libcore/option.rs b/src/libcore/option.rs index a471b174534..cb4247d9874 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -151,6 +151,7 @@ use crate::{ /// The `Option` type. See [the module level documentation](index.html) for more. #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +#[rustc_diagnostic_item = "option_type"] #[stable(feature = "rust1", since = "1.0.0")] pub enum Option { /// No value diff --git a/src/libcore/result.rs b/src/libcore/result.rs index c657ce33f60..bc70dbd62eb 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -242,6 +242,7 @@ use crate::ops::{self, Deref, DerefMut}; /// [`Err`]: enum.Result.html#variant.Err #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[must_use = "this `Result` may be an `Err` variant, which should be handled"] +#[rustc_diagnostic_item = "result_type"] #[stable(feature = "rust1", since = "1.0.0")] pub enum Result { /// Contains the success value diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs index c016cc90b1b..43121b38da0 100644 --- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs @@ -2,7 +2,7 @@ use rustc::mir::*; use rustc::ty; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_span::source_map::DesugaringKind; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; use crate::borrow_check::diagnostics::UseSpans; use crate::borrow_check::prefixes::PrefixSet; @@ -384,10 +384,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } }; - let move_ty = format!("{:?}", move_place.ty(*self.body, self.infcx.tcx).ty,); if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { - let is_option = move_ty.starts_with("std::option::Option"); - let is_result = move_ty.starts_with("std::result::Result"); + let def_id = match move_place.ty(*self.body, self.infcx.tcx).ty.kind { + ty::Adt(self_def, _) => self_def.did, + ty::Foreign(def_id) + | ty::FnDef(def_id, _) + | ty::Closure(def_id, _) + | ty::Generator(def_id, ..) + | ty::Opaque(def_id, _) => def_id, + _ => return err, + }; + let is_option = + self.infcx.tcx.is_diagnostic_item(Symbol::intern("option_type"), def_id); + let is_result = + self.infcx.tcx.is_diagnostic_item(Symbol::intern("result_type"), def_id); if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) { err.span_suggestion( span, @@ -399,12 +409,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); } else if span.is_desugaring(DesugaringKind::ForLoop) - && move_ty.starts_with("std::vec::Vec") + && self.infcx.tcx.is_diagnostic_item(Symbol::intern("vec_type"), def_id) { // FIXME: suggest for anything that implements `IntoIterator`. err.span_suggestion( span, - "consider iterating over a slice of the `Vec`'s content", + "consider iterating over a slice of the `Vec<_>`'s content", format!("&{}", snippet), Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/suggestions/for-i-in-vec.stderr b/src/test/ui/suggestions/for-i-in-vec.stderr index 0fd10489bd0..576a7cc2f60 100644 --- a/src/test/ui/suggestions/for-i-in-vec.stderr +++ b/src/test/ui/suggestions/for-i-in-vec.stderr @@ -5,7 +5,7 @@ LL | for _ in self.v { | ^^^^^^ | | | move occurs because `self.v` has type `std::vec::Vec`, which does not implement the `Copy` trait - | help: consider iterating over a slice of the `Vec`'s content: `&self.v` + | help: consider iterating over a slice of the `Vec<_>`'s content: `&self.v` error: aborting due to previous error -- cgit 1.4.1-3-g733a5