From 92130a36fb57b2fad1a46e8adcd2b5cb4b945125 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 12 Mar 2024 22:21:29 +0000 Subject: [PATCH 1/3] Add `core::convert::absurd` --- compiler/rustc_hir/src/lang_items.rs | 2 + compiler/rustc_span/src/symbol.rs | 1 + library/core/src/convert/mod.rs | 60 ++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 2a796ca5465c9..ab7a62fc1fcc3 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -317,6 +317,8 @@ language_item_table! { TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None; + Absurd, sym::absurd, absurd, Target::Fn, GenericRequirement::Exact(1); + PointerLike, sym::pointer_like, pointer_like, Target::Trait, GenericRequirement::Exact(0); ConstParamTy, sym::const_param_ty, const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b1d4a63812f42..727a292b0e782 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -354,6 +354,7 @@ symbols! { abi_vectorcall, abi_x86_interrupt, abort, + absurd, add, add_assign, add_with_overflow, diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 432e55e8c9a4c..152d2968e899d 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -105,6 +105,66 @@ pub const fn identity(x: T) -> T { x } +/// Converts [`!`] (the never type) to any type. +/// +/// This is possible because `!` is uninhabited (has no values), so this function can't actually +/// be ever called at runtime. +/// +/// Even though `!` can be coerced to any type implicitly anyway (and indeed this function +/// implemented by just "returning" the argument), this is still useful, as this prevents the +/// fallback from happening during typechecking. +/// +/// For example, this snippet type checks: +/// +/// ```rust +/// let x: Result<_, ()> = Err(()); +/// let y = match x { +/// Ok(v) => v, +/// Err(()) => return, +/// }; +/// ``` +/// +/// This is a bit unexpected, because the type of `y` is seemingly unbound (indeed, it can be any +/// type). However, the `match` unifies type of `v` with type of `return` (which is `!`), so `y` +/// becomes `!` (or `()`, because of backwards compatibility shenanigans). +/// +/// This can be avoided by adding `absurd`; +/// +/// ```compile_fail,E0282 +/// use core::convert::absurd; +/// +/// let x: Result<_, ()> = Err(()); +/// let y = match x { //~ error[E0282]: type annotations needed +/// Ok(v) => v, +/// +/// // the call to `absurd` *is* unreachable, but it's still important for type check reasons +/// #[allow(unreachable_code)] +/// Err(()) => absurd(return), +/// }; +/// ``` +/// +/// This might be handy when writing macros. +/// +/// `absurd` can also be passed to higher order functions, just like any other function: +/// +/// ``` +/// #![feature(never_type)] +/// use core::convert::absurd; +/// +/// let x: Result<_, !> = Ok(1); +/// let x: u32 = x.unwrap_or_else(absurd); +/// ``` +/// +/// [`!`]: ../../primitive.never.html +#[inline(always)] +#[lang = "absurd"] +#[unstable(feature = "convert_absurd", issue = "none")] +#[rustc_const_unstable(feature = "convert_absurd", issue = "none")] +#[cfg(not(bootstrap))] +pub const fn absurd(x: !) -> T { + x +} + /// Used to do a cheap reference-to-reference conversion. /// /// This trait is similar to [`AsMut`] which is used for converting between mutable references. From b478d2b0556151e7a3e0bc405aa1691b1e347470 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 12 Mar 2024 23:02:18 +0000 Subject: [PATCH 2/3] Stop skewing inference in `?`'s desugaring --- compiler/rustc_ast_lowering/src/expr.rs | 30 ++++++++++++++----- compiler/rustc_ast_lowering/src/lib.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + .../issue-67765-async-diagnostic.rs | 2 +- .../issue-67765-async-diagnostic.stderr | 4 +-- tests/ui/consts/try-operator.rs | 4 +-- tests/ui/consts/try-operator.stderr | 16 +++++----- .../did_you_mean/compatible-variants.stderr | 2 -- .../impl-trait/cross-return-site-inference.rs | 10 +++---- tests/ui/inference/cannot-infer-closure.rs | 2 +- ...1632-try-desugar-incompatible-types.stderr | 2 -- .../label_break_value_desugared_break.rs | 4 +-- tests/ui/parser/try-with-nonterminal-block.rs | 2 +- .../remove-question-symbol-with-paren.stderr | 3 -- tests/ui/suggestions/suggest-box.fixed | 2 +- tests/ui/suggestions/suggest-box.rs | 2 +- tests/ui/suggestions/suggest-box.stderr | 4 +-- tests/ui/try-block/try-block-bad-lifetime.rs | 10 +++---- .../try-block/try-block-bad-lifetime.stderr | 12 ++++---- .../try-block/try-block-maybe-bad-lifetime.rs | 6 ++-- tests/ui/try-block/try-block-opt-init.rs | 2 +- tests/ui/try-block/try-block.rs | 21 ++++++++----- 22 files changed, 80 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 389cf4e313216..4e7476e4e6c61 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1758,9 +1758,9 @@ impl<'hir> LoweringContext<'_, 'hir> { /// ControlFlow::Break(residual) => /// #[allow(unreachable_code)] /// // If there is an enclosing `try {...}`: - /// break 'catch_target Try::from_residual(residual), + /// absurd(break 'catch_target Try::from_residual(residual)), /// // Otherwise: - /// return Try::from_residual(residual), + /// absurd(return Try::from_residual(residual)), /// } /// ``` fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir> { @@ -1769,6 +1769,13 @@ impl<'hir> LoweringContext<'_, 'hir> { span, Some(self.allow_try_trait.clone()), ); + + let absurd_allowed_span = self.mark_span_with_reason( + DesugaringKind::QuestionMark, + span, + Some(self.allow_convert_absurd.clone()), + ); + let try_span = self.tcx.sess.source_map().end_point(span); let try_span = self.mark_span_with_reason( DesugaringKind::QuestionMark, @@ -1810,7 +1817,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // `ControlFlow::Break(residual) => // #[allow(unreachable_code)] - // return Try::from_residual(residual),` + // absurd(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); @@ -1823,20 +1830,27 @@ impl<'hir> LoweringContext<'_, 'hir> { ); let ret_expr = if let Some(catch_node) = self.catch_scope { let target_id = Ok(self.lower_node_id(catch_node)); - self.arena.alloc(self.expr( + self.expr( try_span, hir::ExprKind::Break( hir::Destination { label: None, target_id }, Some(from_residual_expr), ), - )) + ) } else { - self.arena.alloc(self.expr(try_span, hir::ExprKind::Ret(Some(from_residual_expr)))) + self.expr(try_span, hir::ExprKind::Ret(Some(from_residual_expr))) }; - self.lower_attrs(ret_expr.hir_id, &attrs); + + let absurd_expr = self.expr_call_lang_item_fn( + absurd_allowed_span, + hir::LangItem::Absurd, + arena_vec![self; ret_expr], + ); + + self.lower_attrs(absurd_expr.hir_id, &attrs); let break_pat = self.pat_cf_break(try_span, residual_local); - self.arm(break_pat, ret_expr) + self.arm(break_pat, absurd_expr) }; hir::ExprKind::Match( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 833b0e9b5679e..90be5ffff4c2a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -130,6 +130,7 @@ struct LoweringContext<'a, 'hir> { node_id_to_local_id: NodeMap, allow_try_trait: Lrc<[Symbol]>, + allow_convert_absurd: Lrc<[Symbol]>, allow_gen_future: Lrc<[Symbol]>, allow_async_iterator: Lrc<[Symbol]>, allow_for_await: Lrc<[Symbol]>, @@ -173,6 +174,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { impl_trait_defs: Vec::new(), impl_trait_bounds: Vec::new(), allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(), + allow_convert_absurd: [sym::convert_absurd].into(), allow_gen_future: if tcx.features().async_fn_track_caller { [sym::gen_future, sym::closure_track_caller].into() } else { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 727a292b0e782..4b2b02493a798 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -602,6 +602,7 @@ symbols! { const_try, constant, constructor, + convert_absurd, convert_identity, copy, copy_closures, diff --git a/tests/ui/async-await/issue-67765-async-diagnostic.rs b/tests/ui/async-await/issue-67765-async-diagnostic.rs index 7fe1baef952e1..20bf543d24667 100644 --- a/tests/ui/async-await/issue-67765-async-diagnostic.rs +++ b/tests/ui/async-await/issue-67765-async-diagnostic.rs @@ -10,7 +10,7 @@ async fn func<'a>() -> Result<(), &'a str> { let b = &s[..]; - Err(b)?; //~ ERROR cannot return value referencing local variable `s` + Err::<(), _>(b)?; //~ ERROR cannot return value referencing local variable `s` Ok(()) } diff --git a/tests/ui/async-await/issue-67765-async-diagnostic.stderr b/tests/ui/async-await/issue-67765-async-diagnostic.stderr index 833df51a7aac8..31f3fc57b19b3 100644 --- a/tests/ui/async-await/issue-67765-async-diagnostic.stderr +++ b/tests/ui/async-await/issue-67765-async-diagnostic.stderr @@ -4,8 +4,8 @@ error[E0515]: cannot return value referencing local variable `s` LL | let b = &s[..]; | - `s` is borrowed here LL | -LL | Err(b)?; - | ^^^^^^^ returns a value referencing data owned by the current function +LL | Err::<(), _>(b)?; + | ^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function error: aborting due to 1 previous error diff --git a/tests/ui/consts/try-operator.rs b/tests/ui/consts/try-operator.rs index 352dbeefa8a60..87b5531af8612 100644 --- a/tests/ui/consts/try-operator.rs +++ b/tests/ui/consts/try-operator.rs @@ -7,7 +7,7 @@ fn main() { const fn result() -> Result { - Err(())?; + Err::<(), _>(())?; Ok(true) } @@ -15,7 +15,7 @@ fn main() { assert_eq!(Err(()), FOO); const fn option() -> Option<()> { - None?; + None::<()>?; Some(()) } const BAR: Option<()> = option(); diff --git a/tests/ui/consts/try-operator.stderr b/tests/ui/consts/try-operator.stderr index 2c8b4c7fcd9cb..6176cefe81ad9 100644 --- a/tests/ui/consts/try-operator.stderr +++ b/tests/ui/consts/try-operator.stderr @@ -7,8 +7,8 @@ LL | #![feature(const_convert)] error[E0015]: `?` cannot determine the branch of `Result<(), ()>` in constant functions --> $DIR/try-operator.rs:10:9 | -LL | Err(())?; - | ^^^^^^^^ +LL | Err::<(), _>(())?; + | ^^^^^^^^^^^^^^^^^ | note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/result.rs:LL:COL @@ -21,8 +21,8 @@ LL + #![feature(effects)] error[E0015]: `?` cannot convert from residual of `Result` in constant functions --> $DIR/try-operator.rs:10:9 | -LL | Err(())?; - | ^^^^^^^^ +LL | Err::<(), _>(())?; + | ^^^^^^^^^^^^^^^^^ | note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/result.rs:LL:COL @@ -35,8 +35,8 @@ LL + #![feature(effects)] error[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions --> $DIR/try-operator.rs:18:9 | -LL | None?; - | ^^^^^ +LL | None::<()>?; + | ^^^^^^^^^^^ | note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/option.rs:LL:COL @@ -49,8 +49,8 @@ LL + #![feature(effects)] error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions --> $DIR/try-operator.rs:18:9 | -LL | None?; - | ^^^^^ +LL | None::<()>?; + | ^^^^^^^^^^^ | note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/option.rs:LL:COL diff --git a/tests/ui/did_you_mean/compatible-variants.stderr b/tests/ui/did_you_mean/compatible-variants.stderr index f2bbd8ced8f24..7b88d93ead112 100644 --- a/tests/ui/did_you_mean/compatible-variants.stderr +++ b/tests/ui/did_you_mean/compatible-variants.stderr @@ -61,8 +61,6 @@ LL + Some(()) error[E0308]: `?` operator has incompatible types --> $DIR/compatible-variants.rs:35:5 | -LL | fn d() -> Option<()> { - | ---------- expected `Option<()>` because of return type LL | c()? | ^^^^ expected `Option<()>`, found `()` | diff --git a/tests/ui/impl-trait/cross-return-site-inference.rs b/tests/ui/impl-trait/cross-return-site-inference.rs index bed08a6c4186e..a0491ab0eebea 100644 --- a/tests/ui/impl-trait/cross-return-site-inference.rs +++ b/tests/ui/impl-trait/cross-return-site-inference.rs @@ -2,34 +2,34 @@ fn foo(b: bool) -> impl std::fmt::Debug { if b { - return vec![42] + return vec![42]; } [].into_iter().collect() } fn bar(b: bool) -> impl std::fmt::Debug { if b { - return [].into_iter().collect() + return [].into_iter().collect(); } vec![42] } fn bak(b: bool) -> impl std::fmt::Debug { if b { - return std::iter::empty().collect() + return std::iter::empty().collect(); } vec![42] } fn baa(b: bool) -> impl std::fmt::Debug { if b { - return [42].into_iter().collect() + return [42].into_iter().collect(); } vec![] } fn muh() -> Result<(), impl std::fmt::Debug> { - Err("whoops")?; + Err::<(), _>("whoops")?; Ok(()) //~^ ERROR type annotations needed } diff --git a/tests/ui/inference/cannot-infer-closure.rs b/tests/ui/inference/cannot-infer-closure.rs index bd5d10b417342..183ef9abd89f0 100644 --- a/tests/ui/inference/cannot-infer-closure.rs +++ b/tests/ui/inference/cannot-infer-closure.rs @@ -1,6 +1,6 @@ fn main() { let x = |a: (), b: ()| { - Err(a)?; + Err::<(), _>(a)?; Ok(b) //~^ ERROR type annotations needed }; diff --git a/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr b/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr index 99fce1eeea6f6..72f05088dbaf0 100644 --- a/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr +++ b/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr @@ -1,8 +1,6 @@ error[E0308]: `?` operator has incompatible types --> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5 | -LL | fn forbidden_narratives() -> Result { - | ----------------- expected `Result` because of return type LL | missing_discourses()? | ^^^^^^^^^^^^^^^^^^^^^ expected `Result`, found `isize` | diff --git a/tests/ui/label/label_break_value_desugared_break.rs b/tests/ui/label/label_break_value_desugared_break.rs index b7e7fd47c27f3..aac459102ef7d 100644 --- a/tests/ui/label/label_break_value_desugared_break.rs +++ b/tests/ui/label/label_break_value_desugared_break.rs @@ -5,14 +5,14 @@ fn main() { let _: Result<(), ()> = try { 'foo: { - Err(())?; + Err::<(), _>(())?; break 'foo; } }; 'foo: { let _: Result<(), ()> = try { - Err(())?; + Err::<(), _>(())?; break 'foo; }; } diff --git a/tests/ui/parser/try-with-nonterminal-block.rs b/tests/ui/parser/try-with-nonterminal-block.rs index bc52dcd0e01d3..0648b047518ec 100644 --- a/tests/ui/parser/try-with-nonterminal-block.rs +++ b/tests/ui/parser/try-with-nonterminal-block.rs @@ -11,7 +11,7 @@ macro_rules! create_try { fn main() { let x: Option<&str> = create_try! {{ - None?; + None::<()>?; "Hello world" }}; diff --git a/tests/ui/suggestions/remove-question-symbol-with-paren.stderr b/tests/ui/suggestions/remove-question-symbol-with-paren.stderr index bdea727a09816..f142f8875e5ab 100644 --- a/tests/ui/suggestions/remove-question-symbol-with-paren.stderr +++ b/tests/ui/suggestions/remove-question-symbol-with-paren.stderr @@ -1,9 +1,6 @@ error[E0308]: `?` operator has incompatible types --> $DIR/remove-question-symbol-with-paren.rs:5:6 | -LL | fn foo() -> Option<()> { - | ---------- expected `Option<()>` because of return type -LL | let x = Some(()); LL | (x?) | ^^ expected `Option<()>`, found `()` | diff --git a/tests/ui/suggestions/suggest-box.fixed b/tests/ui/suggestions/suggest-box.fixed index 7cd62c4318347..112b2a00578dc 100644 --- a/tests/ui/suggestions/suggest-box.fixed +++ b/tests/ui/suggestions/suggest-box.fixed @@ -2,7 +2,7 @@ fn main() { let _x: Box Result<(), ()>> = Box::new(|| { //~ ERROR mismatched types - Err(())?; + Err::<(), _>(())?; Ok(()) }); } diff --git a/tests/ui/suggestions/suggest-box.rs b/tests/ui/suggestions/suggest-box.rs index c31320c548594..39b7b7407ce6c 100644 --- a/tests/ui/suggestions/suggest-box.rs +++ b/tests/ui/suggestions/suggest-box.rs @@ -2,7 +2,7 @@ fn main() { let _x: Box Result<(), ()>> = || { //~ ERROR mismatched types - Err(())?; + Err::<(), _>(())?; Ok(()) }; } diff --git a/tests/ui/suggestions/suggest-box.stderr b/tests/ui/suggestions/suggest-box.stderr index 58f8774fe9ddd..f5ecc663a2906 100644 --- a/tests/ui/suggestions/suggest-box.stderr +++ b/tests/ui/suggestions/suggest-box.stderr @@ -5,7 +5,7 @@ LL | let _x: Box Result<(), ()>> = || { | _____________-------------------------------___^ | | | | | expected due to this -LL | | Err(())?; +LL | | Err::<(), _>(())?; LL | | Ok(()) LL | | }; | |_____^ expected `Box Result<(), ()>>`, found closure @@ -16,7 +16,7 @@ LL | | }; help: store this in the heap by calling `Box::new` | LL ~ let _x: Box Result<(), ()>> = Box::new(|| { -LL | Err(())?; +LL | Err::<(), _>(())?; LL | Ok(()) LL ~ }); | diff --git a/tests/ui/try-block/try-block-bad-lifetime.rs b/tests/ui/try-block/try-block-bad-lifetime.rs index bfff757a2df63..560eee44862df 100644 --- a/tests/ui/try-block/try-block-bad-lifetime.rs +++ b/tests/ui/try-block/try-block-bad-lifetime.rs @@ -12,10 +12,10 @@ pub fn main() { // result variable let result: Result<(), &str> = try { let my_string = String::from(""); - let my_str: & str = & my_string; + let my_str: &str = &my_string; //~^ ERROR `my_string` does not live long enough - Err(my_str) ?; - Err("") ?; + Err::<(), _>(my_str)?; + Err::<(), _>("")?; }; do_something_with(result); } @@ -25,13 +25,13 @@ pub fn main() { let mut i = 5; let k = &mut i; let mut j: Result<(), &mut i32> = try { - Err(k) ?; + Err::<(), _>(k)?; i = 10; //~ ERROR cannot assign to `i` because it is borrowed }; ::std::mem::drop(k); //~ ERROR use of moved value: `k` i = 40; //~ ERROR cannot assign to `i` because it is borrowed - let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") }; + let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic!("") }; *i_ptr = 50; } } diff --git a/tests/ui/try-block/try-block-bad-lifetime.stderr b/tests/ui/try-block/try-block-bad-lifetime.stderr index 28941cb0a9e40..eb0787b33979a 100644 --- a/tests/ui/try-block/try-block-bad-lifetime.stderr +++ b/tests/ui/try-block/try-block-bad-lifetime.stderr @@ -1,12 +1,12 @@ error[E0597]: `my_string` does not live long enough - --> $DIR/try-block-bad-lifetime.rs:15:33 + --> $DIR/try-block-bad-lifetime.rs:15:32 | LL | let result: Result<(), &str> = try { | ------ borrow later stored here LL | let my_string = String::from(""); | --------- binding `my_string` declared here -LL | let my_str: & str = & my_string; - | ^^^^^^^^^^^ borrowed value does not live long enough +LL | let my_str: &str = &my_string; + | ^^^^^^^^^^ borrowed value does not live long enough ... LL | }; | - `my_string` dropped here while still borrowed @@ -29,8 +29,8 @@ error[E0382]: use of moved value: `k` LL | let k = &mut i; | - move occurs because `k` has type `&mut i32`, which does not implement the `Copy` trait LL | let mut j: Result<(), &mut i32> = try { -LL | Err(k) ?; - | - value moved here +LL | Err::<(), _>(k)?; + | - value moved here ... LL | ::std::mem::drop(k); | ^ value used here after move @@ -44,7 +44,7 @@ LL | let k = &mut i; LL | i = 40; | ^^^^^^ `i` is assigned to here but it was already borrowed LL | -LL | let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") }; +LL | let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic!("") }; | - borrow later used here error: aborting due to 4 previous errors diff --git a/tests/ui/try-block/try-block-maybe-bad-lifetime.rs b/tests/ui/try-block/try-block-maybe-bad-lifetime.rs index 52ec0c44a059c..e339f724b5926 100644 --- a/tests/ui/try-block/try-block-maybe-bad-lifetime.rs +++ b/tests/ui/try-block/try-block-maybe-bad-lifetime.rs @@ -11,7 +11,7 @@ pub fn main() { // Test that a borrow which *might* be returned still freezes its referent let mut i = 222; let x: Result<&i32, ()> = try { - Err(())?; + Err::<(), _>(())?; &i }; i = 0; //~ ERROR cannot assign to `i` because it is borrowed @@ -22,7 +22,7 @@ pub fn main() { { let x = String::new(); let _y: Result<(), ()> = try { - Err(())?; + Err::<(), _>(())?; ::std::mem::drop(x); }; println!("{}", x); //~ ERROR borrow of moved value: `x` @@ -34,7 +34,7 @@ pub fn main() { let mut i = 222; let mut j = &-1; let _x: Result<(), ()> = try { - Err(())?; + Err::<(), _>(())?; j = &i; }; i = 0; //~ ERROR cannot assign to `i` because it is borrowed diff --git a/tests/ui/try-block/try-block-opt-init.rs b/tests/ui/try-block/try-block-opt-init.rs index fbe7f90d03039..7dc635de468af 100644 --- a/tests/ui/try-block/try-block-opt-init.rs +++ b/tests/ui/try-block/try-block-opt-init.rs @@ -7,7 +7,7 @@ fn use_val(_x: T) {} pub fn main() { let cfg_res; let _: Result<(), ()> = try { - Err(())?; + Err::<(), _>(())?; cfg_res = 5; Ok::<(), ()>(())?; use_val(cfg_res); diff --git a/tests/ui/try-block/try-block.rs b/tests/ui/try-block/try-block.rs index 7520cbaad378e..b7a68638d26ec 100644 --- a/tests/ui/try-block/try-block.rs +++ b/tests/ui/try-block/try-block.rs @@ -3,7 +3,6 @@ #![allow(non_camel_case_types)] #![allow(dead_code)] //@ compile-flags: --edition 2018 - #![feature(try_blocks)] struct catch {} @@ -16,7 +15,9 @@ pub fn main() { assert_eq!(catch_result, Some(5)); let mut catch = true; - while catch { catch = false; } + while catch { + catch = false; + } assert_eq!(catch, false); catch = if catch { false } else { true }; @@ -27,13 +28,15 @@ pub fn main() { }; let catch_err: Result<_, i32> = try { - Err(22)?; + Err::<(), _>(22)?; 1 }; assert_eq!(catch_err, Err(22)); let catch_okay: Result = try { - if false { Err(25)?; } + if false { + Err::<(), _>(25)?; + } Ok::<(), i32>(())?; 28 }; @@ -41,7 +44,11 @@ pub fn main() { let catch_from_loop: Result = try { for i in 0..10 { - if i < 5 { Ok::(i)?; } else { Err(i)?; } + if i < 5 { + Ok::(i)?; + } else { + Err::<(), _>(i)?; + } } 22 }; @@ -56,7 +63,7 @@ pub fn main() { let cfg_init_2; let _res: Result<(), ()> = try { cfg_init_2 = 6; - Err(())?; + Err::<(), _>(())?; }; assert_eq!(cfg_init_2, 6); @@ -70,6 +77,6 @@ pub fn main() { let my_opt: Option<_> = try { () }; assert_eq!(my_opt, Some(())); - let my_opt: Option<_> = try { }; + let my_opt: Option<_> = try {}; assert_eq!(my_opt, Some(())); } From 9cd668cc5c152520a2a8acbc6fcb16213e5bccc3 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 4 Apr 2024 16:12:50 +0000 Subject: [PATCH 3/3] disable `cargo-0.60.0`-based PGO Old cargo has `Err()?`-kind of looking code, which fails `bors try`. This is a band-aid for a crater run, we should find a way to keep PGO (do we just update the cargo version used?...) --- src/tools/opt-dist/src/training.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs index 46040e32a0399..5ded6ceb4f807 100644 --- a/src/tools/opt-dist/src/training.rs +++ b/src/tools/opt-dist/src/training.rs @@ -8,7 +8,7 @@ use humansize::BINARY; const LLVM_PGO_CRATES: &[&str] = &[ "syn-1.0.89", - "cargo-0.60.0", + //"cargo-0.60.0", "serde-1.0.136", "ripgrep-13.0.0", "regex-1.5.5", @@ -19,7 +19,7 @@ const LLVM_PGO_CRATES: &[&str] = &[ const RUSTC_PGO_CRATES: &[&str] = &[ "externs", "ctfe-stress-5", - "cargo-0.60.0", + //"cargo-0.60.0", "token-stream-stress", "match-stress", "tuple-stress",