From c10eec3a1ca0a328f406f6b752eb0fd3a90dca91 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 14 Apr 2021 16:40:23 -0700 Subject: [PATCH 01/11] Bootstrapping preparation for the library Since just `ops::Try` will need to change meaning. --- .../alloc/src/collections/vec_deque/iter.rs | 6 +++--- library/alloc/src/lib.rs | 1 + library/core/src/iter/adapters/chain.rs | 6 +++--- library/core/src/iter/adapters/cloned.rs | 6 +++--- library/core/src/iter/adapters/copied.rs | 6 +++--- library/core/src/iter/adapters/cycle.rs | 4 ++-- library/core/src/iter/adapters/enumerate.rs | 6 +++--- library/core/src/iter/adapters/filter.rs | 8 ++++---- library/core/src/iter/adapters/filter_map.rs | 8 ++++---- library/core/src/iter/adapters/flatten.rs | 18 +++++++++--------- library/core/src/iter/adapters/fuse.rs | 18 +++++++++--------- library/core/src/iter/adapters/inspect.rs | 6 +++--- library/core/src/iter/adapters/map.rs | 6 +++--- library/core/src/iter/adapters/map_while.rs | 4 ++-- library/core/src/iter/adapters/mod.rs | 4 ++-- library/core/src/iter/adapters/peekable.rs | 8 ++++---- library/core/src/iter/adapters/rev.rs | 6 +++--- library/core/src/iter/adapters/scan.rs | 6 +++--- library/core/src/iter/adapters/skip.rs | 8 ++++---- library/core/src/iter/adapters/skip_while.rs | 4 ++-- library/core/src/iter/adapters/step_by.rs | 6 +++--- library/core/src/iter/adapters/take.rs | 8 ++++---- library/core/src/iter/adapters/take_while.rs | 6 +++--- library/core/src/iter/range.rs | 6 +++--- library/core/src/iter/traits/double_ended.rs | 4 ++-- library/core/src/iter/traits/iterator.rs | 10 +++++----- library/core/src/ops/control_flow.rs | 13 ++++++------- library/core/src/ops/mod.rs | 19 +++++++++++++++++++ library/core/src/option.rs | 2 +- library/core/src/result.rs | 2 +- library/core/src/slice/ascii.rs | 2 +- library/core/src/str/iter.rs | 4 ++-- library/core/src/task/poll.rs | 6 +++--- 33 files changed, 123 insertions(+), 104 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs index e4cfb3acdfd5c..793adfb0c0fc8 100644 --- a/library/alloc/src/collections/vec_deque/iter.rs +++ b/library/alloc/src/collections/vec_deque/iter.rs @@ -1,6 +1,6 @@ use core::fmt; use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess}; -use core::ops::Try; +use core::ops::TryWhereOutputEquals; use super::{count, wrap_index, RingSlices}; @@ -66,7 +66,7 @@ impl<'a, T> Iterator for Iter<'a, T> { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { let (mut iter, final_res); if self.tail <= self.head { @@ -140,7 +140,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { let (mut iter, final_res); if self.tail <= self.head { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 66b1036f2ab0b..af973c29bde61 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -141,6 +141,7 @@ #![feature(alloc_layout_extra)] #![feature(trusted_random_access)] #![feature(try_trait)] +#![feature(try_trait_transition)] #![feature(min_type_alias_impl_trait)] #![feature(associated_type_bounds)] #![feature(slice_group_by)] diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs index ce5e9936bbd7f..19bc44776c9a6 100644 --- a/library/core/src/iter/adapters/chain.rs +++ b/library/core/src/iter/adapters/chain.rs @@ -1,5 +1,5 @@ use crate::iter::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen}; -use crate::ops::Try; +use crate::ops::TryWhereOutputEquals; /// An iterator that links two iterators together, in a chain. /// @@ -98,7 +98,7 @@ where where Self: Sized, F: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { if let Some(ref mut a) = self.a { acc = a.try_fold(acc, &mut f)?; @@ -281,7 +281,7 @@ where where Self: Sized, F: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { if let Some(ref mut b) = self.b { acc = b.try_rfold(acc, &mut f)?; diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs index 0abdbba2ef1b0..b0344ce1388ae 100644 --- a/library/core/src/iter/adapters/cloned.rs +++ b/library/core/src/iter/adapters/cloned.rs @@ -1,6 +1,6 @@ use crate::iter::adapters::{zip::try_get_unchecked, TrustedRandomAccess}; use crate::iter::{FusedIterator, TrustedLen}; -use crate::ops::Try; +use crate::ops::TryWhereOutputEquals; /// An iterator that clones the elements of an underlying iterator. /// @@ -46,7 +46,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.it.try_fold(init, clone_try_fold(f)) } @@ -82,7 +82,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.it.try_rfold(init, clone_try_fold(f)) } diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs index 0a5822452a347..d261effc10431 100644 --- a/library/core/src/iter/adapters/copied.rs +++ b/library/core/src/iter/adapters/copied.rs @@ -1,6 +1,6 @@ use crate::iter::adapters::{zip::try_get_unchecked, TrustedRandomAccess}; use crate::iter::{FusedIterator, TrustedLen}; -use crate::ops::Try; +use crate::ops::TryWhereOutputEquals; /// An iterator that copies the elements of an underlying iterator. /// @@ -50,7 +50,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.it.try_fold(init, copy_try_fold(f)) } @@ -98,7 +98,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.it.try_rfold(init, copy_try_fold(f)) } diff --git a/library/core/src/iter/adapters/cycle.rs b/library/core/src/iter/adapters/cycle.rs index 6e9a011f819af..5704dc3590103 100644 --- a/library/core/src/iter/adapters/cycle.rs +++ b/library/core/src/iter/adapters/cycle.rs @@ -1,4 +1,4 @@ -use crate::{iter::FusedIterator, ops::Try}; +use crate::{iter::FusedIterator, ops::TryWhereOutputEquals}; /// An iterator that repeats endlessly. /// @@ -53,7 +53,7 @@ where fn try_fold(&mut self, mut acc: Acc, mut f: F) -> R where F: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { // fully iterate the current iterator. this is necessary because // `self.iter` may be empty even when `self.orig` isn't diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index 73cee1df30c5e..8b37cc4d4a50d 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -1,6 +1,6 @@ use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess}; use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; -use crate::ops::Try; +use crate::ops::TryWhereOutputEquals; /// An iterator that yields the current count and the element during iteration. /// @@ -71,7 +71,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { #[inline] fn enumerate<'a, T, Acc, R>( @@ -150,7 +150,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { // Can safely add and subtract the count, as `ExactSizeIterator` promises // that the number of elements fits into a `usize`. diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs index 0337892b9e8e1..8f5484c9a5c2f 100644 --- a/library/core/src/iter/adapters/filter.rs +++ b/library/core/src/iter/adapters/filter.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; -use crate::ops::Try; +use crate::ops::TryWhereOutputEquals; /// An iterator that filters the elements of `iter` with `predicate`. /// @@ -37,7 +37,7 @@ fn filter_fold( move |acc, item| if predicate(&item) { fold(acc, item) } else { acc } } -fn filter_try_fold<'a, T, Acc, R: Try>( +fn filter_try_fold<'a, T, Acc, R: TryWhereOutputEquals>( predicate: &'a mut impl FnMut(&T) -> bool, mut fold: impl FnMut(Acc, T) -> R + 'a, ) -> impl FnMut(Acc, T) -> R + 'a { @@ -88,7 +88,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.iter.try_fold(init, filter_try_fold(&mut self.predicate, fold)) } @@ -117,7 +117,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.iter.try_rfold(init, filter_try_fold(&mut self.predicate, fold)) } diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs index 0dccf2c533b57..308f984cd940e 100644 --- a/library/core/src/iter/adapters/filter_map.rs +++ b/library/core/src/iter/adapters/filter_map.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; -use crate::ops::{ControlFlow, Try}; +use crate::ops::{ControlFlow, TryWhereOutputEquals}; /// An iterator that uses `f` to both filter and map elements from `iter`. /// @@ -39,7 +39,7 @@ fn filter_map_fold( } } -fn filter_map_try_fold<'a, T, B, Acc, R: Try>( +fn filter_map_try_fold<'a, T, B, Acc, R: TryWhereOutputEquals>( f: &'a mut impl FnMut(T) -> Option, mut fold: impl FnMut(Acc, B) -> R + 'a, ) -> impl FnMut(Acc, T) -> R + 'a { @@ -72,7 +72,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.iter.try_fold(init, filter_map_try_fold(&mut self.f, fold)) } @@ -111,7 +111,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.iter.try_rfold(init, filter_map_try_fold(&mut self.f, fold)) } diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 0114d7af4f410..b2fe1499ca663 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map}; -use crate::ops::Try; +use crate::ops::TryWhereOutputEquals; /// An iterator that maps each element to an iterator, and yields the elements /// of the produced iterators. @@ -61,7 +61,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.inner.try_fold(init, fold) } @@ -91,7 +91,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.inner.try_rfold(init, fold) } @@ -178,7 +178,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.inner.try_fold(init, fold) } @@ -208,7 +208,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.inner.try_rfold(init, fold) } @@ -293,10 +293,10 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { #[inline] - fn flatten<'a, T: IntoIterator, Acc, R: Try>( + fn flatten<'a, T: IntoIterator, Acc, R: TryWhereOutputEquals>( frontiter: &'a mut Option, fold: &'a mut impl FnMut(Acc, T::Item) -> R, ) -> impl FnMut(Acc, T) -> R + 'a { @@ -382,10 +382,10 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { #[inline] - fn flatten<'a, T: IntoIterator, Acc, R: Try>( + fn flatten<'a, T: IntoIterator, Acc, R: TryWhereOutputEquals>( backiter: &'a mut Option, fold: &'a mut impl FnMut(Acc, T::Item) -> R, ) -> impl FnMut(Acc, T) -> R + 'a diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index c01f384dec5d6..43d0626e3b7e8 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -3,7 +3,7 @@ use crate::iter::adapters::{zip::try_get_unchecked, InPlaceIterable, SourceIter} use crate::iter::{ DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess, }; -use crate::ops::Try; +use crate::ops::TryWhereOutputEquals; /// An iterator that yields `None` forever after the underlying iterator /// yields `None` once. @@ -92,7 +92,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { FuseImpl::try_fold(self, acc, fold) } @@ -148,7 +148,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { FuseImpl::try_rfold(self, acc, fold) } @@ -219,7 +219,7 @@ trait FuseImpl { where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try; + R: TryWhereOutputEquals; fn fold(self, acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc; @@ -238,7 +238,7 @@ trait FuseImpl { where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, I: DoubleEndedIterator; fn rfold(self, acc: Acc, fold: Fold) -> Acc where @@ -305,7 +305,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { if let Some(ref mut iter) = self.iter { acc = iter.try_fold(acc, fold)?; @@ -354,7 +354,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, I: DoubleEndedIterator, { if let Some(ref mut iter) = self.iter { @@ -443,7 +443,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { unchecked!(self).try_fold(init, fold) } @@ -485,7 +485,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, I: DoubleEndedIterator, { unchecked!(self).try_rfold(init, fold) diff --git a/library/core/src/iter/adapters/inspect.rs b/library/core/src/iter/adapters/inspect.rs index 88f5ee61b6b73..3221a0eeafa03 100644 --- a/library/core/src/iter/adapters/inspect.rs +++ b/library/core/src/iter/adapters/inspect.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; -use crate::ops::Try; +use crate::ops::TryWhereOutputEquals; /// An iterator that calls a function with a reference to each element before /// yielding it. @@ -87,7 +87,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold)) } @@ -117,7 +117,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold)) } diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index 2a4b7efd5e665..8ca7adb013fe4 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -1,7 +1,7 @@ use crate::fmt; use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess}; use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; -use crate::ops::Try; +use crate::ops::TryWhereOutputEquals; /// An iterator that maps the values of `iter` with `f`. /// @@ -110,7 +110,7 @@ where where Self: Sized, G: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.iter.try_fold(init, map_try_fold(&mut self.f, g)) } @@ -146,7 +146,7 @@ where where Self: Sized, G: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.iter.try_rfold(init, map_try_fold(&mut self.f, g)) } diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs index 26114d5328498..ab16dbdb073dd 100644 --- a/library/core/src/iter/adapters/map_while.rs +++ b/library/core/src/iter/adapters/map_while.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, InPlaceIterable}; -use crate::ops::{ControlFlow, Try}; +use crate::ops::{ControlFlow, TryWhereOutputEquals}; /// An iterator that only accepts elements while `predicate` returns `Some(_)`. /// @@ -54,7 +54,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { let Self { iter, predicate } = self; iter.try_fold(init, |acc, x| match predicate(x) { diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 61d8351d59f09..048d209561b42 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1,5 +1,5 @@ use crate::iter::{InPlaceIterable, Iterator}; -use crate::ops::{ControlFlow, Try}; +use crate::ops::{ControlFlow, TryWhereOutputEquals}; mod chain; mod cloned; @@ -167,7 +167,7 @@ where fn try_fold(&mut self, init: B, mut f: F) -> R where F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { let error = &mut *self.error; self.iter diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 21386e28a9643..7e851c67de434 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -1,5 +1,5 @@ use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen}; -use crate::ops::Try; +use crate::ops::TryWhereOutputEquals; /// An iterator with a `peek()` that returns an optional reference to the next /// element. @@ -91,7 +91,7 @@ impl Iterator for Peekable { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { let acc = match self.peeked.take() { Some(None) => return try { init }, @@ -134,7 +134,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { match self.peeked.take() { Some(None) => try { init }, @@ -142,7 +142,7 @@ where Ok(acc) => f(acc, v), Err(e) => { self.peeked = Some(Some(v)); - Try::from_error(e) + R::from_error(e) } }, None => self.iter.try_rfold(init, f), diff --git a/library/core/src/iter/adapters/rev.rs b/library/core/src/iter/adapters/rev.rs index 105ed40a3ed11..f24bde9f6ad8e 100644 --- a/library/core/src/iter/adapters/rev.rs +++ b/library/core/src/iter/adapters/rev.rs @@ -1,5 +1,5 @@ use crate::iter::{FusedIterator, TrustedLen}; -use crate::ops::Try; +use crate::ops::TryWhereOutputEquals; /// A double-ended iterator with the direction inverted. /// @@ -51,7 +51,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.iter.try_rfold(init, f) } @@ -96,7 +96,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { self.iter.try_fold(init, f) } diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs index 0214899295e35..38a3f255389d9 100644 --- a/library/core/src/iter/adapters/scan.rs +++ b/library/core/src/iter/adapters/scan.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, InPlaceIterable}; -use crate::ops::{ControlFlow, Try}; +use crate::ops::{ControlFlow, TryWhereOutputEquals}; /// An iterator to maintain state while iterating another iterator. /// @@ -56,9 +56,9 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { - fn scan<'a, T, St, B, Acc, R: Try>( + fn scan<'a, T, St, B, Acc, R: TryWhereOutputEquals>( state: &'a mut St, f: &'a mut impl FnMut(&mut St, T) -> Option, mut fold: impl FnMut(Acc, B) -> R + 'a, diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs index e55c7a6bf5df1..bee160baaad82 100644 --- a/library/core/src/iter/adapters/skip.rs +++ b/library/core/src/iter/adapters/skip.rs @@ -1,6 +1,6 @@ use crate::intrinsics::unlikely; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; -use crate::ops::{ControlFlow, Try}; +use crate::ops::{ControlFlow, TryWhereOutputEquals}; /// An iterator that skips over `n` elements of `iter`. /// @@ -88,7 +88,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { let n = self.n; self.n = 0; @@ -146,9 +146,9 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { - fn check>( + fn check>( mut n: usize, mut fold: impl FnMut(Acc, T) -> R, ) -> impl FnMut(Acc, T) -> ControlFlow { diff --git a/library/core/src/iter/adapters/skip_while.rs b/library/core/src/iter/adapters/skip_while.rs index efcb469fc9577..3c679187c62b1 100644 --- a/library/core/src/iter/adapters/skip_while.rs +++ b/library/core/src/iter/adapters/skip_while.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; -use crate::ops::Try; +use crate::ops::TryWhereOutputEquals; /// An iterator that rejects elements while `predicate` returns `true`. /// @@ -70,7 +70,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { if !self.flag { match self.next() { diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs index 2ba56eeccba17..ad29bff213c8c 100644 --- a/library/core/src/iter/adapters/step_by.rs +++ b/library/core/src/iter/adapters/step_by.rs @@ -1,4 +1,4 @@ -use crate::{intrinsics, iter::from_fn, ops::Try}; +use crate::{intrinsics, iter::from_fn, ops::TryWhereOutputEquals}; /// An iterator for stepping iterators by a custom amount. /// @@ -111,7 +111,7 @@ where fn try_fold(&mut self, mut acc: Acc, mut f: F) -> R where F: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { #[inline] fn nth(iter: &mut I, step: usize) -> impl FnMut() -> Option + '_ { @@ -187,7 +187,7 @@ where fn try_rfold(&mut self, init: Acc, mut f: F) -> R where F: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { #[inline] fn nth_back( diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index 54a47f1323ebf..4852efebdf40f 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -3,7 +3,7 @@ use crate::iter::{ adapters::zip::try_get_unchecked, adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen, TrustedRandomAccess, }; -use crate::ops::{ControlFlow, Try}; +use crate::ops::{ControlFlow, TryWhereOutputEquals}; /// An iterator that only iterates over the first `n` iterations of `iter`. /// @@ -80,9 +80,9 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { - fn check<'a, T, Acc, R: Try>( + fn check<'a, T, Acc, R: TryWhereOutputEquals>( n: &'a mut usize, mut fold: impl FnMut(Acc, T) -> R + 'a, ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { @@ -178,7 +178,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { if self.n == 0 { try { init } diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs index 746eb41f4c387..d97d3141496af 100644 --- a/library/core/src/iter/adapters/take_while.rs +++ b/library/core/src/iter/adapters/take_while.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; -use crate::ops::{ControlFlow, Try}; +use crate::ops::{ControlFlow, TryWhereOutputEquals}; /// An iterator that only accepts elements while `predicate` returns `true`. /// @@ -68,9 +68,9 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { - fn check<'a, T, Acc, R: Try>( + fn check<'a, T, Acc, R: TryWhereOutputEquals>( flag: &'a mut bool, p: &'a mut impl FnMut(&T) -> bool, mut fold: impl FnMut(Acc, T) -> R + 'a, diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 4b293c596e7af..d3da606665497 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -1,7 +1,7 @@ use crate::char; use crate::convert::TryFrom; use crate::mem; -use crate::ops::{self, Try}; +use crate::ops::{self, TryWhereOutputEquals}; use super::{FusedIterator, TrustedLen, TrustedRandomAccess}; @@ -755,7 +755,7 @@ impl Iterator for ops::RangeInclusive { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { if self.is_empty() { return try { init }; @@ -860,7 +860,7 @@ impl DoubleEndedIterator for ops::RangeInclusive { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { if self.is_empty() { return try { init }; diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index 6f8cb6b5a65b6..aed48a48ddedb 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -1,4 +1,4 @@ -use crate::ops::{ControlFlow, Try}; +use crate::ops::{ControlFlow, TryWhereOutputEquals}; /// An iterator able to yield elements from both ends. /// @@ -218,7 +218,7 @@ pub trait DoubleEndedIterator: Iterator { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { let mut accum = init; while let Some(x) = self.next_back() { diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index da9e5fde7ccec..30f47443ecb15 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3,7 +3,7 @@ // can't split that into multiple files. use crate::cmp::{self, Ordering}; -use crate::ops::{ControlFlow, Try}; +use crate::ops::{ControlFlow, TryWhereOutputEquals}; use super::super::TrustedRandomAccess; use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; @@ -1999,7 +1999,7 @@ pub trait Iterator { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { let mut accum = init; while let Some(x) = self.next() { @@ -2041,7 +2041,7 @@ pub trait Iterator { where Self: Sized, F: FnMut(Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals<()>, { #[inline] fn call(mut f: impl FnMut(T) -> R) -> impl FnMut((), T) -> R { @@ -2416,13 +2416,13 @@ pub trait Iterator { where Self: Sized, F: FnMut(&Self::Item) -> R, - R: Try, + R: TryWhereOutputEquals, { #[inline] fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow> where F: FnMut(&T) -> R, - R: Try, + R: TryWhereOutputEquals, { move |(), x| match f(&x).into_result() { Ok(false) => ControlFlow::CONTINUE, diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index ecaff053bd5c0..b5ac590b59d7e 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -1,5 +1,4 @@ -use crate::convert; -use crate::ops::{self, Try}; +use crate::{convert, ops}; /// Used to tell an operation whether it should exit early or go on as usual. /// @@ -62,7 +61,7 @@ pub enum ControlFlow { } #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] -impl Try for ControlFlow { +impl ops::TryV1 for ControlFlow { type Ok = C; type Error = B; #[inline] @@ -182,14 +181,14 @@ impl ControlFlow { } } -impl ControlFlow { +impl ControlFlow { /// Create a `ControlFlow` from any type implementing `Try`. #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] #[inline] pub fn from_try(r: R) -> Self { - match Try::into_result(r) { + match R::into_result(r) { Ok(v) => ControlFlow::Continue(v), - Err(v) => ControlFlow::Break(Try::from_error(v)), + Err(v) => ControlFlow::Break(R::from_error(v)), } } @@ -198,7 +197,7 @@ impl ControlFlow { #[inline] pub fn into_try(self) -> R { match self { - ControlFlow::Continue(v) => Try::from_ok(v), + ControlFlow::Continue(v) => R::from_ok(v), ControlFlow::Break(v) => v, } } diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 1b07936ccde1d..7f747ced39749 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -185,6 +185,9 @@ pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; #[unstable(feature = "try_trait", issue = "42327")] pub use self::r#try::Try; +#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] +pub use self::r#try::Try as TryV1; + #[unstable(feature = "try_trait_v2", issue = "84277")] pub use self::try_trait::FromResidual; @@ -202,3 +205,19 @@ pub use self::unsize::DispatchFromDyn; #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] pub use self::control_flow::ControlFlow; + +/// [`TryV1`] and [`TryV2`] have different associated type names, +/// so rather than need `bootstrap` checks all over the library, +/// centralize the difference to this one trait alias. +/// +/// As with all `try_trait_transition` stuff, this will be deleted +/// after the bootstrap compiler uses V2 for `?`. +/// +/// ``` +/// #![feature(try_trait_transition)] +/// use std::ops::TryWhereOutputEquals; +/// fn foo() where T: TryWhereOutputEquals {} +/// foo::, i32>(); +/// ``` +#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] +pub trait TryWhereOutputEquals = TryV1; diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 04551dded8c77..928d8441fa6d1 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1644,7 +1644,7 @@ impl> FromIterator> for Option { pub struct NoneError; #[unstable(feature = "try_trait", issue = "42327")] -impl ops::Try for Option { +impl ops::TryV1 for Option { type Ok = T; type Error = NoneError; diff --git a/library/core/src/result.rs b/library/core/src/result.rs index e0071f806aaaf..5f6afcc822182 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1627,7 +1627,7 @@ impl> FromIterator> for Result { } #[unstable(feature = "try_trait", issue = "42327")] -impl ops::Try for Result { +impl ops::TryV1 for Result { type Ok = T; type Error = E; diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 906dcb1e8bcee..c3ba8b23e8df9 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -110,7 +110,7 @@ impl<'a> iter::Iterator for EscapeAscii<'a> { fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Fold: FnMut(Acc, Self::Item) -> R, - R: ops::Try, + R: ops::TryWhereOutputEquals, { self.inner.try_fold(init, fold) } diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 724137aba9f3c..612f17a1e6161 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -5,7 +5,7 @@ use crate::fmt::{self, Write}; use crate::iter::TrustedRandomAccess; use crate::iter::{Chain, FlatMap, Flatten}; use crate::iter::{Copied, Filter, FusedIterator, Map, TrustedLen}; -use crate::ops::Try; +use crate::ops::TryWhereOutputEquals; use crate::option; use crate::slice::{self, Split as SliceSplit}; @@ -1467,7 +1467,7 @@ macro_rules! escape_types_impls { #[inline] fn try_fold(&mut self, init: Acc, fold: Fold) -> R where - Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: TryWhereOutputEquals { self.inner.try_fold(init, fold) } diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 2765c21a46db1..2ccfc22c27cac 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -1,7 +1,7 @@ #![stable(feature = "futures_api", since = "1.36.0")] use crate::convert; -use crate::ops::{self, ControlFlow, Try}; +use crate::ops::{self, ControlFlow}; use crate::result::Result; /// Indicates whether a value is available or if the current task has been @@ -129,7 +129,7 @@ impl From for Poll { } #[stable(feature = "futures_api", since = "1.36.0")] -impl Try for Poll> { +impl ops::TryV1 for Poll> { type Ok = Poll; type Error = E; @@ -184,7 +184,7 @@ impl> ops::FromResidual> for Pol } #[stable(feature = "futures_api", since = "1.36.0")] -impl Try for Poll>> { +impl ops::TryV1 for Poll>> { type Ok = Poll>; type Error = E; From ca92b5a23a9bb30a0741e9969e73d838eeba1ad1 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 15 Apr 2021 00:33:55 -0700 Subject: [PATCH 02/11] Actually implement the feature in the compiler Including all the bootstrapping tweaks in the library. --- compiler/rustc_ast_lowering/src/expr.rs | 58 ++++++++++------------ compiler/rustc_ast_lowering/src/lib.rs | 10 ++-- compiler/rustc_hir/src/lang_items.rs | 11 ++-- compiler/rustc_span/src/symbol.rs | 13 +++-- library/core/src/iter/adapters/peekable.rs | 25 +++++++++- library/core/src/iter/traits/iterator.rs | 30 +++++++++++ library/core/src/ops/control_flow.rs | 26 ++++++++++ library/core/src/ops/mod.rs | 10 ++++ library/core/src/ops/try.rs | 8 +-- library/core/src/ops/try_trait.rs | 4 ++ 10 files changed, 144 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index bf70a41fd79e0..11de954a1f460 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -562,8 +562,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ) } - /// Desugar `try { ; }` into `{ ; ::std::ops::Try::from_ok() }`, - /// `try { ; }` into `{ ; ::std::ops::Try::from_ok(()) }` + /// Desugar `try { ; }` into `{ ; ::std::ops::Try::from_output() }`, + /// `try { ; }` into `{ ; ::std::ops::Try::from_output(()) }` /// and save the block id to use it as a break target for desugaring of the `?` operator. fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> { self.with_catch_scope(body.id, |this| { @@ -592,9 +592,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let ok_wrapped_span = this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None); - // `::std::ops::Try::from_ok($tail_expr)` + // `::std::ops::Try::from_output($tail_expr)` block.expr = Some(this.wrap_in_try_constructor( - hir::LangItem::TryFromOk, + hir::LangItem::TryTraitFromOutput, try_span, tail_expr, ok_wrapped_span, @@ -1896,14 +1896,14 @@ impl<'hir> LoweringContext<'_, 'hir> { self.allow_try_trait.clone(), ); - // `Try::into_result()` + // `Try::branch()` let scrutinee = { // expand let sub_expr = self.lower_expr_mut(sub_expr); self.expr_call_lang_item_fn( unstable_span, - hir::LangItem::TryIntoResult, + hir::LangItem::TryTraitBranch, arena_vec![self; sub_expr], ) }; @@ -1921,8 +1921,8 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let attrs = vec![attr]; - // `Ok(val) => #[allow(unreachable_code)] val,` - let ok_arm = { + // `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,` + let continue_arm = { let val_ident = Ident::with_dummy_span(sym::val); let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident); let val_expr = self.arena.alloc(self.expr_ident_with_attrs( @@ -1931,27 +1931,21 @@ impl<'hir> LoweringContext<'_, 'hir> { val_pat_nid, ThinVec::from(attrs.clone()), )); - let ok_pat = self.pat_ok(span, val_pat); - self.arm(ok_pat, val_expr) + let continue_pat = self.pat_cf_continue(unstable_span, val_pat); + self.arm(continue_pat, val_expr) }; - // `Err(err) => #[allow(unreachable_code)] - // return Try::from_error(From::from(err)),` - let err_arm = { - let err_ident = Ident::with_dummy_span(sym::err); - let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident); - let from_expr = { - let err_expr = self.expr_ident_mut(try_span, err_ident, err_local_nid); - self.expr_call_lang_item_fn( - try_span, - hir::LangItem::FromFrom, - arena_vec![self; err_expr], - ) - }; - let from_err_expr = self.wrap_in_try_constructor( - hir::LangItem::TryFromError, - unstable_span, - from_expr, + // `ControlFlow::Break(residual) => + // #[allow(unreachable_code)] + // return Try::from_residual(residual),` + let break_arm = { + let residual_ident = Ident::with_dummy_span(sym::residual); + let (residual_local, residual_local_nid) = self.pat_ident(try_span, residual_ident); + let residual_expr = self.expr_ident_mut(try_span, residual_ident, residual_local_nid); + let from_residual_expr = self.wrap_in_try_constructor( + hir::LangItem::TryTraitFromResidual, + try_span, + self.arena.alloc(residual_expr), unstable_span, ); let thin_attrs = ThinVec::from(attrs); @@ -1962,25 +1956,25 @@ impl<'hir> LoweringContext<'_, 'hir> { try_span, hir::ExprKind::Break( hir::Destination { label: None, target_id }, - Some(from_err_expr), + Some(from_residual_expr), ), thin_attrs, )) } else { self.arena.alloc(self.expr( try_span, - hir::ExprKind::Ret(Some(from_err_expr)), + hir::ExprKind::Ret(Some(from_residual_expr)), thin_attrs, )) }; - let err_pat = self.pat_err(try_span, err_local); - self.arm(err_pat, ret_expr) + let break_pat = self.pat_cf_break(try_span, residual_local); + self.arm(break_pat, ret_expr) }; hir::ExprKind::Match( scrutinee, - arena_vec![self; err_arm, ok_arm], + arena_vec![self; break_arm, continue_arm], hir::MatchSource::TryDesugar, ) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 32320130b677c..2e5e92bfcce44 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -331,7 +331,7 @@ pub fn lower_crate<'a, 'hir>( lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, in_scope_lifetimes: Vec::new(), - allow_try_trait: Some([sym::try_trait][..].into()), + allow_try_trait: Some([sym::control_flow_enum, sym::try_trait_v2][..].into()), allow_gen_future: Some([sym::gen_future][..].into()), } .lower_crate(krate) @@ -2479,14 +2479,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.pat(span, hir::PatKind::Lit(expr)) } - fn pat_ok(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { + fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ResultOk, field) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field) } - fn pat_err(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { + fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ResultErr, field) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field) } fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 498000db50f43..40fcb60a86b1e 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -308,12 +308,12 @@ language_item_table! { Termination, sym::termination, termination, Target::Trait; - Try, kw::Try, try_trait, Target::Trait; + Try, sym::Try, try_trait, Target::Trait; // Language items from AST lowering - TryFromError, sym::from_error, from_error_fn, Target::Method(MethodKind::Trait { body: false }); - TryFromOk, sym::from_ok, from_ok_fn, Target::Method(MethodKind::Trait { body: false }); - TryIntoResult, sym::into_result, into_result_fn, Target::Method(MethodKind::Trait { body: false }); + TryTraitFromResidual, sym::from_residual, from_residual_fn, Target::Method(MethodKind::Trait { body: false }); + TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }); + TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }); PollReady, sym::Ready, poll_ready_variant, Target::Variant; PollPending, sym::Pending, poll_pending_variant, Target::Variant; @@ -331,6 +331,9 @@ language_item_table! { ResultOk, sym::Ok, result_ok_variant, Target::Variant; ResultErr, sym::Err, result_err_variant, Target::Variant; + ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant; + ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant; + IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }); IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 4c80b84e3d275..615e1052d1951 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -130,10 +130,12 @@ symbols! { BTreeSet, BinaryHeap, Borrow, + Break, C, CString, Center, Clone, + Continue, Copy, Count, Debug, @@ -326,6 +328,7 @@ symbols! { box_patterns, box_syntax, braced_empty_structs, + branch, breakpoint, bridge, bswap, @@ -410,6 +413,7 @@ symbols! { constructor, contents, context, + control_flow_enum, convert, copy, copy_closures, @@ -510,7 +514,6 @@ symbols! { env, eq, ermsb_target_feature, - err, exact_div, except, exchange_malloc, @@ -580,10 +583,10 @@ symbols! { frem_fast, from, from_desugaring, - from_error, from_generator, from_method, - from_ok, + from_output, + from_residual, from_size_align_unchecked, from_trait, from_usize, @@ -652,7 +655,6 @@ symbols! { instruction_set, intel, into_iter, - into_result, into_trait, intra_doc_pointers, intrinsics, @@ -962,6 +964,7 @@ symbols! { repr_packed, repr_simd, repr_transparent, + residual, result, result_type, rhs, @@ -1227,7 +1230,7 @@ symbols! { try_blocks, try_from_trait, try_into_trait, - try_trait, + try_trait_v2, tt, tuple, tuple_from_req, diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 7e851c67de434..c9c9d95239214 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -1,5 +1,5 @@ use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen}; -use crate::ops::TryWhereOutputEquals; +use crate::ops::{ControlFlow, TryWhereOutputEquals}; /// An iterator with a `peek()` that returns an optional reference to the next /// element. @@ -130,12 +130,35 @@ where } #[inline] + #[cfg(not(bootstrap))] fn try_rfold(&mut self, init: B, mut f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: TryWhereOutputEquals, { + match self.peeked.take() { + Some(None) => try { init }, + Some(Some(v)) => match self.iter.try_rfold(init, &mut f).branch() { + ControlFlow::Continue(acc) => f(acc, v), + ControlFlow::Break(r) => { + self.peeked = Some(Some(v)); + R::from_residual(r) + } + }, + None => self.iter.try_rfold(init, f), + } + } + + #[inline] + #[cfg(bootstrap)] + fn try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: TryWhereOutputEquals, + { + let _use_the_import: ControlFlow<()>; match self.peeked.take() { Some(None) => try { init }, Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() { diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 30f47443ecb15..04315003dd7b2 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2412,6 +2412,36 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "try_find", reason = "new API", issue = "63178")] + #[cfg(not(bootstrap))] + fn try_find(&mut self, f: F) -> Result, E> + where + Self: Sized, + F: FnMut(&Self::Item) -> R, + R: TryWhereOutputEquals, + // FIXME: This is a weird bound; the API should change + R: crate::ops::TryV2>, + { + #[inline] + fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow> + where + F: FnMut(&T) -> R, + R: TryWhereOutputEquals, + R: crate::ops::TryV2>, + { + move |(), x| match f(&x).branch() { + ControlFlow::Continue(false) => ControlFlow::CONTINUE, + ControlFlow::Continue(true) => ControlFlow::Break(Ok(x)), + ControlFlow::Break(Err(x)) => ControlFlow::Break(Err(x)), + } + } + + self.try_fold((), check(f)).break_value().transpose() + } + + /// We're bootstrapping. + #[inline] + #[unstable(feature = "try_find", reason = "new API", issue = "63178")] + #[cfg(bootstrap)] fn try_find(&mut self, f: F) -> Result, R::Error> where Self: Sized, diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index b5ac590b59d7e..238fcd447bd1c 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -52,8 +52,10 @@ use crate::{convert, ops}; #[derive(Debug, Clone, Copy, PartialEq)] pub enum ControlFlow { /// Move on to the next phase of the operation as normal. + #[cfg_attr(not(bootstrap), lang = "Continue")] Continue(C), /// Exit the operation without running subsequent phases. + #[cfg_attr(not(bootstrap), lang = "Break")] Break(B), // Yes, the order of the variants doesn't match the type parameters. // They're in this order so that `ControlFlow` <-> `Result` @@ -181,6 +183,7 @@ impl ControlFlow { } } +#[cfg(bootstrap)] impl ControlFlow { /// Create a `ControlFlow` from any type implementing `Try`. #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] @@ -203,6 +206,29 @@ impl ControlFlow { } } +#[cfg(not(bootstrap))] +impl ControlFlow { + /// Create a `ControlFlow` from any type implementing `Try`. + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + #[inline] + pub fn from_try(r: R) -> Self { + match R::branch(r) { + ControlFlow::Continue(v) => ControlFlow::Continue(v), + ControlFlow::Break(v) => ControlFlow::Break(R::from_residual(v)), + } + } + + /// Convert a `ControlFlow` into any type implementing `Try`; + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + #[inline] + pub fn into_try(self) -> R { + match self { + ControlFlow::Continue(v) => R::from_output(v), + ControlFlow::Break(v) => v, + } + } +} + impl ControlFlow { /// It's frequently the case that there's no value needed with `Continue`, /// so this provides a way to avoid typing `(())`, if you prefer it. diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 7f747ced39749..426b45a925eda 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -183,6 +183,7 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; #[unstable(feature = "try_trait", issue = "42327")] +#[cfg(bootstrap)] pub use self::r#try::Try; #[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] @@ -191,6 +192,10 @@ pub use self::r#try::Try as TryV1; #[unstable(feature = "try_trait_v2", issue = "84277")] pub use self::try_trait::FromResidual; +#[unstable(feature = "try_trait_v2", issue = "84277")] +#[cfg(not(bootstrap))] +pub use self::try_trait::Try; + #[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] pub use self::try_trait::Try as TryV2; @@ -220,4 +225,9 @@ pub use self::control_flow::ControlFlow; /// foo::, i32>(); /// ``` #[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] +#[cfg(not(bootstrap))] +pub trait TryWhereOutputEquals = TryV2; + +#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] +#[cfg(bootstrap)] pub trait TryWhereOutputEquals = TryV1; diff --git a/library/core/src/ops/try.rs b/library/core/src/ops/try.rs index 3bede5699781c..18e2f951ce5a9 100644 --- a/library/core/src/ops/try.rs +++ b/library/core/src/ops/try.rs @@ -25,7 +25,7 @@ ) )] #[doc(alias = "?")] -#[lang = "try"] +#[cfg_attr(bootstrap, lang = "try")] pub trait Try { /// The type of this value when viewed as successful. #[unstable(feature = "try_trait", issue = "42327")] @@ -43,19 +43,19 @@ pub trait Try { /// in the return type of the enclosing scope (which must itself implement /// `Try`). Specifically, the value `X::from_error(From::from(e))` /// is returned, where `X` is the return type of the enclosing function. - #[lang = "into_result"] + #[cfg_attr(bootstrap, lang = "into_result")] #[unstable(feature = "try_trait", issue = "42327")] fn into_result(self) -> Result; /// Wrap an error value to construct the composite result. For example, /// `Result::Err(x)` and `Result::from_error(x)` are equivalent. - #[lang = "from_error"] + #[cfg_attr(bootstrap, lang = "from_error")] #[unstable(feature = "try_trait", issue = "42327")] fn from_error(v: Self::Error) -> Self; /// Wrap an OK value to construct the composite result. For example, /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent. - #[lang = "from_ok"] + #[cfg_attr(bootstrap, lang = "from_ok")] #[unstable(feature = "try_trait", issue = "42327")] fn from_ok(v: Self::Ok) -> Self; } diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 0c819b000aaab..52a7608194700 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -119,6 +119,7 @@ use crate::ops::ControlFlow; /// } /// ``` #[unstable(feature = "try_trait_v2", issue = "84277")] +#[cfg_attr(not(bootstrap), lang = "Try")] pub trait Try: FromResidual { /// The type of the value produced by `?` when *not* short-circuiting. #[unstable(feature = "try_trait_v2", issue = "84277")] @@ -178,6 +179,7 @@ pub trait Try: FromResidual { /// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() }); /// assert_eq!(r, Some(4)); /// ``` + #[cfg_attr(not(bootstrap), lang = "from_output")] #[unstable(feature = "try_trait_v2", issue = "84277")] fn from_output(output: Self::Output) -> Self; @@ -206,6 +208,7 @@ pub trait Try: FromResidual { /// ControlFlow::Break(ControlFlow::Break(3)), /// ); /// ``` + #[cfg_attr(not(bootstrap), lang = "branch")] #[unstable(feature = "try_trait_v2", issue = "84277")] fn branch(self) -> ControlFlow; } @@ -238,6 +241,7 @@ pub trait FromResidual::Residual> { /// ControlFlow::Break(5), /// ); /// ``` + #[cfg_attr(not(bootstrap), lang = "from_residual")] #[unstable(feature = "try_trait_v2", issue = "84277")] fn from_residual(residual: R) -> Self; } From 266a72637a5bb79eeaaa741950a6f9501bfd2f8d Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 15 Apr 2021 01:13:39 -0700 Subject: [PATCH 03/11] Simple library test updates --- library/core/src/ops/try_trait.rs | 20 +++++++------------- library/core/tests/lib.rs | 1 + library/core/tests/option.rs | 12 ------------ library/core/tests/result.rs | 30 ++++++++++++++++-------------- 4 files changed, 24 insertions(+), 39 deletions(-) diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 52a7608194700..80a5800bcbb89 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -41,8 +41,7 @@ use crate::ops::ControlFlow; /// output type that we want: /// ``` /// # #![feature(try_trait_v2)] -/// # #![feature(try_trait_transition)] -/// # use std::ops::TryV2 as Try; +/// # use std::ops::Try; /// fn simple_try_fold_1>( /// iter: impl Iterator, /// mut accum: A, @@ -56,9 +55,8 @@ use crate::ops::ControlFlow; /// into the return type using [`Try::from_output`]: /// ``` /// # #![feature(try_trait_v2)] -/// # #![feature(try_trait_transition)] /// # #![feature(control_flow_enum)] -/// # use std::ops::{ControlFlow, TryV2 as Try}; +/// # use std::ops::{ControlFlow, Try}; /// fn simple_try_fold_2>( /// iter: impl Iterator, /// mut accum: A, @@ -81,9 +79,8 @@ use crate::ops::ControlFlow; /// recreated from their corresponding residual, so we'll just call it: /// ``` /// # #![feature(try_trait_v2)] -/// # #![feature(try_trait_transition)] /// # #![feature(control_flow_enum)] -/// # use std::ops::{ControlFlow, TryV2 as Try}; +/// # use std::ops::{ControlFlow, Try}; /// pub fn simple_try_fold_3>( /// iter: impl Iterator, /// mut accum: A, @@ -103,10 +100,9 @@ use crate::ops::ControlFlow; /// But this "call `branch`, then `match` on it, and `return` if it was a /// `Break`" is exactly what happens inside the `?` operator. So rather than /// do all this manually, we can just use `?` instead: -/// ```compile_fail (enable again once ? converts to the new trait) +/// ``` /// # #![feature(try_trait_v2)] -/// # #![feature(try_trait_transition)] -/// # use std::ops::TryV2 as Try; +/// # use std::ops::Try; /// fn simple_try_fold>( /// iter: impl Iterator, /// mut accum: A, @@ -160,8 +156,7 @@ pub trait Try: FromResidual { /// ``` /// #![feature(try_trait_v2)] /// #![feature(control_flow_enum)] - /// #![feature(try_trait_transition)] - /// use std::ops::TryV2 as Try; + /// use std::ops::Try; /// /// assert_eq!( as Try>::from_output(3), Ok(3)); /// assert_eq!( as Try>::from_output(4), Some(4)); @@ -193,8 +188,7 @@ pub trait Try: FromResidual { /// ``` /// #![feature(try_trait_v2)] /// #![feature(control_flow_enum)] - /// #![feature(try_trait_transition)] - /// use std::ops::{ControlFlow, TryV2 as Try}; + /// use std::ops::{ControlFlow, Try}; /// /// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3)); /// assert_eq!(Err::(3).branch(), ControlFlow::Break(Err(3))); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 35e4d213dde1e..db12d79c00c30 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -45,6 +45,7 @@ #![feature(test)] #![feature(trusted_len)] #![feature(try_trait)] +#![feature(try_trait_v2)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] #![feature(int_error_matching)] diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs index 9470451278cc4..88ea15a3b33fa 100644 --- a/library/core/tests/option.rs +++ b/library/core/tests/option.rs @@ -301,18 +301,6 @@ fn test_try() { Some(val) } assert_eq!(try_option_none(), None); - - fn try_option_ok() -> Result { - let val = Some(1)?; - Ok(val) - } - assert_eq!(try_option_ok(), Ok(1)); - - fn try_option_err() -> Result { - let val = None?; - Ok(val) - } - assert_eq!(try_option_err(), Err(NoneError)); } #[test] diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs index c461ab380ad3d..f4e5e7751b8e3 100644 --- a/library/core/tests/result.rs +++ b/library/core/tests/result.rs @@ -249,26 +249,14 @@ pub fn test_into_err() { #[test] fn test_try() { - fn try_result_some() -> Option { - let val = Ok(1)?; - Some(val) - } - assert_eq!(try_result_some(), Some(1)); - - fn try_result_none() -> Option { - let val = Err(NoneError)?; - Some(val) - } - assert_eq!(try_result_none(), None); - - fn try_result_ok() -> Result { + fn try_result_ok() -> Result { let result: Result = Ok(1); let val = result?; Ok(val) } assert_eq!(try_result_ok(), Ok(1)); - fn try_result_err() -> Result { + fn try_result_err() -> Result { let result: Result = Err(1); let val = result?; Ok(val) @@ -401,3 +389,17 @@ fn result_opt_conversions() { assert_eq!(res, Err(BadNumErr)) } + +#[test] +#[cfg(not(bootstrap))] // Needs the V2 trait +fn result_try_trait_v2_branch() { + use core::num::NonZeroU32; + use core::ops::{ControlFlow::*, Try}; + assert_eq!(Ok::(4).branch(), Continue(4)); + assert_eq!(Err::(4).branch(), Break(Err(4))); + let one = NonZeroU32::new(1).unwrap(); + assert_eq!(Ok::<(), NonZeroU32>(()).branch(), Continue(())); + assert_eq!(Err::<(), NonZeroU32>(one).branch(), Break(Err(one))); + assert_eq!(Ok::(one).branch(), Continue(one)); + assert_eq!(Err::(()).branch(), Break(Err(()))); +} From 47b99485a391e21caf3e0312969ed00ccbc6c167 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 25 Apr 2021 22:02:48 -0700 Subject: [PATCH 04/11] mir-opt & codegen test updates `SimplifyArm` and such are currently in `-Zunsound-mir-opts` and thus weren't running by default, so having something like them for the new desugar shouldn't be necessary for switching. --- src/test/codegen/try_identity.rs | 21 ++- ...issue_62289.test.ElaborateDrops.before.mir | 70 ++++----- src/test/mir-opt/simplify-arm.rs | 17 ++- ...mplify_arm.id_try.SimplifyArmIdentity.diff | 140 +++++++++--------- ...implify_arm.id_try.SimplifyBranchSame.diff | 91 ++++++------ src/test/mir-opt/simplify_try.rs | 18 ++- ...y.try_identity.DestinationPropagation.diff | 93 ++++++------ ..._try.try_identity.SimplifyArmIdentity.diff | 136 ++++++++--------- ....try_identity.SimplifyBranchSame.after.mir | 75 +++++----- ..._try.try_identity.SimplifyLocals.after.mir | 34 ++--- 10 files changed, 349 insertions(+), 346 deletions(-) diff --git a/src/test/codegen/try_identity.rs b/src/test/codegen/try_identity.rs index 81e2435e5b80e..78da06b2fe440 100644 --- a/src/test/codegen/try_identity.rs +++ b/src/test/codegen/try_identity.rs @@ -7,11 +7,28 @@ type R = Result; +// This was written to the `?` from `try_trait`, +// but `try_trait_v2` uses a different structure, +// so the relevant desugar is copied inline +// in order to keep the test testing the same thing. #[no_mangle] -fn try_identity(x: R) -> R { +pub fn try_identity(x: R) -> R { // CHECK: start: // CHECK-NOT: br {{.*}} // CHECK ret void - let y = x?; + let y = match into_result(x) { + Err(e) => return from_error(From::from(e)), + Ok(v) => v, + }; Ok(y) } + +#[inline] +fn into_result(r: Result) -> Result { + r +} + +#[inline] +fn from_error(e: E) -> Result { + Err(e) +} diff --git a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir index c1421f20a0ba2..ba17a45f984ef 100644 --- a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir +++ b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir @@ -4,21 +4,20 @@ fn test() -> Option> { let mut _0: std::option::Option>; // return place in scope 0 at $DIR/issue-62289.rs:8:14: 8:30 let mut _1: std::boxed::Box; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21 let mut _2: std::boxed::Box; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21 - let mut _3: std::result::Result; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + let mut _3: std::ops::ControlFlow, u32>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20 let mut _4: std::option::Option; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:19 let mut _5: isize; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - let _6: std::option::NoneError; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + let _6: std::option::Option; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 let mut _7: !; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - let mut _8: std::option::NoneError; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - let mut _9: std::option::NoneError; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - let _10: u32; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + let mut _8: std::option::Option; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + let _9: u32; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20 scope 1 { - debug err => _6; // in scope 1 at $DIR/issue-62289.rs:9:19: 9:20 + debug residual => _6; // in scope 1 at $DIR/issue-62289.rs:9:19: 9:20 scope 2 { } } scope 3 { - debug val => _10; // in scope 3 at $DIR/issue-62289.rs:9:15: 9:20 + debug val => _9; // in scope 3 at $DIR/issue-62289.rs:9:15: 9:20 scope 4 { } } @@ -30,10 +29,10 @@ fn test() -> Option> { StorageLive(_3); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 StorageLive(_4); // scope 0 at $DIR/issue-62289.rs:9:15: 9:19 _4 = Option::::None; // scope 0 at $DIR/issue-62289.rs:9:15: 9:19 - _3 = as Try>::into_result(move _4) -> [return: bb1, unwind: bb12]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + _3 = as Try>::branch(move _4) -> [return: bb1, unwind: bb11]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 // mir::Constant // + span: $DIR/issue-62289.rs:9:15: 9:20 - // + literal: Const { ty: fn(std::option::Option) -> std::result::Result< as std::ops::Try>::Ok, as std::ops::Try>::Error> { as std::ops::Try>::into_result}, val: Value(Scalar()) } + // + literal: Const { ty: fn(std::option::Option) -> std::ops::ControlFlow< as std::ops::Try>::Residual, as std::ops::Try>::Output> { as std::ops::Try>::branch}, val: Value(Scalar()) } } bb1: { @@ -43,12 +42,12 @@ fn test() -> Option> { } bb2: { - StorageLive(_10); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 - _10 = ((_3 as Ok).0: u32); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 - (*_2) = _10; // scope 4 at $DIR/issue-62289.rs:9:15: 9:20 - StorageDead(_10); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + StorageLive(_9); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + _9 = ((_3 as Continue).0: u32); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + (*_2) = _9; // scope 4 at $DIR/issue-62289.rs:9:15: 9:20 + StorageDead(_9); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 _1 = move _2; // scope 0 at $DIR/issue-62289.rs:9:10: 9:21 - drop(_2) -> [return: bb7, unwind: bb11]; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 + drop(_2) -> [return: bb6, unwind: bb10]; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 } bb3: { @@ -57,62 +56,53 @@ fn test() -> Option> { bb4: { StorageLive(_6); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - _6 = ((_3 as Err).0: std::option::NoneError); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + _6 = ((_3 as Break).0: std::option::Option); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 StorageLive(_8); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 - StorageLive(_9); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 - _9 = _6; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 - _8 = >::from(move _9) -> [return: bb5, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 + _8 = _6; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 + _0 = > as FromResidual>>::from_residual(move _8) -> [return: bb5, unwind: bb11]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20 // mir::Constant // + span: $DIR/issue-62289.rs:9:19: 9:20 - // + literal: Const { ty: fn(std::option::NoneError) -> std::option::NoneError {>::from}, val: Value(Scalar()) } + // + literal: Const { ty: fn(std::option::Option) -> std::option::Option> {> as std::ops::FromResidual>>::from_residual}, val: Value(Scalar()) } } bb5: { - StorageDead(_9); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 - _0 = > as Try>::from_error(move _8) -> [return: bb6, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20 - // mir::Constant - // + span: $DIR/issue-62289.rs:9:15: 9:20 - // + literal: Const { ty: fn(> as std::ops::Try>::Error) -> std::option::Option> {> as std::ops::Try>::from_error}, val: Value(Scalar()) } - } - - bb6: { StorageDead(_8); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 StorageDead(_6); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - drop(_2) -> bb9; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 + drop(_2) -> bb8; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 } - bb7: { + bb6: { StorageDead(_2); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 _0 = Option::>::Some(move _1); // scope 0 at $DIR/issue-62289.rs:9:5: 9:22 - drop(_1) -> bb8; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 + drop(_1) -> bb7; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 } - bb8: { + bb7: { StorageDead(_1); // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 StorageDead(_3); // scope 0 at $DIR/issue-62289.rs:10:1: 10:2 - goto -> bb10; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 + goto -> bb9; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 } - bb9: { + bb8: { StorageDead(_2); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 StorageDead(_1); // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 StorageDead(_3); // scope 0 at $DIR/issue-62289.rs:10:1: 10:2 - goto -> bb10; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 + goto -> bb9; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 } - bb10: { + bb9: { return; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 } - bb11 (cleanup): { - drop(_1) -> bb13; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 + bb10 (cleanup): { + drop(_1) -> bb12; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 } - bb12 (cleanup): { - drop(_2) -> bb13; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 + bb11 (cleanup): { + drop(_2) -> bb12; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 } - bb13 (cleanup): { + bb12 (cleanup): { resume; // scope 0 at $DIR/issue-62289.rs:8:1: 10:2 } } diff --git a/src/test/mir-opt/simplify-arm.rs b/src/test/mir-opt/simplify-arm.rs index 50b5147e0cf65..b789b87f6c2dc 100644 --- a/src/test/mir-opt/simplify-arm.rs +++ b/src/test/mir-opt/simplify-arm.rs @@ -20,8 +20,23 @@ fn id_result(r: Result) -> Result { } } +fn into_result(r: Result) -> Result { + r +} + +fn from_error(e: E) -> Result { + Err(e) +} + +// This was written to the `?` from `try_trait`, +// but `try_trait_v2` uses a different structure, +// so the relevant desugar is copied inline +// in order to keep the test testing the same thing. fn id_try(r: Result) -> Result { - let x = r?; + let x = match into_result(r) { + Err(e) => return from_error(From::from(e)), + Ok(v) => v, + }; Ok(x) } diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff index ccb3b71817ff6..a3bad4f0c623d 100644 --- a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff @@ -2,101 +2,93 @@ + // MIR for `id_try` after SimplifyArmIdentity fn id_try(_1: Result) -> Result { - debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12 - let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:23:34: 23:49 - let _2: u8; // in scope 0 at $DIR/simplify-arm.rs:24:9: 24:10 - let mut _3: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 - let mut _4: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:14 - let mut _5: isize; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - let _6: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - let mut _7: !; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - let mut _8: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - let mut _9: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - let _10: u8; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 - let mut _11: u8; // in scope 0 at $DIR/simplify-arm.rs:25:8: 25:9 + debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:35:11: 35:12 + let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:35:34: 35:49 + let _2: u8; // in scope 0 at $DIR/simplify-arm.rs:36:9: 36:10 + let mut _3: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:36:19: 36:33 + let mut _4: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:36:31: 36:32 + let mut _5: isize; // in scope 0 at $DIR/simplify-arm.rs:37:9: 37:15 + let _6: i32; // in scope 0 at $DIR/simplify-arm.rs:37:13: 37:14 + let mut _7: !; // in scope 0 at $DIR/simplify-arm.rs:37:19: 37:51 + let mut _8: i32; // in scope 0 at $DIR/simplify-arm.rs:37:37: 37:50 + let mut _9: i32; // in scope 0 at $DIR/simplify-arm.rs:37:48: 37:49 + let _10: u8; // in scope 0 at $DIR/simplify-arm.rs:38:12: 38:13 + let mut _11: u8; // in scope 0 at $DIR/simplify-arm.rs:40:8: 40:9 scope 1 { -- debug x => _2; // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10 -+ debug x => ((_0 as Ok).0: u8); // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10 +- debug x => _2; // in scope 1 at $DIR/simplify-arm.rs:36:9: 36:10 ++ debug x => ((_0 as Ok).0: u8); // in scope 1 at $DIR/simplify-arm.rs:36:9: 36:10 } scope 2 { -- debug err => _6; // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15 -+ debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15 - scope 3 { - scope 7 (inlined >::from) { // at $DIR/simplify-arm.rs:24:14: 24:15 -- debug t => _9; // in scope 7 at $DIR/simplify-arm.rs:24:14: 24:15 -+ debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify-arm.rs:24:14: 24:15 - } - scope 8 (inlined as Try>::from_error) { // at $DIR/simplify-arm.rs:24:13: 24:15 -- debug v => _8; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 -+ debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 - let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 - } +- debug e => _6; // in scope 2 at $DIR/simplify-arm.rs:37:13: 37:14 ++ debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:37:13: 37:14 + scope 5 (inlined >::from) { // at $DIR/simplify-arm.rs:37:37: 37:50 +- debug t => _9; // in scope 5 at $DIR/simplify-arm.rs:37:37: 37:50 ++ debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify-arm.rs:37:37: 37:50 } - } - scope 4 { -- debug val => _10; // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15 -+ debug val => ((_0 as Ok).0: u8); // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15 - scope 5 { + scope 6 (inlined from_error::) { // at $DIR/simplify-arm.rs:37:26: 37:51 +- debug e => _8; // in scope 6 at $DIR/simplify-arm.rs:37:26: 37:51 ++ debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify-arm.rs:37:26: 37:51 } } - scope 6 (inlined as Try>::into_result) { // at $DIR/simplify-arm.rs:24:13: 24:15 - debug self => _4; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + scope 3 { +- debug v => _10; // in scope 3 at $DIR/simplify-arm.rs:38:12: 38:13 ++ debug v => ((_0 as Ok).0: u8); // in scope 3 at $DIR/simplify-arm.rs:38:12: 38:13 + } + scope 4 (inlined into_result::) { // at $DIR/simplify-arm.rs:36:19: 36:33 + debug r => _4; // in scope 4 at $DIR/simplify-arm.rs:36:19: 36:33 } bb0: { - StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10 - StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 - StorageLive(_4); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14 - _4 = _1; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14 - _3 = move _4; // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 - StorageDead(_4); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - _5 = discriminant(_3); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:36:9: 36:10 + StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33 + StorageLive(_4); // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32 + _4 = _1; // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32 + _3 = move _4; // scope 4 at $DIR/simplify-arm.rs:36:19: 36:33 + StorageDead(_4); // scope 0 at $DIR/simplify-arm.rs:36:32: 36:33 + _5 = discriminant(_3); // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15 + switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15 } bb1: { -- StorageLive(_10); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 -- _10 = ((_3 as Ok).0: u8); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 -- _2 = _10; // scope 5 at $DIR/simplify-arm.rs:24:13: 24:15 -- StorageDead(_10); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 -+ _0 = move _3; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10 - StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16 -- StorageLive(_11); // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9 -- _11 = _2; // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9 -- ((_0 as Ok).0: u8) = move _11; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10 -- discriminant(_0) = 0; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10 -- StorageDead(_11); // scope 1 at $DIR/simplify-arm.rs:25:9: 25:10 - StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 +- StorageLive(_10); // scope 0 at $DIR/simplify-arm.rs:38:12: 38:13 +- _10 = ((_3 as Ok).0: u8); // scope 0 at $DIR/simplify-arm.rs:38:12: 38:13 +- _2 = _10; // scope 3 at $DIR/simplify-arm.rs:38:18: 38:19 +- StorageDead(_10); // scope 0 at $DIR/simplify-arm.rs:38:18: 38:19 ++ _0 = move _3; // scope 1 at $DIR/simplify-arm.rs:40:5: 40:10 + StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:39:6: 39:7 +- StorageLive(_11); // scope 1 at $DIR/simplify-arm.rs:40:8: 40:9 +- _11 = _2; // scope 1 at $DIR/simplify-arm.rs:40:8: 40:9 +- ((_0 as Ok).0: u8) = move _11; // scope 1 at $DIR/simplify-arm.rs:40:5: 40:10 +- discriminant(_0) = 0; // scope 1 at $DIR/simplify-arm.rs:40:5: 40:10 +- StorageDead(_11); // scope 1 at $DIR/simplify-arm.rs:40:9: 40:10 + StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:41:1: 41:2 + goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2 } bb2: { - unreachable; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + unreachable; // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33 } bb3: { -- StorageLive(_6); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 -- _6 = ((_3 as Err).0: i32); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 -- StorageLive(_8); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 -- StorageLive(_9); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 -- _9 = _6; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 -- _8 = move _9; // scope 7 at $DIR/simplify-arm.rs:24:14: 24:15 -- StorageDead(_9); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 -- StorageLive(_12); // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 -- _12 = move _8; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 -- ((_0 as Err).0: i32) = move _12; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 -- discriminant(_0) = 1; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 -- StorageDead(_12); // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 -- StorageDead(_8); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 -- StorageDead(_6); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 -+ _0 = move _3; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 - StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16 - StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 +- StorageLive(_6); // scope 0 at $DIR/simplify-arm.rs:37:13: 37:14 +- _6 = ((_3 as Err).0: i32); // scope 0 at $DIR/simplify-arm.rs:37:13: 37:14 +- StorageLive(_8); // scope 2 at $DIR/simplify-arm.rs:37:37: 37:50 +- StorageLive(_9); // scope 2 at $DIR/simplify-arm.rs:37:48: 37:49 +- _9 = _6; // scope 2 at $DIR/simplify-arm.rs:37:48: 37:49 +- _8 = move _9; // scope 5 at $DIR/simplify-arm.rs:37:37: 37:50 +- StorageDead(_9); // scope 2 at $DIR/simplify-arm.rs:37:49: 37:50 +- ((_0 as Err).0: i32) = move _8; // scope 6 at $DIR/simplify-arm.rs:37:26: 37:51 +- discriminant(_0) = 1; // scope 6 at $DIR/simplify-arm.rs:37:26: 37:51 +- StorageDead(_8); // scope 2 at $DIR/simplify-arm.rs:37:50: 37:51 +- StorageDead(_6); // scope 0 at $DIR/simplify-arm.rs:37:50: 37:51 ++ _0 = move _3; // scope 6 at $DIR/simplify-arm.rs:37:26: 37:51 + StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:39:6: 39:7 + StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:41:1: 41:2 + goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2 } bb4: { - return; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 + return; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2 } } diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff index ec8ac30228e59..b6b7511b3f597 100644 --- a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff +++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff @@ -2,75 +2,70 @@ + // MIR for `id_try` after SimplifyBranchSame fn id_try(_1: Result) -> Result { - debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12 - let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:23:34: 23:49 - let _2: u8; // in scope 0 at $DIR/simplify-arm.rs:24:9: 24:10 - let mut _3: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 - let mut _4: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:14 - let mut _5: isize; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - let _6: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - let mut _7: !; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - let mut _8: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - let mut _9: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - let _10: u8; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 - let mut _11: u8; // in scope 0 at $DIR/simplify-arm.rs:25:8: 25:9 + debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:35:11: 35:12 + let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:35:34: 35:49 + let _2: u8; // in scope 0 at $DIR/simplify-arm.rs:36:9: 36:10 + let mut _3: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:36:19: 36:33 + let mut _4: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:36:31: 36:32 + let mut _5: isize; // in scope 0 at $DIR/simplify-arm.rs:37:9: 37:15 + let _6: i32; // in scope 0 at $DIR/simplify-arm.rs:37:13: 37:14 + let mut _7: !; // in scope 0 at $DIR/simplify-arm.rs:37:19: 37:51 + let mut _8: i32; // in scope 0 at $DIR/simplify-arm.rs:37:37: 37:50 + let mut _9: i32; // in scope 0 at $DIR/simplify-arm.rs:37:48: 37:49 + let _10: u8; // in scope 0 at $DIR/simplify-arm.rs:38:12: 38:13 + let mut _11: u8; // in scope 0 at $DIR/simplify-arm.rs:40:8: 40:9 scope 1 { - debug x => ((_0 as Ok).0: u8); // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10 + debug x => ((_0 as Ok).0: u8); // in scope 1 at $DIR/simplify-arm.rs:36:9: 36:10 } scope 2 { - debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15 - scope 3 { - scope 7 (inlined >::from) { // at $DIR/simplify-arm.rs:24:14: 24:15 - debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify-arm.rs:24:14: 24:15 - } - scope 8 (inlined as Try>::from_error) { // at $DIR/simplify-arm.rs:24:13: 24:15 - debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 - let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 - } + debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:37:13: 37:14 + scope 5 (inlined >::from) { // at $DIR/simplify-arm.rs:37:37: 37:50 + debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify-arm.rs:37:37: 37:50 } - } - scope 4 { - debug val => ((_0 as Ok).0: u8); // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15 - scope 5 { + scope 6 (inlined from_error::) { // at $DIR/simplify-arm.rs:37:26: 37:51 + debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify-arm.rs:37:26: 37:51 } } - scope 6 (inlined as Try>::into_result) { // at $DIR/simplify-arm.rs:24:13: 24:15 - debug self => _4; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + scope 3 { + debug v => ((_0 as Ok).0: u8); // in scope 3 at $DIR/simplify-arm.rs:38:12: 38:13 + } + scope 4 (inlined into_result::) { // at $DIR/simplify-arm.rs:36:19: 36:33 + debug r => _4; // in scope 4 at $DIR/simplify-arm.rs:36:19: 36:33 } bb0: { - StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10 - StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 - StorageLive(_4); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14 - _4 = _1; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14 - _3 = move _4; // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 - StorageDead(_4); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - _5 = discriminant(_3); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 -- switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 -+ goto -> bb1; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:36:9: 36:10 + StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33 + StorageLive(_4); // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32 + _4 = _1; // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32 + _3 = move _4; // scope 4 at $DIR/simplify-arm.rs:36:19: 36:33 + StorageDead(_4); // scope 0 at $DIR/simplify-arm.rs:36:32: 36:33 + _5 = discriminant(_3); // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15 +- switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15 ++ goto -> bb1; // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15 } bb1: { - _0 = move _3; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10 - StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16 - StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 -- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 -+ goto -> bb2; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 + _0 = move _3; // scope 1 at $DIR/simplify-arm.rs:40:5: 40:10 + StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:39:6: 39:7 + StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:41:1: 41:2 +- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2 ++ goto -> bb2; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2 } bb2: { -- unreachable; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 +- unreachable; // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33 - } - - bb3: { -- _0 = move _3; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 -- StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16 -- StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 -- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 +- _0 = move _3; // scope 6 at $DIR/simplify-arm.rs:37:26: 37:51 +- StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:39:6: 39:7 +- StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:41:1: 41:2 +- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2 - } - - bb4: { - return; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 + return; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2 } } diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs index eb307de20744a..a95cb665a97f3 100644 --- a/src/test/mir-opt/simplify_try.rs +++ b/src/test/mir-opt/simplify_try.rs @@ -4,8 +4,24 @@ // EMIT_MIR simplify_try.try_identity.SimplifyLocals.after.mir // EMIT_MIR simplify_try.try_identity.DestinationPropagation.diff + +fn into_result(r: Result) -> Result { + r +} + +fn from_error(e: E) -> Result { + Err(e) +} + +// This was written to the `?` from `try_trait`, +// but `try_trait_v2` uses a different structure, +// so the relevant desugar is copied inline +// in order to keep the test testing the same thing. fn try_identity(x: Result) -> Result { - let y = x?; + let y = match into_result(x) { + Err(e) => return from_error(From::from(e)), + Ok(v) => v, + }; Ok(y) } diff --git a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff index b1bae447f9c65..e09b8cb39bd51 100644 --- a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff +++ b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff @@ -2,67 +2,62 @@ + // MIR for `try_identity` after DestinationPropagation fn try_identity(_1: Result) -> Result { - debug x => _1; // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18 - let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify_try.rs:7:41: 7:57 - let _2: u32; // in scope 0 at $DIR/simplify_try.rs:8:9: 8:10 - let mut _3: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 - let mut _4: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:14 - let mut _5: isize; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let _6: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let mut _7: !; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let mut _8: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let mut _9: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let _10: u32; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 - let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:9:8: 9:9 + debug x => _1; // in scope 0 at $DIR/simplify_try.rs:20:17: 20:18 + let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify_try.rs:20:41: 20:57 + let _2: u32; // in scope 0 at $DIR/simplify_try.rs:21:9: 21:10 + let mut _3: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:21:19: 21:33 + let mut _4: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:21:31: 21:32 + let mut _5: isize; // in scope 0 at $DIR/simplify_try.rs:22:9: 22:15 + let _6: i32; // in scope 0 at $DIR/simplify_try.rs:22:13: 22:14 + let mut _7: !; // in scope 0 at $DIR/simplify_try.rs:22:19: 22:51 + let mut _8: i32; // in scope 0 at $DIR/simplify_try.rs:22:37: 22:50 + let mut _9: i32; // in scope 0 at $DIR/simplify_try.rs:22:48: 22:49 + let _10: u32; // in scope 0 at $DIR/simplify_try.rs:23:12: 23:13 + let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:25:8: 25:9 scope 1 { - debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10 + debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10 } scope 2 { - debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 - scope 3 { - scope 7 (inlined >::from) { // at $DIR/simplify_try.rs:8:14: 8:15 - debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15 - } - scope 8 (inlined as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15 - debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 - let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 - } + debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14 + scope 5 (inlined >::from) { // at $DIR/simplify_try.rs:22:37: 22:50 + debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50 } - } - scope 4 { - debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15 - scope 5 { + scope 6 (inlined from_error::) { // at $DIR/simplify_try.rs:22:26: 22:51 + debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51 } } - scope 6 (inlined as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15 -- debug self => _4; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 -+ debug self => _0; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + scope 3 { + debug v => ((_0 as Ok).0: u32); // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13 + } + scope 4 (inlined into_result::) { // at $DIR/simplify_try.rs:21:19: 21:33 +- debug r => _4; // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33 ++ debug r => _0; // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33 } bb0: { - StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:8:9: 8:10 -- StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 -- StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:8:13: 8:14 -- _4 = _1; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14 -- _3 = move _4; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 -- StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 -- _5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 -+ nop; // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 -+ nop; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14 -+ _0 = _1; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14 -+ nop; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 -+ nop; // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 -+ _5 = discriminant(_0); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - goto -> bb1; // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:21:9: 21:10 +- StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:21:19: 21:33 +- StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:21:31: 21:32 +- _4 = _1; // scope 0 at $DIR/simplify_try.rs:21:31: 21:32 +- _3 = move _4; // scope 4 at $DIR/simplify_try.rs:21:19: 21:33 +- StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:21:32: 21:33 +- _5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:22:9: 22:15 ++ nop; // scope 0 at $DIR/simplify_try.rs:21:19: 21:33 ++ nop; // scope 0 at $DIR/simplify_try.rs:21:31: 21:32 ++ _0 = _1; // scope 0 at $DIR/simplify_try.rs:21:31: 21:32 ++ nop; // scope 4 at $DIR/simplify_try.rs:21:19: 21:33 ++ nop; // scope 0 at $DIR/simplify_try.rs:21:32: 21:33 ++ _5 = discriminant(_0); // scope 0 at $DIR/simplify_try.rs:22:9: 22:15 + goto -> bb1; // scope 0 at $DIR/simplify_try.rs:22:9: 22:15 } bb1: { -- _0 = move _3; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10 -- StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:8:15: 8:16 -+ nop; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10 -+ nop; // scope 0 at $DIR/simplify_try.rs:8:15: 8:16 - StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:10:1: 10:2 - return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2 +- _0 = move _3; // scope 1 at $DIR/simplify_try.rs:25:5: 25:10 +- StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:24:6: 24:7 ++ nop; // scope 1 at $DIR/simplify_try.rs:25:5: 25:10 ++ nop; // scope 0 at $DIR/simplify_try.rs:24:6: 24:7 + StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:26:1: 26:2 + return; // scope 0 at $DIR/simplify_try.rs:26:2: 26:2 } } diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff index df274852f6820..488ad33f80a2d 100644 --- a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff @@ -2,93 +2,85 @@ + // MIR for `try_identity` after SimplifyArmIdentity fn try_identity(_1: Result) -> Result { - debug x => _1; // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18 - let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify_try.rs:7:41: 7:57 - let _2: u32; // in scope 0 at $DIR/simplify_try.rs:8:9: 8:10 - let mut _3: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 - let mut _4: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:14 - let mut _5: isize; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let _6: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let mut _7: !; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let mut _8: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let mut _9: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let _10: u32; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 - let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:9:8: 9:9 + debug x => _1; // in scope 0 at $DIR/simplify_try.rs:20:17: 20:18 + let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify_try.rs:20:41: 20:57 + let _2: u32; // in scope 0 at $DIR/simplify_try.rs:21:9: 21:10 + let mut _3: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:21:19: 21:33 + let mut _4: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:21:31: 21:32 + let mut _5: isize; // in scope 0 at $DIR/simplify_try.rs:22:9: 22:15 + let _6: i32; // in scope 0 at $DIR/simplify_try.rs:22:13: 22:14 + let mut _7: !; // in scope 0 at $DIR/simplify_try.rs:22:19: 22:51 + let mut _8: i32; // in scope 0 at $DIR/simplify_try.rs:22:37: 22:50 + let mut _9: i32; // in scope 0 at $DIR/simplify_try.rs:22:48: 22:49 + let _10: u32; // in scope 0 at $DIR/simplify_try.rs:23:12: 23:13 + let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:25:8: 25:9 scope 1 { -- debug y => _2; // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10 -+ debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10 +- debug y => _2; // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10 ++ debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10 } scope 2 { -- debug err => _6; // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 -+ debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 - scope 3 { - scope 7 (inlined >::from) { // at $DIR/simplify_try.rs:8:14: 8:15 -- debug t => _9; // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15 -+ debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15 - } - scope 8 (inlined as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15 -- debug v => _8; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 -+ debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 - let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 - } +- debug e => _6; // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14 ++ debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14 + scope 5 (inlined >::from) { // at $DIR/simplify_try.rs:22:37: 22:50 +- debug t => _9; // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50 ++ debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50 } - } - scope 4 { -- debug val => _10; // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15 -+ debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15 - scope 5 { + scope 6 (inlined from_error::) { // at $DIR/simplify_try.rs:22:26: 22:51 +- debug e => _8; // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51 ++ debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51 } } - scope 6 (inlined as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15 - debug self => _4; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + scope 3 { +- debug v => _10; // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13 ++ debug v => ((_0 as Ok).0: u32); // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13 + } + scope 4 (inlined into_result::) { // at $DIR/simplify_try.rs:21:19: 21:33 + debug r => _4; // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33 } bb0: { - StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:8:9: 8:10 - StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 - StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:8:13: 8:14 - _4 = _1; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14 - _3 = move _4; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 - StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - _5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:21:9: 21:10 + StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:21:19: 21:33 + StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:21:31: 21:32 + _4 = _1; // scope 0 at $DIR/simplify_try.rs:21:31: 21:32 + _3 = move _4; // scope 4 at $DIR/simplify_try.rs:21:19: 21:33 + StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:21:32: 21:33 + _5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:22:9: 22:15 + switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:22:9: 22:15 } bb1: { -- StorageLive(_10); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 -- _10 = ((_3 as Ok).0: u32); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 -- _2 = _10; // scope 5 at $DIR/simplify_try.rs:8:13: 8:15 -- StorageDead(_10); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 -+ _0 = move _3; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10 - StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:8:15: 8:16 -- StorageLive(_11); // scope 1 at $DIR/simplify_try.rs:9:8: 9:9 -- _11 = _2; // scope 1 at $DIR/simplify_try.rs:9:8: 9:9 -- ((_0 as Ok).0: u32) = move _11; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10 -- discriminant(_0) = 0; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10 -- StorageDead(_11); // scope 1 at $DIR/simplify_try.rs:9:9: 9:10 - StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:10:1: 10:2 - return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2 +- StorageLive(_10); // scope 0 at $DIR/simplify_try.rs:23:12: 23:13 +- _10 = ((_3 as Ok).0: u32); // scope 0 at $DIR/simplify_try.rs:23:12: 23:13 +- _2 = _10; // scope 3 at $DIR/simplify_try.rs:23:18: 23:19 +- StorageDead(_10); // scope 0 at $DIR/simplify_try.rs:23:18: 23:19 ++ _0 = move _3; // scope 1 at $DIR/simplify_try.rs:25:5: 25:10 + StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:24:6: 24:7 +- StorageLive(_11); // scope 1 at $DIR/simplify_try.rs:25:8: 25:9 +- _11 = _2; // scope 1 at $DIR/simplify_try.rs:25:8: 25:9 +- ((_0 as Ok).0: u32) = move _11; // scope 1 at $DIR/simplify_try.rs:25:5: 25:10 +- discriminant(_0) = 0; // scope 1 at $DIR/simplify_try.rs:25:5: 25:10 +- StorageDead(_11); // scope 1 at $DIR/simplify_try.rs:25:9: 25:10 + StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:26:1: 26:2 + return; // scope 0 at $DIR/simplify_try.rs:26:2: 26:2 } bb2: { -- StorageLive(_6); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 -- _6 = ((_3 as Err).0: i32); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 -- StorageLive(_8); // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 -- StorageLive(_9); // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 -- _9 = _6; // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 -- _8 = move _9; // scope 7 at $DIR/simplify_try.rs:8:14: 8:15 -- StorageDead(_9); // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 -- StorageLive(_12); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 -- _12 = move _8; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 -- ((_0 as Err).0: i32) = move _12; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 -- discriminant(_0) = 1; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 -- StorageDead(_12); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 -- StorageDead(_8); // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 -- StorageDead(_6); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 -+ _0 = move _3; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 - StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:8:15: 8:16 - StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:10:1: 10:2 - return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2 +- StorageLive(_6); // scope 0 at $DIR/simplify_try.rs:22:13: 22:14 +- _6 = ((_3 as Err).0: i32); // scope 0 at $DIR/simplify_try.rs:22:13: 22:14 +- StorageLive(_8); // scope 2 at $DIR/simplify_try.rs:22:37: 22:50 +- StorageLive(_9); // scope 2 at $DIR/simplify_try.rs:22:48: 22:49 +- _9 = _6; // scope 2 at $DIR/simplify_try.rs:22:48: 22:49 +- _8 = move _9; // scope 5 at $DIR/simplify_try.rs:22:37: 22:50 +- StorageDead(_9); // scope 2 at $DIR/simplify_try.rs:22:49: 22:50 +- ((_0 as Err).0: i32) = move _8; // scope 6 at $DIR/simplify_try.rs:22:26: 22:51 +- discriminant(_0) = 1; // scope 6 at $DIR/simplify_try.rs:22:26: 22:51 +- StorageDead(_8); // scope 2 at $DIR/simplify_try.rs:22:50: 22:51 +- StorageDead(_6); // scope 0 at $DIR/simplify_try.rs:22:50: 22:51 ++ _0 = move _3; // scope 6 at $DIR/simplify_try.rs:22:26: 22:51 + StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:24:6: 24:7 + StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:26:1: 26:2 + return; // scope 0 at $DIR/simplify_try.rs:26:2: 26:2 } } diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir index 37274691fb476..5d829f859e9d9 100644 --- a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir +++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir @@ -1,57 +1,52 @@ // MIR for `try_identity` after SimplifyBranchSame fn try_identity(_1: Result) -> Result { - debug x => _1; // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18 - let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify_try.rs:7:41: 7:57 - let _2: u32; // in scope 0 at $DIR/simplify_try.rs:8:9: 8:10 - let mut _3: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 - let mut _4: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:14 - let mut _5: isize; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let _6: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let mut _7: !; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let mut _8: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let mut _9: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - let _10: u32; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 - let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:9:8: 9:9 + debug x => _1; // in scope 0 at $DIR/simplify_try.rs:20:17: 20:18 + let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify_try.rs:20:41: 20:57 + let _2: u32; // in scope 0 at $DIR/simplify_try.rs:21:9: 21:10 + let mut _3: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:21:19: 21:33 + let mut _4: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:21:31: 21:32 + let mut _5: isize; // in scope 0 at $DIR/simplify_try.rs:22:9: 22:15 + let _6: i32; // in scope 0 at $DIR/simplify_try.rs:22:13: 22:14 + let mut _7: !; // in scope 0 at $DIR/simplify_try.rs:22:19: 22:51 + let mut _8: i32; // in scope 0 at $DIR/simplify_try.rs:22:37: 22:50 + let mut _9: i32; // in scope 0 at $DIR/simplify_try.rs:22:48: 22:49 + let _10: u32; // in scope 0 at $DIR/simplify_try.rs:23:12: 23:13 + let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:25:8: 25:9 scope 1 { - debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10 + debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10 } scope 2 { - debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 - scope 3 { - scope 7 (inlined >::from) { // at $DIR/simplify_try.rs:8:14: 8:15 - debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15 - } - scope 8 (inlined as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15 - debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 - let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 - } + debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14 + scope 5 (inlined >::from) { // at $DIR/simplify_try.rs:22:37: 22:50 + debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50 } - } - scope 4 { - debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15 - scope 5 { + scope 6 (inlined from_error::) { // at $DIR/simplify_try.rs:22:26: 22:51 + debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51 } } - scope 6 (inlined as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15 - debug self => _4; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + scope 3 { + debug v => ((_0 as Ok).0: u32); // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13 + } + scope 4 (inlined into_result::) { // at $DIR/simplify_try.rs:21:19: 21:33 + debug r => _4; // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33 } bb0: { - StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:8:9: 8:10 - StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 - StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:8:13: 8:14 - _4 = _1; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14 - _3 = move _4; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 - StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - _5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - goto -> bb1; // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:21:9: 21:10 + StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:21:19: 21:33 + StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:21:31: 21:32 + _4 = _1; // scope 0 at $DIR/simplify_try.rs:21:31: 21:32 + _3 = move _4; // scope 4 at $DIR/simplify_try.rs:21:19: 21:33 + StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:21:32: 21:33 + _5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:22:9: 22:15 + goto -> bb1; // scope 0 at $DIR/simplify_try.rs:22:9: 22:15 } bb1: { - _0 = move _3; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10 - StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:8:15: 8:16 - StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:10:1: 10:2 - return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2 + _0 = move _3; // scope 1 at $DIR/simplify_try.rs:25:5: 25:10 + StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:24:6: 24:7 + StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:26:1: 26:2 + return; // scope 0 at $DIR/simplify_try.rs:26:2: 26:2 } } diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir index f8adcced4b306..1b5232422b6c3 100644 --- a/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir +++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir @@ -1,33 +1,29 @@ // MIR for `try_identity` after SimplifyLocals fn try_identity(_1: Result) -> Result { - debug x => _1; // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18 - let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify_try.rs:7:41: 7:57 + debug x => _1; // in scope 0 at $DIR/simplify_try.rs:20:17: 20:18 + let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify_try.rs:20:41: 20:57 scope 1 { - debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10 + debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10 } scope 2 { - debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 - scope 3 { - scope 7 (inlined >::from) { // at $DIR/simplify_try.rs:8:14: 8:15 - debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15 - } - scope 8 (inlined as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15 - debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 - } + debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14 + scope 5 (inlined >::from) { // at $DIR/simplify_try.rs:22:37: 22:50 + debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50 } - } - scope 4 { - debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15 - scope 5 { + scope 6 (inlined from_error::) { // at $DIR/simplify_try.rs:22:26: 22:51 + debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51 } } - scope 6 (inlined as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15 - debug self => _0; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + scope 3 { + debug v => ((_0 as Ok).0: u32); // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13 + } + scope 4 (inlined into_result::) { // at $DIR/simplify_try.rs:21:19: 21:33 + debug r => _0; // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33 } bb0: { - _0 = _1; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14 - return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2 + _0 = _1; // scope 0 at $DIR/simplify_try.rs:21:31: 21:32 + return; // scope 0 at $DIR/simplify_try.rs:26:2: 26:2 } } From 4a7ceea930e0029bccb8f7bfcc70ef4ba3d550d8 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 17 Apr 2021 11:56:07 -0700 Subject: [PATCH 05/11] Better rustc_on_unimplemented, and UI test fixes --- library/core/src/ops/mod.rs | 4 +- library/core/src/ops/try_trait.rs | 79 ++++++++++++ src/test/ui/async-await/issue-61076.rs | 4 +- src/test/ui/async-await/issue-61076.stderr | 4 +- .../async-await/try-on-option-in-async.stderr | 30 ++--- ...infer-async-enabled-impl-trait-bindings.rs | 4 +- ...r-async-enabled-impl-trait-bindings.stderr | 11 +- src/test/ui/inference/cannot-infer-async.rs | 4 +- .../ui/inference/cannot-infer-async.stderr | 9 +- .../cannot-infer-closure-circular.stderr | 2 +- src/test/ui/inference/cannot-infer-closure.rs | 4 +- .../ui/inference/cannot-infer-closure.stderr | 7 +- .../cannot-infer-partial-try-return.stderr | 3 +- src/test/ui/issues/issue-32709.stderr | 3 +- src/test/ui/option-to-result.stderr | 35 ------ src/test/ui/question-mark-type-infer.stderr | 7 +- .../disallowed-positions.stderr | 42 +++---- src/test/ui/suggestions/issue-72766.stderr | 2 +- src/test/ui/try-block/try-block-bad-type.rs | 5 +- .../ui/try-block/try-block-bad-type.stderr | 31 +++-- src/test/ui/try-block/try-block-in-while.rs | 2 +- .../ui/try-block/try-block-in-while.stderr | 7 +- .../ui/try-block/try-block-type-error.stderr | 4 +- src/test/ui/try-on-option.stderr | 33 ----- src/test/ui/try-operator-custom.rs | 63 ---------- src/test/ui/try-trait/bad-interconversion.rs | 48 ++++++++ .../ui/try-trait/bad-interconversion.stderr | 115 ++++++++++++++++++ .../ui/{ => try-trait}/option-to-result.rs | 4 +- src/test/ui/try-trait/option-to-result.stderr | 31 +++++ src/test/ui/try-trait/try-as-monad.rs | 24 ++++ .../try-on-option-diagnostics.rs | 0 .../try-on-option-diagnostics.stderr | 40 +++--- src/test/ui/{ => try-trait}/try-on-option.rs | 2 +- src/test/ui/try-trait/try-on-option.stderr | 31 +++++ src/test/ui/try-trait/try-operator-custom.rs | 91 ++++++++++++++ .../{ => try-trait}/try-operator-on-main.rs | 7 +- .../try-operator-on-main.stderr | 38 ++++-- src/test/ui/{ => try-trait}/try-poll.rs | 0 38 files changed, 564 insertions(+), 266 deletions(-) delete mode 100644 src/test/ui/option-to-result.stderr delete mode 100644 src/test/ui/try-on-option.stderr delete mode 100644 src/test/ui/try-operator-custom.rs create mode 100644 src/test/ui/try-trait/bad-interconversion.rs create mode 100644 src/test/ui/try-trait/bad-interconversion.stderr rename src/test/ui/{ => try-trait}/option-to-result.rs (63%) create mode 100644 src/test/ui/try-trait/option-to-result.stderr create mode 100644 src/test/ui/try-trait/try-as-monad.rs rename src/test/ui/{ => try-trait}/try-on-option-diagnostics.rs (100%) rename src/test/ui/{ => try-trait}/try-on-option-diagnostics.stderr (60%) rename src/test/ui/{ => try-trait}/try-on-option.rs (80%) create mode 100644 src/test/ui/try-trait/try-on-option.stderr create mode 100644 src/test/ui/try-trait/try-operator-custom.rs rename src/test/ui/{ => try-trait}/try-operator-on-main.rs (75%) rename src/test/ui/{ => try-trait}/try-operator-on-main.stderr (52%) rename src/test/ui/{ => try-trait}/try-poll.rs (100%) diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 426b45a925eda..4fca2898b56b4 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -187,7 +187,7 @@ pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; pub use self::r#try::Try; #[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] -pub use self::r#try::Try as TryV1; +pub(crate) use self::r#try::Try as TryV1; #[unstable(feature = "try_trait_v2", issue = "84277")] pub use self::try_trait::FromResidual; @@ -197,7 +197,7 @@ pub use self::try_trait::FromResidual; pub use self::try_trait::Try; #[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] -pub use self::try_trait::Try as TryV2; +pub(crate) use self::try_trait::Try as TryV2; #[unstable(feature = "generator_trait", issue = "43122")] pub use self::generator::{Generator, GeneratorState}; diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 80a5800bcbb89..35989d2bc052c 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -115,6 +115,21 @@ use crate::ops::ControlFlow; /// } /// ``` #[unstable(feature = "try_trait_v2", issue = "84277")] +#[rustc_on_unimplemented( + on( + all(from_method = "from_output", from_desugaring = "TryBlock"), + message = "a `try` block must return `Result` or `Option` \ + (or another type that implements `{Try}`)", + label = "could not wrap the final value of the block as `{Self}` doesn't implement `Try`", + ), + on( + all(from_method = "branch", from_desugaring = "QuestionMark"), + message = "the `?` operator can only be applied to values \ + that implement `{Try}`", + label = "the `?` operator cannot be applied to type `{Self}`" + ) +)] +#[doc(alias = "?")] #[cfg_attr(not(bootstrap), lang = "Try")] pub trait Try: FromResidual { /// The type of the value produced by `?` when *not* short-circuiting. @@ -212,6 +227,70 @@ pub trait Try: FromResidual { /// Every `Try` type needs to be recreatable from its own associated /// `Residual` type, but can also have additional `FromResidual` implementations /// to support interconversion with other `Try` types. +#[rustc_on_unimplemented( + on( + all( + from_method = "from_residual", + from_desugaring = "QuestionMark", + _Self = "std::result::Result", + R = "std::option::Option" + ), + message = "the `?` operator can only be used on `Result`s, not `Option`s, \ + in {ItemContext} that returns `Result`", + label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`", + enclosing_scope = "this function returns a `Result`" + ), + on( + all( + from_method = "from_residual", + from_desugaring = "QuestionMark", + _Self = "std::result::Result", + ), + // There's a special error message in the trait selection code for + // `From` in `?`, so this is not shown for result-in-result errors, + // and thus it can be phrased more strongly than `ControlFlow`'s. + message = "the `?` operator can only be used on `Result`s \ + in {ItemContext} that returns `Result`", + label = "this `?` produces `{R}`, which is incompatible with `{Self}`", + enclosing_scope = "this function returns a `Result`" + ), + on( + all( + from_method = "from_residual", + from_desugaring = "QuestionMark", + _Self = "std::option::Option", + ), + // `Option`-in-`Option` always works, as there's only one possible + // residual, so this can also be phrased strongly. + message = "the `?` operator can only be used on `Option`s \ + in {ItemContext} that returns `Option`", + label = "this `?` produces `{R}`, which is incompatible with `{Self}`", + enclosing_scope = "this function returns an `Option`" + ), + on( + all( + from_method = "from_residual", + from_desugaring = "QuestionMark", + _Self = "std::ops::ControlFlow", + ), + message = "the `?` operator can only be used on `ControlFlow`s \ + in {ItemContext} that returns `ControlFlow`", + label = "this `?` produces `{R}`, which is incompatible with `{Self}`", + enclosing_scope = "this function returns a `ControlFlow`", + note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`" + ), + on( + all( + from_method = "from_residual", + from_desugaring = "QuestionMark" + ), + message = "the `?` operator can only be used in {ItemContext} \ + that returns `Result` or `Option` \ + (or another type that implements `{FromResidual}`)", + label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`", + enclosing_scope = "this function should return `Result` or `Option` to accept `?`" + ), +)] #[unstable(feature = "try_trait_v2", issue = "84277")] pub trait FromResidual::Residual> { /// Constructs the type from a compatible `Residual` type. diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs index 4a8e841b33d49..9fe3313ee6cc6 100644 --- a/src/test/ui/async-await/issue-61076.rs +++ b/src/test/ui/async-await/issue-61076.rs @@ -42,7 +42,7 @@ async fn bar() -> Result<(), ()> { foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Try` //~^ NOTE the `?` operator cannot be applied to type `impl Future` //~| HELP the trait `Try` is not implemented for `impl Future` - //~| NOTE required by `into_result` + //~| NOTE required by `branch` //~| HELP consider `await`ing on the `Future` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` @@ -65,7 +65,7 @@ async fn baz() -> Result<(), ()> { t?; //~ ERROR the `?` operator can only be applied to values that implement `Try` //~^ NOTE the `?` operator cannot be applied to type `T` //~| HELP the trait `Try` is not implemented for `T` - //~| NOTE required by `into_result` + //~| NOTE required by `branch` //~| HELP consider `await`ing on the `Future` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr index fd00522fac703..ad661fb2833fa 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -5,7 +5,7 @@ LL | foo()?; | ^^^^^^ the `?` operator cannot be applied to type `impl Future` | = help: the trait `Try` is not implemented for `impl Future` - = note: required by `into_result` + = note: required by `branch` help: consider `await`ing on the `Future` | LL | foo().await?; @@ -18,7 +18,7 @@ LL | t?; | ^^ the `?` operator cannot be applied to type `T` | = help: the trait `Try` is not implemented for `T` - = note: required by `into_result` + = note: required by `branch` help: consider `await`ing on the `Future` | LL | t.await?; diff --git a/src/test/ui/async-await/try-on-option-in-async.stderr b/src/test/ui/async-await/try-on-option-in-async.stderr index 8e7823f3571b1..a3f122a466361 100644 --- a/src/test/ui/async-await/try-on-option-in-async.stderr +++ b/src/test/ui/async-await/try-on-option-in-async.stderr @@ -1,47 +1,47 @@ -error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `Try`) - --> $DIR/try-on-option-in-async.rs:8:9 +error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-in-async.rs:8:10 | LL | async { | ___________- LL | | let x: Option = None; LL | | x?; - | | ^^ cannot use the `?` operator in an async block that returns `{integer}` + | | ^ cannot use the `?` operator in an async block that returns `{integer}` LL | | 22 LL | | } | |_____- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try` is not implemented for `{integer}` - = note: required by `from_error` + = help: the trait `FromResidual>` is not implemented for `{integer}` + = note: required by `from_residual` -error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `Try`) - --> $DIR/try-on-option-in-async.rs:17:9 +error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-in-async.rs:17:10 | LL | let async_closure = async || { | __________________________________- LL | | let x: Option = None; LL | | x?; - | | ^^ cannot use the `?` operator in an async closure that returns `u32` + | | ^ cannot use the `?` operator in an async closure that returns `u32` LL | | 22_u32 LL | | }; | |_____- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try` is not implemented for `u32` - = note: required by `from_error` + = help: the trait `FromResidual>` is not implemented for `u32` + = note: required by `from_residual` -error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `Try`) - --> $DIR/try-on-option-in-async.rs:26:5 +error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-in-async.rs:26:6 | LL | async fn an_async_function() -> u32 { | _____________________________________- LL | | let x: Option = None; LL | | x?; - | | ^^ cannot use the `?` operator in an async function that returns `u32` + | | ^ cannot use the `?` operator in an async function that returns `u32` LL | | 22 LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try` is not implemented for `u32` - = note: required by `from_error` + = help: the trait `FromResidual>` is not implemented for `u32` + = note: required by `from_residual` error: aborting due to 3 previous errors diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs index 2e96022318b47..7beb2db3969c8 100644 --- a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs @@ -10,8 +10,8 @@ fn make_unit() -> Result<(), Error> { fn main() { let fut = async { - make_unit()?; //~ ERROR type annotations needed + make_unit()?; - Ok(()) + Ok(()) //~ ERROR type annotations needed }; } diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr index 2875cef680117..8e632fbc1de1b 100644 --- a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr @@ -8,14 +8,13 @@ LL | #![feature(impl_trait_in_bindings)] = note: see issue #63065 for more information error[E0282]: type annotations needed for `impl Future` - --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:20 + --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:15:9 | LL | let fut = async { - | --- consider giving `fut` the explicit type `impl Future`, with the type parameters specified -LL | make_unit()?; - | ^ cannot infer type of error for `?` operator - | - = note: `?` implicitly converts the error value into a type implementing `From` + | --- consider giving `fut` the explicit type `impl Future`, where the type parameter `E` is specified +... +LL | Ok(()) + | ^^ cannot infer type for type parameter `E` declared on the enum `Result` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/inference/cannot-infer-async.rs b/src/test/ui/inference/cannot-infer-async.rs index 05f62f3d8cbc0..e7fabd0ffbc8b 100644 --- a/src/test/ui/inference/cannot-infer-async.rs +++ b/src/test/ui/inference/cannot-infer-async.rs @@ -8,8 +8,8 @@ fn make_unit() -> Result<(), Error> { fn main() { let fut = async { - make_unit()?; //~ ERROR type annotations needed + make_unit()?; - Ok(()) + Ok(()) //~ ERROR type annotations needed }; } diff --git a/src/test/ui/inference/cannot-infer-async.stderr b/src/test/ui/inference/cannot-infer-async.stderr index 282bc13e9e780..233604833612a 100644 --- a/src/test/ui/inference/cannot-infer-async.stderr +++ b/src/test/ui/inference/cannot-infer-async.stderr @@ -1,12 +1,11 @@ error[E0282]: type annotations needed - --> $DIR/cannot-infer-async.rs:11:20 + --> $DIR/cannot-infer-async.rs:13:9 | LL | let fut = async { | --- consider giving `fut` a type -LL | make_unit()?; - | ^ cannot infer type of error for `?` operator - | - = note: `?` implicitly converts the error value into a type implementing `From` +... +LL | Ok(()) + | ^^ cannot infer type for type parameter `E` declared on the enum `Result` error: aborting due to previous error diff --git a/src/test/ui/inference/cannot-infer-closure-circular.stderr b/src/test/ui/inference/cannot-infer-closure-circular.stderr index 211ae13e46df1..a6ddb7ae908fc 100644 --- a/src/test/ui/inference/cannot-infer-closure-circular.stderr +++ b/src/test/ui/inference/cannot-infer-closure-circular.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Result<(), E>` --> $DIR/cannot-infer-closure-circular.rs:7:14 | LL | let x = |r| { - | ^ consider giving this closure parameter the explicit type `Result<(), E>`, with the type parameters specified + | ^ consider giving this closure parameter the explicit type `Result<(), E>`, where the type parameter `E` is specified error: aborting due to previous error diff --git a/src/test/ui/inference/cannot-infer-closure.rs b/src/test/ui/inference/cannot-infer-closure.rs index 8f48483c25421..6e84b6d5ad0bd 100644 --- a/src/test/ui/inference/cannot-infer-closure.rs +++ b/src/test/ui/inference/cannot-infer-closure.rs @@ -1,6 +1,6 @@ fn main() { let x = |a: (), b: ()| { - Err(a)?; //~ ERROR type annotations needed for the closure - Ok(b) + Err(a)?; + Ok(b) //~ ERROR type annotations needed for the closure }; } diff --git a/src/test/ui/inference/cannot-infer-closure.stderr b/src/test/ui/inference/cannot-infer-closure.stderr index 0dcce9e990b53..e055d1a94ffe9 100644 --- a/src/test/ui/inference/cannot-infer-closure.stderr +++ b/src/test/ui/inference/cannot-infer-closure.stderr @@ -1,10 +1,9 @@ error[E0282]: type annotations needed for the closure `fn((), ()) -> Result<(), _>` - --> $DIR/cannot-infer-closure.rs:3:15 + --> $DIR/cannot-infer-closure.rs:4:9 | -LL | Err(a)?; - | ^ cannot infer type of error for `?` operator +LL | Ok(b) + | ^^ cannot infer type for type parameter `E` declared on the enum `Result` | - = note: `?` implicitly converts the error value into a type implementing `From<()>` help: give this closure an explicit return type without `_` placeholders | LL | let x = |a: (), b: ()| -> Result<(), _> { diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.stderr b/src/test/ui/inference/cannot-infer-partial-try-return.stderr index 86e2126e1ae7b..c394f6efbda9b 100644 --- a/src/test/ui/inference/cannot-infer-partial-try-return.stderr +++ b/src/test/ui/inference/cannot-infer-partial-try-return.stderr @@ -2,9 +2,8 @@ error[E0282]: type annotations needed for the closure `fn() -> Result<(), Qualif --> $DIR/cannot-infer-partial-try-return.rs:19:9 | LL | infallible()?; - | ^^^^^^^^^^^^^ cannot infer type of error for `?` operator + | ^^^^^^^^^^^^^ cannot infer type | - = note: `?` implicitly converts the error value into `QualifiedError<_>` using its implementation of `From` help: give this closure an explicit return type without `_` placeholders | LL | let x = || -> Result<(), QualifiedError<_>> { diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr index cc12c153621cc..2d020188198af 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr @@ -7,7 +7,8 @@ LL | Err(5)?; | ^ the trait `From<{integer}>` is not implemented for `()` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = note: required by `from` + = note: required because of the requirements on the impl of `FromResidual>` for `Result` + = note: required by `from_residual` error: aborting due to previous error diff --git a/src/test/ui/option-to-result.stderr b/src/test/ui/option-to-result.stderr deleted file mode 100644 index 551b9f4650aac..0000000000000 --- a/src/test/ui/option-to-result.stderr +++ /dev/null @@ -1,35 +0,0 @@ -error[E0277]: `?` couldn't convert the error to `()` - --> $DIR/option-to-result.rs:5:6 - | -LL | fn test_result() -> Result<(),()> { - | ------------- expected `()` because of this -LL | let a:Option<()> = Some(()); -LL | a?; - | ^ the trait `From` is not implemented for `()` - | - = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = note: required by `from` -help: consider converting the `Option` into a `Result` using `Option::ok_or` or `Option::ok_or_else` - | -LL | a.ok_or_else(|| /* error value */)?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: `?` couldn't convert the error to `NoneError` - --> $DIR/option-to-result.rs:11:6 - | -LL | fn test_option() -> Option{ - | ----------- expected `NoneError` because of this -LL | let a:Result = Ok(5); -LL | a?; - | ^ the trait `From` is not implemented for `NoneError` - | - = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = note: required by `from` -help: consider converting the `Result` into an `Option` using `Result::ok` - | -LL | a.ok()?; - | ^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr index 381959b7ae4cd..db5042b40d8bc 100644 --- a/src/test/ui/question-mark-type-infer.stderr +++ b/src/test/ui/question-mark-type-infer.stderr @@ -1,11 +1,10 @@ -error[E0283]: type annotations needed +error[E0284]: type annotations needed --> $DIR/question-mark-type-infer.rs:12:21 | LL | l.iter().map(f).collect()? | ^^^^^^^ cannot infer type | - = note: cannot satisfy `_: Try` - = note: required by `into_result` + = note: cannot satisfy `<_ as Try>::Residual == _` help: consider specifying the type argument in the method call | LL | l.iter().map(f).collect::()? @@ -13,4 +12,4 @@ LL | l.iter().map(f).collect::()? error: aborting due to previous error -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0284`. diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index 1adce5e01506d..6985f1b71a8db 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -502,10 +502,10 @@ LL | if (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | = help: the trait `Try` is not implemented for `bool` - = note: required by `into_result` + = note: required by `branch` -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`) - --> $DIR/disallowed-positions.rs:46:8 +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/disallowed-positions.rs:46:19 | LL | / fn nested_within_if_expr() { LL | | if &let 0 = 0 {} @@ -513,14 +513,14 @@ LL | | LL | | ... | LL | | if (let 0 = 0)? {} - | | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()` + | | ^ cannot use the `?` operator in a function that returns `()` ... | LL | | if let true = let true = true {} LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try` is not implemented for `()` - = note: required by `from_error` + = help: the trait `FromResidual<_>` is not implemented for `()` + = note: required by `from_residual` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:56:8 @@ -660,7 +660,7 @@ LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` - = note: required by `into_result` + = note: required by `branch` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:96:11 @@ -690,10 +690,10 @@ LL | while (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | = help: the trait `Try` is not implemented for `bool` - = note: required by `into_result` + = note: required by `branch` -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`) - --> $DIR/disallowed-positions.rs:110:11 +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/disallowed-positions.rs:110:22 | LL | / fn nested_within_while_expr() { LL | | while &let 0 = 0 {} @@ -701,14 +701,14 @@ LL | | LL | | ... | LL | | while (let 0 = 0)? {} - | | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()` + | | ^ cannot use the `?` operator in a function that returns `()` ... | LL | | while let true = let true = true {} LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try` is not implemented for `()` - = note: required by `from_error` + = help: the trait `FromResidual<_>` is not implemented for `()` + = note: required by `from_residual` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:120:11 @@ -848,7 +848,7 @@ LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` - = note: required by `into_result` + = note: required by `branch` error[E0614]: type `bool` cannot be dereferenced --> $DIR/disallowed-positions.rs:173:5 @@ -869,10 +869,10 @@ LL | (let 0 = 0)?; | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | = help: the trait `Try` is not implemented for `bool` - = note: required by `into_result` + = note: required by `branch` -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`) - --> $DIR/disallowed-positions.rs:183:5 +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/disallowed-positions.rs:183:16 | LL | / fn outside_if_and_while_expr() { LL | | &let 0 = 0; @@ -880,14 +880,14 @@ LL | | LL | | !let 0 = 0; ... | LL | | (let 0 = 0)?; - | | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()` + | | ^ cannot use the `?` operator in a function that returns `()` ... | LL | | LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try` is not implemented for `()` - = note: required by `from_error` + = help: the trait `FromResidual<_>` is not implemented for `()` + = note: required by `from_residual` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:198:10 @@ -916,7 +916,7 @@ LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` - = note: required by `into_result` + = note: required by `branch` error: aborting due to 104 previous errors; 2 warnings emitted diff --git a/src/test/ui/suggestions/issue-72766.stderr b/src/test/ui/suggestions/issue-72766.stderr index 5c9c549fa0779..eb67170d47cdf 100644 --- a/src/test/ui/suggestions/issue-72766.stderr +++ b/src/test/ui/suggestions/issue-72766.stderr @@ -5,7 +5,7 @@ LL | SadGirl {}.call()?; | ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future` | = help: the trait `Try` is not implemented for `impl Future` - = note: required by `into_result` + = note: required by `branch` help: consider `await`ing on the `Future` | LL | SadGirl {}.call().await?; diff --git a/src/test/ui/try-block/try-block-bad-type.rs b/src/test/ui/try-block/try-block-bad-type.rs index ef6e690e1bd0e..30ae96763c0e2 100644 --- a/src/test/ui/try-block/try-block-bad-type.rs +++ b/src/test/ui/try-block/try-block-bad-type.rs @@ -15,8 +15,7 @@ pub fn main() { let res: Result = try { }; //~ ERROR type mismatch let res: () = try { }; - //~^ ERROR the trait bound `(): Try` is not satisfied - //~| ERROR the trait bound `(): Try` is not satisfied + //~^ ERROR a `try` block must return `Result` or `Option` - let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try` is not satisfied + let res: i32 = try { 5 }; //~ ERROR a `try` block must return `Result` or `Option` } diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr index 75a42c0d6b71b..ec5e91f10c286 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -7,43 +7,40 @@ LL | Err("")?; = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the following implementations were found: > - = note: required by `from` + = note: required because of the requirements on the impl of `FromResidual>` for `Result` + = note: required by `from_residual` -error[E0271]: type mismatch resolving ` as Try>::Ok == &str` +error[E0271]: type mismatch resolving ` as Try>::Output == &str` --> $DIR/try-block-bad-type.rs:12:9 | LL | "" | ^^ expected `i32`, found `&str` -error[E0271]: type mismatch resolving ` as Try>::Ok == ()` +error[E0271]: type mismatch resolving ` as Try>::Output == ()` --> $DIR/try-block-bad-type.rs:15:39 | LL | let res: Result = try { }; | ^ expected `i32`, found `()` -error[E0277]: the trait bound `(): Try` is not satisfied +error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`) --> $DIR/try-block-bad-type.rs:17:25 | LL | let res: () = try { }; - | ^ the trait `Try` is not implemented for `()` + | ^ could not wrap the final value of the block as `()` doesn't implement `Try` | - = note: required by `from_ok` + = help: the trait `Try` is not implemented for `()` + = note: required by `from_output` -error[E0277]: the trait bound `(): Try` is not satisfied - --> $DIR/try-block-bad-type.rs:17:25 - | -LL | let res: () = try { }; - | ^ the trait `Try` is not implemented for `()` - -error[E0277]: the trait bound `i32: Try` is not satisfied - --> $DIR/try-block-bad-type.rs:21:26 +error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`) + --> $DIR/try-block-bad-type.rs:20:26 | LL | let res: i32 = try { 5 }; - | ^ the trait `Try` is not implemented for `i32` + | ^ could not wrap the final value of the block as `i32` doesn't implement `Try` | - = note: required by `from_ok` + = help: the trait `Try` is not implemented for `i32` + = note: required by `from_output` -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0271, E0277. For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/try-block/try-block-in-while.rs b/src/test/ui/try-block/try-block-in-while.rs index 5d8748f1dd325..69793df525e77 100644 --- a/src/test/ui/try-block/try-block-in-while.rs +++ b/src/test/ui/try-block/try-block-in-while.rs @@ -4,5 +4,5 @@ fn main() { while try { false } {} - //~^ ERROR the trait bound `bool: Try` is not satisfied + //~^ ERROR a `try` block must } diff --git a/src/test/ui/try-block/try-block-in-while.stderr b/src/test/ui/try-block/try-block-in-while.stderr index 75a4e8d065cab..c83351d5c4346 100644 --- a/src/test/ui/try-block/try-block-in-while.stderr +++ b/src/test/ui/try-block/try-block-in-while.stderr @@ -1,10 +1,11 @@ -error[E0277]: the trait bound `bool: Try` is not satisfied +error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`) --> $DIR/try-block-in-while.rs:6:17 | LL | while try { false } {} - | ^^^^^ the trait `Try` is not implemented for `bool` + | ^^^^^ could not wrap the final value of the block as `bool` doesn't implement `Try` | - = note: required by `from_ok` + = help: the trait `Try` is not implemented for `bool` + = note: required by `from_output` error: aborting due to previous error diff --git a/src/test/ui/try-block/try-block-type-error.stderr b/src/test/ui/try-block/try-block-type-error.stderr index df1441c83d4f1..3e9a584a5510a 100644 --- a/src/test/ui/try-block/try-block-type-error.stderr +++ b/src/test/ui/try-block/try-block-type-error.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving ` as Try>::Ok == {integer}` +error[E0271]: type mismatch resolving ` as Try>::Output == {integer}` --> $DIR/try-block-type-error.rs:10:9 | LL | 42 @@ -7,7 +7,7 @@ LL | 42 | expected `f32`, found integer | help: use a float literal: `42.0` -error[E0271]: type mismatch resolving ` as Try>::Ok == ()` +error[E0271]: type mismatch resolving ` as Try>::Output == ()` --> $DIR/try-block-type-error.rs:16:5 | LL | }; diff --git a/src/test/ui/try-on-option.stderr b/src/test/ui/try-on-option.stderr deleted file mode 100644 index ecd12c430f1f6..0000000000000 --- a/src/test/ui/try-on-option.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0277]: `?` couldn't convert the error to `()` - --> $DIR/try-on-option.rs:7:6 - | -LL | fn foo() -> Result { - | --------------- expected `()` because of this -LL | let x: Option = None; -LL | x?; - | ^ the trait `From` is not implemented for `()` - | - = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = note: required by `from` -help: consider converting the `Option` into a `Result` using `Option::ok_or` or `Option::ok_or_else` - | -LL | x.ok_or_else(|| /* error value */)?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`) - --> $DIR/try-on-option.rs:13:5 - | -LL | / fn bar() -> u32 { -LL | | let x: Option = None; -LL | | x?; - | | ^^ cannot use the `?` operator in a function that returns `u32` -LL | | 22 -LL | | } - | |_- this function should return `Result` or `Option` to accept `?` - | - = help: the trait `Try` is not implemented for `u32` - = note: required by `from_error` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/try-operator-custom.rs b/src/test/ui/try-operator-custom.rs deleted file mode 100644 index 9993061ea6155..0000000000000 --- a/src/test/ui/try-operator-custom.rs +++ /dev/null @@ -1,63 +0,0 @@ -// run-pass - -#![feature(try_trait)] - -use std::ops::Try; - -enum MyResult { - Awesome(T), - Terrible(U) -} - -impl Try for MyResult { - type Ok = U; - type Error = V; - - fn from_ok(u: U) -> MyResult { - MyResult::Awesome(u) - } - - fn from_error(e: V) -> MyResult { - MyResult::Terrible(e) - } - - fn into_result(self) -> Result { - match self { - MyResult::Awesome(u) => Ok(u), - MyResult::Terrible(e) => Err(e), - } - } -} - -fn f(x: i32) -> Result { - if x == 0 { - Ok(42) - } else { - let y = g(x)?; - Ok(y) - } -} - -fn g(x: i32) -> MyResult { - let _y = f(x - 1)?; - MyResult::Terrible("Hello".to_owned()) -} - -fn h() -> MyResult { - let a: Result = Err("Hello"); - let b = a?; - MyResult::Awesome(b) -} - -fn i() -> MyResult { - let a: MyResult = MyResult::Terrible("Hello"); - let b = a?; - MyResult::Awesome(b) -} - -fn main() { - assert!(f(0) == Ok(42)); - assert!(f(10) == Err("Hello".to_owned())); - let _ = h(); - let _ = i(); -} diff --git a/src/test/ui/try-trait/bad-interconversion.rs b/src/test/ui/try-trait/bad-interconversion.rs new file mode 100644 index 0000000000000..87585822f5719 --- /dev/null +++ b/src/test/ui/try-trait/bad-interconversion.rs @@ -0,0 +1,48 @@ +#![feature(control_flow_enum)] + +use std::ops::ControlFlow; + +fn result_to_result() -> Result { + Ok(Err(123_i32)?) + //~^ ERROR `?` couldn't convert the error to `u8` +} + +fn option_to_result() -> Result { + Some(3)?; + //~^ ERROR the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` + Ok(10) +} + +fn control_flow_to_result() -> Result { + Ok(ControlFlow::Break(123)?) + //~^ ERROR the `?` operator can only be used on `Result`s in a function that returns `Result` +} + +fn result_to_option() -> Option { + Some(Err("hello")?) + //~^ ERROR the `?` operator can only be used on `Option`s in a function that returns `Option` +} + +fn control_flow_to_option() -> Option { + Some(ControlFlow::Break(123)?) + //~^ ERROR the `?` operator can only be used on `Option`s in a function that returns `Option` +} + +fn result_to_control_flow() -> ControlFlow { + ControlFlow::Continue(Err("hello")?) + //~^ ERROR the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` +} + +fn option_to_control_flow() -> ControlFlow { + Some(3)?; + //~^ ERROR the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` + ControlFlow::Break(10) +} + +fn control_flow_to_control_flow() -> ControlFlow { + ControlFlow::Break(4_u8)?; + //~^ ERROR the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` + ControlFlow::Continue(()) +} + +fn main() {} diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr new file mode 100644 index 0000000000000..e396256de2245 --- /dev/null +++ b/src/test/ui/try-trait/bad-interconversion.stderr @@ -0,0 +1,115 @@ +error[E0277]: `?` couldn't convert the error to `u8` + --> $DIR/bad-interconversion.rs:6:20 + | +LL | fn result_to_result() -> Result { + | --------------- expected `u8` because of this +LL | Ok(Err(123_i32)?) + | ^ the trait `From` is not implemented for `u8` + | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = help: the following implementations were found: + > + > + = note: required because of the requirements on the impl of `FromResidual>` for `Result` + = note: required by `from_residual` + +error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` + --> $DIR/bad-interconversion.rs:11:12 + | +LL | / fn option_to_result() -> Result { +LL | | Some(3)?; + | | ^ use `.ok_or(...)?` to provide an error compatible with `Result` +LL | | +LL | | Ok(10) +LL | | } + | |_- this function returns a `Result` + | + = help: the trait `FromResidual>` is not implemented for `Result` + = note: required by `from_residual` + +error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result` + --> $DIR/bad-interconversion.rs:17:31 + | +LL | / fn control_flow_to_result() -> Result { +LL | | Ok(ControlFlow::Break(123)?) + | | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Result` +LL | | +LL | | } + | |_- this function returns a `Result` + | + = help: the trait `FromResidual>` is not implemented for `Result` + = note: required by `from_residual` + +error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option` + --> $DIR/bad-interconversion.rs:22:22 + | +LL | / fn result_to_option() -> Option { +LL | | Some(Err("hello")?) + | | ^ this `?` produces `Result`, which is incompatible with `Option` +LL | | +LL | | } + | |_- this function returns an `Option` + | + = help: the trait `FromResidual>` is not implemented for `Option` + = note: required by `from_residual` + +error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option` + --> $DIR/bad-interconversion.rs:27:33 + | +LL | / fn control_flow_to_option() -> Option { +LL | | Some(ControlFlow::Break(123)?) + | | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option` +LL | | +LL | | } + | |_- this function returns an `Option` + | + = help: the trait `FromResidual>` is not implemented for `Option` + = note: required by `from_residual` + +error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` + --> $DIR/bad-interconversion.rs:32:39 + | +LL | / fn result_to_control_flow() -> ControlFlow { +LL | | ControlFlow::Continue(Err("hello")?) + | | ^ this `?` produces `Result`, which is incompatible with `ControlFlow` +LL | | +LL | | } + | |_- this function returns a `ControlFlow` + | + = help: the trait `FromResidual>` is not implemented for `ControlFlow` + = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow` + = note: required by `from_residual` + +error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` + --> $DIR/bad-interconversion.rs:37:12 + | +LL | / fn option_to_control_flow() -> ControlFlow { +LL | | Some(3)?; + | | ^ this `?` produces `Option`, which is incompatible with `ControlFlow` +LL | | +LL | | ControlFlow::Break(10) +LL | | } + | |_- this function returns a `ControlFlow` + | + = help: the trait `FromResidual>` is not implemented for `ControlFlow` + = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow` + = note: required by `from_residual` + +error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` + --> $DIR/bad-interconversion.rs:43:29 + | +LL | / fn control_flow_to_control_flow() -> ControlFlow { +LL | | ControlFlow::Break(4_u8)?; + | | ^ this `?` produces `ControlFlow`, which is incompatible with `ControlFlow` +LL | | +LL | | ControlFlow::Continue(()) +LL | | } + | |_- this function returns a `ControlFlow` + | + = help: the trait `FromResidual>` is not implemented for `ControlFlow` + = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow` + = note: required by `from_residual` + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/option-to-result.rs b/src/test/ui/try-trait/option-to-result.rs similarity index 63% rename from src/test/ui/option-to-result.rs rename to src/test/ui/try-trait/option-to-result.rs index 00e8b5244c54a..45aaf361a9c0e 100644 --- a/src/test/ui/option-to-result.rs +++ b/src/test/ui/try-trait/option-to-result.rs @@ -2,12 +2,12 @@ fn main(){ } fn test_result() -> Result<(),()> { let a:Option<()> = Some(()); - a?;//~ ERROR `?` couldn't convert the error + a?;//~ ERROR the `?` operator can only be used Ok(()) } fn test_option() -> Option{ let a:Result = Ok(5); - a?;//~ ERROR `?` couldn't convert the error + a?;//~ ERROR the `?` operator can only be used Some(5) } diff --git a/src/test/ui/try-trait/option-to-result.stderr b/src/test/ui/try-trait/option-to-result.stderr new file mode 100644 index 0000000000000..92087c2aba252 --- /dev/null +++ b/src/test/ui/try-trait/option-to-result.stderr @@ -0,0 +1,31 @@ +error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` + --> $DIR/option-to-result.rs:5:6 + | +LL | / fn test_result() -> Result<(),()> { +LL | | let a:Option<()> = Some(()); +LL | | a?; + | | ^ use `.ok_or(...)?` to provide an error compatible with `Result<(), ()>` +LL | | Ok(()) +LL | | } + | |_- this function returns a `Result` + | + = help: the trait `FromResidual>` is not implemented for `Result<(), ()>` + = note: required by `from_residual` + +error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option` + --> $DIR/option-to-result.rs:11:6 + | +LL | / fn test_option() -> Option{ +LL | | let a:Result = Ok(5); +LL | | a?; + | | ^ this `?` produces `Result`, which is incompatible with `Option` +LL | | Some(5) +LL | | } + | |_- this function returns an `Option` + | + = help: the trait `FromResidual>` is not implemented for `Option` + = note: required by `from_residual` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/try-trait/try-as-monad.rs b/src/test/ui/try-trait/try-as-monad.rs new file mode 100644 index 0000000000000..cf09838b304b3 --- /dev/null +++ b/src/test/ui/try-trait/try-as-monad.rs @@ -0,0 +1,24 @@ +// run-pass + +#![feature(try_trait_v2)] + +use std::ops::Try; + +fn monad_unit(x: ::Output) -> T { + T::from_output(x) +} + +fn monad_bind, T2: Try, R>( + mx: T1, + f: impl FnOnce(::Output) -> T2) +-> T2 { + let x = mx?; + f(x) +} + +fn main() { + let mx: Option = monad_unit(1); + let my = monad_bind(mx, |x| Some(x + 1)); + let mz = monad_bind(my, |x| Some(-x)); + assert_eq!(mz, Some(-2)); +} diff --git a/src/test/ui/try-on-option-diagnostics.rs b/src/test/ui/try-trait/try-on-option-diagnostics.rs similarity index 100% rename from src/test/ui/try-on-option-diagnostics.rs rename to src/test/ui/try-trait/try-on-option-diagnostics.rs diff --git a/src/test/ui/try-on-option-diagnostics.stderr b/src/test/ui/try-trait/try-on-option-diagnostics.stderr similarity index 60% rename from src/test/ui/try-on-option-diagnostics.stderr rename to src/test/ui/try-trait/try-on-option-diagnostics.stderr index a71ee20aacf93..e7c67c21bb3e3 100644 --- a/src/test/ui/try-on-option-diagnostics.stderr +++ b/src/test/ui/try-trait/try-on-option-diagnostics.stderr @@ -1,57 +1,57 @@ -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`) - --> $DIR/try-on-option-diagnostics.rs:7:5 +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-diagnostics.rs:7:6 | LL | / fn a_function() -> u32 { LL | | let x: Option = None; LL | | x?; - | | ^^ cannot use the `?` operator in a function that returns `u32` + | | ^ cannot use the `?` operator in a function that returns `u32` LL | | 22 LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try` is not implemented for `u32` - = note: required by `from_error` + = help: the trait `FromResidual>` is not implemented for `u32` + = note: required by `from_residual` -error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `Try`) - --> $DIR/try-on-option-diagnostics.rs:14:9 +error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-diagnostics.rs:14:10 | LL | let a_closure = || { | _____________________- LL | | let x: Option = None; LL | | x?; - | | ^^ cannot use the `?` operator in a closure that returns `{integer}` + | | ^ cannot use the `?` operator in a closure that returns `{integer}` LL | | 22 LL | | }; | |_____- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try` is not implemented for `{integer}` - = note: required by `from_error` + = help: the trait `FromResidual>` is not implemented for `{integer}` + = note: required by `from_residual` -error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `Try`) - --> $DIR/try-on-option-diagnostics.rs:26:13 +error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-diagnostics.rs:26:14 | LL | / fn a_method() { LL | | let x: Option = None; LL | | x?; - | | ^^ cannot use the `?` operator in a method that returns `()` + | | ^ cannot use the `?` operator in a method that returns `()` LL | | } | |_________- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try` is not implemented for `()` - = note: required by `from_error` + = help: the trait `FromResidual>` is not implemented for `()` + = note: required by `from_residual` -error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `Try`) - --> $DIR/try-on-option-diagnostics.rs:39:13 +error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-diagnostics.rs:39:14 | LL | / fn a_trait_method() { LL | | let x: Option = None; LL | | x?; - | | ^^ cannot use the `?` operator in a trait method that returns `()` + | | ^ cannot use the `?` operator in a trait method that returns `()` LL | | } | |_________- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try` is not implemented for `()` - = note: required by `from_error` + = help: the trait `FromResidual>` is not implemented for `()` + = note: required by `from_residual` error: aborting due to 4 previous errors diff --git a/src/test/ui/try-on-option.rs b/src/test/ui/try-trait/try-on-option.rs similarity index 80% rename from src/test/ui/try-on-option.rs rename to src/test/ui/try-trait/try-on-option.rs index 5d94cee8e3721..f2012936a1174 100644 --- a/src/test/ui/try-on-option.rs +++ b/src/test/ui/try-trait/try-on-option.rs @@ -4,7 +4,7 @@ fn main() {} fn foo() -> Result { let x: Option = None; - x?; //~ ERROR `?` couldn't convert the error + x?; //~ ERROR the `?` operator Ok(22) } diff --git a/src/test/ui/try-trait/try-on-option.stderr b/src/test/ui/try-trait/try-on-option.stderr new file mode 100644 index 0000000000000..604baa8550b45 --- /dev/null +++ b/src/test/ui/try-trait/try-on-option.stderr @@ -0,0 +1,31 @@ +error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` + --> $DIR/try-on-option.rs:7:6 + | +LL | / fn foo() -> Result { +LL | | let x: Option = None; +LL | | x?; + | | ^ use `.ok_or(...)?` to provide an error compatible with `Result` +LL | | Ok(22) +LL | | } + | |_- this function returns a `Result` + | + = help: the trait `FromResidual>` is not implemented for `Result` + = note: required by `from_residual` + +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option.rs:13:6 + | +LL | / fn bar() -> u32 { +LL | | let x: Option = None; +LL | | x?; + | | ^ cannot use the `?` operator in a function that returns `u32` +LL | | 22 +LL | | } + | |_- this function should return `Result` or `Option` to accept `?` + | + = help: the trait `FromResidual>` is not implemented for `u32` + = note: required by `from_residual` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/try-trait/try-operator-custom.rs b/src/test/ui/try-trait/try-operator-custom.rs new file mode 100644 index 0000000000000..45636a7fceddf --- /dev/null +++ b/src/test/ui/try-trait/try-operator-custom.rs @@ -0,0 +1,91 @@ +// run-pass + +#![feature(control_flow_enum)] +#![feature(try_trait_v2)] + +use std::ops::{ControlFlow, FromResidual, Try}; + +enum MyResult { + Awesome(T), + Terrible(U) +} + +enum Never {} + +impl Try for MyResult { + type Output = U; + type Residual = MyResult; + + fn from_output(u: U) -> MyResult { + MyResult::Awesome(u) + } + + fn branch(self) -> ControlFlow { + match self { + MyResult::Awesome(u) => ControlFlow::Continue(u), + MyResult::Terrible(e) => ControlFlow::Break(MyResult::Terrible(e)), + } + } +} + +impl FromResidual> for MyResult where V: Into { + fn from_residual(x: MyResult) -> Self { + match x { + MyResult::Awesome(u) => match u {}, + MyResult::Terrible(e) => MyResult::Terrible(e.into()), + } + } +} + +type ResultResidual = Result; + +impl FromResidual> for MyResult where V: Into { + fn from_residual(x: ResultResidual) -> Self { + match x { + Ok(v) => match v {} + Err(e) => MyResult::Terrible(e.into()), + } + } +} + +impl FromResidual> for Result where V: Into { + fn from_residual(x: MyResult) -> Self { + match x { + MyResult::Awesome(u) => match u {}, + MyResult::Terrible(e) => Err(e.into()), + } + } +} + +fn f(x: i32) -> Result { + if x == 0 { + Ok(42) + } else { + let y = g(x)?; + Ok(y) + } +} + +fn g(x: i32) -> MyResult { + let _y = f(x - 1)?; + MyResult::Terrible("Hello".to_owned()) +} + +fn h() -> MyResult { + let a: Result = Err("Hello"); + let b = a?; + MyResult::Awesome(b) +} + +fn i() -> MyResult { + let a: MyResult = MyResult::Terrible("Hello"); + let b = a?; + MyResult::Awesome(b) +} + +fn main() { + assert!(f(0) == Ok(42)); + assert!(f(10) == Err("Hello".to_owned())); + let _ = h(); + let _ = i(); +} diff --git a/src/test/ui/try-operator-on-main.rs b/src/test/ui/try-trait/try-operator-on-main.rs similarity index 75% rename from src/test/ui/try-operator-on-main.rs rename to src/test/ui/try-trait/try-operator-on-main.rs index e1b6cfbe5ae1b..3b364f7e7d39d 100644 --- a/src/test/ui/try-operator-on-main.rs +++ b/src/test/ui/try-trait/try-operator-on-main.rs @@ -1,4 +1,4 @@ -#![feature(try_trait)] +#![feature(try_trait_v2)] use std::ops::Try; @@ -7,14 +7,13 @@ fn main() { std::fs::File::open("foo")?; //~ ERROR the `?` operator can only // a non-`Try` type on a non-`Try` fn - ()?; //~ ERROR the `?` operator can only + ()?; //~ ERROR the `?` operator can only be applied to + //~^ ERROR the `?` operator can only be used in a function that // an unrelated use of `Try` try_trait_generic::<()>(); //~ ERROR the trait bound } - - fn try_trait_generic() -> T { // and a non-`Try` object on a `Try` fn. ()?; //~ ERROR the `?` operator can only be applied to values that implement `Try` diff --git a/src/test/ui/try-operator-on-main.stderr b/src/test/ui/try-trait/try-operator-on-main.stderr similarity index 52% rename from src/test/ui/try-operator-on-main.stderr rename to src/test/ui/try-trait/try-operator-on-main.stderr index be17de2fe7cc0..7d42c2e4d10d3 100644 --- a/src/test/ui/try-operator-on-main.stderr +++ b/src/test/ui/try-trait/try-operator-on-main.stderr @@ -1,18 +1,18 @@ -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`) - --> $DIR/try-operator-on-main.rs:7:5 +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-operator-on-main.rs:7:31 | LL | / fn main() { LL | | // error for a `Try` type on a non-`Try` fn LL | | std::fs::File::open("foo")?; - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()` + | | ^ cannot use the `?` operator in a function that returns `()` LL | | ... | LL | | try_trait_generic::<()>(); LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try` is not implemented for `()` - = note: required by `from_error` + = help: the trait `FromResidual>` is not implemented for `()` + = note: required by `from_residual` error[E0277]: the `?` operator can only be applied to values that implement `Try` --> $DIR/try-operator-on-main.rs:10:5 @@ -21,10 +21,28 @@ LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | = help: the trait `Try` is not implemented for `()` - = note: required by `into_result` + = note: required by `branch` + +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-operator-on-main.rs:10:7 + | +LL | / fn main() { +LL | | // error for a `Try` type on a non-`Try` fn +LL | | std::fs::File::open("foo")?; +LL | | +LL | | // a non-`Try` type on a non-`Try` fn +LL | | ()?; + | | ^ cannot use the `?` operator in a function that returns `()` +... | +LL | | try_trait_generic::<()>(); +LL | | } + | |_- this function should return `Result` or `Option` to accept `?` + | + = help: the trait `FromResidual<_>` is not implemented for `()` + = note: required by `from_residual` error[E0277]: the trait bound `(): Try` is not satisfied - --> $DIR/try-operator-on-main.rs:13:25 + --> $DIR/try-operator-on-main.rs:14:25 | LL | try_trait_generic::<()>(); | ^^ the trait `Try` is not implemented for `()` @@ -33,14 +51,14 @@ LL | fn try_trait_generic() -> T { | --- required by this bound in `try_trait_generic` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/try-operator-on-main.rs:20:5 + --> $DIR/try-operator-on-main.rs:19:5 | LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | = help: the trait `Try` is not implemented for `()` - = note: required by `into_result` + = note: required by `branch` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/try-poll.rs b/src/test/ui/try-trait/try-poll.rs similarity index 100% rename from src/test/ui/try-poll.rs rename to src/test/ui/try-trait/try-poll.rs From 5fd6081de67a7fd306ba509b6ebf85b8e07b636a Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 30 Apr 2021 18:40:34 -0700 Subject: [PATCH 06/11] Fix clippy --- src/tools/clippy/clippy_lints/src/needless_question_mark.rs | 2 +- src/tools/clippy/clippy_lints/src/try_err.rs | 2 +- src/tools/clippy/clippy_lints/src/unused_io_amount.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs index 7b156a8c49dd9..d8417c7dc70d8 100644 --- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs @@ -147,7 +147,7 @@ fn is_some_or_ok_call<'a>(cx: &'a LateContext<'_>, expr: &'a Expr<'_>) -> Option if let ExprKind::Call(called, args) = &inner_expr_with_q.kind; if args.len() == 1; - if let ExprKind::Path(QPath::LangItem(LangItem::TryIntoResult, _)) = &called.kind; + if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, _)) = &called.kind; then { // Extract inner expr type from match argument generated by // question mark operator diff --git a/src/tools/clippy/clippy_lints/src/try_err.rs b/src/tools/clippy/clippy_lints/src/try_err.rs index ebb39ea4877de..f2ba2b2ecf639 100644 --- a/src/tools/clippy/clippy_lints/src/try_err.rs +++ b/src/tools/clippy/clippy_lints/src/try_err.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for TryErr { if let ExprKind::Match(match_arg, _, MatchSource::TryDesugar) = expr.kind; if let ExprKind::Call(match_fun, try_args) = match_arg.kind; if let ExprKind::Path(ref match_fun_path) = match_fun.kind; - if matches!(match_fun_path, QPath::LangItem(LangItem::TryIntoResult, _)); + if matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, _)); if let Some(try_arg) = try_args.get(0); if let ExprKind::Call(err_fun, err_args) = try_arg.kind; if let Some(err_arg) = err_args.get(0); diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index 3387f35bac3d4..c27a6d4e347b5 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { if let hir::ExprKind::Call(func, args) = res.kind { if matches!( func.kind, - hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryIntoResult, _)) + hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, _)) ) { check_map_error(cx, &args[0], expr); } From 3d9660111cd8a99f4bd08eac282202bff37103b3 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 30 Apr 2021 19:42:25 -0700 Subject: [PATCH 07/11] Fix rustdoc::private-intra-doc-links errors in the docs --- library/core/src/ops/mod.rs | 2 +- library/core/src/ops/try_trait.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 4fca2898b56b4..2c4de92d38399 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -211,7 +211,7 @@ pub use self::unsize::DispatchFromDyn; #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] pub use self::control_flow::ControlFlow; -/// [`TryV1`] and [`TryV2`] have different associated type names, +/// `TryV1` and `TryV2` have different associated type names, /// so rather than need `bootstrap` checks all over the library, /// centralize the difference to this one trait alias. /// diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 35989d2bc052c..87044ed2fcee1 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -222,7 +222,7 @@ pub trait Try: FromResidual { fn branch(self) -> ControlFlow; } -/// Used to specify which residuals can be converted into which [`Try`] types. +/// Used to specify which residuals can be converted into which [`crate::ops::Try`] types. /// /// Every `Try` type needs to be recreatable from its own associated /// `Residual` type, but can also have additional `FromResidual` implementations From b7a6c4a905e9e4b13785a6544434f6ffe859329c Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 5 May 2021 22:47:02 -0700 Subject: [PATCH 08/11] Perf Experiment: Wait, what if I just skip the trait alias --- .../alloc/src/collections/vec_deque/iter.rs | 6 +++--- library/alloc/src/lib.rs | 2 +- library/core/src/iter/adapters/chain.rs | 6 +++--- library/core/src/iter/adapters/cloned.rs | 6 +++--- library/core/src/iter/adapters/copied.rs | 6 +++--- library/core/src/iter/adapters/cycle.rs | 4 ++-- library/core/src/iter/adapters/enumerate.rs | 6 +++--- library/core/src/iter/adapters/filter.rs | 8 +++---- library/core/src/iter/adapters/filter_map.rs | 8 +++---- library/core/src/iter/adapters/flatten.rs | 18 ++++++++-------- library/core/src/iter/adapters/fuse.rs | 18 ++++++++-------- library/core/src/iter/adapters/inspect.rs | 6 +++--- library/core/src/iter/adapters/map.rs | 6 +++--- library/core/src/iter/adapters/map_while.rs | 4 ++-- library/core/src/iter/adapters/mod.rs | 4 ++-- library/core/src/iter/adapters/peekable.rs | 8 +++---- library/core/src/iter/adapters/rev.rs | 6 +++--- library/core/src/iter/adapters/scan.rs | 6 +++--- library/core/src/iter/adapters/skip.rs | 8 +++---- library/core/src/iter/adapters/skip_while.rs | 4 ++-- library/core/src/iter/adapters/step_by.rs | 6 +++--- library/core/src/iter/adapters/take.rs | 8 +++---- library/core/src/iter/adapters/take_while.rs | 6 +++--- library/core/src/iter/range.rs | 6 +++--- library/core/src/iter/traits/double_ended.rs | 4 ++-- library/core/src/iter/traits/iterator.rs | 14 ++++++------- library/core/src/ops/control_flow.rs | 8 +++---- library/core/src/ops/mod.rs | 21 ------------------- library/core/src/ops/try.rs | 6 +++--- library/core/src/option.rs | 2 +- library/core/src/result.rs | 2 +- library/core/src/slice/ascii.rs | 2 +- library/core/src/str/iter.rs | 4 ++-- library/core/src/task/poll.rs | 12 +++++------ 34 files changed, 110 insertions(+), 131 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs index 793adfb0c0fc8..f3eb228c9e380 100644 --- a/library/alloc/src/collections/vec_deque/iter.rs +++ b/library/alloc/src/collections/vec_deque/iter.rs @@ -1,6 +1,6 @@ use core::fmt; use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess}; -use core::ops::TryWhereOutputEquals; +use core::ops::Try; use super::{count, wrap_index, RingSlices}; @@ -66,7 +66,7 @@ impl<'a, T> Iterator for Iter<'a, T> { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { let (mut iter, final_res); if self.tail <= self.head { @@ -140,7 +140,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { let (mut iter, final_res); if self.tail <= self.head { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index af973c29bde61..a635d6ffe995a 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -141,7 +141,7 @@ #![feature(alloc_layout_extra)] #![feature(trusted_random_access)] #![feature(try_trait)] -#![feature(try_trait_transition)] +#![feature(try_trait_v2)] #![feature(min_type_alias_impl_trait)] #![feature(associated_type_bounds)] #![feature(slice_group_by)] diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs index 19bc44776c9a6..53e48500e3b4d 100644 --- a/library/core/src/iter/adapters/chain.rs +++ b/library/core/src/iter/adapters/chain.rs @@ -1,5 +1,5 @@ use crate::iter::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen}; -use crate::ops::TryWhereOutputEquals; +use crate::ops::Try; /// An iterator that links two iterators together, in a chain. /// @@ -98,7 +98,7 @@ where where Self: Sized, F: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { if let Some(ref mut a) = self.a { acc = a.try_fold(acc, &mut f)?; @@ -281,7 +281,7 @@ where where Self: Sized, F: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { if let Some(ref mut b) = self.b { acc = b.try_rfold(acc, &mut f)?; diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs index b0344ce1388ae..7efc155175c34 100644 --- a/library/core/src/iter/adapters/cloned.rs +++ b/library/core/src/iter/adapters/cloned.rs @@ -1,6 +1,6 @@ use crate::iter::adapters::{zip::try_get_unchecked, TrustedRandomAccess}; use crate::iter::{FusedIterator, TrustedLen}; -use crate::ops::TryWhereOutputEquals; +use crate::ops::Try; /// An iterator that clones the elements of an underlying iterator. /// @@ -46,7 +46,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.it.try_fold(init, clone_try_fold(f)) } @@ -82,7 +82,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.it.try_rfold(init, clone_try_fold(f)) } diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs index d261effc10431..def2408927589 100644 --- a/library/core/src/iter/adapters/copied.rs +++ b/library/core/src/iter/adapters/copied.rs @@ -1,6 +1,6 @@ use crate::iter::adapters::{zip::try_get_unchecked, TrustedRandomAccess}; use crate::iter::{FusedIterator, TrustedLen}; -use crate::ops::TryWhereOutputEquals; +use crate::ops::Try; /// An iterator that copies the elements of an underlying iterator. /// @@ -50,7 +50,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.it.try_fold(init, copy_try_fold(f)) } @@ -98,7 +98,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.it.try_rfold(init, copy_try_fold(f)) } diff --git a/library/core/src/iter/adapters/cycle.rs b/library/core/src/iter/adapters/cycle.rs index 5704dc3590103..815e708f9ec0f 100644 --- a/library/core/src/iter/adapters/cycle.rs +++ b/library/core/src/iter/adapters/cycle.rs @@ -1,4 +1,4 @@ -use crate::{iter::FusedIterator, ops::TryWhereOutputEquals}; +use crate::{iter::FusedIterator, ops::Try}; /// An iterator that repeats endlessly. /// @@ -53,7 +53,7 @@ where fn try_fold(&mut self, mut acc: Acc, mut f: F) -> R where F: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { // fully iterate the current iterator. this is necessary because // `self.iter` may be empty even when `self.orig` isn't diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index 8b37cc4d4a50d..91722a4b62a2e 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -1,6 +1,6 @@ use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess}; use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; -use crate::ops::TryWhereOutputEquals; +use crate::ops::Try; /// An iterator that yields the current count and the element during iteration. /// @@ -71,7 +71,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { #[inline] fn enumerate<'a, T, Acc, R>( @@ -150,7 +150,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { // Can safely add and subtract the count, as `ExactSizeIterator` promises // that the number of elements fits into a `usize`. diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs index 8f5484c9a5c2f..d5f19f127470e 100644 --- a/library/core/src/iter/adapters/filter.rs +++ b/library/core/src/iter/adapters/filter.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; -use crate::ops::TryWhereOutputEquals; +use crate::ops::Try; /// An iterator that filters the elements of `iter` with `predicate`. /// @@ -37,7 +37,7 @@ fn filter_fold( move |acc, item| if predicate(&item) { fold(acc, item) } else { acc } } -fn filter_try_fold<'a, T, Acc, R: TryWhereOutputEquals>( +fn filter_try_fold<'a, T, Acc, R: Try>( predicate: &'a mut impl FnMut(&T) -> bool, mut fold: impl FnMut(Acc, T) -> R + 'a, ) -> impl FnMut(Acc, T) -> R + 'a { @@ -88,7 +88,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.iter.try_fold(init, filter_try_fold(&mut self.predicate, fold)) } @@ -117,7 +117,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.iter.try_rfold(init, filter_try_fold(&mut self.predicate, fold)) } diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs index 308f984cd940e..01b7be9d52daf 100644 --- a/library/core/src/iter/adapters/filter_map.rs +++ b/library/core/src/iter/adapters/filter_map.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; -use crate::ops::{ControlFlow, TryWhereOutputEquals}; +use crate::ops::{ControlFlow, Try}; /// An iterator that uses `f` to both filter and map elements from `iter`. /// @@ -39,7 +39,7 @@ fn filter_map_fold( } } -fn filter_map_try_fold<'a, T, B, Acc, R: TryWhereOutputEquals>( +fn filter_map_try_fold<'a, T, B, Acc, R: Try>( f: &'a mut impl FnMut(T) -> Option, mut fold: impl FnMut(Acc, B) -> R + 'a, ) -> impl FnMut(Acc, T) -> R + 'a { @@ -72,7 +72,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.iter.try_fold(init, filter_map_try_fold(&mut self.f, fold)) } @@ -111,7 +111,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.iter.try_rfold(init, filter_map_try_fold(&mut self.f, fold)) } diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index b2fe1499ca663..3315d34659611 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map}; -use crate::ops::TryWhereOutputEquals; +use crate::ops::Try; /// An iterator that maps each element to an iterator, and yields the elements /// of the produced iterators. @@ -61,7 +61,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.inner.try_fold(init, fold) } @@ -91,7 +91,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.inner.try_rfold(init, fold) } @@ -178,7 +178,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.inner.try_fold(init, fold) } @@ -208,7 +208,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.inner.try_rfold(init, fold) } @@ -293,10 +293,10 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { #[inline] - fn flatten<'a, T: IntoIterator, Acc, R: TryWhereOutputEquals>( + fn flatten<'a, T: IntoIterator, Acc, R: Try>( frontiter: &'a mut Option, fold: &'a mut impl FnMut(Acc, T::Item) -> R, ) -> impl FnMut(Acc, T) -> R + 'a { @@ -382,10 +382,10 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { #[inline] - fn flatten<'a, T: IntoIterator, Acc, R: TryWhereOutputEquals>( + fn flatten<'a, T: IntoIterator, Acc, R: Try>( backiter: &'a mut Option, fold: &'a mut impl FnMut(Acc, T::Item) -> R, ) -> impl FnMut(Acc, T) -> R + 'a diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index 43d0626e3b7e8..aff48b1b220c4 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -3,7 +3,7 @@ use crate::iter::adapters::{zip::try_get_unchecked, InPlaceIterable, SourceIter} use crate::iter::{ DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess, }; -use crate::ops::TryWhereOutputEquals; +use crate::ops::Try; /// An iterator that yields `None` forever after the underlying iterator /// yields `None` once. @@ -92,7 +92,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { FuseImpl::try_fold(self, acc, fold) } @@ -148,7 +148,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { FuseImpl::try_rfold(self, acc, fold) } @@ -219,7 +219,7 @@ trait FuseImpl { where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals; + R: Try; fn fold(self, acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc; @@ -238,7 +238,7 @@ trait FuseImpl { where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, I: DoubleEndedIterator; fn rfold(self, acc: Acc, fold: Fold) -> Acc where @@ -305,7 +305,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { if let Some(ref mut iter) = self.iter { acc = iter.try_fold(acc, fold)?; @@ -354,7 +354,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, I: DoubleEndedIterator, { if let Some(ref mut iter) = self.iter { @@ -443,7 +443,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { unchecked!(self).try_fold(init, fold) } @@ -485,7 +485,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, I: DoubleEndedIterator, { unchecked!(self).try_rfold(init, fold) diff --git a/library/core/src/iter/adapters/inspect.rs b/library/core/src/iter/adapters/inspect.rs index 3221a0eeafa03..36835d12e5685 100644 --- a/library/core/src/iter/adapters/inspect.rs +++ b/library/core/src/iter/adapters/inspect.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; -use crate::ops::TryWhereOutputEquals; +use crate::ops::Try; /// An iterator that calls a function with a reference to each element before /// yielding it. @@ -87,7 +87,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold)) } @@ -117,7 +117,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold)) } diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index 8ca7adb013fe4..0bf9f4b0327e9 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -1,7 +1,7 @@ use crate::fmt; use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess}; use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; -use crate::ops::TryWhereOutputEquals; +use crate::ops::Try; /// An iterator that maps the values of `iter` with `f`. /// @@ -110,7 +110,7 @@ where where Self: Sized, G: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.iter.try_fold(init, map_try_fold(&mut self.f, g)) } @@ -146,7 +146,7 @@ where where Self: Sized, G: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.iter.try_rfold(init, map_try_fold(&mut self.f, g)) } diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs index ab16dbdb073dd..8f89e1588048f 100644 --- a/library/core/src/iter/adapters/map_while.rs +++ b/library/core/src/iter/adapters/map_while.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, InPlaceIterable}; -use crate::ops::{ControlFlow, TryWhereOutputEquals}; +use crate::ops::{ControlFlow, Try}; /// An iterator that only accepts elements while `predicate` returns `Some(_)`. /// @@ -54,7 +54,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { let Self { iter, predicate } = self; iter.try_fold(init, |acc, x| match predicate(x) { diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 048d209561b42..915585086b01f 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1,5 +1,5 @@ use crate::iter::{InPlaceIterable, Iterator}; -use crate::ops::{ControlFlow, TryWhereOutputEquals}; +use crate::ops::{ControlFlow, Try}; mod chain; mod cloned; @@ -167,7 +167,7 @@ where fn try_fold(&mut self, init: B, mut f: F) -> R where F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { let error = &mut *self.error; self.iter diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index c9c9d95239214..8ee7d0955c6d1 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -1,5 +1,5 @@ use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen}; -use crate::ops::{ControlFlow, TryWhereOutputEquals}; +use crate::ops::{ControlFlow, Try}; /// An iterator with a `peek()` that returns an optional reference to the next /// element. @@ -91,7 +91,7 @@ impl Iterator for Peekable { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { let acc = match self.peeked.take() { Some(None) => return try { init }, @@ -135,7 +135,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { match self.peeked.take() { Some(None) => try { init }, @@ -156,7 +156,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { let _use_the_import: ControlFlow<()>; match self.peeked.take() { diff --git a/library/core/src/iter/adapters/rev.rs b/library/core/src/iter/adapters/rev.rs index f24bde9f6ad8e..139fb7bbdd996 100644 --- a/library/core/src/iter/adapters/rev.rs +++ b/library/core/src/iter/adapters/rev.rs @@ -1,5 +1,5 @@ use crate::iter::{FusedIterator, TrustedLen}; -use crate::ops::TryWhereOutputEquals; +use crate::ops::Try; /// A double-ended iterator with the direction inverted. /// @@ -51,7 +51,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.iter.try_rfold(init, f) } @@ -96,7 +96,7 @@ where where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { self.iter.try_fold(init, f) } diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs index 38a3f255389d9..96705b01f661f 100644 --- a/library/core/src/iter/adapters/scan.rs +++ b/library/core/src/iter/adapters/scan.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, InPlaceIterable}; -use crate::ops::{ControlFlow, TryWhereOutputEquals}; +use crate::ops::{ControlFlow, Try}; /// An iterator to maintain state while iterating another iterator. /// @@ -56,9 +56,9 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { - fn scan<'a, T, St, B, Acc, R: TryWhereOutputEquals>( + fn scan<'a, T, St, B, Acc, R: Try>( state: &'a mut St, f: &'a mut impl FnMut(&mut St, T) -> Option, mut fold: impl FnMut(Acc, B) -> R + 'a, diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs index bee160baaad82..c358a6d12b7bc 100644 --- a/library/core/src/iter/adapters/skip.rs +++ b/library/core/src/iter/adapters/skip.rs @@ -1,6 +1,6 @@ use crate::intrinsics::unlikely; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; -use crate::ops::{ControlFlow, TryWhereOutputEquals}; +use crate::ops::{ControlFlow, Try}; /// An iterator that skips over `n` elements of `iter`. /// @@ -88,7 +88,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { let n = self.n; self.n = 0; @@ -146,9 +146,9 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { - fn check>( + fn check>( mut n: usize, mut fold: impl FnMut(Acc, T) -> R, ) -> impl FnMut(Acc, T) -> ControlFlow { diff --git a/library/core/src/iter/adapters/skip_while.rs b/library/core/src/iter/adapters/skip_while.rs index 3c679187c62b1..93e29edc8df39 100644 --- a/library/core/src/iter/adapters/skip_while.rs +++ b/library/core/src/iter/adapters/skip_while.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; -use crate::ops::TryWhereOutputEquals; +use crate::ops::Try; /// An iterator that rejects elements while `predicate` returns `true`. /// @@ -70,7 +70,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { if !self.flag { match self.next() { diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs index ad29bff213c8c..4252c34a0e0fc 100644 --- a/library/core/src/iter/adapters/step_by.rs +++ b/library/core/src/iter/adapters/step_by.rs @@ -1,4 +1,4 @@ -use crate::{intrinsics, iter::from_fn, ops::TryWhereOutputEquals}; +use crate::{intrinsics, iter::from_fn, ops::Try}; /// An iterator for stepping iterators by a custom amount. /// @@ -111,7 +111,7 @@ where fn try_fold(&mut self, mut acc: Acc, mut f: F) -> R where F: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { #[inline] fn nth(iter: &mut I, step: usize) -> impl FnMut() -> Option + '_ { @@ -187,7 +187,7 @@ where fn try_rfold(&mut self, init: Acc, mut f: F) -> R where F: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { #[inline] fn nth_back( diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index 4852efebdf40f..92f82ae232502 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -3,7 +3,7 @@ use crate::iter::{ adapters::zip::try_get_unchecked, adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen, TrustedRandomAccess, }; -use crate::ops::{ControlFlow, TryWhereOutputEquals}; +use crate::ops::{ControlFlow, Try}; /// An iterator that only iterates over the first `n` iterations of `iter`. /// @@ -80,9 +80,9 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { - fn check<'a, T, Acc, R: TryWhereOutputEquals>( + fn check<'a, T, Acc, R: Try>( n: &'a mut usize, mut fold: impl FnMut(Acc, T) -> R + 'a, ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { @@ -178,7 +178,7 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { if self.n == 0 { try { init } diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs index d97d3141496af..93457d20f7c23 100644 --- a/library/core/src/iter/adapters/take_while.rs +++ b/library/core/src/iter/adapters/take_while.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; -use crate::ops::{ControlFlow, TryWhereOutputEquals}; +use crate::ops::{ControlFlow, Try}; /// An iterator that only accepts elements while `predicate` returns `true`. /// @@ -68,9 +68,9 @@ where where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { - fn check<'a, T, Acc, R: TryWhereOutputEquals>( + fn check<'a, T, Acc, R: Try>( flag: &'a mut bool, p: &'a mut impl FnMut(&T) -> bool, mut fold: impl FnMut(Acc, T) -> R + 'a, diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index d3da606665497..d0b2b4dd6311a 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -1,7 +1,7 @@ use crate::char; use crate::convert::TryFrom; use crate::mem; -use crate::ops::{self, TryWhereOutputEquals}; +use crate::ops::{self, Try}; use super::{FusedIterator, TrustedLen, TrustedRandomAccess}; @@ -755,7 +755,7 @@ impl Iterator for ops::RangeInclusive { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { if self.is_empty() { return try { init }; @@ -860,7 +860,7 @@ impl DoubleEndedIterator for ops::RangeInclusive { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { if self.is_empty() { return try { init }; diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index aed48a48ddedb..c302502b3b7e6 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -1,4 +1,4 @@ -use crate::ops::{ControlFlow, TryWhereOutputEquals}; +use crate::ops::{ControlFlow, Try}; /// An iterator able to yield elements from both ends. /// @@ -218,7 +218,7 @@ pub trait DoubleEndedIterator: Iterator { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { let mut accum = init; while let Some(x) = self.next_back() { diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 04315003dd7b2..ffac4534b2073 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3,7 +3,7 @@ // can't split that into multiple files. use crate::cmp::{self, Ordering}; -use crate::ops::{ControlFlow, TryWhereOutputEquals}; +use crate::ops::{ControlFlow, Try}; use super::super::TrustedRandomAccess; use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; @@ -1999,7 +1999,7 @@ pub trait Iterator { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { let mut accum = init; while let Some(x) = self.next() { @@ -2041,7 +2041,7 @@ pub trait Iterator { where Self: Sized, F: FnMut(Self::Item) -> R, - R: TryWhereOutputEquals<()>, + R: Try, { #[inline] fn call(mut f: impl FnMut(T) -> R) -> impl FnMut((), T) -> R { @@ -2417,7 +2417,7 @@ pub trait Iterator { where Self: Sized, F: FnMut(&Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, // FIXME: This is a weird bound; the API should change R: crate::ops::TryV2>, { @@ -2425,7 +2425,7 @@ pub trait Iterator { fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow> where F: FnMut(&T) -> R, - R: TryWhereOutputEquals, + R: Try, R: crate::ops::TryV2>, { move |(), x| match f(&x).branch() { @@ -2446,13 +2446,13 @@ pub trait Iterator { where Self: Sized, F: FnMut(&Self::Item) -> R, - R: TryWhereOutputEquals, + R: Try, { #[inline] fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow> where F: FnMut(&T) -> R, - R: TryWhereOutputEquals, + R: Try, { move |(), x| match f(&x).into_result() { Ok(false) => ControlFlow::CONTINUE, diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 238fcd447bd1c..dbb51540bd475 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -64,10 +64,10 @@ pub enum ControlFlow { #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] impl ops::TryV1 for ControlFlow { - type Ok = C; + type Output = C; type Error = B; #[inline] - fn into_result(self) -> Result { + fn into_result(self) -> Result { match self { ControlFlow::Continue(y) => Ok(y), ControlFlow::Break(x) => Err(x), @@ -78,7 +78,7 @@ impl ops::TryV1 for ControlFlow { ControlFlow::Break(v) } #[inline] - fn from_ok(v: Self::Ok) -> Self { + fn from_ok(v: Self::Output) -> Self { ControlFlow::Continue(v) } } @@ -184,7 +184,7 @@ impl ControlFlow { } #[cfg(bootstrap)] -impl ControlFlow { +impl ControlFlow { /// Create a `ControlFlow` from any type implementing `Try`. #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] #[inline] diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 2c4de92d38399..beef74de61728 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -210,24 +210,3 @@ pub use self::unsize::DispatchFromDyn; #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] pub use self::control_flow::ControlFlow; - -/// `TryV1` and `TryV2` have different associated type names, -/// so rather than need `bootstrap` checks all over the library, -/// centralize the difference to this one trait alias. -/// -/// As with all `try_trait_transition` stuff, this will be deleted -/// after the bootstrap compiler uses V2 for `?`. -/// -/// ``` -/// #![feature(try_trait_transition)] -/// use std::ops::TryWhereOutputEquals; -/// fn foo() where T: TryWhereOutputEquals {} -/// foo::, i32>(); -/// ``` -#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] -#[cfg(not(bootstrap))] -pub trait TryWhereOutputEquals = TryV2; - -#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] -#[cfg(bootstrap)] -pub trait TryWhereOutputEquals = TryV1; diff --git a/library/core/src/ops/try.rs b/library/core/src/ops/try.rs index 18e2f951ce5a9..9d659e78d3cce 100644 --- a/library/core/src/ops/try.rs +++ b/library/core/src/ops/try.rs @@ -29,7 +29,7 @@ pub trait Try { /// The type of this value when viewed as successful. #[unstable(feature = "try_trait", issue = "42327")] - type Ok; + type Output; // This no longer follows its RFC, but is only used in bootstrap. /// The type of this value when viewed as failed. #[unstable(feature = "try_trait", issue = "42327")] type Error; @@ -45,7 +45,7 @@ pub trait Try { /// is returned, where `X` is the return type of the enclosing function. #[cfg_attr(bootstrap, lang = "into_result")] #[unstable(feature = "try_trait", issue = "42327")] - fn into_result(self) -> Result; + fn into_result(self) -> Result; /// Wrap an error value to construct the composite result. For example, /// `Result::Err(x)` and `Result::from_error(x)` are equivalent. @@ -57,5 +57,5 @@ pub trait Try { /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent. #[cfg_attr(bootstrap, lang = "from_ok")] #[unstable(feature = "try_trait", issue = "42327")] - fn from_ok(v: Self::Ok) -> Self; + fn from_ok(v: Self::Output) -> Self; } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 928d8441fa6d1..c5b1c804eadd2 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1645,7 +1645,7 @@ pub struct NoneError; #[unstable(feature = "try_trait", issue = "42327")] impl ops::TryV1 for Option { - type Ok = T; + type Output = T; type Error = NoneError; #[inline] diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 5f6afcc822182..21e406194bc9e 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1628,7 +1628,7 @@ impl> FromIterator> for Result { #[unstable(feature = "try_trait", issue = "42327")] impl ops::TryV1 for Result { - type Ok = T; + type Output = T; type Error = E; #[inline] diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index c3ba8b23e8df9..b92ab7e347555 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -110,7 +110,7 @@ impl<'a> iter::Iterator for EscapeAscii<'a> { fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Fold: FnMut(Acc, Self::Item) -> R, - R: ops::TryWhereOutputEquals, + R: ops::Try, { self.inner.try_fold(init, fold) } diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 612f17a1e6161..6ec6b70b57119 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -5,7 +5,7 @@ use crate::fmt::{self, Write}; use crate::iter::TrustedRandomAccess; use crate::iter::{Chain, FlatMap, Flatten}; use crate::iter::{Copied, Filter, FusedIterator, Map, TrustedLen}; -use crate::ops::TryWhereOutputEquals; +use crate::ops::Try; use crate::option; use crate::slice::{self, Split as SliceSplit}; @@ -1467,7 +1467,7 @@ macro_rules! escape_types_impls { #[inline] fn try_fold(&mut self, init: Acc, fold: Fold) -> R where - Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: TryWhereOutputEquals + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try { self.inner.try_fold(init, fold) } diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 2ccfc22c27cac..188639e7962e4 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -130,11 +130,11 @@ impl From for Poll { #[stable(feature = "futures_api", since = "1.36.0")] impl ops::TryV1 for Poll> { - type Ok = Poll; + type Output = Poll; type Error = E; #[inline] - fn into_result(self) -> Result { + fn into_result(self) -> Result { match self { Poll::Ready(Ok(x)) => Ok(Poll::Ready(x)), Poll::Ready(Err(e)) => Err(e), @@ -148,7 +148,7 @@ impl ops::TryV1 for Poll> { } #[inline] - fn from_ok(x: Self::Ok) -> Self { + fn from_ok(x: Self::Output) -> Self { x.map(Ok) } } @@ -185,11 +185,11 @@ impl> ops::FromResidual> for Pol #[stable(feature = "futures_api", since = "1.36.0")] impl ops::TryV1 for Poll>> { - type Ok = Poll>; + type Output = Poll>; type Error = E; #[inline] - fn into_result(self) -> Result { + fn into_result(self) -> Result { match self { Poll::Ready(Some(Ok(x))) => Ok(Poll::Ready(Some(x))), Poll::Ready(Some(Err(e))) => Err(e), @@ -204,7 +204,7 @@ impl ops::TryV1 for Poll>> { } #[inline] - fn from_ok(x: Self::Ok) -> Self { + fn from_ok(x: Self::Output) -> Self { x.map(|x| x.map(Ok)) } } From bf0e34c00159b60472ca2f78adb8837b9f5849a2 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 9 May 2021 22:05:02 -0700 Subject: [PATCH 09/11] PR feedback --- library/alloc/src/lib.rs | 4 ++-- library/core/src/iter/traits/iterator.rs | 3 ++- src/test/codegen/try_identity.rs | 8 ++++---- src/test/mir-opt/simplify-arm.rs | 8 ++++---- src/test/mir-opt/simplify_try.rs | 8 ++++---- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index a635d6ffe995a..3bc376482e998 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -140,8 +140,8 @@ #![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_uninit_array)] #![feature(alloc_layout_extra)] #![feature(trusted_random_access)] -#![feature(try_trait)] -#![feature(try_trait_v2)] +#![cfg_attr(bootstrap, feature(try_trait))] +#![cfg_attr(not(bootstrap), feature(try_trait_v2))] #![feature(min_type_alias_impl_trait)] #![feature(associated_type_bounds)] #![feature(slice_group_by)] diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index ffac4534b2073..777e4bc2c8920 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2418,7 +2418,8 @@ pub trait Iterator { Self: Sized, F: FnMut(&Self::Item) -> R, R: Try, - // FIXME: This is a weird bound; the API should change + // FIXME: This bound is rather strange, but means minimal breakage on nightly. + // See #85115 for the issue tracking a holistic solution for this and try_map. R: crate::ops::TryV2>, { #[inline] diff --git a/src/test/codegen/try_identity.rs b/src/test/codegen/try_identity.rs index 78da06b2fe440..71bfc3b44daf6 100644 --- a/src/test/codegen/try_identity.rs +++ b/src/test/codegen/try_identity.rs @@ -7,10 +7,10 @@ type R = Result; -// This was written to the `?` from `try_trait`, -// but `try_trait_v2` uses a different structure, -// so the relevant desugar is copied inline -// in order to keep the test testing the same thing. +// This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure, +// so the relevant desugar is copied inline in order to keep the test testing the same thing. +// FIXME: while this might be useful for `r#try!`, it would be nice to have a MIR optimization +// that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. See #85133 #[no_mangle] pub fn try_identity(x: R) -> R { // CHECK: start: diff --git a/src/test/mir-opt/simplify-arm.rs b/src/test/mir-opt/simplify-arm.rs index b789b87f6c2dc..6a6e39e68f939 100644 --- a/src/test/mir-opt/simplify-arm.rs +++ b/src/test/mir-opt/simplify-arm.rs @@ -28,10 +28,10 @@ fn from_error(e: E) -> Result { Err(e) } -// This was written to the `?` from `try_trait`, -// but `try_trait_v2` uses a different structure, -// so the relevant desugar is copied inline -// in order to keep the test testing the same thing. +// This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure, +// so the relevant desugar is copied inline in order to keep the test testing the same thing. +// FIXME: while this might be useful for `r#try!`, it would be nice to have a MIR optimization +// that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. See #85133 fn id_try(r: Result) -> Result { let x = match into_result(r) { Err(e) => return from_error(From::from(e)), diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs index a95cb665a97f3..b91a7bfe68fa6 100644 --- a/src/test/mir-opt/simplify_try.rs +++ b/src/test/mir-opt/simplify_try.rs @@ -13,10 +13,10 @@ fn from_error(e: E) -> Result { Err(e) } -// This was written to the `?` from `try_trait`, -// but `try_trait_v2` uses a different structure, -// so the relevant desugar is copied inline -// in order to keep the test testing the same thing. +// This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure, +// so the relevant desugar is copied inline in order to keep the test testing the same thing. +// FIXME: while this might be useful for `r#try!`, it would be nice to have a MIR optimization +// that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. See #85133 fn try_identity(x: Result) -> Result { let y = match into_result(x) { Err(e) => return from_error(From::from(e)), From 6f7dea74d7699707cfdcf81435c200923d0a5047 Mon Sep 17 00:00:00 2001 From: scottmcm Date: Tue, 18 May 2021 18:29:34 +0000 Subject: [PATCH 10/11] Mention the issue number for the new mir-opt in the FIXMEs Thanks for the suggestions, lcnr! Co-authored-by: lcnr --- src/test/codegen/try_identity.rs | 2 +- src/test/mir-opt/simplify-arm.rs | 2 +- src/test/mir-opt/simplify_try.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/codegen/try_identity.rs b/src/test/codegen/try_identity.rs index 71bfc3b44daf6..0363b9dd19eb7 100644 --- a/src/test/codegen/try_identity.rs +++ b/src/test/codegen/try_identity.rs @@ -9,7 +9,7 @@ type R = Result; // This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure, // so the relevant desugar is copied inline in order to keep the test testing the same thing. -// FIXME: while this might be useful for `r#try!`, it would be nice to have a MIR optimization +// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR optimization // that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. See #85133 #[no_mangle] pub fn try_identity(x: R) -> R { diff --git a/src/test/mir-opt/simplify-arm.rs b/src/test/mir-opt/simplify-arm.rs index 6a6e39e68f939..e0c7b95a5ec36 100644 --- a/src/test/mir-opt/simplify-arm.rs +++ b/src/test/mir-opt/simplify-arm.rs @@ -30,7 +30,7 @@ fn from_error(e: E) -> Result { // This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure, // so the relevant desugar is copied inline in order to keep the test testing the same thing. -// FIXME: while this might be useful for `r#try!`, it would be nice to have a MIR optimization +// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR optimization // that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. See #85133 fn id_try(r: Result) -> Result { let x = match into_result(r) { diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs index b91a7bfe68fa6..46c239ebe323a 100644 --- a/src/test/mir-opt/simplify_try.rs +++ b/src/test/mir-opt/simplify_try.rs @@ -15,7 +15,7 @@ fn from_error(e: E) -> Result { // This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure, // so the relevant desugar is copied inline in order to keep the test testing the same thing. -// FIXME: while this might be useful for `r#try!`, it would be nice to have a MIR optimization +// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR optimization // that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. See #85133 fn try_identity(x: Result) -> Result { let y = match into_result(x) { From e2edee4da07032de72ac930df1453780dbe73f3b Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 18 May 2021 11:48:00 -0700 Subject: [PATCH 11/11] No matter how trivial the change, tidy always finds a way to complain... --- src/test/codegen/try_identity.rs | 4 ++-- src/test/mir-opt/simplify-arm.rs | 4 ++-- src/test/mir-opt/simplify_try.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/codegen/try_identity.rs b/src/test/codegen/try_identity.rs index 0363b9dd19eb7..3ff77163b9f3d 100644 --- a/src/test/codegen/try_identity.rs +++ b/src/test/codegen/try_identity.rs @@ -9,8 +9,8 @@ type R = Result; // This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure, // so the relevant desugar is copied inline in order to keep the test testing the same thing. -// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR optimization -// that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. See #85133 +// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR +// optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. #[no_mangle] pub fn try_identity(x: R) -> R { // CHECK: start: diff --git a/src/test/mir-opt/simplify-arm.rs b/src/test/mir-opt/simplify-arm.rs index e0c7b95a5ec36..f7dcaa13449ea 100644 --- a/src/test/mir-opt/simplify-arm.rs +++ b/src/test/mir-opt/simplify-arm.rs @@ -30,8 +30,8 @@ fn from_error(e: E) -> Result { // This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure, // so the relevant desugar is copied inline in order to keep the test testing the same thing. -// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR optimization -// that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. See #85133 +// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR +// optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. fn id_try(r: Result) -> Result { let x = match into_result(r) { Err(e) => return from_error(From::from(e)), diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs index 46c239ebe323a..15e351e7d5016 100644 --- a/src/test/mir-opt/simplify_try.rs +++ b/src/test/mir-opt/simplify_try.rs @@ -15,8 +15,8 @@ fn from_error(e: E) -> Result { // This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure, // so the relevant desugar is copied inline in order to keep the test testing the same thing. -// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR optimization -// that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. See #85133 +// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR +// optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. fn try_identity(x: Result) -> Result { let y = match into_result(x) { Err(e) => return from_error(From::from(e)),