From 121caa927bc4dace0df64f728f62fbce42a15fe9 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 5 May 2019 12:03:32 +0900 Subject: Correct handling of arguments in async fn --- src/libsyntax/parse/parser.rs | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d46feeab335..83f8b0e90c5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1576,7 +1576,7 @@ impl<'a> Parser<'a> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; - let d = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| { + let mut decl = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| { // This is somewhat dubious; We don't want to allow // argument names to be left off if there is a // definition... @@ -1585,7 +1585,7 @@ impl<'a> Parser<'a> { p.parse_arg_general(p.span.rust_2018(), true, false) })?; generics.where_clause = self.parse_where_clause()?; - self.construct_async_arguments(&mut asyncness, &d); + self.construct_async_arguments(&mut asyncness, &mut decl); let sig = ast::MethodSig { header: FnHeader { @@ -1594,7 +1594,7 @@ impl<'a> Parser<'a> { abi, asyncness, }, - decl: d, + decl, }; let body = match self.token { @@ -6479,10 +6479,10 @@ impl<'a> Parser<'a> { -> PResult<'a, ItemInfo> { let (ident, mut generics) = self.parse_fn_header()?; let allow_c_variadic = abi == Abi::C && unsafety == Unsafety::Unsafe; - let decl = self.parse_fn_decl(allow_c_variadic)?; + let mut decl = self.parse_fn_decl(allow_c_variadic)?; generics.where_clause = self.parse_where_clause()?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - self.construct_async_arguments(&mut asyncness, &decl); + self.construct_async_arguments(&mut asyncness, &mut decl); let header = FnHeader { unsafety, asyncness, constness, abi }; Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs))) } @@ -6666,9 +6666,9 @@ impl<'a> Parser<'a> { let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; - let decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?; + let mut decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?; generics.where_clause = self.parse_where_clause()?; - self.construct_async_arguments(&mut asyncness, &decl); + self.construct_async_arguments(&mut asyncness, &mut decl); *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; let header = ast::FnHeader { abi, unsafety, constness, asyncness }; @@ -8714,9 +8714,9 @@ impl<'a> Parser<'a> { /// /// The arguments of the function are replaced in HIR lowering with the arguments created by /// this function and the statements created here are inserted at the top of the closure body. - fn construct_async_arguments(&mut self, asyncness: &mut Spanned, decl: &FnDecl) { + fn construct_async_arguments(&mut self, asyncness: &mut Spanned, decl: &mut FnDecl) { if let IsAsync::Async { ref mut arguments, .. } = asyncness.node { - for (index, input) in decl.inputs.iter().enumerate() { + for (index, input) in decl.inputs.iter_mut().enumerate() { let id = ast::DUMMY_NODE_ID; let span = input.pat.span; @@ -8728,8 +8728,10 @@ impl<'a> Parser<'a> { // `let = __argN;` statement, instead just adding a `let = ;` // statement. let (binding_mode, ident, is_simple_pattern) = match input.pat.node { - PatKind::Ident(binding_mode, ident, _) => (binding_mode, ident, true), - _ => (BindingMode::ByValue(Mutability::Immutable), ident, false), + PatKind::Ident(binding_mode @ BindingMode::ByValue(_), ident, _) => { + (binding_mode, ident, true) + } + _ => (BindingMode::ByValue(Mutability::Mutable), ident, false), }; // Construct an argument representing `__argN: ` to replace the argument of the @@ -8796,6 +8798,15 @@ impl<'a> Parser<'a> { }) }; + // Remove mutability from arguments. If this is not a simple pattern, + // those arguments are replaced by `__argN`, so there is no need to do this. + if let PatKind::Ident(BindingMode::ByValue(mutability @ Mutability::Mutable), ..) = + &mut input.pat.node + { + assert!(is_simple_pattern); + *mutability = Mutability::Immutable; + } + let move_stmt = Stmt { id, node: StmtKind::Local(P(move_local)), span }; arguments.push(AsyncArgument { ident, arg, pat_stmt, move_stmt }); } -- cgit 1.4.1-3-g733a5 From 594685b5a2f35e2ff4fc01aca2ae91de92ed0993 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 May 2019 17:00:01 +0100 Subject: `token::LArrow` can begin arguments `<-` may indicate the start of a negative const argument. --- src/libsyntax/parse/parser.rs | 3 ++- src/test/ui/const-generics/const-expression-parameter.rs | 2 +- src/test/ui/const-generics/const-expression-parameter.stderr | 8 +------- 3 files changed, 4 insertions(+), 9 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d46feeab335..2f7b6f9fa66 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2319,7 +2319,8 @@ impl<'a> Parser<'a> { let ident = self.parse_path_segment_ident()?; let is_args_start = |token: &token::Token| match *token { - token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) => true, + token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) + | token::LArrow => true, _ => false, }; let check_args_start = |this: &mut Self| { diff --git a/src/test/ui/const-generics/const-expression-parameter.rs b/src/test/ui/const-generics/const-expression-parameter.rs index 662c7b767ba..22c6c351622 100644 --- a/src/test/ui/const-generics/const-expression-parameter.rs +++ b/src/test/ui/const-generics/const-expression-parameter.rs @@ -6,7 +6,7 @@ fn i32_identity() -> i32 { } fn foo_a() { - i32_identity::<-1>(); //~ ERROR expected identifier, found `<-` + i32_identity::<-1>(); // ok } fn foo_b() { diff --git a/src/test/ui/const-generics/const-expression-parameter.stderr b/src/test/ui/const-generics/const-expression-parameter.stderr index 2f7a80f0c8f..c255127c280 100644 --- a/src/test/ui/const-generics/const-expression-parameter.stderr +++ b/src/test/ui/const-generics/const-expression-parameter.stderr @@ -1,9 +1,3 @@ -error: expected identifier, found `<-` - --> $DIR/const-expression-parameter.rs:9:19 - | -LL | i32_identity::<-1>(); - | ^^ expected identifier - error: expected one of `,` or `>`, found `+` --> $DIR/const-expression-parameter.rs:13:22 | @@ -16,5 +10,5 @@ warning: the feature `const_generics` is incomplete and may cause the compiler t LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From e570fe5b220c1c9064587f94a885587b7f910ab1 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 May 2019 17:00:34 +0100 Subject: Remove resolved FIXME --- src/libsyntax/parse/parser.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2f7b6f9fa66..67e3132b2fc 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6061,8 +6061,6 @@ impl<'a> Parser<'a> { self.fatal("identifiers may currently not be used for const generics") ); } else { - // FIXME(const_generics): this currently conflicts with emplacement syntax - // with negative integer literals. self.parse_literal_maybe_minus()? }; let value = AnonConst { -- cgit 1.4.1-3-g733a5