Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[move-compiler] Parser resilience #16673

Merged
merged 5 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions external-crates/move/crates/move-analyzer/src/symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2108,6 +2108,7 @@ impl<'a> ParsingSymbolicator<'a> {
}
T::Multiple(v) => v.iter().for_each(|t| self.type_symbols(t)),
T::Unit => (),
T::UnresolvedError => (),
}
}

Expand Down
15 changes: 15 additions & 0 deletions external-crates/move/crates/move-compiler/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,17 @@ impl Diagnostics {
.any(|d| d.info.external_prefix() == Some(prefix))
}

/// Returns true if any diagnostic in the Syntax category have already been recorded.
pub fn any_syntax_error_with_primary_loc(&self, loc: Loc) -> bool {
let Self(Some(inner)) = self else {
return false;
};
inner
.diagnostics
.iter()
.any(|d| d.info().category() == Category::Syntax as u8 && d.primary_label.0 == loc)
}

/// Returns the number of diags filtered in source (user) code (an not in the dependencies) that
/// have a given prefix (first value returned) and how many different categories of diags were
/// filtered.
Expand Down Expand Up @@ -622,6 +633,10 @@ impl Diagnostic {
&self.primary_label.1
}

pub fn primary_loc(&self) -> Loc {
self.primary_label.0
}

pub fn is_migration(&self) -> bool {
const MIGRATION_CATEGORY: u8 = codes::Category::Migration as u8;
self.info.category() == MIGRATION_CATEGORY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2312,6 +2312,7 @@ fn type_(context: &mut Context, sp!(loc, pt_): P::Type) -> E::Type {
let result = type_(context, *result);
ET::Fun(args, Box::new(result))
}
PT::UnresolvedError => ET::UnresolvedError,
};
sp(loc, t_)
}
Expand Down Expand Up @@ -2343,6 +2344,20 @@ fn optional_types(context: &mut Context, pts_opt: Option<Vec<P::Type>>) -> Optio

#[growing_stack]
fn sequence(context: &mut Context, loc: Loc, seq: P::Sequence) -> E::Sequence {
// removes an unresolved sequence item if it is the only item in the sequence
fn remove_single_unresolved(items: &mut VecDeque<E::SequenceItem>) -> Option<Box<E::Exp>> {
if items.len() != 1 {
return None;
}
let seq_item = items.pop_front().unwrap();
if let E::SequenceItem_::Seq(exp) = &seq_item.value {
if exp.value == E::Exp_::UnresolvedError {
return Some(exp.clone());
}
}
items.push_front(seq_item);
None
}
let (puses, pitems, maybe_last_semicolon_loc, pfinal_item) = seq;

let (new_scope, use_funs_builder) = uses(context, puses);
Expand All @@ -2355,11 +2370,17 @@ fn sequence(context: &mut Context, loc: Loc, seq: P::Sequence) -> E::Sequence {
let final_e_opt = pfinal_item.map(|item| exp(context, Box::new(item)));
let final_e = match final_e_opt {
None => {
let last_semicolon_loc = match maybe_last_semicolon_loc {
Some(l) => l,
None => loc,
};
Box::new(sp(last_semicolon_loc, E::Exp_::Unit { trailing: true }))
// if there is only one item in the sequence and it is unresolved, do not generated the
// final sequence unit-typed expression
if let Some(unresolved) = remove_single_unresolved(&mut items) {
unresolved
} else {
let last_semicolon_loc = match maybe_last_semicolon_loc {
Some(l) => l,
None => loc,
};
Box::new(sp(last_semicolon_loc, E::Exp_::Unit { trailing: true }))
}
}
Some(e) => e,
};
Expand Down
3 changes: 3 additions & 0 deletions external-crates/move/crates/move-compiler/src/parser/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ pub enum Type_ {
// (t1, t2, ... , tn)
// Used for return values and expression blocks
Multiple(Vec<Type>),
UnresolvedError,
}
pub type Type = Spanned<Type_>;

Expand Down Expand Up @@ -1270,6 +1271,7 @@ impl fmt::Display for Type_ {
write!(f, "{}", format_comma(tys))?;
write!(f, ")")
}
UnresolvedError => write!(f, "_|_"),
}
}
}
Expand Down Expand Up @@ -1779,6 +1781,7 @@ impl AstDebug for Type_ {
w.write("):");
result.ast_debug(w);
}
Type_::UnresolvedError => w.write("_|_"),
}
}
}
Expand Down
21 changes: 18 additions & 3 deletions external-crates/move/crates/move-compiler/src/parser/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ use crate::{
diag,
diagnostics::Diagnostic,
editions::{create_feature_error, Edition, FeatureGate},
parser::syntax::make_loc,
parser::{syntax::make_loc, token_set::TokenSet},
shared::CompilationEnv,
FileCommentMap, MatchedFileCommentMap,
};
use move_command_line_common::{character_sets::DisplayChar, files::FileHash};
use move_ir_types::location::Loc;
use std::fmt;
use std::{collections::BTreeSet, fmt};

// This should be replaced with std::mem::variant::count::<Tok>() if it ever comes out of nightly.
pub const TOK_COUNT: usize = 77;

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Tok {
Expand Down Expand Up @@ -182,7 +185,7 @@ impl fmt::Display for Tok {
}

pub struct Lexer<'input> {
text: &'input str,
pub text: &'input str,
file_hash: FileHash,
edition: Edition,
doc_comments: FileCommentMap,
Expand Down Expand Up @@ -216,6 +219,18 @@ impl<'input> Lexer<'input> {
&self.text[self.cur_start..]
}

pub fn at(&self, tok: Tok) -> bool {
self.token == tok
}

pub fn at_any(&self, toks: &BTreeSet<Tok>) -> bool {
toks.contains(&self.token)
}

pub fn at_set(&self, set: &TokenSet) -> bool {
set.contains(self.token, self.content())
}

pub fn content(&self) -> &'input str {
&self.text[self.cur_start..self.cur_end]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub(crate) mod filter;
pub mod keywords;
pub mod lexer;
pub(crate) mod syntax;
mod token_set;
pub(crate) mod verification_attribute_filter;

use crate::{
Expand Down