Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 42 additions & 10 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3037,27 +3037,53 @@ impl<'a> Parser<'a> {
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)
if long_kind == short_kind {
// For conflict marker chars like `%` and `\`.
(0..7).all(|i| self.look_ahead(i, |tok| tok == long_kind))
} else {
// For conflict marker chars like `<` and `|`.
(0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind))
&& self.look_ahead(3, |tok| tok == short_kind || tok == long_kind)
}
}

fn conflict_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> Option<Span> {
fn conflict_marker(
&mut self,
long_kind: &TokenKind,
short_kind: &TokenKind,
expected: Option<usize>,
) -> Option<(Span, usize)> {
if self.is_vcs_conflict_marker(long_kind, short_kind) {
let lo = self.token.span;
for _ in 0..4 {
if self.psess.source_map().span_to_margin(lo) != Some(0) {
return None;
}
let mut len = 0;
while self.token.kind == *long_kind || self.token.kind == *short_kind {
if self.token.kind.break_two_token_op(1).is_some() {
len += 2;
} else {
len += 1;
}
self.bump();
if expected == Some(len) {
break;
}
}
if expected.is_some() && expected != Some(len) {
return None;
}
return Some(lo.to(self.prev_token.span));
return Some((lo.to(self.prev_token.span), len));
}
None
}

pub(super) fn recover_vcs_conflict_marker(&mut self) {
// <<<<<<<
let Some(start) = self.conflict_marker(&TokenKind::Shl, &TokenKind::Lt) else {
let Some((start, len)) = self.conflict_marker(&TokenKind::Shl, &TokenKind::Lt, None) else {
return;
};
let mut spans = Vec::with_capacity(3);
let mut spans = Vec::with_capacity(2);
spans.push(start);
// |||||||
let mut middlediff3 = None;
Expand All @@ -3069,13 +3095,19 @@ impl<'a> Parser<'a> {
if self.token == TokenKind::Eof {
break;
}
if let Some(span) = self.conflict_marker(&TokenKind::OrOr, &TokenKind::Or) {
if let Some((span, _)) =
self.conflict_marker(&TokenKind::OrOr, &TokenKind::Or, Some(len))
{
middlediff3 = Some(span);
}
if let Some(span) = self.conflict_marker(&TokenKind::EqEq, &TokenKind::Eq) {
if let Some((span, _)) =
self.conflict_marker(&TokenKind::EqEq, &TokenKind::Eq, Some(len))
{
middle = Some(span);
}
if let Some(span) = self.conflict_marker(&TokenKind::Shr, &TokenKind::Gt) {
if let Some((span, _)) =
self.conflict_marker(&TokenKind::Shr, &TokenKind::Gt, Some(len))
{
spans.push(span);
end = Some(span);
break;
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/parser/diff-markers/long-conflict-markers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
enum E {
Foo {
<<<<<<<<< HEAD //~ ERROR encountered diff marker
x: u8,
|||||||
z: (),
=========
y: i8,
>>>>>>>>> branch
}
}
20 changes: 20 additions & 0 deletions tests/ui/parser/diff-markers/long-conflict-markers.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error: encountered diff marker
--> $DIR/long-conflict-markers.rs:3:1
|
LL | <<<<<<<<< HEAD
| ^^^^^^^^^ between this marker and `=======` is the code that you are merging into
...
LL | =========
| --------- between this marker and `>>>>>>>` is the incoming code
LL | y: i8,
LL | >>>>>>>>> branch
| ^^^^^^^^^ this marker concludes the conflict region
|
= note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts
to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers
= help: if you are in a merge, the top section is the code you already had checked out and the bottom section is the new code
if you are in a rebase, the top section is the code being rebased onto and the bottom section is the code you had checked out which is being rebased
= note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>

error: aborting due to 1 previous error

Loading