Experimentally add *heterogeneous* try blocks
148725 moved the default to being homogeneous; this adds heterogeneous ones back under an obvious-bikeshed syntax so people can experiment with that as well. Essentially resolves 149025 by letting them move to this syntax instead.
This commit is contained in:
parent
ba2142a19c
commit
4033d19b79
21 changed files with 278 additions and 59 deletions
|
|
@ -1806,8 +1806,14 @@ pub enum ExprKind {
|
|||
/// A use expression (`x.use`). Span is of use keyword.
|
||||
Use(Box<Expr>, Span),
|
||||
|
||||
/// A try block (`try { ... }`).
|
||||
TryBlock(Box<Block>),
|
||||
/// A try block (`try { ... }`), if the type is `None`, or
|
||||
/// A try block (`try bikeshed Ty { ... }`) if the type is `Some`.
|
||||
///
|
||||
/// Note that `try bikeshed` is a *deliberately ridiculous* placeholder
|
||||
/// syntax to avoid deciding what keyword or symbol should go there.
|
||||
/// It's that way for experimentation only; an RFC to decide the final
|
||||
/// semantics and syntax would be needed to put it on stabilization-track.
|
||||
TryBlock(Box<Block>, Option<Box<Ty>>),
|
||||
|
||||
/// An assignment (`a = foo()`).
|
||||
/// The `Span` argument is the span of the `=` token.
|
||||
|
|
|
|||
|
|
@ -1048,8 +1048,8 @@ macro_rules! common_visitor_and_walkers {
|
|||
visit_visitable!($($mut)? vis, kind),
|
||||
ExprKind::Try(subexpression) =>
|
||||
visit_visitable!($($mut)? vis, subexpression),
|
||||
ExprKind::TryBlock(body) =>
|
||||
visit_visitable!($($mut)? vis, body),
|
||||
ExprKind::TryBlock(body, optional_type) =>
|
||||
visit_visitable!($($mut)? vis, body, optional_type),
|
||||
ExprKind::Lit(token) =>
|
||||
visit_visitable!($($mut)? vis, token),
|
||||
ExprKind::IncludedBytes(bytes) =>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::mem;
|
||||
use std::ops::ControlFlow;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
|
@ -27,7 +28,9 @@ use super::{
|
|||
GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt,
|
||||
};
|
||||
use crate::errors::{InvalidLegacyConstGenericArg, UseConstGenericArg, YieldInClosure};
|
||||
use crate::{AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, fluent_generated};
|
||||
use crate::{
|
||||
AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, TryBlockScope, fluent_generated,
|
||||
};
|
||||
|
||||
struct WillCreateDefIdsVisitor {}
|
||||
|
||||
|
|
@ -199,7 +202,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
)
|
||||
})
|
||||
}
|
||||
ExprKind::TryBlock(body) => self.lower_expr_try_block(body),
|
||||
ExprKind::TryBlock(body, opt_ty) => {
|
||||
self.lower_expr_try_block(body, opt_ty.as_deref())
|
||||
}
|
||||
ExprKind::Match(expr, arms, kind) => hir::ExprKind::Match(
|
||||
self.lower_expr(expr),
|
||||
self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
|
||||
|
|
@ -562,9 +567,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
/// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`,
|
||||
/// `try { <stmts>; }` into `{ <stmts>; ::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> {
|
||||
fn lower_expr_try_block(&mut self, body: &Block, opt_ty: Option<&Ty>) -> hir::ExprKind<'hir> {
|
||||
let body_hir_id = self.lower_node_id(body.id);
|
||||
self.with_catch_scope(body_hir_id, |this| {
|
||||
let new_scope = if opt_ty.is_some() {
|
||||
TryBlockScope::Heterogeneous(body_hir_id)
|
||||
} else {
|
||||
TryBlockScope::Homogeneous(body_hir_id)
|
||||
};
|
||||
let whole_block = self.with_try_block_scope(new_scope, |this| {
|
||||
let mut block = this.lower_block_noalloc(body_hir_id, body, true);
|
||||
|
||||
// Final expression of the block (if present) or `()` with span at the end of block
|
||||
|
|
@ -598,8 +608,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ok_wrapped_span,
|
||||
));
|
||||
|
||||
hir::ExprKind::Block(this.arena.alloc(block), None)
|
||||
})
|
||||
this.arena.alloc(block)
|
||||
});
|
||||
|
||||
if let Some(ty) = opt_ty {
|
||||
let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Path));
|
||||
let block_expr = self.arena.alloc(self.expr_block(whole_block));
|
||||
hir::ExprKind::Type(block_expr, ty)
|
||||
} else {
|
||||
hir::ExprKind::Block(whole_block, None)
|
||||
}
|
||||
}
|
||||
|
||||
fn wrap_in_try_constructor(
|
||||
|
|
@ -1617,10 +1635,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
fn with_catch_scope<T>(&mut self, catch_id: hir::HirId, f: impl FnOnce(&mut Self) -> T) -> T {
|
||||
let old_scope = self.catch_scope.replace(catch_id);
|
||||
fn with_try_block_scope<T>(
|
||||
&mut self,
|
||||
scope: TryBlockScope,
|
||||
f: impl FnOnce(&mut Self) -> T,
|
||||
) -> T {
|
||||
let old_scope = mem::replace(&mut self.try_block_scope, scope);
|
||||
let result = f(self);
|
||||
self.catch_scope = old_scope;
|
||||
self.try_block_scope = old_scope;
|
||||
result
|
||||
}
|
||||
|
||||
|
|
@ -1978,18 +2000,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
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 (constructor_item, target_id) = match self.try_block_scope {
|
||||
TryBlockScope::Function => {
|
||||
(hir::LangItem::TryTraitFromResidual, Err(hir::LoopIdError::OutsideLoopScope))
|
||||
}
|
||||
TryBlockScope::Homogeneous(block_id) => {
|
||||
(hir::LangItem::ResidualIntoTryType, Ok(block_id))
|
||||
}
|
||||
TryBlockScope::Heterogeneous(block_id) => {
|
||||
(hir::LangItem::TryTraitFromResidual, Ok(block_id))
|
||||
}
|
||||
};
|
||||
let from_residual_expr = self.wrap_in_try_constructor(
|
||||
if self.catch_scope.is_some() {
|
||||
hir::LangItem::ResidualIntoTryType
|
||||
} else {
|
||||
hir::LangItem::TryTraitFromResidual
|
||||
},
|
||||
constructor_item,
|
||||
try_span,
|
||||
self.arena.alloc(residual_expr),
|
||||
unstable_span,
|
||||
);
|
||||
let ret_expr = if let Some(catch_id) = self.catch_scope {
|
||||
let target_id = Ok(catch_id);
|
||||
let ret_expr = if target_id.is_ok() {
|
||||
self.arena.alloc(self.expr(
|
||||
try_span,
|
||||
hir::ExprKind::Break(
|
||||
|
|
@ -2044,11 +2073,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
yeeted_span,
|
||||
);
|
||||
|
||||
if let Some(catch_id) = self.catch_scope {
|
||||
let target_id = Ok(catch_id);
|
||||
hir::ExprKind::Break(hir::Destination { label: None, target_id }, Some(from_yeet_expr))
|
||||
} else {
|
||||
self.checked_return(Some(from_yeet_expr))
|
||||
match self.try_block_scope {
|
||||
TryBlockScope::Homogeneous(block_id) | TryBlockScope::Heterogeneous(block_id) => {
|
||||
hir::ExprKind::Break(
|
||||
hir::Destination { label: None, target_id: Ok(block_id) },
|
||||
Some(from_yeet_expr),
|
||||
)
|
||||
}
|
||||
TryBlockScope::Function => self.checked_return(Some(from_yeet_expr)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#![feature(if_let_guard)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::node_id::NodeMap;
|
||||
|
|
@ -117,7 +118,7 @@ struct LoweringContext<'a, 'hir> {
|
|||
/// outside of an `async fn`.
|
||||
current_item: Option<Span>,
|
||||
|
||||
catch_scope: Option<HirId>,
|
||||
try_block_scope: TryBlockScope,
|
||||
loop_scope: Option<HirId>,
|
||||
is_in_loop_condition: bool,
|
||||
is_in_dyn_type: bool,
|
||||
|
|
@ -173,7 +174,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
trait_map: Default::default(),
|
||||
|
||||
// Lowering state.
|
||||
catch_scope: None,
|
||||
try_block_scope: TryBlockScope::Function,
|
||||
loop_scope: None,
|
||||
is_in_loop_condition: false,
|
||||
is_in_dyn_type: false,
|
||||
|
|
@ -423,6 +424,18 @@ enum AstOwner<'a> {
|
|||
ForeignItem(&'a ast::ForeignItem),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum TryBlockScope {
|
||||
/// There isn't a `try` block, so a `?` will use `return`.
|
||||
Function,
|
||||
/// We're inside a `try { … }` block, so a `?` will block-break
|
||||
/// from that block using a type depending only on the argument.
|
||||
Homogeneous(HirId),
|
||||
/// We're inside a `try as _ { … }` block, so a `?` will block-break
|
||||
/// from that block using the type specified.
|
||||
Heterogeneous(HirId),
|
||||
}
|
||||
|
||||
fn index_crate<'a>(
|
||||
node_id_to_def_id: &NodeMap<LocalDefId>,
|
||||
krate: &'a Crate,
|
||||
|
|
@ -943,10 +956,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
let old_contract = self.contract_ensures.take();
|
||||
|
||||
let catch_scope = self.catch_scope.take();
|
||||
let try_block_scope = mem::replace(&mut self.try_block_scope, TryBlockScope::Function);
|
||||
let loop_scope = self.loop_scope.take();
|
||||
let ret = f(self);
|
||||
self.catch_scope = catch_scope;
|
||||
self.try_block_scope = try_block_scope;
|
||||
self.loop_scope = loop_scope;
|
||||
|
||||
self.contract_ensures = old_contract;
|
||||
|
|
|
|||
|
|
@ -339,9 +339,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
|
||||
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||
match e.kind {
|
||||
ast::ExprKind::TryBlock(_) => {
|
||||
ast::ExprKind::TryBlock(_, None) => {
|
||||
gate!(&self, try_blocks, e.span, "`try` expression is experimental");
|
||||
}
|
||||
ast::ExprKind::TryBlock(_, Some(_)) => {
|
||||
gate!(
|
||||
&self,
|
||||
try_blocks_heterogeneous,
|
||||
e.span,
|
||||
"`try bikeshed` expression is experimental"
|
||||
);
|
||||
}
|
||||
ast::ExprKind::Lit(token::Lit {
|
||||
kind: token::LitKind::Float | token::LitKind::Integer,
|
||||
suffix,
|
||||
|
|
|
|||
|
|
@ -818,10 +818,15 @@ impl<'a> State<'a> {
|
|||
);
|
||||
self.word("?")
|
||||
}
|
||||
ast::ExprKind::TryBlock(blk) => {
|
||||
ast::ExprKind::TryBlock(blk, opt_ty) => {
|
||||
let cb = self.cbox(0);
|
||||
let ib = self.ibox(0);
|
||||
self.word_nbsp("try");
|
||||
if let Some(ty) = opt_ty {
|
||||
self.word_nbsp("bikeshed");
|
||||
self.print_type(ty);
|
||||
self.space();
|
||||
}
|
||||
self.print_block_with_attrs(blk, attrs, cb, ib)
|
||||
}
|
||||
ast::ExprKind::UnsafeBinderCast(kind, expr, ty) => {
|
||||
|
|
|
|||
|
|
@ -315,7 +315,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
| ExprKind::Path(_, _)
|
||||
| ExprKind::Ret(_)
|
||||
| ExprKind::Try(_)
|
||||
| ExprKind::TryBlock(_)
|
||||
| ExprKind::TryBlock(_, _)
|
||||
| ExprKind::Type(_, _)
|
||||
| ExprKind::Underscore
|
||||
| ExprKind::While(_, _, _)
|
||||
|
|
|
|||
|
|
@ -663,6 +663,8 @@ declare_features! (
|
|||
(unstable, trivial_bounds, "1.28.0", Some(48214)),
|
||||
/// Allows using `try {...}` expressions.
|
||||
(unstable, try_blocks, "1.29.0", Some(31436)),
|
||||
/// Allows using `try bikeshed TargetType {...}` expressions.
|
||||
(unstable, try_blocks_heterogeneous, "CURRENT_RUSTC_VERSION", Some(149488)),
|
||||
/// 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
|
||||
|
|
|
|||
|
|
@ -3544,15 +3544,20 @@ impl<'a> Parser<'a> {
|
|||
self.token.is_keyword(kw::Builtin) && self.look_ahead(1, |t| *t == token::Pound)
|
||||
}
|
||||
|
||||
/// Parses a `try {...}` expression (`try` token already eaten).
|
||||
/// Parses a `try {...}` or `try bikeshed Ty {...}` expression (`try` token already eaten).
|
||||
fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, Box<Expr>> {
|
||||
let annotation =
|
||||
if self.eat_keyword(exp!(Bikeshed)) { Some(self.parse_ty()?) } else { None };
|
||||
|
||||
let (attrs, body) = self.parse_inner_attrs_and_block(None)?;
|
||||
if self.eat_keyword(exp!(Catch)) {
|
||||
Err(self.dcx().create_err(errors::CatchAfterTry { span: self.prev_token.span }))
|
||||
} else {
|
||||
let span = span_lo.to(body.span);
|
||||
self.psess.gated_spans.gate(sym::try_blocks, span);
|
||||
Ok(self.mk_expr_with_attrs(span, ExprKind::TryBlock(body), attrs))
|
||||
let gate_sym =
|
||||
if annotation.is_none() { sym::try_blocks } else { sym::try_blocks_heterogeneous };
|
||||
self.psess.gated_spans.gate(gate_sym, span);
|
||||
Ok(self.mk_expr_with_attrs(span, ExprKind::TryBlock(body, annotation), attrs))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3569,7 +3574,11 @@ impl<'a> Parser<'a> {
|
|||
|
||||
fn is_try_block(&self) -> bool {
|
||||
self.token.is_keyword(kw::Try)
|
||||
&& self.look_ahead(1, |t| *t == token::OpenBrace || t.is_metavar_block())
|
||||
&& self.look_ahead(1, |t| {
|
||||
*t == token::OpenBrace
|
||||
|| t.is_metavar_block()
|
||||
|| t.kind == TokenKind::Ident(sym::bikeshed, IdentIsRaw::No)
|
||||
})
|
||||
&& self.token_uninterpolated_span().at_least_rust_2018()
|
||||
}
|
||||
|
||||
|
|
@ -4264,7 +4273,7 @@ impl MutVisitor for CondChecker<'_> {
|
|||
| ExprKind::Closure(_)
|
||||
| ExprKind::Block(_, _)
|
||||
| ExprKind::Gen(_, _, _, _)
|
||||
| ExprKind::TryBlock(_)
|
||||
| ExprKind::TryBlock(_, _)
|
||||
| ExprKind::Underscore
|
||||
| ExprKind::Path(_, _)
|
||||
| ExprKind::Break(_, _)
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ pub enum TokenType {
|
|||
// Keyword-like symbols.
|
||||
// tidy-alphabetical-start
|
||||
SymAttSyntax,
|
||||
SymBikeshed,
|
||||
SymClobberAbi,
|
||||
SymInlateout,
|
||||
SymInout,
|
||||
|
|
@ -556,6 +557,7 @@ macro_rules! exp {
|
|||
(Yield) => { exp!(@kw, Yield, KwYield) };
|
||||
|
||||
(AttSyntax) => { exp!(@sym, att_syntax, SymAttSyntax) };
|
||||
(Bikeshed) => { exp!(@sym, bikeshed, SymBikeshed) };
|
||||
(ClobberAbi) => { exp!(@sym, clobber_abi, SymClobberAbi) };
|
||||
(Inlateout) => { exp!(@sym, inlateout, SymInlateout) };
|
||||
(Inout) => { exp!(@sym, inout, SymInout) };
|
||||
|
|
|
|||
|
|
@ -572,6 +572,7 @@ symbols! {
|
|||
begin_panic,
|
||||
bench,
|
||||
bevy_ecs,
|
||||
bikeshed,
|
||||
bikeshed_guaranteed_no_drop,
|
||||
bin,
|
||||
binaryheap_iter,
|
||||
|
|
@ -2284,6 +2285,7 @@ symbols! {
|
|||
truncf64,
|
||||
truncf128,
|
||||
try_blocks,
|
||||
try_blocks_heterogeneous,
|
||||
try_capture,
|
||||
try_from,
|
||||
try_from_fn,
|
||||
|
|
|
|||
6
tests/pretty/try-blocks.rs
Normal file
6
tests/pretty/try-blocks.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
//@ pp-exact
|
||||
//@ edition: 2024
|
||||
|
||||
#![feature(try_blocks, try_blocks_heterogeneous)]
|
||||
|
||||
fn main() { try { Some(1)? }; try bikeshed Result<u32, ()> { 3 }; }
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
//@ edition: 2018
|
||||
|
||||
pub fn main() {
|
||||
let try_result = try bikeshed Option<_> { //~ ERROR `try bikeshed` expression is experimental
|
||||
let x = 5;
|
||||
x
|
||||
};
|
||||
assert_eq!(try_result, Some(5));
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
error[E0658]: `try bikeshed` expression is experimental
|
||||
--> $DIR/feature-gate-try_blocks_heterogeneous.rs:4:22
|
||||
|
|
||||
LL | let try_result = try bikeshed Option<_> {
|
||||
| ______________________^
|
||||
LL | | let x = 5;
|
||||
LL | | x
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
= note: see issue #149488 <https://github.com/rust-lang/rust/issues/149488> for more information
|
||||
= help: add `#![feature(try_blocks_heterogeneous)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
21
tests/ui/try-block/try-block-bad-type-heterogeneous.rs
Normal file
21
tests/ui/try-block/try-block-bad-type-heterogeneous.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//@ edition: 2018
|
||||
|
||||
#![feature(try_blocks_heterogeneous)]
|
||||
|
||||
pub fn main() {
|
||||
let res = try bikeshed Result<u32, std::array::TryFromSliceError> {
|
||||
Err("")?; //~ ERROR `?` couldn't convert the error
|
||||
5
|
||||
};
|
||||
|
||||
let res = try bikeshed Result<i32, i32> {
|
||||
"" //~ ERROR type mismatch
|
||||
};
|
||||
|
||||
let res = try bikeshed Result<i32, i32> { }; //~ ERROR type mismatch
|
||||
|
||||
let res = try bikeshed () { };
|
||||
//~^ ERROR a `try` block must return `Result` or `Option`
|
||||
|
||||
let res = try bikeshed i32 { 5 }; //~ ERROR a `try` block must return `Result` or `Option`
|
||||
}
|
||||
46
tests/ui/try-block/try-block-bad-type-heterogeneous.stderr
Normal file
46
tests/ui/try-block/try-block-bad-type-heterogeneous.stderr
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
error[E0277]: `?` couldn't convert the error to `TryFromSliceError`
|
||||
--> $DIR/try-block-bad-type-heterogeneous.rs:7:16
|
||||
|
|
||||
LL | Err("")?;
|
||||
| -------^ the trait `From<&str>` is not implemented for `TryFromSliceError`
|
||||
| |
|
||||
| this can't be annotated with `?` because it has type `Result<_, &str>`
|
||||
|
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
help: the trait `From<&str>` is not implemented for `TryFromSliceError`
|
||||
but trait `From<Infallible>` is implemented for it
|
||||
--> $SRC_DIR/core/src/array/mod.rs:LL:COL
|
||||
= help: for that trait implementation, expected `Infallible`, found `&str`
|
||||
|
||||
error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str`
|
||||
--> $DIR/try-block-bad-type-heterogeneous.rs:12:9
|
||||
|
|
||||
LL | ""
|
||||
| ^^ expected `&str`, found `i32`
|
||||
|
||||
error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == ()`
|
||||
--> $DIR/try-block-bad-type-heterogeneous.rs:15:47
|
||||
|
|
||||
LL | let res = try bikeshed Result<i32, i32> { };
|
||||
| ^ expected `()`, found `i32`
|
||||
|
||||
error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-block-bad-type-heterogeneous.rs:17:33
|
||||
|
|
||||
LL | let res = try bikeshed () { };
|
||||
| ^ could not wrap the final value of the block as `()` doesn't implement `Try`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
|
||||
error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-block-bad-type-heterogeneous.rs:20:34
|
||||
|
|
||||
LL | let res = try bikeshed i32 { 5 };
|
||||
| ^ could not wrap the final value of the block as `i32` doesn't implement `Try`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `i32`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0277.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
19
tests/ui/try-block/try-block-heterogeneous.rs
Normal file
19
tests/ui/try-block/try-block-heterogeneous.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
//@ check-pass
|
||||
//@ edition: 2018
|
||||
|
||||
#![feature(try_blocks_heterogeneous)]
|
||||
|
||||
fn foo() -> Result<(), u16> { Ok(()) }
|
||||
|
||||
fn bar() -> Result<(), u32> { Ok(()) }
|
||||
|
||||
fn whatever() -> Result<(), String> {
|
||||
try bikeshed _ {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
try bikeshed Result<(), u64> {
|
||||
foo()?;
|
||||
bar()?;
|
||||
};
|
||||
}
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
#![feature(trace_macros)]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(try_blocks_heterogeneous)]
|
||||
#![feature(yeet_expr)]
|
||||
#![allow(incomplete_features)]
|
||||
#[macro_use]
|
||||
|
|
@ -222,7 +223,12 @@ mod expressions {
|
|||
}
|
||||
|
||||
/// ExprKind::TryBlock
|
||||
fn expr_try_block() { try {} try { return; } }
|
||||
fn expr_try_block() {
|
||||
try {}
|
||||
try { return; }
|
||||
try bikeshed Option<_> {}
|
||||
try bikeshed Option<String> { None? }
|
||||
}
|
||||
|
||||
/// ExprKind::Assign
|
||||
fn expr_assign() { let expr; expr = true; }
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
error[E0697]: closures cannot be static
|
||||
--> $DIR/exhaustive.rs:210:9
|
||||
--> $DIR/exhaustive.rs:211:9
|
||||
|
|
||||
LL | static || value;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error[E0697]: closures cannot be static
|
||||
--> $DIR/exhaustive.rs:211:9
|
||||
--> $DIR/exhaustive.rs:212:9
|
||||
|
|
||||
LL | static move || value;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||
--> $DIR/exhaustive.rs:240:13
|
||||
--> $DIR/exhaustive.rs:241:13
|
||||
|
|
||||
LL | fn expr_await() {
|
||||
| --------------- this is not `async`
|
||||
|
|
@ -20,19 +20,19 @@ LL | fut.await;
|
|||
| ^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
error: in expressions, `_` can only be used on the left-hand side of an assignment
|
||||
--> $DIR/exhaustive.rs:289:9
|
||||
--> $DIR/exhaustive.rs:292:9
|
||||
|
|
||||
LL | _;
|
||||
| ^ `_` not allowed here
|
||||
|
||||
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
|
||||
--> $DIR/exhaustive.rs:299:9
|
||||
--> $DIR/exhaustive.rs:302:9
|
||||
|
|
||||
LL | x::();
|
||||
| ^^^^^ only `Fn` traits may use parentheses
|
||||
|
||||
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
|
||||
--> $DIR/exhaustive.rs:300:9
|
||||
--> $DIR/exhaustive.rs:303:9
|
||||
|
|
||||
LL | x::(T, T) -> T;
|
||||
| ^^^^^^^^^^^^^^ only `Fn` traits may use parentheses
|
||||
|
|
@ -44,31 +44,31 @@ LL + x::<T, T> -> T;
|
|||
|
|
||||
|
||||
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
|
||||
--> $DIR/exhaustive.rs:301:9
|
||||
--> $DIR/exhaustive.rs:304:9
|
||||
|
|
||||
LL | crate::() -> ()::expressions::() -> ()::expr_path;
|
||||
| ^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses
|
||||
|
||||
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
|
||||
--> $DIR/exhaustive.rs:301:26
|
||||
--> $DIR/exhaustive.rs:304:26
|
||||
|
|
||||
LL | crate::() -> ()::expressions::() -> ()::expr_path;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses
|
||||
|
||||
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
|
||||
--> $DIR/exhaustive.rs:304:9
|
||||
--> $DIR/exhaustive.rs:307:9
|
||||
|
|
||||
LL | core::()::marker::()::PhantomData;
|
||||
| ^^^^^^^^ only `Fn` traits may use parentheses
|
||||
|
||||
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
|
||||
--> $DIR/exhaustive.rs:304:19
|
||||
--> $DIR/exhaustive.rs:307:19
|
||||
|
|
||||
LL | core::()::marker::()::PhantomData;
|
||||
| ^^^^^^^^^^ only `Fn` traits may use parentheses
|
||||
|
||||
error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
|
||||
--> $DIR/exhaustive.rs:391:9
|
||||
--> $DIR/exhaustive.rs:394:9
|
||||
|
|
||||
LL | yield;
|
||||
| ^^^^^
|
||||
|
|
@ -79,7 +79,7 @@ LL | #[coroutine] fn expr_yield() {
|
|||
| ++++++++++++
|
||||
|
||||
error[E0703]: invalid ABI: found `C++`
|
||||
--> $DIR/exhaustive.rs:471:23
|
||||
--> $DIR/exhaustive.rs:474:23
|
||||
|
|
||||
LL | unsafe extern "C++" {}
|
||||
| ^^^^^ invalid ABI
|
||||
|
|
@ -87,7 +87,7 @@ LL | unsafe extern "C++" {}
|
|||
= note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions
|
||||
|
||||
error: `..` patterns are not allowed here
|
||||
--> $DIR/exhaustive.rs:678:13
|
||||
--> $DIR/exhaustive.rs:681:13
|
||||
|
|
||||
LL | let ..;
|
||||
| ^^
|
||||
|
|
@ -95,13 +95,13 @@ LL | let ..;
|
|||
= note: only allowed in tuple, tuple struct, and slice patterns
|
||||
|
||||
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
|
||||
--> $DIR/exhaustive.rs:793:16
|
||||
--> $DIR/exhaustive.rs:796:16
|
||||
|
|
||||
LL | let _: T() -> !;
|
||||
| ^^^^^^^^ only `Fn` traits may use parentheses
|
||||
|
||||
error[E0562]: `impl Trait` is not allowed in the type of variable bindings
|
||||
--> $DIR/exhaustive.rs:807:16
|
||||
--> $DIR/exhaustive.rs:810:16
|
||||
|
|
||||
LL | let _: impl Send;
|
||||
| ^^^^^^^^^
|
||||
|
|
@ -112,7 +112,7 @@ LL | let _: impl Send;
|
|||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0562]: `impl Trait` is not allowed in the type of variable bindings
|
||||
--> $DIR/exhaustive.rs:808:16
|
||||
--> $DIR/exhaustive.rs:811:16
|
||||
|
|
||||
LL | let _: impl Send + 'static;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -123,7 +123,7 @@ LL | let _: impl Send + 'static;
|
|||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0562]: `impl Trait` is not allowed in the type of variable bindings
|
||||
--> $DIR/exhaustive.rs:809:16
|
||||
--> $DIR/exhaustive.rs:812:16
|
||||
|
|
||||
LL | let _: impl 'static + Send;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -134,7 +134,7 @@ LL | let _: impl 'static + Send;
|
|||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0562]: `impl Trait` is not allowed in the type of variable bindings
|
||||
--> $DIR/exhaustive.rs:810:16
|
||||
--> $DIR/exhaustive.rs:813:16
|
||||
|
|
||||
LL | let _: impl ?Sized;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
@ -145,7 +145,7 @@ LL | let _: impl ?Sized;
|
|||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0562]: `impl Trait` is not allowed in the type of variable bindings
|
||||
--> $DIR/exhaustive.rs:811:16
|
||||
--> $DIR/exhaustive.rs:814:16
|
||||
|
|
||||
LL | let _: impl [const] Clone;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -156,7 +156,7 @@ LL | let _: impl [const] Clone;
|
|||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0562]: `impl Trait` is not allowed in the type of variable bindings
|
||||
--> $DIR/exhaustive.rs:812:16
|
||||
--> $DIR/exhaustive.rs:815:16
|
||||
|
|
||||
LL | let _: impl for<'a> Send;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#![feature(trace_macros)]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(try_blocks_heterogeneous)]
|
||||
#![feature(yeet_expr)]
|
||||
#![allow(incomplete_features)]
|
||||
#[attr = MacroUse {arguments: UseAll}]
|
||||
|
|
@ -253,7 +254,19 @@ mod expressions {
|
|||
}
|
||||
|
||||
/// ExprKind::TryBlock
|
||||
fn expr_try_block() { { from_output(()) } { return; from_output(()) } }
|
||||
fn expr_try_block() {
|
||||
{ from_output(()) }
|
||||
{ return; from_output(()) }
|
||||
type_ascribe!({ from_output(()) }, Option<_>);
|
||||
type_ascribe!({
|
||||
from_output(match branch(None) {
|
||||
Break { 0: residual } => #[allow(unreachable_code)]
|
||||
break from_residual(residual),
|
||||
Continue { 0: val } => #[allow(unreachable_code)]
|
||||
val,
|
||||
})
|
||||
}, Option<String>)
|
||||
}
|
||||
|
||||
/// ExprKind::Assign
|
||||
fn expr_assign() { let expr; expr = true; }
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#![feature(trace_macros)]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(try_blocks_heterogeneous)]
|
||||
#![feature(yeet_expr)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
|
|
@ -244,6 +245,8 @@ mod expressions {
|
|||
fn expr_try_block() {
|
||||
try {}
|
||||
try { return; }
|
||||
try bikeshed Option<_> { }
|
||||
try bikeshed Option<String> { None? }
|
||||
}
|
||||
|
||||
/// ExprKind::Assign
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue