diff options
27 files changed, 781 insertions, 322 deletions
diff --git a/Cargo.lock b/Cargo.lock index 369c6c8ae47..a4f30d1ebcf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -475,7 +475,6 @@ version = "0.0.0" dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index e3d99e34b35..de30b58526a 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -7,11 +7,11 @@ <Item Name="[capacity]" ExcludeView="simple">buf.cap</Item> <ArrayItems> <Size>len</Size> - <ValuePointer>buf.ptr.pointer.__0</ValuePointer> + <ValuePointer>buf.ptr.pointer</ValuePointer> </ArrayItems> </Expand> </Type> - <Type Name="alloc::vec_deque::VecDeque<*>"> + <Type Name="alloc::collections::vec_deque::VecDeque<*>"> <DisplayString>{{ size={tail <= head ? head - tail : buf.cap - tail + head} }}</DisplayString> <Expand> <Item Name="[size]" ExcludeView="simple">tail <= head ? head - tail : buf.cap - tail + head</Item> @@ -24,19 +24,19 @@ <If Condition="i == head"> <Break/> </If> - <Item>buf.ptr.pointer.__0 + i</Item> + <Item>buf.ptr.pointer[i]</Item> <Exec>i = (i + 1 == buf.cap ? 0 : i + 1)</Exec> </Loop> </CustomListItems> </Expand> </Type> - <Type Name="alloc::linked_list::LinkedList<*>"> + <Type Name="alloc::collections::linked_list::LinkedList<*>"> <DisplayString>{{ size={len} }}</DisplayString> <Expand> <LinkedListItems> <Size>len</Size> - <HeadPointer>*(alloc::linked_list::Node<$T1> **)&head</HeadPointer> - <NextPointer>*(alloc::linked_list::Node<$T1> **)&next</NextPointer> + <HeadPointer>*(alloc::collections::linked_list::Node<$T1> **)&head</HeadPointer> + <NextPointer>*(alloc::collections::linked_list::Node<$T1> **)&next</NextPointer> <ValueNode>element</ValueNode> </LinkedListItems> </Expand> diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis index 37d64be1ce9..0e703b3b950 100644 --- a/src/etc/natvis/libcore.natvis +++ b/src/etc/natvis/libcore.natvis @@ -1,15 +1,15 @@ <?xml version="1.0" encoding="utf-8"?> <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> <Type Name="core::ptr::Unique<*>"> - <DisplayString>{{ Unique {*pointer.__0} }}</DisplayString> + <DisplayString>{{ Unique {pointer} }}</DisplayString> <Expand> - <Item Name="[ptr]">pointer.__0</Item> + <Item Name="[ptr]">pointer</Item> </Expand> </Type> <Type Name="core::ptr::Shared<*>"> - <DisplayString>{{ Shared {*pointer.__0} }}</DisplayString> + <DisplayString>{{ Shared {pointer} }}</DisplayString> <Expand> - <Item Name="[ptr]">pointer.__0</Item> + <Item Name="[ptr]">pointer</Item> </Expand> </Type> <Type Name="core::option::Option<*>"> diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index dd0d13d8f5a..3a8b139236c 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -97,6 +97,10 @@ pub struct LoweringContext<'a> { is_generator: bool, is_async_body: bool, + /// Used to get the current `fn`'s def span to point to when using `await` + /// outside of an `async fn`. + current_item: Option<Span>, + catch_scopes: Vec<NodeId>, loop_scopes: Vec<NodeId>, is_in_loop_condition: bool, @@ -250,6 +254,7 @@ pub fn lower_crate( node_id_to_hir_id: IndexVec::new(), is_generator: false, is_async_body: false, + current_item: None, is_in_trait_impl: false, lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, @@ -3116,6 +3121,7 @@ impl<'a> LoweringContext<'a> { ItemKind::Fn(ref decl, ref header, ref generics, ref body) => { let fn_def_id = self.resolver.definitions().local_def_id(id); self.with_new_scopes(|this| { + this.current_item = Some(ident.span); let mut lower_fn = |decl: &FnDecl| { // Note: we don't need to change the return type from `T` to // `impl Future<Output = T>` here because lower_body @@ -3654,6 +3660,7 @@ impl<'a> LoweringContext<'a> { } else { lower_method(sig) }; + self.current_item = Some(i.span); (generics, hir::ImplItemKind::Method(sig, body_id)) } @@ -4270,6 +4277,7 @@ impl<'a> LoweringContext<'a> { let fn_decl = self.lower_fn_decl(decl, None, false, None); self.with_new_scopes(|this| { + this.current_item = Some(fn_decl_span); let mut is_generator = false; let body_id = this.lower_body(Some(decl), |this| { let e = this.lower_expr(body); @@ -5551,13 +5559,18 @@ impl<'a> LoweringContext<'a> { // } // } if !self.is_async_body { - span_err!( + let mut err = struct_span_err!( self.sess, await_span, E0728, "`await` is only allowed inside `async` functions and blocks" ); - self.sess.abort_if_errors(); + err.span_label(await_span, "only allowed inside `async` functions and blocks"); + if let Some(item_sp) = self.current_item { + err.span_label(item_sp, "this is not `async`"); + } + err.emit(); + return hir::ExprKind::Err; } let span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::Await, diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 8021d4b11d0..06d7b6c78f1 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -243,9 +243,8 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> } PlaceContext::MutatingUse(MutatingUseContext::Drop) => { - let ty = mir::Place::Base(mir::PlaceBase::Local(local)).ty(self.fx.mir, - self.fx.cx.tcx()); - let ty = self.fx.monomorphize(&ty.ty); + let ty = self.fx.mir.local_decls[local].ty; + let ty = self.fx.monomorphize(&ty); // Only need the place if we're actually dropping it. if self.fx.cx.type_needs_drop(ty) { diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index ad5d62f667a..5d797b75621 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -3,7 +3,7 @@ authors = ["The Rust Project Developers"] name = "std" version = "0.0.0" build = "build.rs" -license = "MIT/Apache-2.0" +license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/rust.git" description = "The Rust Standard Library" edition = "2018" diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index b56a27c80bc..403914c0707 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -618,6 +618,62 @@ impl<T, S> HashSet<T, S> self.map.get_key_value(value).map(|(k, _)| k) } + /// Inserts the given `value` into the set if it is not present, then + /// returns a reference to the value in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(hash_set_entry)] + /// + /// use std::collections::HashSet; + /// + /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// assert_eq!(set.len(), 3); + /// assert_eq!(set.get_or_insert(2), &2); + /// assert_eq!(set.get_or_insert(100), &100); + /// assert_eq!(set.len(), 4); // 100 was inserted + /// ``` + #[inline] + #[unstable(feature = "hash_set_entry", issue = "60896")] + pub fn get_or_insert(&mut self, value: T) -> &T { + // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with + // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`. + self.map.raw_entry_mut().from_key(&value).or_insert(value, ()).0 + } + + /// Inserts a value computed from `f` into the set if the given `value` is + /// not present, then returns a reference to the value in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(hash_set_entry)] + /// + /// use std::collections::HashSet; + /// + /// let mut set: HashSet<String> = ["cat", "dog", "horse"] + /// .iter().map(|&pet| pet.to_owned()).collect(); + /// + /// assert_eq!(set.len(), 3); + /// for &pet in &["cat", "dog", "fish"] { + /// let value = set.get_or_insert_with(pet, str::to_owned); + /// assert_eq!(value, pet); + /// } + /// assert_eq!(set.len(), 4); // a new "fish" was inserted + /// ``` + #[inline] + #[unstable(feature = "hash_set_entry", issue = "60896")] + pub fn get_or_insert_with<Q: ?Sized, F>(&mut self, value: &Q, f: F) -> &T + where T: Borrow<Q>, + Q: Hash + Eq, + F: FnOnce(&Q) -> T + { + // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with + // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`. + self.map.raw_entry_mut().from_key(value).or_insert_with(|| (f(value), ())).0 + } + /// Returns `true` if `self` has no elements in common with `other`. /// This is equivalent to checking for an empty intersection. /// diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 32e1ee94f0d..1a2393be806 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -1,14 +1,16 @@ use crate::ast; -use crate::ast::{Expr, ExprKind, Item, ItemKind, Pat, PatKind, QSelf, Ty, TyKind}; -use crate::parse::parser::PathStyle; +use crate::ast::{BlockCheckMode, Expr, ExprKind, Item, ItemKind, Pat, PatKind, QSelf, Ty, TyKind}; +use crate::parse::parser::{BlockMode, PathStyle, TokenType, SemiColonMode}; use crate::parse::token; use crate::parse::PResult; use crate::parse::Parser; use crate::print::pprust; use crate::ptr::P; +use crate::symbol::keywords; use crate::ThinVec; -use errors::Applicability; +use errors::{Applicability, DiagnosticBuilder}; use syntax_pos::Span; +use log::debug; pub trait RecoverQPath: Sized + 'static { const PATH_STYLE: PathStyle = PathStyle::Expr; @@ -223,4 +225,300 @@ impl<'a> Parser<'a> { false } } + + /// Consume alternative await syntaxes like `await <expr>`, `await? <expr>`, `await(<expr>)` + /// and `await { <expr> }`. + crate fn parse_incorrect_await_syntax( + &mut self, + lo: Span, + await_sp: Span, + ) -> PResult<'a, (Span, ExprKind)> { + let is_question = self.eat(&token::Question); // Handle `await? <expr>`. + let expr = if self.token == token::OpenDelim(token::Brace) { + // Handle `await { <expr> }`. + // This needs to be handled separatedly from the next arm to avoid + // interpreting `await { <expr> }?` as `<expr>?.await`. + self.parse_block_expr( + None, + self.span, + BlockCheckMode::Default, + ThinVec::new(), + ) + } else { + self.parse_expr() + }.map_err(|mut err| { + err.span_label(await_sp, "while parsing this incorrect await expression"); + err + })?; + let expr_str = self.sess.source_map().span_to_snippet(expr.span) + .unwrap_or_else(|_| pprust::expr_to_string(&expr)); + let suggestion = format!("{}.await{}", expr_str, if is_question { "?" } else { "" }); + let sp = lo.to(expr.span); + let app = match expr.node { + ExprKind::Try(_) => Applicability::MaybeIncorrect, // `await <expr>?` + _ => Applicability::MachineApplicable, + }; + self.struct_span_err(sp, "incorrect use of `await`") + .span_suggestion(sp, "`await` is a postfix operation", suggestion, app) + .emit(); + Ok((sp, ExprKind::Await(ast::AwaitOrigin::FieldLike, expr))) + } + + /// If encountering `future.await()`, consume and emit error. + crate fn recover_from_await_method_call(&mut self) { + if self.token == token::OpenDelim(token::Paren) && + self.look_ahead(1, |t| t == &token::CloseDelim(token::Paren)) + { + // future.await() + let lo = self.span; + self.bump(); // ( + let sp = lo.to(self.span); + self.bump(); // ) + self.struct_span_err(sp, "incorrect use of `await`") + .span_suggestion( + sp, + "`await` is not a method call, remove the parentheses", + String::new(), + Applicability::MachineApplicable, + ).emit() + } + } + + crate fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool { + self.token.is_ident() && + if let ast::ExprKind::Path(..) = node { true } else { false } && + !self.token.is_reserved_ident() && // v `foo:bar(baz)` + self.look_ahead(1, |t| t == &token::OpenDelim(token::Paren)) || + self.look_ahead(1, |t| t == &token::Lt) && // `foo:bar<baz` + self.look_ahead(2, |t| t.is_ident()) || + self.look_ahead(1, |t| t == &token::Colon) && // `foo:bar:baz` + self.look_ahead(2, |t| t.is_ident()) || + self.look_ahead(1, |t| t == &token::ModSep) && // `foo:bar::baz` + self.look_ahead(2, |t| t.is_ident()) + } + + crate fn bad_type_ascription( + &self, + err: &mut DiagnosticBuilder<'a>, + lhs_span: Span, + cur_op_span: Span, + next_sp: Span, + maybe_path: bool, + ) { + err.span_label(self.span, "expecting a type here because of type ascription"); + let cm = self.sess.source_map(); + let next_pos = cm.lookup_char_pos(next_sp.lo()); + let op_pos = cm.lookup_char_pos(cur_op_span.hi()); + if op_pos.line != next_pos.line { + err.span_suggestion( + cur_op_span, + "try using a semicolon", + ";".to_string(), + Applicability::MaybeIncorrect, + ); + } else { + if maybe_path { + err.span_suggestion( + cur_op_span, + "maybe you meant to write a path separator here", + "::".to_string(), + Applicability::MaybeIncorrect, + ); + } else { + err.note("type ascription is a nightly-only feature that lets \ + you annotate an expression with a type: `<expr>: <type>`") + .span_note( + lhs_span, + "this expression expects an ascribed type after the colon", + ) + .help("this might be indicative of a syntax error elsewhere"); + } + } + } + + crate fn recover_seq_parse_error( + &mut self, + delim: token::DelimToken, + lo: Span, + result: PResult<'a, P<Expr>>, + ) -> P<Expr> { + match result { + Ok(x) => x, + Err(mut err) => { + err.emit(); + // recover from parse error + self.consume_block(delim); + self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new()) + } + } + } + + crate fn recover_closing_delimiter( + &mut self, + tokens: &[token::Token], + mut err: DiagnosticBuilder<'a>, + ) -> PResult<'a, bool> { + let mut pos = None; + // we want to use the last closing delim that would apply + for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() { + if tokens.contains(&token::CloseDelim(unmatched.expected_delim)) + && Some(self.span) > unmatched.unclosed_span + { + pos = Some(i); + } + } + match pos { + Some(pos) => { + // Recover and assume that the detected unclosed delimiter was meant for + // this location. Emit the diagnostic and act as if the delimiter was + // present for the parser's sake. + + // Don't attempt to recover from this unclosed delimiter more than once. + let unmatched = self.unclosed_delims.remove(pos); + let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim)); + + // We want to suggest the inclusion of the closing delimiter where it makes + // the most sense, which is immediately after the last token: + // + // {foo(bar {}} + // - ^ + // | | + // | help: `)` may belong here (FIXME: #58270) + // | + // unclosed delimiter + if let Some(sp) = unmatched.unclosed_span { + err.span_label(sp, "unclosed delimiter"); + } + err.span_suggestion_short( + self.sess.source_map().next_point(self.prev_span), + &format!("{} may belong here", delim.to_string()), + delim.to_string(), + Applicability::MaybeIncorrect, + ); + err.emit(); + self.expected_tokens.clear(); // reduce errors + Ok(true) + } + _ => Err(err), + } + } + + /// Recover from `pub` keyword in places where it seems _reasonable_ but isn't valid. + crate fn eat_bad_pub(&mut self) { + if self.token.is_keyword(keywords::Pub) { + match self.parse_visibility(false) { + Ok(vis) => { + self.diagnostic() + .struct_span_err(vis.span, "unnecessary visibility qualifier") + .span_label(vis.span, "`pub` not permitted here") + .emit(); + } + Err(mut err) => err.emit(), + } + } + } + + // Eat tokens until we can be relatively sure we reached the end of the + // statement. This is something of a best-effort heuristic. + // + // We terminate when we find an unmatched `}` (without consuming it). + crate fn recover_stmt(&mut self) { + self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore) + } + + // If `break_on_semi` is `Break`, then we will stop consuming tokens after + // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is + // approximate - it can mean we break too early due to macros, but that + // should only lead to sub-optimal recovery, not inaccurate parsing). + // + // If `break_on_block` is `Break`, then we will stop consuming tokens + // after finding (and consuming) a brace-delimited block. + crate fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) { + let mut brace_depth = 0; + let mut bracket_depth = 0; + let mut in_block = false; + debug!("recover_stmt_ enter loop (semi={:?}, block={:?})", + break_on_semi, break_on_block); + loop { + debug!("recover_stmt_ loop {:?}", self.token); + match self.token { + token::OpenDelim(token::DelimToken::Brace) => { + brace_depth += 1; + self.bump(); + if break_on_block == BlockMode::Break && + brace_depth == 1 && + bracket_depth == 0 { + in_block = true; + } + } + token::OpenDelim(token::DelimToken::Bracket) => { + bracket_depth += 1; + self.bump(); + } + token::CloseDelim(token::DelimToken::Brace) => { + if brace_depth == 0 { + debug!("recover_stmt_ return - close delim {:?}", self.token); + break; + } + brace_depth -= 1; + self.bump(); + if in_block && bracket_depth == 0 && brace_depth == 0 { + debug!("recover_stmt_ return - block end {:?}", self.token); + break; + } + } + token::CloseDelim(token::DelimToken::Bracket) => { + bracket_depth -= 1; + if bracket_depth < 0 { + bracket_depth = 0; + } + self.bump(); + } + token::Eof => { + debug!("recover_stmt_ return - Eof"); + break; + } + token::Semi => { + self.bump(); + if break_on_semi == SemiColonMode::Break && + brace_depth == 0 && + bracket_depth == 0 { + debug!("recover_stmt_ return - Semi"); + break; + } + } + token::Comma if break_on_semi == SemiColonMode::Comma && + brace_depth == 0 && + bracket_depth == 0 => + { + debug!("recover_stmt_ return - Semi"); + break; + } + _ => { + self.bump() + } + } + } + } + + crate fn consume_block(&mut self, delim: token::DelimToken) { + let mut brace_depth = 0; + loop { + if self.eat(&token::OpenDelim(delim)) { + brace_depth += 1; + } else if self.eat(&token::CloseDelim(delim)) { + if brace_depth == 0 { + return; + } else { + brace_depth -= 1; + continue; + } + } else if self.token == token::Eof || self.eat(&token::CloseDelim(token::NoDelim)) { + return; + } else { + self.bump(); + } + } + } + } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 99e8db9d8e6..b1c3e46adc0 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -104,14 +104,14 @@ pub enum PathStyle { } #[derive(Clone, Copy, PartialEq, Debug)] -enum SemiColonMode { +crate enum SemiColonMode { Break, Ignore, Comma, } #[derive(Clone, Copy, PartialEq, Debug)] -enum BlockMode { +crate enum BlockMode { Break, Ignore, } @@ -389,7 +389,7 @@ crate enum TokenType { } impl TokenType { - fn to_string(&self) -> String { + crate fn to_string(&self) -> String { match *self { TokenType::Token(ref t) => format!("`{}`", pprust::token_to_string(t)), TokenType::Keyword(kw) => format!("`{}`", kw.name()), @@ -673,56 +673,6 @@ impl<'a> Parser<'a> { } } - fn recover_closing_delimiter( - &mut self, - tokens: &[token::Token], - mut err: DiagnosticBuilder<'a>, - ) -> PResult<'a, bool> { - let mut pos = None; - // we want to use the last closing delim that would apply - for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() { - if tokens.contains(&token::CloseDelim(unmatched.expected_delim)) - && Some(self.span) > unmatched.unclosed_span - { - pos = Some(i); - } - } - match pos { - Some(pos) => { - // Recover and assume that the detected unclosed delimiter was meant for - // this location. Emit the diagnostic and act as if the delimiter was - // present for the parser's sake. - - // Don't attempt to recover from this unclosed delimiter more than once. - let unmatched = self.unclosed_delims.remove(pos); - let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim)); - - // We want to suggest the inclusion of the closing delimiter where it makes - // the most sense, which is immediately after the last token: - // - // {foo(bar {}} - // - ^ - // | | - // | help: `)` may belong here (FIXME: #58270) - // | - // unclosed delimiter - if let Some(sp) = unmatched.unclosed_span { - err.span_label(sp, "unclosed delimiter"); - } - err.span_suggestion_short( - self.sess.source_map().next_point(self.prev_span), - &format!("{} may belong here", delim.to_string()), - delim.to_string(), - Applicability::MaybeIncorrect, - ); - err.emit(); - self.expected_tokens.clear(); // reduce errors - Ok(true) - } - _ => Err(err), - } - } - /// Expect next token to be edible or inedible token. If edible, /// then consume it; if inedible, then return without consuming /// anything. Signal a fatal error if next token is unexpected. @@ -2343,7 +2293,7 @@ impl<'a> Parser<'a> { }) } - fn mk_expr(&self, span: Span, node: ExprKind, attrs: ThinVec<Attribute>) -> P<Expr> { + crate fn mk_expr(&self, span: Span, node: ExprKind, attrs: ThinVec<Attribute>) -> P<Expr> { P(Expr { node, span, attrs, id: ast::DUMMY_NODE_ID }) } @@ -2629,14 +2579,9 @@ impl<'a> Parser<'a> { db.note("variable declaration using `let` is a statement"); return Err(db); } else if self.span.rust_2018() && self.eat_keyword(keywords::Await) { - // FIXME: remove this branch when `await!` is no longer supported - // https://github.com/rust-lang/rust/issues/60610 - self.expect(&token::Not)?; - self.expect(&token::OpenDelim(token::Paren))?; - let expr = self.parse_expr()?; - self.expect(&token::CloseDelim(token::Paren))?; - hi = self.prev_span; - ex = ExprKind::Await(ast::AwaitOrigin::MacroLike, expr); + let (await_hi, e_kind) = self.parse_await_macro_or_alt(lo, self.prev_span)?; + hi = await_hi; + ex = e_kind; } else if self.token.is_path_start() { let path = self.parse_path(PathStyle::Expr)?; @@ -2701,6 +2646,31 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr, true) } + /// Parse `await!(<expr>)` calls, or alternatively recover from incorrect but reasonable + /// alternative syntaxes `await <expr>`, `await? <expr>`, `await(<expr>)` and + /// `await { <expr> }`. + fn parse_await_macro_or_alt( + &mut self, + lo: Span, + await_sp: Span, + ) -> PResult<'a, (Span, ExprKind)> { + if self.token == token::Not { + // Handle correct `await!(<expr>)`. + // FIXME: make this an error when `await!` is no longer supported + // https://github.com/rust-lang/rust/issues/60610 + self.expect(&token::Not)?; + self.expect(&token::OpenDelim(token::Paren))?; + let expr = self.parse_expr().map_err(|mut err| { + err.span_label(await_sp, "while parsing this await macro call"); + err + })?; + self.expect(&token::CloseDelim(token::Paren))?; + Ok((self.prev_span, ExprKind::Await(ast::AwaitOrigin::MacroLike, expr))) + } else { // Handle `await <expr>`. + self.parse_incorrect_await_syntax(lo, await_sp) + } + } + fn maybe_parse_struct_expr( &mut self, lo: Span, @@ -2849,10 +2819,13 @@ impl<'a> Parser<'a> { } /// Parses a block or unsafe block. - fn parse_block_expr(&mut self, opt_label: Option<Label>, - lo: Span, blk_mode: BlockCheckMode, - outer_attrs: ThinVec<Attribute>) - -> PResult<'a, P<Expr>> { + crate fn parse_block_expr( + &mut self, + opt_label: Option<Label>, + lo: Span, + blk_mode: BlockCheckMode, + outer_attrs: ThinVec<Attribute>, + ) -> PResult<'a, P<Expr>> { self.expect(&token::OpenDelim(token::Brace))?; let mut attrs = outer_attrs; @@ -2913,6 +2886,7 @@ impl<'a> Parser<'a> { ExprKind::Await(ast::AwaitOrigin::FieldLike, self_arg), ThinVec::new(), ); + self.recover_from_await_method_call(); return Ok(await_expr); } let segment = self.parse_path_segment(PathStyle::Expr)?; @@ -3151,23 +3125,6 @@ impl<'a> Parser<'a> { return Ok(e); } - fn recover_seq_parse_error( - &mut self, - delim: token::DelimToken, - lo: Span, - result: PResult<'a, P<Expr>>, - ) -> P<Expr> { - match result { - Ok(x) => x, - Err(mut err) => { - err.emit(); - // recover from parse error - self.consume_block(delim); - self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new()) - } - } - } - crate fn process_potential_macro_variable(&mut self) { let (token, span) = match self.token { token::Dollar if self.span.ctxt() != syntax_pos::hygiene::SyntaxContext::empty() && @@ -3570,58 +3527,6 @@ impl<'a> Parser<'a> { Ok(lhs) } - fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool { - self.token.is_ident() && - if let ast::ExprKind::Path(..) = node { true } else { false } && - !self.token.is_reserved_ident() && // v `foo:bar(baz)` - self.look_ahead(1, |t| t == &token::OpenDelim(token::Paren)) || - self.look_ahead(1, |t| t == &token::Lt) && // `foo:bar<baz` - self.look_ahead(2, |t| t.is_ident()) || - self.look_ahead(1, |t| t == &token::Colon) && // `foo:bar:baz` - self.look_ahead(2, |t| t.is_ident()) || - self.look_ahead(1, |t| t == &token::ModSep) && // `foo:bar::baz` - self.look_ahead(2, |t| t.is_ident()) - } - - fn bad_type_ascription( - &self, - err: &mut DiagnosticBuilder<'a>, - lhs_span: Span, - cur_op_span: Span, - next_sp: Span, - maybe_path: bool, - ) { - err.span_label(self.span, "expecting a type here because of type ascription"); - let cm = self.sess.source_map(); - let next_pos = cm.lookup_char_pos(next_sp.lo()); - let op_pos = cm.lookup_char_pos(cur_op_span.hi()); - if op_pos.line != next_pos.line { - err.span_suggestion( - cur_op_span, - "try using a semicolon", - ";".to_string(), - Applicability::MaybeIncorrect, - ); - } else { - if maybe_path { - err.span_suggestion( - cur_op_span, - "maybe you meant to write a path separator here", - "::".to_string(), - Applicability::MaybeIncorrect, - ); - } else { - err.note("type ascription is a nightly-only feature that lets \ - you annotate an expression with a type: `<expr>: <type>`"); - err.span_note( - lhs_span, - "this expression expects an ascribed type after the colon", - ); - err.help("this might be indicative of a syntax error elsewhere"); - } - } - } - fn parse_assoc_op_cast(&mut self, lhs: P<Expr>, lhs_span: Span, expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind) -> PResult<'a, P<Expr>> { @@ -4903,92 +4808,6 @@ impl<'a> Parser<'a> { Ok(self.parse_stmt_(true)) } - // Eat tokens until we can be relatively sure we reached the end of the - // statement. This is something of a best-effort heuristic. - // - // We terminate when we find an unmatched `}` (without consuming it). - fn recover_stmt(&mut self) { - self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore) - } - - // If `break_on_semi` is `Break`, then we will stop consuming tokens after - // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is - // approximate - it can mean we break too early due to macros, but that - // should only lead to sub-optimal recovery, not inaccurate parsing). - // - // If `break_on_block` is `Break`, then we will stop consuming tokens - // after finding (and consuming) a brace-delimited block. - fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) { - let mut brace_depth = 0; - let mut bracket_depth = 0; - let mut in_block = false; - debug!("recover_stmt_ enter loop (semi={:?}, block={:?})", - break_on_semi, break_on_block); - loop { - debug!("recover_stmt_ loop {:?}", self.token); - match self.token { - token::OpenDelim(token::DelimToken::Brace) => { - brace_depth += 1; - self.bump(); - if break_on_block == BlockMode::Break && - brace_depth == 1 && - bracket_depth == 0 { - in_block = true; - } - } - token::OpenDelim(token::DelimToken::Bracket) => { - bracket_depth += 1; - self.bump(); - } - token::CloseDelim(token::DelimToken::Brace) => { - if brace_depth == 0 { - debug!("recover_stmt_ return - close delim {:?}", self.token); - break; - } - brace_depth -= 1; - self.bump(); - if in_block && bracket_depth == 0 && brace_depth == 0 { - debug!("recover_stmt_ return - block end {:?}", self.token); - break; - } - } - token::CloseDelim(token::DelimToken::Bracket) => { - bracket_depth -= 1; - if bracket_depth < 0 { - bracket_depth = 0; - } - self.bump(); - } - token::Eof => { - debug!("recover_stmt_ return - Eof"); - break; - } - token::Semi => { - self.bump(); - if break_on_semi == SemiColonMode::Break && - brace_depth == 0 && - bracket_depth == 0 { - debug!("recover_stmt_ return - Semi"); - break; - } - } - token::Comma => { - if break_on_semi == SemiColonMode::Comma && - brace_depth == 0 && - bracket_depth == 0 { - debug!("recover_stmt_ return - Semi"); - break; - } else { - self.bump(); - } - } - _ => { - self.bump() - } - } - } - } - fn parse_stmt_(&mut self, macro_legacy_warnings: bool) -> Option<Stmt> { self.parse_stmt_without_recovery(macro_legacy_warnings).unwrap_or_else(|mut e| { e.emit(); @@ -6892,26 +6711,6 @@ impl<'a> Parser<'a> { Ok((class_name, ItemKind::Union(vdata, generics), None)) } - fn consume_block(&mut self, delim: token::DelimToken) { - let mut brace_depth = 0; - loop { - if self.eat(&token::OpenDelim(delim)) { - brace_depth += 1; - } else if self.eat(&token::CloseDelim(delim)) { - if brace_depth == 0 { - return; - } else { - brace_depth -= 1; - continue; - } - } else if self.token == token::Eof || self.eat(&token::CloseDelim(token::NoDelim)) { - return; - } else { - self.bump(); - } - } - } - fn parse_record_struct_body( &mut self, ) -> PResult<'a, (Vec<StructField>, /* recovered */ bool)> { @@ -8609,21 +8408,6 @@ impl<'a> Parser<'a> { ).emit(); } - /// Recover from `pub` keyword in places where it seems _reasonable_ but isn't valid. - fn eat_bad_pub(&mut self) { - if self.token.is_keyword(keywords::Pub) { - match self.parse_visibility(false) { - Ok(vis) => { - let mut err = self.diagnostic() - .struct_span_err(vis.span, "unnecessary visibility qualifier"); - err.span_label(vis.span, "`pub` not permitted here"); - err.emit(); - } - Err(mut err) => err.emit(), - } - } - } - /// When lowering a `async fn` to the HIR, we need to move all of the arguments of the function /// into the generated closure so that they are dropped when the future is polled and not when /// it is created. diff --git a/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.rs b/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.rs index b2e8e4be172..f59f1160e70 100644 --- a/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.rs +++ b/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.rs @@ -22,6 +22,4 @@ macro_rules! await { () => {} } -fn main() { - match await { await => () } //~ ERROR expected `!`, found `{` -} +fn main() {} diff --git a/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.stderr b/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.stderr index 076a31bd9ce..c4b82b29f02 100644 --- a/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.stderr +++ b/src/test/ui/await-keyword/2018-edition-error-in-non-macro-position.stderr @@ -68,13 +68,5 @@ help: you can escape reserved keywords to use them as identifiers LL | macro_rules! r#await { | ^^^^^^^ -error: expected `!`, found `{` - --> $DIR/2018-edition-error-in-non-macro-position.rs:26:17 - | -LL | match await { await => () } - | ----- ^ expected `!` - | | - | while parsing this match expression - -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors diff --git a/src/test/ui/await-keyword/2018-edition-error.rs b/src/test/ui/await-keyword/2018-edition-error.rs index e0b2962ce97..d8568696842 100644 --- a/src/test/ui/await-keyword/2018-edition-error.rs +++ b/src/test/ui/await-keyword/2018-edition-error.rs @@ -9,6 +9,4 @@ mod outer_mod { use self::outer_mod::await::await; //~ ERROR expected identifier //~^ ERROR expected identifier, found reserved keyword `await` -fn main() { - match await { await => () } //~ ERROR expected `!`, found `{` -} +fn main() {} diff --git a/src/test/ui/await-keyword/2018-edition-error.stderr b/src/test/ui/await-keyword/2018-edition-error.stderr index c8bf9b42ca5..8afe5c1a36b 100644 --- a/src/test/ui/await-keyword/2018-edition-error.stderr +++ b/src/test/ui/await-keyword/2018-edition-error.stderr @@ -38,13 +38,5 @@ help: you can escape reserved keywords to use them as identifiers LL | use self::outer_mod::await::r#await; | ^^^^^^^ -error: expected `!`, found `{` - --> $DIR/2018-edition-error.rs:13:17 - | -LL | match await { await => () } - | ----- ^ expected `!` - | | - | while parsing this match expression - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors diff --git a/src/test/ui/await-keyword/incorrect-syntax-suggestions.rs b/src/test/ui/await-keyword/incorrect-syntax-suggestions.rs new file mode 100644 index 00000000000..e1e5bdd3d1b --- /dev/null +++ b/src/test/ui/await-keyword/incorrect-syntax-suggestions.rs @@ -0,0 +1,111 @@ +// edition:2018 + +#![feature(async_await)] + +async fn bar() -> Result<(), ()> { + Ok(()) +} + +async fn foo1() -> Result<(), ()> { + let _ = await bar(); //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo2() -> Result<(), ()> { + let _ = await? bar(); //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo3() -> Result<(), ()> { + let _ = await bar()?; //~ ERROR incorrect use of `await` + //~^ ERROR the `?` operator can only be applied to values that implement `std::ops::Try` + Ok(()) +} +async fn foo21() -> Result<(), ()> { + let _ = await { bar() }; //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo22() -> Result<(), ()> { + let _ = await(bar()); //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo23() -> Result<(), ()> { + let _ = await { bar() }?; //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo4() -> Result<(), ()> { + let _ = (await bar())?; //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo5() -> Result<(), ()> { + let _ = bar().await(); //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo6() -> Result<(), ()> { + let _ = bar().await()?; //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo7() -> Result<(), ()> { + let _ = bar().await; // OK + Ok(()) +} +async fn foo8() -> Result<(), ()> { + let _ = bar().await?; // OK + Ok(()) +} +fn foo9() -> Result<(), ()> { + let _ = await bar(); //~ ERROR `await` is only allowed inside `async` functions and blocks + //~^ ERROR incorrect use of `await` + Ok(()) +} +fn foo10() -> Result<(), ()> { + let _ = await? bar(); //~ ERROR `await` is only allowed inside `async` functions and blocks + //~^ ERROR incorrect use of `await` + Ok(()) +} +fn foo11() -> Result<(), ()> { + let _ = await bar()?; //~ ERROR `await` is only allowed inside `async` functions and blocks + //~^ ERROR incorrect use of `await` + Ok(()) +} +fn foo12() -> Result<(), ()> { + let _ = (await bar())?; //~ ERROR `await` is only allowed inside `async` functions and blocks + //~^ ERROR incorrect use of `await` + Ok(()) +} +fn foo13() -> Result<(), ()> { + let _ = bar().await(); //~ ERROR `await` is only allowed inside `async` functions and blocks + //~^ ERROR incorrect use of `await` + Ok(()) +} +fn foo14() -> Result<(), ()> { + let _ = bar().await()?; //~ ERROR `await` is only allowed inside `async` functions and blocks + //~^ ERROR incorrect use of `await` + Ok(()) +} +fn foo15() -> Result<(), ()> { + let _ = bar().await; //~ ERROR `await` is only allowed inside `async` functions and blocks + Ok(()) +} +fn foo16() -> Result<(), ()> { + let _ = bar().await?; //~ ERROR `await` is only allowed inside `async` functions and blocks + Ok(()) +} +fn foo24() -> Result<(), ()> { + fn foo() -> Result<(), ()> { + let _ = bar().await?; //~ ERROR `await` is only allowed inside `async` functions and blocks + Ok(()) + } + foo() +} +fn foo25() -> Result<(), ()> { + let foo = || { + let _ = bar().await?; //~ ERROR `await` is only allowed inside `async` functions and blocks + Ok(()) + }; + foo() +} + +fn main() { + match await { await => () } + //~^ ERROR expected expression, found `=>` + //~| ERROR incorrect use of `await` +} //~ ERROR expected one of `.`, `?`, `{`, or an operator, found `}` diff --git a/src/test/ui/await-keyword/incorrect-syntax-suggestions.stderr b/src/test/ui/await-keyword/incorrect-syntax-suggestions.stderr new file mode 100644 index 00000000000..380da4448ad --- /dev/null +++ b/src/test/ui/await-keyword/incorrect-syntax-suggestions.stderr @@ -0,0 +1,207 @@ +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:10:13 + | +LL | let _ = await bar(); + | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:14:13 + | +LL | let _ = await? bar(); + | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:18:13 + | +LL | let _ = await bar()?; + | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:23:13 + | +LL | let _ = await { bar() }; + | ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:27:13 + | +LL | let _ = await(bar()); + | ^^^^^^^^^^^^ help: `await` is a postfix operation: `(bar()).await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:31:13 + | +LL | let _ = await { bar() }?; + | ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:35:14 + | +LL | let _ = (await bar())?; + | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:39:24 + | +LL | let _ = bar().await(); + | ^^ help: `await` is not a method call, remove the parentheses + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:43:24 + | +LL | let _ = bar().await()?; + | ^^ help: `await` is not a method call, remove the parentheses + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:55:13 + | +LL | let _ = await bar(); + | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:60:13 + | +LL | let _ = await? bar(); + | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:65:13 + | +LL | let _ = await bar()?; + | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:70:14 + | +LL | let _ = (await bar())?; + | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:75:24 + | +LL | let _ = bar().await(); + | ^^ help: `await` is not a method call, remove the parentheses + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:80:24 + | +LL | let _ = bar().await()?; + | ^^ help: `await` is not a method call, remove the parentheses + +error: expected expression, found `=>` + --> $DIR/incorrect-syntax-suggestions.rs:108:25 + | +LL | match await { await => () } + | ----- ^^ expected expression + | | + | while parsing this incorrect await expression + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:108:11 + | +LL | match await { await => () } + | ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await` + +error: expected one of `.`, `?`, `{`, or an operator, found `}` + --> $DIR/incorrect-syntax-suggestions.rs:111:1 + | +LL | match await { await => () } + | ----- - expected one of `.`, `?`, `{`, or an operator here + | | + | while parsing this match expression +... +LL | } + | ^ unexpected token + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:55:13 + | +LL | fn foo9() -> Result<(), ()> { + | ---- this is not `async` +LL | let _ = await bar(); + | ^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:60:13 + | +LL | fn foo10() -> Result<(), ()> { + | ----- this is not `async` +LL | let _ = await? bar(); + | ^^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:65:13 + | +LL | fn foo11() -> Result<(), ()> { + | ----- this is not `async` +LL | let _ = await bar()?; + | ^^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:70:14 + | +LL | fn foo12() -> Result<(), ()> { + | ----- this is not `async` +LL | let _ = (await bar())?; + | ^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:75:13 + | +LL | fn foo13() -> Result<(), ()> { + | ----- this is not `async` +LL | let _ = bar().await(); + | ^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:80:13 + | +LL | fn foo14() -> Result<(), ()> { + | ----- this is not `async` +LL | let _ = bar().await()?; + | ^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:85:13 + | +LL | fn foo15() -> Result<(), ()> { + | ----- this is not `async` +LL | let _ = bar().await; + | ^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:89:13 + | +LL | fn foo16() -> Result<(), ()> { + | ----- this is not `async` +LL | let _ = bar().await?; + | ^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:94:17 + | +LL | fn foo() -> Result<(), ()> { + | --- this is not `async` +LL | let _ = bar().await?; + | ^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:101:17 + | +LL | let foo = || { + | -- this is not `async` +LL | let _ = bar().await?; + | ^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` + --> $DIR/incorrect-syntax-suggestions.rs:18:19 + | +LL | let _ = await bar()?; + | ^^^^^^ the `?` operator cannot be applied to type `impl std::future::Future` + | + = help: the trait `std::ops::Try` is not implemented for `impl std::future::Future` + = note: required by `std::ops::Try::into_result` + +error: aborting due to 29 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/await-keyword/post_expansion_error.stderr b/src/test/ui/await-keyword/post_expansion_error.stderr index 0996c38b3b6..4e525974c2c 100644 --- a/src/test/ui/await-keyword/post_expansion_error.stderr +++ b/src/test/ui/await-keyword/post_expansion_error.stderr @@ -2,7 +2,9 @@ error: expected expression, found `)` --> $DIR/post_expansion_error.rs:8:12 | LL | await!() - | ^ expected expression + | ----- ^ expected expression + | | + | while parsing this await macro call error: aborting due to previous error diff --git a/src/test/ui/issues/issue-51719.rs b/src/test/ui/issues/issue-51719.rs index 2c02ac01142..5966edd0bf0 100644 --- a/src/test/ui/issues/issue-51719.rs +++ b/src/test/ui/issues/issue-51719.rs @@ -9,3 +9,5 @@ async fn foo() {} fn make_generator() { let _gen = || foo.await; //~ ERROR `await` is only allowed inside `async` functions and blocks } + +fn main() {} diff --git a/src/test/ui/issues/issue-51719.stderr b/src/test/ui/issues/issue-51719.stderr index 768909b66ec..c06165b2446 100644 --- a/src/test/ui/issues/issue-51719.stderr +++ b/src/test/ui/issues/issue-51719.stderr @@ -2,7 +2,9 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/issue-51719.rs:10:19 | LL | let _gen = || foo.await; - | ^^^^^^^^^ + | -- ^^^^^^^^^ only allowed inside `async` functions and blocks + | | + | this is not `async` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-51751.stderr b/src/test/ui/issues/issue-51751.stderr index 0c4cb034a93..97b63d1590e 100644 --- a/src/test/ui/issues/issue-51751.stderr +++ b/src/test/ui/issues/issue-51751.stderr @@ -1,8 +1,11 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/issue-51751.rs:11:20 | +LL | fn main() { + | ---- this is not `async` +LL | let result = inc(10000); LL | let finished = result.await; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ only allowed inside `async` functions and blocks error: aborting due to previous error diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 336d7e32024..e759ad1f35d 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -7,7 +7,6 @@ edition = "2018" [dependencies] diff = "0.1.10" env_logger = { version = "0.5", default-features = false } -filetime = "0.2" getopts = "0.2" log = "0.4" regex = "1.0" diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index e253934e566..442e58bfd74 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -9,7 +9,6 @@ use crate::common::CompareMode; use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS}; use crate::common::{Config, TestPaths}; use crate::common::{DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Mode, Pretty}; -use filetime::FileTime; use getopts::Options; use std::env; use std::ffi::OsString; @@ -17,6 +16,7 @@ use std::fs; use std::io::{self, ErrorKind}; use std::path::{Path, PathBuf}; use std::process::Command; +use std::time::SystemTime; use test::ColorConfig; use crate::util::logv; use walkdir::WalkDir; @@ -752,31 +752,36 @@ fn up_to_date( #[derive(Debug, PartialEq, PartialOrd, Ord, Eq)] struct Stamp { - time: FileTime, + time: SystemTime, file: PathBuf, } impl Stamp { fn from_path(p: &Path) -> Self { + let time = fs::metadata(p) + .and_then(|metadata| metadata.modified()) + .unwrap_or(SystemTime::UNIX_EPOCH); + Stamp { - time: mtime(&p), + time, file: p.into(), } } - fn from_dir(path: &Path) -> impl Iterator<Item=Stamp> { + fn from_dir(path: &Path) -> impl Iterator<Item = Stamp> { WalkDir::new(path) .into_iter() .map(|entry| entry.unwrap()) .filter(|entry| entry.file_type().is_file()) - .map(|entry| Stamp::from_path(entry.path())) - } -} + .map(|entry| { + let time = (|| -> io::Result<_> { entry.metadata()?.modified() })(); -fn mtime(path: &Path) -> FileTime { - fs::metadata(path) - .map(|f| FileTime::from_last_modification_time(&f)) - .unwrap_or_else(|_| FileTime::zero()) + Stamp { + time: time.unwrap_or(SystemTime::UNIX_EPOCH), + file: entry.path().into(), + } + }) + } } fn make_test_name( diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index b335fe3ae18..1e4deee6bf1 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -9,7 +9,6 @@ use crate::common::{Config, TestPaths}; use crate::common::{Incremental, MirOpt, RunMake, Ui, JsDocTest, Assembly}; use diff; use crate::errors::{self, Error, ErrorKind}; -use filetime::FileTime; use crate::header::TestProps; use crate::json; use regex::{Captures, Regex}; @@ -3029,7 +3028,7 @@ impl<'test> TestCx<'test> { } fn check_mir_test_timestamp(&self, test_name: &str, output_file: &Path) { - let t = |file| FileTime::from_last_modification_time(&fs::metadata(file).unwrap()); + let t = |file| fs::metadata(file).unwrap().modified().unwrap(); let source_file = &self.testpaths.file; let output_time = t(output_file); let source_time = t(source_file); diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 5bf1553b227..d2b1a7bac60 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -2,7 +2,7 @@ authors = ["The Rust Project Developers"] name = "rustbook" version = "0.1.0" -license = "MIT/Apache-2.0" +license = "MIT OR Apache-2.0" edition = "2018" [dependencies] diff --git a/src/tools/rustc-std-workspace-alloc/Cargo.toml b/src/tools/rustc-std-workspace-alloc/Cargo.toml index 98578914963..05df1fddc7f 100644 --- a/src/tools/rustc-std-workspace-alloc/Cargo.toml +++ b/src/tools/rustc-std-workspace-alloc/Cargo.toml @@ -2,7 +2,7 @@ name = "rustc-std-workspace-alloc" version = "1.0.0" authors = ["Alex Crichton <alex@alexcrichton.com>"] -license = 'MIT/Apache-2.0' +license = 'MIT OR Apache-2.0' description = """ Hack for the compiler's own build system """ diff --git a/src/tools/rustc-std-workspace-core/Cargo.toml b/src/tools/rustc-std-workspace-core/Cargo.toml index d527ce12bc3..38ca56a557b 100644 --- a/src/tools/rustc-std-workspace-core/Cargo.toml +++ b/src/tools/rustc-std-workspace-core/Cargo.toml @@ -2,7 +2,7 @@ name = "rustc-std-workspace-core" version = "1.0.0" authors = ["Alex Crichton <alex@alexcrichton.com>"] -license = 'MIT/Apache-2.0' +license = 'MIT OR Apache-2.0' description = """ Hack for the compiler's own build system """ diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index d51841cd650..290c4481c00 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -2,7 +2,7 @@ name = "rustc-workspace-hack" version = "1.0.0" authors = ["Alex Crichton <alex@alexcrichton.com>"] -license = 'MIT/Apache-2.0' +license = 'MIT OR Apache-2.0' description = """ Hack for the compiler's own build system """ diff --git a/src/tools/unstable-book-gen/Cargo.toml b/src/tools/unstable-book-gen/Cargo.toml index 3209de09aeb..e43e4e6c7cb 100644 --- a/src/tools/unstable-book-gen/Cargo.toml +++ b/src/tools/unstable-book-gen/Cargo.toml @@ -3,7 +3,7 @@ authors = ["est31 <MTest31@outlook.com>", "The Rust Project Developers"] name = "unstable-book-gen" version = "0.1.0" -license = "MIT/Apache-2.0" +license = "MIT OR Apache-2.0" edition = "2018" [dependencies] |
