Skip to content

Remove diff marker detection. #134189

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ pub(crate) fn lex_token_trees<'psess, 'src>(
.filter_map(|unmatched_delim| make_unclosed_delims_error(unmatched_delim, psess))
.collect();
if let Err(errs) = res {
// Add unclosing delimiter or diff marker errors
// Add unclosing delimiter errors.
buffer.extend(errs);
}
Err(buffer)
Expand Down
25 changes: 5 additions & 20 deletions compiler/rustc_parse/src/lexer/tokentrees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
// We stop at any delimiter so we can try to recover if the user
// uses an incorrect delimiter.
let (open_spacing, tts, res) = self.lex_token_trees(/* is_delimited */ true);
if let Err(errs) = res {
return Err(self.unclosed_delim_err(tts, errs));
if let Err(mut errs) = res {
self.unclosed_delim_err(tts, &mut errs);
return Err(errs);
}

// Expand to cover the entire delimited token tree.
Expand Down Expand Up @@ -247,23 +248,14 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
this_spacing
}

fn unclosed_delim_err(
&mut self,
tts: TokenStream,
mut errs: Vec<PErr<'psess>>,
) -> Vec<PErr<'psess>> {
// If there are unclosed delims, see if there are diff markers and if so, point them
// out instead of complaining about the unclosed delims.
fn unclosed_delim_err(&mut self, tts: TokenStream, errs: &mut Vec<PErr<'psess>>) {
let mut parser = Parser::new(self.psess, tts, None);
let mut diff_errs = vec![];
// Suggest removing a `{` we think appears in an `if`/`while` condition.
// We want to suggest removing a `{` only if we think we're in an `if`/`while` condition,
// but we have no way of tracking this in the lexer itself, so we piggyback on the parser.
let mut in_cond = false;
while parser.token != token::Eof {
if let Err(diff_err) = parser.err_vcs_conflict_marker() {
diff_errs.push(diff_err);
} else if parser.is_keyword_ahead(0, &[kw::If, kw::While]) {
if parser.is_keyword_ahead(0, &[kw::If, kw::While]) {
in_cond = true;
} else if matches!(
parser.token.kind,
Expand Down Expand Up @@ -299,13 +291,6 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
}
parser.bump();
}
if !diff_errs.is_empty() {
for err in errs {
err.cancel();
}
return diff_errs;
}
errs
}

fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'psess> {
Expand Down
116 changes: 1 addition & 115 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, PErr, PResult, Subdiagnostic,
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, PErr, PResult, Subdiagnostic,
Suggestions, pluralize,
};
use rustc_session::errors::ExprParenthesesNeeded;
Expand Down Expand Up @@ -3029,120 +3029,6 @@ impl<'a> Parser<'a> {
err
}

/// This checks if this is a conflict marker, depending of the parameter passed.
///
/// * `<<<<<<<`
/// * `|||||||`
/// * `=======`
/// * `>>>>>>>`
///
pub(super) fn is_vcs_conflict_marker(
&mut self,
long_kind: &TokenKind,
short_kind: &TokenKind,
) -> bool {
(0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind))
&& self.look_ahead(3, |tok| tok == short_kind)
}

fn conflict_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> Option<Span> {
if self.is_vcs_conflict_marker(long_kind, short_kind) {
let lo = self.token.span;
for _ in 0..4 {
self.bump();
}
return Some(lo.to(self.prev_token.span));
}
None
}

pub(super) fn recover_vcs_conflict_marker(&mut self) {
if let Err(err) = self.err_vcs_conflict_marker() {
err.emit();
FatalError.raise();
}
}

pub(crate) fn err_vcs_conflict_marker(&mut self) -> PResult<'a, ()> {
// <<<<<<<
let Some(start) = self.conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt)
else {
return Ok(());
};
let mut spans = Vec::with_capacity(3);
spans.push(start);
// |||||||
let mut middlediff3 = None;
// =======
let mut middle = None;
// >>>>>>>
let mut end = None;
loop {
if self.token == TokenKind::Eof {
break;
}
if let Some(span) = self.conflict_marker(&TokenKind::OrOr, &TokenKind::BinOp(token::Or))
{
middlediff3 = Some(span);
}
if let Some(span) = self.conflict_marker(&TokenKind::EqEq, &TokenKind::Eq) {
middle = Some(span);
}
if let Some(span) = self.conflict_marker(&TokenKind::BinOp(token::Shr), &TokenKind::Gt)
{
spans.push(span);
end = Some(span);
break;
}
self.bump();
}

let mut err = self.dcx().struct_span_err(spans, "encountered diff marker");
match middlediff3 {
// We're using diff3
Some(middlediff3) => {
err.span_label(
start,
"between this marker and `|||||||` is the code that we're merging into",
);
err.span_label(middlediff3, "between this marker and `=======` is the base code (what the two refs diverged from)");
}
None => {
err.span_label(
start,
"between this marker and `=======` is the code that we're merging into",
);
}
};

if let Some(middle) = middle {
err.span_label(middle, "between this marker and `>>>>>>>` is the incoming code");
}
if let Some(end) = end {
err.span_label(end, "this marker concludes the conflict region");
}
err.note(
"conflict markers indicate that a merge was started but could not be completed due \
to merge conflicts\n\
to resolve a conflict, keep only the code you want and then delete the lines \
containing conflict markers",
);
err.help(
"if you're having merge conflicts after pulling new code:\n\
the top section is the code you already had and the bottom section is the remote code\n\
if you're in the middle of a rebase:\n\
the top section is the code being rebased onto and the bottom section is the code \
coming from the current commit being rebased",
);

err.note(
"for an explanation on these markers from the `git` documentation:\n\
visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>",
);

Err(err)
}

/// Parse and throw away a parenthesized comma separated
/// sequence of patterns until `)` is reached.
fn skip_pat_list(&mut self) -> PResult<'a, ()> {
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3739,7 +3739,6 @@ impl<'a> Parser<'a> {
/// Parses `ident (COLON expr)?`.
fn parse_expr_field(&mut self) -> PResult<'a, ExprField> {
let attrs = self.parse_outer_attributes()?;
self.recover_vcs_conflict_marker();
self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
let lo = this.token.span;

Expand Down
42 changes: 4 additions & 38 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,7 @@ impl<'a> Parser<'a> {
fn_parse_mode: FnParseMode,
force_collect: ForceCollect,
) -> PResult<'a, Option<Item>> {
self.recover_vcs_conflict_marker();
let attrs = self.parse_outer_attributes()?;
self.recover_vcs_conflict_marker();
self.parse_item_common(attrs, true, false, fn_parse_mode, force_collect)
}

Expand Down Expand Up @@ -775,7 +773,6 @@ impl<'a> Parser<'a> {
if self.recover_doc_comment_before_brace() {
continue;
}
self.recover_vcs_conflict_marker();
match parse_item(self) {
Ok(None) => {
let mut is_unnecessary_semicolon = !items.is_empty()
Expand Down Expand Up @@ -1121,11 +1118,8 @@ impl<'a> Parser<'a> {
/// USE_TREE_LIST = ∅ | (USE_TREE `,`)* USE_TREE [`,`]
/// ```
fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {
self.parse_delim_comma_seq(Delimiter::Brace, |p| {
p.recover_vcs_conflict_marker();
Ok((p.parse_use_tree()?, DUMMY_NODE_ID))
})
.map(|(r, _)| r)
self.parse_delim_comma_seq(Delimiter::Brace, |p| Ok((p.parse_use_tree()?, DUMMY_NODE_ID)))
.map(|(r, _)| r)
}

fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
Expand Down Expand Up @@ -1564,9 +1558,7 @@ impl<'a> Parser<'a> {
}

fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
self.recover_vcs_conflict_marker();
let variant_attrs = self.parse_outer_attributes()?;
self.recover_vcs_conflict_marker();
let help = "enum variants can be `Variant`, `Variant = <integer>`, \
`Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";
self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| {
Expand Down Expand Up @@ -1808,34 +1800,11 @@ impl<'a> Parser<'a> {
self.parse_paren_comma_seq(|p| {
let attrs = p.parse_outer_attributes()?;
p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
let mut snapshot = None;
if p.is_vcs_conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) {
// Account for `<<<<<<<` diff markers. We can't proactively error here because
// that can be a valid type start, so we snapshot and reparse only we've
// encountered another parse error.
snapshot = Some(p.create_snapshot_for_diagnostic());
}
let lo = p.token.span;
let vis = match p.parse_visibility(FollowedByType::Yes) {
Ok(vis) => vis,
Err(err) => {
if let Some(ref mut snapshot) = snapshot {
snapshot.recover_vcs_conflict_marker();
}
return Err(err);
}
};
let vis = p.parse_visibility(FollowedByType::Yes)?;
// Unsafe fields are not supported in tuple structs, as doing so would result in a
// parsing ambiguity for `struct X(unsafe fn())`.
let ty = match p.parse_ty() {
Ok(ty) => ty,
Err(err) => {
if let Some(ref mut snapshot) = snapshot {
snapshot.recover_vcs_conflict_marker();
}
return Err(err);
}
};
let ty = p.parse_ty()?;
let mut default = None;
if p.token == token::Eq {
let mut snapshot = p.create_snapshot_for_diagnostic();
Expand Down Expand Up @@ -1875,9 +1844,7 @@ impl<'a> Parser<'a> {

/// Parses an element of a struct declaration.
fn parse_field_def(&mut self, adt_ty: &str) -> PResult<'a, FieldDef> {
self.recover_vcs_conflict_marker();
let attrs = self.parse_outer_attributes()?;
self.recover_vcs_conflict_marker();
self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
let lo = this.token.span;
let vis = this.parse_visibility(FollowedByType::No)?;
Expand Down Expand Up @@ -2830,7 +2797,6 @@ impl<'a> Parser<'a> {
}

let (mut params, _) = self.parse_paren_comma_seq(|p| {
p.recover_vcs_conflict_marker();
let snapshot = p.create_snapshot_for_diagnostic();
let param = p.parse_param_general(req_name, first_param).or_else(|e| {
let guar = e.emit();
Expand Down
12 changes: 1 addition & 11 deletions compiler/rustc_parse/src/parser/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::ops::Bound;
use ast::Label;
use rustc_ast as ast;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, TokenKind};
use rustc_ast::token::{self, Delimiter};
use rustc_ast::util::classify::{self, TrailingBrace};
use rustc_ast::{
AttrStyle, AttrVec, Block, BlockCheckMode, DUMMY_NODE_ID, Expr, ExprKind, HasAttrs, Local,
Expand Down Expand Up @@ -678,22 +678,12 @@ impl<'a> Parser<'a> {
recover: AttemptLocalParseRecovery,
) -> PResult<'a, P<Block>> {
let mut stmts = ThinVec::new();
let mut snapshot = None;
while !self.eat(&token::CloseDelim(Delimiter::Brace)) {
if self.token == token::Eof {
break;
}
if self.is_vcs_conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) {
// Account for `<<<<<<<` diff markers. We can't proactively error here because
// that can be a valid path start, so we snapshot and reparse only we've
// encountered another parse error.
snapshot = Some(self.create_snapshot_for_diagnostic());
}
let stmt = match self.parse_full_stmt(recover) {
Err(mut err) if recover.yes() => {
if let Some(ref mut snapshot) = snapshot {
snapshot.recover_vcs_conflict_marker();
}
if self.token == token::Colon {
// if a previous and next token of the current one is
// integer literal (e.g. `1:42`), it's likely a range
Expand Down
11 changes: 0 additions & 11 deletions tests/ui/parser/diff-markers/enum-2.rs

This file was deleted.

26 changes: 0 additions & 26 deletions tests/ui/parser/diff-markers/enum-2.stderr

This file was deleted.

7 changes: 0 additions & 7 deletions tests/ui/parser/diff-markers/enum.rs

This file was deleted.

23 changes: 0 additions & 23 deletions tests/ui/parser/diff-markers/enum.stderr

This file was deleted.

Loading
Loading