diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index cdcd221e811a7..1a18d1964c978 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1275,6 +1275,7 @@ impl Expr {
ExprKind::Paren(..) => ExprPrecedence::Paren,
ExprKind::Try(..) => ExprPrecedence::Try,
ExprKind::Yield(..) => ExprPrecedence::Yield,
+ ExprKind::Yeet(..) => ExprPrecedence::Yeet,
ExprKind::Err => ExprPrecedence::Err,
}
}
@@ -1462,6 +1463,10 @@ pub enum ExprKind {
/// A `yield`, with an optional value to be yielded.
Yield(Option
>),
+ /// A `do yeet` (aka `throw`/`fail`/`bail`/`raise`/whatever),
+ /// with an optional value to be returned.
+ Yeet(Option
>),
+
/// Placeholder for an expression that wasn't syntactically well formed in some way.
Err,
}
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index d7b1bc6a7f580..4bf3d483f7358 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1394,6 +1394,9 @@ pub fn noop_visit_expr(
ExprKind::Ret(expr) => {
visit_opt(expr, |expr| vis.visit_expr(expr));
}
+ ExprKind::Yeet(expr) => {
+ visit_opt(expr, |expr| vis.visit_expr(expr));
+ }
ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
ExprKind::Struct(se) => {
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 742a7d1d2df70..74b7fe9e24955 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -247,6 +247,7 @@ pub enum ExprPrecedence {
Continue,
Ret,
Yield,
+ Yeet,
Range,
@@ -299,7 +300,8 @@ impl ExprPrecedence {
ExprPrecedence::Break |
ExprPrecedence::Continue |
ExprPrecedence::Ret |
- ExprPrecedence::Yield => PREC_JUMP,
+ ExprPrecedence::Yield |
+ ExprPrecedence::Yeet => PREC_JUMP,
// `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
// parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index e08ba73e0ae31..fa26716083f86 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -893,6 +893,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
ExprKind::Ret(ref optional_expression) => {
walk_list!(visitor, visit_expr, optional_expression);
}
+ ExprKind::Yeet(ref optional_expression) => {
+ walk_list!(visitor, visit_expr, optional_expression);
+ }
ExprKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
ExprKind::Paren(ref subexpression) => visitor.visit_expr(subexpression),
ExprKind::InlineAsm(ref asm) => walk_inline_asm(visitor, asm),
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 37ae41fabf987..5c3e3be21167a 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -221,6 +221,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let e = e.as_ref().map(|x| self.lower_expr(x));
hir::ExprKind::Ret(e)
}
+ ExprKind::Yeet(ref sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()),
ExprKind::InlineAsm(ref asm) => {
hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
}
@@ -1543,6 +1544,44 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
}
+ /// Desugar `ExprKind::Yeet` from: `do yeet ` into:
+ /// ```rust
+ /// // If there is an enclosing `try {...}`:
+ /// break 'catch_target FromResidual::from_residual(Yeet(residual)),
+ /// // Otherwise:
+ /// return FromResidual::from_residual(Yeet(residual)),
+ /// ```
+ /// But to simplify this, there's a `from_yeet` lang item function which
+ /// handles the combined `FromResidual::from_residual(Yeet(residual))`.
+ fn lower_expr_yeet(&mut self, span: Span, sub_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
+ // The expression (if present) or `()` otherwise.
+ let (yeeted_span, yeeted_expr) = if let Some(sub_expr) = sub_expr {
+ (sub_expr.span, self.lower_expr(sub_expr))
+ } else {
+ (self.mark_span_with_reason(DesugaringKind::YeetExpr, span, None), self.expr_unit(span))
+ };
+
+ let unstable_span = self.mark_span_with_reason(
+ DesugaringKind::YeetExpr,
+ span,
+ self.allow_try_trait.clone(),
+ );
+
+ let from_yeet_expr = self.wrap_in_try_constructor(
+ hir::LangItem::TryTraitFromYeet,
+ unstable_span,
+ yeeted_expr,
+ yeeted_span,
+ );
+
+ if let Some(catch_node) = self.catch_scope {
+ let target_id = Ok(self.lower_node_id(catch_node));
+ hir::ExprKind::Break(hir::Destination { label: None, target_id }, Some(from_yeet_expr))
+ } else {
+ hir::ExprKind::Ret(Some(from_yeet_expr))
+ }
+ }
+
// =========================================================================
// Helper methods for building HIR.
// =========================================================================
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 125acdcc27d97..5a95e5b084ad4 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -85,7 +85,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
task_context: None,
current_item: None,
captured_lifetimes: None,
- allow_try_trait: Some([sym::try_trait_v2][..].into()),
+ allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
allow_gen_future: Some([sym::gen_future][..].into()),
allow_into_future: Some([sym::into_future][..].into()),
};
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 649af48e48adf..0e8af549692fc 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -783,6 +783,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(inline_const, "inline-const is experimental");
gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
gate_all!(associated_const_equality, "associated const equality is incomplete");
+ gate_all!(yeet_expr, "`do yeet` expression is experimental");
// All uses of `gate_all!` below this point were added in #65742,
// and subsequently disabled (with the non-early gating readded).
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 9de4cbbee13f0..9f44f1b6cc205 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -64,7 +64,10 @@ impl<'a> State<'a> {
// parses as the erroneous construct `if (return {})`, not `if (return) {}`.
pub(super) fn cond_needs_par(expr: &ast::Expr) -> bool {
match expr.kind {
- ast::ExprKind::Break(..) | ast::ExprKind::Closure(..) | ast::ExprKind::Ret(..) => true,
+ ast::ExprKind::Break(..)
+ | ast::ExprKind::Closure(..)
+ | ast::ExprKind::Ret(..)
+ | ast::ExprKind::Yeet(..) => true,
_ => parser::contains_exterior_struct_lit(expr),
}
}
@@ -502,6 +505,15 @@ impl<'a> State<'a> {
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
}
+ ast::ExprKind::Yeet(ref result) => {
+ self.word("do");
+ self.word(" ");
+ self.word("yeet");
+ if let Some(ref expr) = *result {
+ self.word(" ");
+ self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
+ }
+ }
ast::ExprKind::InlineAsm(ref a) => {
self.word("asm!");
self.print_inline_asm(a);
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index f3d4c8ab43843..9159d60463c4c 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -544,6 +544,8 @@ declare_features! (
(active, used_with_arg, "1.60.0", Some(93798), None),
/// Allows `extern "wasm" fn`
(active, wasm_abi, "1.53.0", Some(83788), None),
+ /// Allows `do yeet` expressions
+ (active, yeet_expr, "1.62.0", Some(96373), None),
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
// Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 9318ebb40b09b..b3c22d4ec213d 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -293,6 +293,7 @@ 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;
+ TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;
PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None;
PollPending, sym::Pending, poll_pending_variant, Target::Variant, GenericRequirement::None;
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 13e9a5e660fe6..6114e7aaa7bd7 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1374,6 +1374,8 @@ impl<'a> Parser<'a> {
self.parse_break_expr(attrs)
} else if self.eat_keyword(kw::Yield) {
self.parse_yield_expr(attrs)
+ } else if self.is_do_yeet() {
+ self.parse_yeet_expr(attrs)
} else if self.eat_keyword(kw::Let) {
self.parse_let_expr(attrs)
} else if self.eat_keyword(kw::Underscore) {
@@ -1605,6 +1607,21 @@ impl<'a> Parser<'a> {
self.maybe_recover_from_bad_qpath(expr, true)
}
+ /// Parse `"do" "yeet" expr?`.
+ fn parse_yeet_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> {
+ let lo = self.token.span;
+
+ self.bump(); // `do`
+ self.bump(); // `yeet`
+
+ let kind = ExprKind::Yeet(self.parse_expr_opt()?);
+
+ let span = lo.to(self.prev_token.span);
+ self.sess.gated_spans.gate(sym::yeet_expr, span);
+ let expr = self.mk_expr(span, kind, attrs);
+ self.maybe_recover_from_bad_qpath(expr, true)
+ }
+
/// Parse `"break" (('label (:? expr)?) | expr?)` with `"break"` token already eaten.
/// If the label is followed immediately by a `:` token, the label and `:` are
/// parsed as part of the expression (i.e. a labeled loop). The language team has
@@ -2676,6 +2693,10 @@ impl<'a> Parser<'a> {
&& !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
}
+ fn is_do_yeet(&self) -> bool {
+ self.token.is_keyword(kw::Do) && self.is_keyword_ahead(1, &[kw::Yeet])
+ }
+
fn is_try_block(&self) -> bool {
self.token.is_keyword(kw::Try)
&& self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace))
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 3889639b50f45..447b73fa3c3ce 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1132,6 +1132,7 @@ pub enum DesugaringKind {
CondTemporary,
QuestionMark,
TryBlock,
+ YeetExpr,
/// Desugaring of an `impl Trait` in return type position
/// to an `type Foo = impl Trait;` and replacing the
/// `impl Trait` with `Foo`.
@@ -1152,6 +1153,7 @@ impl DesugaringKind {
DesugaringKind::Await => "`await` expression",
DesugaringKind::QuestionMark => "operator `?`",
DesugaringKind::TryBlock => "`try` block",
+ DesugaringKind::YeetExpr => "`do yeet` expression",
DesugaringKind::OpaqueTy => "`impl Trait`",
DesugaringKind::ForLoop => "`for` loop",
DesugaringKind::LetElse => "`let...else`",
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index e3ce8105a8b47..c1299c94c4bb3 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -101,6 +101,7 @@ symbols! {
MacroRules: "macro_rules",
Raw: "raw",
Union: "union",
+ Yeet: "yeet",
}
// Pre-interned symbols that can be referred to with `rustc_span::sym::*`.
@@ -714,6 +715,7 @@ symbols! {
from_residual,
from_size_align_unchecked,
from_usize,
+ from_yeet,
fsub_fast,
fundamental,
future,
@@ -1534,6 +1536,8 @@ symbols! {
x87_reg,
xer,
xmm_reg,
+ yeet_desugar_details,
+ yeet_expr,
ymm_reg,
zmm_reg,
}
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index 9d1e7e81b0e7e..31c1a1d099dc6 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -187,6 +187,9 @@ pub use self::range::OneSidedRange;
#[unstable(feature = "try_trait_v2", issue = "84277")]
pub use self::try_trait::{FromResidual, Try};
+#[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
+pub use self::try_trait::Yeet;
+
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
pub use self::try_trait::Residual;
diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs
index ba369e7f3aaa0..3eaee958b69bd 100644
--- a/library/core/src/ops/try_trait.rs
+++ b/library/core/src/ops/try_trait.rs
@@ -330,6 +330,22 @@ pub trait FromResidual::Residual> {
fn from_residual(residual: R) -> Self;
}
+#[cfg(not(bootstrap))]
+#[unstable(
+ feature = "yeet_desugar_details",
+ issue = "none",
+ reason = "just here to simplify the desugaring; will never be stabilized"
+)]
+#[inline]
+#[track_caller] // because `Result::from_residual` has it
+#[lang = "from_yeet"]
+pub fn from_yeet(yeeted: Y) -> T
+where
+ T: FromResidual>,
+{
+ FromResidual::from_residual(Yeet(yeeted))
+}
+
/// Allows retrieving the canonical type implementing [`Try`] that has this type
/// as its residual and allows it to hold an `O` as its output.
///
@@ -395,3 +411,9 @@ impl FromResidual for NeverShortCircuit {
impl Residual for NeverShortCircuitResidual {
type TryType = NeverShortCircuit;
}
+
+/// Implement `FromResidual>` on your type to enable
+/// `do yeet expr` syntax in functions returning your type.
+#[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
+#[derive(Debug)]
+pub struct Yeet(pub T);
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 91e4708f6a609..f339b076dd7d0 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -2287,6 +2287,14 @@ impl const ops::FromResidual for Option {
}
}
+#[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
+impl ops::FromResidual> for Option {
+ #[inline]
+ fn from_residual(ops::Yeet(()): ops::Yeet<()>) -> Self {
+ None
+ }
+}
+
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
impl ops::Residual for Option {
type TryType = Option;
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index b2b132300a299..5e5f8a5ab9543 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -2107,6 +2107,14 @@ impl> const ops::FromResidual> ops::FromResidual> for Result {
+ #[inline]
+ fn from_residual(ops::Yeet(e): ops::Yeet) -> Self {
+ Err(From::from(e))
+ }
+}
+
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
impl ops::Residual for Result {
type TryType = Result;
diff --git a/src/doc/unstable-book/src/language-features/yeet-expr.md b/src/doc/unstable-book/src/language-features/yeet-expr.md
new file mode 100644
index 0000000000000..bc1ba4c916b64
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/yeet-expr.md
@@ -0,0 +1,26 @@
+# `yeet_expr`
+
+The tracking issue for this feature is: [#96373]
+
+[#96373]: https://github.com/rust-lang/rust/issues/96373
+
+------------------------
+
+The `yeet_expr` feature adds support for `do yeet` expressions,
+which can be used to early-exit from a function or `try` block.
+
+These are highly experimental, thus the placeholder syntax.
+
+```rust,edition2021
+#![feature(yeet_expr)]
+
+fn foo() -> Result {
+ do yeet 4;
+}
+assert_eq!(foo(), Err(4));
+
+fn bar() -> Option {
+ do yeet;
+}
+assert_eq!(bar(), None);
+```
diff --git a/src/test/pretty/yeet-expr.rs b/src/test/pretty/yeet-expr.rs
new file mode 100644
index 0000000000000..c899f11b7240e
--- /dev/null
+++ b/src/test/pretty/yeet-expr.rs
@@ -0,0 +1,12 @@
+// pp-exact
+#![feature(yeet_expr)]
+
+fn yeet_no_expr() -> Option { do yeet }
+
+fn yeet_no_expr_with_semicolon() -> Option { do yeet; }
+
+fn yeet_with_expr() -> Result { do yeet 1 + 2 }
+
+fn yeet_with_expr_with_semicolon() -> Result { do yeet 1 + 2; }
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs b/src/test/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs
new file mode 100644
index 0000000000000..a33bd34508c5f
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs
@@ -0,0 +1,19 @@
+// compile-flags: --edition 2021
+
+pub fn demo() -> Option {
+ #[cfg(nope)]
+ {
+ do yeet //~ ERROR `do yeet` expression is experimental
+ }
+
+ Some(1)
+}
+
+#[cfg(nope)]
+pub fn alternative() -> Result<(), String> {
+ do yeet "hello"; //~ ERROR `do yeet` expression is experimental
+}
+
+fn main() {
+ demo();
+}
diff --git a/src/test/ui/feature-gates/feature-gate-yeet_expr-in-cfg.stderr b/src/test/ui/feature-gates/feature-gate-yeet_expr-in-cfg.stderr
new file mode 100644
index 0000000000000..f90c379bdafe3
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-yeet_expr-in-cfg.stderr
@@ -0,0 +1,21 @@
+error[E0658]: `do yeet` expression is experimental
+ --> $DIR/feature-gate-yeet_expr-in-cfg.rs:6:9
+ |
+LL | do yeet
+ | ^^^^^^^
+ |
+ = note: see issue #96373 for more information
+ = help: add `#![feature(yeet_expr)]` to the crate attributes to enable
+
+error[E0658]: `do yeet` expression is experimental
+ --> $DIR/feature-gate-yeet_expr-in-cfg.rs:14:5
+ |
+LL | do yeet "hello";
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #96373 for more information
+ = help: add `#![feature(yeet_expr)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-yeet_expr.rs b/src/test/ui/feature-gates/feature-gate-yeet_expr.rs
new file mode 100644
index 0000000000000..978a84cf6e5f0
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-yeet_expr.rs
@@ -0,0 +1,9 @@
+// compile-flags: --edition 2018
+
+pub fn demo() -> Option {
+ do yeet //~ ERROR `do yeet` expression is experimental
+}
+
+pub fn main() -> Result<(), String> {
+ do yeet "hello"; //~ ERROR `do yeet` expression is experimental
+}
diff --git a/src/test/ui/feature-gates/feature-gate-yeet_expr.stderr b/src/test/ui/feature-gates/feature-gate-yeet_expr.stderr
new file mode 100644
index 0000000000000..8d1b92370fbe2
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-yeet_expr.stderr
@@ -0,0 +1,21 @@
+error[E0658]: `do yeet` expression is experimental
+ --> $DIR/feature-gate-yeet_expr.rs:4:5
+ |
+LL | do yeet
+ | ^^^^^^^
+ |
+ = note: see issue #96373 for more information
+ = help: add `#![feature(yeet_expr)]` to the crate attributes to enable
+
+error[E0658]: `do yeet` expression is experimental
+ --> $DIR/feature-gate-yeet_expr.rs:8:5
+ |
+LL | do yeet "hello";
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #96373 for more information
+ = help: add `#![feature(yeet_expr)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/inference/question-mark-type-infer.stderr b/src/test/ui/inference/question-mark-type-infer.stderr
index e7d5fee18127f..9b822714f828a 100644
--- a/src/test/ui/inference/question-mark-type-infer.stderr
+++ b/src/test/ui/inference/question-mark-type-infer.stderr
@@ -1,15 +1,9 @@
-error[E0284]: type annotations needed
- --> $DIR/question-mark-type-infer.rs:10:21
+error[E0282]: type annotations needed
+ --> $DIR/question-mark-type-infer.rs:10:30
|
LL | l.iter().map(f).collect()?
- | ^^^^^^^ cannot infer type
- |
- = note: cannot satisfy `<_ as Try>::Residual == _`
-help: consider specifying the type argument in the method call
- |
-LL | l.iter().map(f).collect::()?
- | +++++
+ | ^ cannot infer type
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0284`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr
index ed5addcbec517..112cb33593223 100644
--- a/src/test/ui/issues/issue-32709.stderr
+++ b/src/test/ui/issues/issue-32709.stderr
@@ -7,7 +7,9 @@ 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
- = help: the trait `FromResidual>` is implemented for `Result`
+ = help: the following other types implement trait `FromResidual`:
+ as FromResidual>>
+ as FromResidual>>
= note: required because of the requirements on the impl of `FromResidual>` for `Result`
error: aborting due to previous error
diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr
index 1a4105231dc75..1dbf3ebdf827c 100644
--- a/src/test/ui/try-trait/bad-interconversion.stderr
+++ b/src/test/ui/try-trait/bad-interconversion.stderr
@@ -31,7 +31,9 @@ LL | | }
| |_- this function returns a `Result`
|
= help: the trait `FromResidual