Auto merge of #60898 - Centril:rollup-76o2g8a, r=Centril
Rollup of 6 pull requests Successful merges: - #60685 (Switch to SPDX 2.1 license expression) - #60687 (Fix .natvis visualizers.) - #60805 (remove compiletest's dependency on `filetime`) - #60862 (Get ty from local_decls instead of using Place) - #60873 (Parse alternative incorrect uses of await and recover) - #60894 (Add entry-like methods to HashSet) Failed merges: r? @ghost
This commit is contained in:
commit
1bbb1353be
27 changed files with 781 additions and 322 deletions
|
@ -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)",
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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<*>">
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -22,6 +22,4 @@ macro_rules! await {
|
|||
() => {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match await { await => () } //~ ERROR expected `!`, found `{`
|
||||
}
|
||||
fn main() {}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
111
src/test/ui/await-keyword/incorrect-syntax-suggestions.rs
Normal file
111
src/test/ui/await-keyword/incorrect-syntax-suggestions.rs
Normal file
|
@ -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 `}`
|
207
src/test/ui/await-keyword/incorrect-syntax-suggestions.stderr
Normal file
207
src/test/ui/await-keyword/incorrect-syntax-suggestions.stderr
Normal file
|
@ -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`.
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
"""
|
||||
|
|
|
@ -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
|
||||
"""
|
||||
|
|
|
@ -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
|
||||
"""
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in a new issue