Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1955,16 +1955,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
Some(Arc::clone(&crate::ALLOW_TRY_TRAIT)),
);

// FIXME: Extend this to edition check on stabilisation with 2027
let has_try_trait = self.tcx.features().try_trait_v2();

let (branch_fn, from_residual_fn) = match has_try_trait {
true => (LangItem::TryTraitBranch, LangItem::TryTraitFromResidual),
false => (LangItem::TryTraitBranchOld, LangItem::TryTraitFromResidualOld),
};

// `Try::branch(<expr>)`
let scrutinee = {
// expand <expr>
let sub_expr = self.lower_expr_mut(sub_expr);

self.expr_call_lang_item_fn(
unstable_span,
LangItem::TryTraitBranch,
arena_vec![self; sub_expr],
)
self.expr_call_lang_item_fn(unstable_span, branch_fn, arena_vec![self; sub_expr])
};

let attrs: AttrVec = thin_vec![self.unreachable_code_attr(try_span)];
Expand All @@ -1989,7 +1993,7 @@ impl<'hir> LoweringContext<'_, 'hir> {

let (constructor_item, target_id) = match self.try_block_scope {
TryBlockScope::Function => {
(LangItem::TryTraitFromResidual, Err(hir::LoopIdError::OutsideLoopScope))
(from_residual_fn, Err(hir::LoopIdError::OutsideLoopScope))
}
TryBlockScope::Homogeneous(block_id) => {
(LangItem::ResidualIntoTryType, Ok(block_id))
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_attr_ir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,8 @@ language_item_table! {
Termination, sym::termination, termination, Target::Trait, GenericRequirement::None;

Try, sym::Try, try_trait, Target::Trait, GenericRequirement::None;
// FIXME: Is TryOld even needed?
TryOld, sym::Try_Old, try_trait_old, Target::Trait, GenericRequirement::None;

Tuple, sym::tuple_trait, tuple_trait, Target::Trait, GenericRequirement::Exact(0);

Expand All @@ -378,6 +380,11 @@ language_item_table! {
TryTraitFromResidual, sym::from_residual, from_residual_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
// Only Try, FromResidual & Branch are needed for `?` outside `try` blocks
// FIXME: Update rust-analyzer src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
TryTraitFromResidualOld, sym::from_residual_old, from_residual_fn_old, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
TryTraitBranchOld, sym::branch_old, branch_fn_old, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;

TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;
ResidualIntoTryType, sym::into_try_type, into_try_type_fn, Target::Fn, GenericRequirement::None;

Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_const_eval/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
// tidy-alphabetical-start
#![allow(
unused_features,
reason = "FIXME: try_trait_v2 shows unused if only needed for desugaring"
)]
#![feature(array_try_map)]
#![feature(decl_macro)]
#![feature(deref_patterns)]
#![feature(slice_ptr_get)]
#![feature(trait_alias)]
#![feature(try_trait_v2)]
#![feature(unqualified_local_imports)]
#![feature(yeet_expr)]
#![warn(unqualified_local_imports)]
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,8 @@ declare_features! (
(unstable, try_blocks, "1.29.0", Some(154391)),
/// Allows using `try bikeshed TargetType {...}` expressions.
(unstable, try_blocks_heterogeneous, "1.94.0", Some(149488)),
/// Provides the `Try` trait in stdlib. We need to check availability when desugaring `?`
(unstable, try_trait_v2, "CURRENT_RUSTC_VERSION", Some(84277)),
/// Allows `impl Trait` to be used inside type aliases (RFC 2515).
(unstable, type_alias_impl_trait, "1.38.0", Some(63063)),
/// Allows creation of instances of a struct by moving fields that have
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_mir_transform/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
// tidy-alphabetical-start
#![allow(
unused_features,
reason = "FIXME: try_trait_v2 shows unused if only needed for desugaring"
)]
#![feature(const_type_name)]
#![feature(cow_is_borrowed)]
#![feature(deref_patterns)]
#![feature(impl_trait_in_assoc_type)]
#![feature(iterator_try_collect)]
#![feature(option_into_flat_iter)]
#![feature(try_blocks)]
#![feature(try_trait_v2)]
#![feature(yeet_expr)]
// tidy-alphabetical-end

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ symbols! {
From,
FromIterator,
FromResidual,
FromResidualOld,
GlobalAlloc,
Hash,
HashMap,
Expand Down Expand Up @@ -353,6 +354,7 @@ symbols! {
TryCapturePrintable,
TryFrom,
TryInto,
Try_Old,
Tuple,
Ty,
TyCtxt,
Expand Down Expand Up @@ -575,6 +577,7 @@ symbols! {
bpf_target_feature,
braced_empty_structs,
branch,
branch_old,
breakpoint,
breg,
bridge,
Expand Down Expand Up @@ -1058,6 +1061,7 @@ symbols! {
from_iter,
from_output,
from_residual,
from_residual_old,
from_size_align_unchecked,
from_size_alignment_unchecked,
from_str,
Expand Down
6 changes: 3 additions & 3 deletions library/core/src/iter/adapters/array_chunks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::array;
use crate::iter::adapters::SourceIter;
use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedRandomAccessNoCoerce};
use crate::num::NonZero;
use crate::ops::{ControlFlow, NeverShortCircuit, Try};
use crate::ops::{ControlFlow, NeverShortCircuit, Try, qmark};

/// An iterator over `N` elements of the iterator at a time.
///
Expand Down Expand Up @@ -85,7 +85,7 @@ where
let mut acc = init;
loop {
match self.iter.next_chunk() {
Ok(chunk) => acc = f(acc, chunk)?,
Ok(chunk) => acc = qmark!(f(acc, chunk)),
Err(remainder) => {
// Make sure to not overwrite `self.remainder` with an empty array
// when `next` is called after `ArrayChunks` exhaustion.
Expand Down Expand Up @@ -131,7 +131,7 @@ where
// `next_chunk_back` can't return `Err` with non-empty remainder
// (assuming correct `I as ExactSizeIterator` impl).
while let Ok(chunk) = self.iter.next_chunk_back() {
acc = f(acc, chunk)?
acc = qmark!(f(acc, chunk))
}

try { acc }
Expand Down
10 changes: 5 additions & 5 deletions library/core/src/iter/adapters/chain.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::iter::{FusedIterator, TrustedLen};
use crate::num::NonZero;
use crate::ops::Try;
use crate::ops::{Try, qmark};

/// An iterator that links two iterators together, in a chain.
///
Expand Down Expand Up @@ -103,11 +103,11 @@ where
R: Try<Output = Acc>,
{
if let Some(ref mut a) = self.a {
acc = a.try_fold(acc, &mut f)?;
acc = qmark!(a.try_fold(acc, &mut f));
self.a = None;
}
if let Some(ref mut b) = self.b {
acc = b.try_fold(acc, f)?;
acc = qmark!(b.try_fold(acc, f));
// we don't fuse the second iterator
}
try { acc }
Expand Down Expand Up @@ -263,11 +263,11 @@ where
R: Try<Output = Acc>,
{
if let Some(ref mut b) = self.b {
acc = b.try_rfold(acc, &mut f)?;
acc = qmark!(b.try_rfold(acc, &mut f));
self.b = None;
}
if let Some(ref mut a) = self.a {
acc = a.try_rfold(acc, f)?;
acc = qmark!(a.try_rfold(acc, f));
// we don't fuse the second iterator
}
try { acc }
Expand Down
10 changes: 5 additions & 5 deletions library/core/src/iter/adapters/cycle.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::iter::FusedIterator;
use crate::num::NonZero;
use crate::ops::Try;
use crate::ops::{Try, qmark};

/// An iterator that repeats endlessly.
///
Expand Down Expand Up @@ -60,25 +60,25 @@ where
{
// fully iterate the current iterator. this is necessary because
// `self.iter` may be empty even when `self.orig` isn't
acc = self.iter.try_fold(acc, &mut f)?;
acc = qmark!(self.iter.try_fold(acc, &mut f));
self.iter = self.orig.clone();

// complete a full cycle, keeping track of whether the cycled
// iterator is empty or not. we need to return early in case
// of an empty iterator to prevent an infinite loop
let mut is_empty = true;
acc = self.iter.try_fold(acc, |acc, x| {
acc = qmark!(self.iter.try_fold(acc, |acc, x| {
is_empty = false;
f(acc, x)
})?;
}));

if is_empty {
return try { acc };
}

loop {
self.iter = self.orig.clone();
acc = self.iter.try_fold(acc, &mut f)?;
acc = qmark!(self.iter.try_fold(acc, &mut f));
}
}

Expand Down
14 changes: 7 additions & 7 deletions library/core/src/iter/adapters/flatten.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::iter::{
TrustedFused, TrustedLen,
};
use crate::num::NonZero;
use crate::ops::{ControlFlow, Try};
use crate::ops::{ControlFlow, Try, qmark};
use crate::{array, fmt, option, result};

/// An iterator that maps each element to an iterator, and yields the elements
Expand Down Expand Up @@ -424,15 +424,15 @@ where
}

if let Some(iter) = &mut self.frontiter {
acc = fold(acc, iter)?;
acc = qmark!(fold(acc, iter));
}
self.frontiter = None;

acc = self.iter.try_fold(acc, flatten(&mut self.frontiter, &mut fold))?;
acc = qmark!(self.iter.try_fold(acc, flatten(&mut self.frontiter, &mut fold)));
self.frontiter = None;

if let Some(iter) = &mut self.backiter {
acc = fold(acc, iter)?;
acc = qmark!(fold(acc, iter));
}
self.backiter = None;

Expand Down Expand Up @@ -493,15 +493,15 @@ where
}

if let Some(iter) = &mut self.backiter {
acc = fold(acc, iter)?;
acc = qmark!(fold(acc, iter));
}
self.backiter = None;

acc = self.iter.try_rfold(acc, flatten(&mut self.backiter, &mut fold))?;
acc = qmark!(self.iter.try_rfold(acc, flatten(&mut self.backiter, &mut fold)));
self.backiter = None;

if let Some(iter) = &mut self.frontiter {
acc = fold(acc, iter)?;
acc = qmark!(fold(acc, iter));
}
self.frontiter = None;

Expand Down
10 changes: 5 additions & 5 deletions library/core/src/iter/adapters/fuse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::iter::{
FusedIterator, TrustedFused, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
};
use crate::num::NonZero;
use crate::ops::Try;
use crate::ops::{Try, qmark};

/// An iterator that yields `None` forever after the underlying iterator
/// yields `None` once.
Expand Down Expand Up @@ -336,7 +336,7 @@ where
R: Try<Output = Acc>,
{
if let Some(ref mut iter) = self.iter {
acc = iter.try_fold(acc, fold)?;
acc = qmark!(iter.try_fold(acc, fold));
self.iter = None;
}
try { acc }
Expand Down Expand Up @@ -375,7 +375,7 @@ where
I: DoubleEndedIterator,
{
if let Some(ref mut iter) = self.iter {
acc = iter.try_rfold(acc, fold)?;
acc = qmark!(iter.try_rfold(acc, fold));
self.iter = None;
}
try { acc }
Expand Down Expand Up @@ -427,7 +427,7 @@ where
R: Try<Output = Acc>,
{
if let Some(ref mut iter) = self.iter {
acc = iter.try_fold(acc, fold)?;
acc = qmark!(iter.try_fold(acc, fold));
}
try { acc }
}
Expand Down Expand Up @@ -465,7 +465,7 @@ where
I: DoubleEndedIterator,
{
if let Some(ref mut iter) = self.iter {
acc = iter.try_rfold(acc, fold)?;
acc = qmark!(iter.try_rfold(acc, fold));
}
try { acc }
}
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/iter/adapters/peekable.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::iter::adapters::SourceIter;
use crate::iter::{FusedIterator, TrustedLen};
use crate::ops::{ControlFlow, Try};
use crate::ops::{ControlFlow, Try, qmark};

/// An iterator with a `peek()` that returns an optional reference to the next
/// element.
Expand Down Expand Up @@ -97,7 +97,7 @@ impl<I: Iterator> Iterator for Peekable<I> {
{
let acc = match self.peeked.take() {
Some(None) => return try { init },
Some(Some(v)) => f(init, v)?,
Some(Some(v)) => qmark!(f(init, v)),
None => init,
};
self.iter.try_fold(acc, f)
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/iter/adapters/skip_while.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::fmt;
use crate::iter::adapters::SourceIter;
use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused};
use crate::num::NonZero;
use crate::ops::Try;
use crate::ops::{Try, qmark};

/// An iterator that rejects elements while `predicate` returns `true`.
///
Expand Down Expand Up @@ -76,7 +76,7 @@ where
{
if !self.flag {
match self.next() {
Some(v) => init = fold(init, v)?,
Some(v) => init = qmark!(fold(init, v)),
None => return try { init },
}
}
Expand Down
Loading
Loading