Skip to content

Commit 97f6445

Browse files
committed
Merge pull request #38 from MicahChalmer/fix-issue-36
Fix emacs state corruption from incorrect "syntax-begin-function" setting
2 parents 3a0a727 + fea20e7 commit 97f6445

File tree

2 files changed

+96
-2
lines changed

2 files changed

+96
-2
lines changed

rust-mode-tests.el

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ very very very long string
293293
;; The indentation will fail in some cases if the syntax properties are
294294
;; not set. This only happens when font-lock fontifies the buffer.
295295
(font-lock-fontify-buffer)
296-
(indent-region 1 (buffer-size)))
296+
(indent-region 1 (+ 1 (buffer-size))))
297297
indented)))
298298

299299

@@ -1110,3 +1110,98 @@ fn main() { // comment here should not push next line out
11101110
}
11111111
"
11121112
)))
1113+
1114+
(ert-deftest test-for-issue-36-syntax-corrupted-state ()
1115+
"This is a test for a issue #36, which involved emacs's
1116+
internal state getting corrupted when actions were done in a
1117+
specific sequence. The test seems arbitrary, and is, but it was
1118+
not clear how to narrow it down further.
1119+
1120+
The cause of the bug was code that used to set
1121+
`syntax-begin-function' to `beginning-of-defun', which doesn't
1122+
actually fulfill the expectations--`syntax-begin-function' is
1123+
supposed to back out of all parens, but `beginning-of-defun'
1124+
could leave it inside parens if a fn appears inside them.
1125+
1126+
Having said that, as I write this I don't understand fully what
1127+
internal state was corruped and how. There wasn't an obvious
1128+
pattern to what did and did not trip it."
1129+
1130+
;; When bug #36 was present, the following test would pass, but running it
1131+
;; caused some unknown emacs state to be corrupted such that the following
1132+
;; test failed. Both the "blank_line" and "indented_closing_brace" functions
1133+
(with-temp-buffer
1134+
(rust-mode)
1135+
(insert "fn blank_line(arg:int) -> bool {
1136+
1137+
}
1138+
1139+
fn indenting_closing_brace() {
1140+
if(true) {
1141+
}
1142+
}
1143+
1144+
fn indented_already() {
1145+
\n // The previous line already has its spaces
1146+
}
1147+
")
1148+
1149+
(goto-line 11)
1150+
(move-to-column 0)
1151+
(indent-for-tab-command)
1152+
(should (equal (current-column) 4))
1153+
)
1154+
1155+
;; This is the test that would fail only after running the previous one. The
1156+
;; code is extracted from src/libstd/collections/table.rs in the rust tree.
1157+
;; It was not clear how to reduce it further--removing various bits of it
1158+
;; would make it no longer fail. In particular, changing only the comment at
1159+
;; the top of the "next" function was sufficient to make it no longer fail.
1160+
(test-indent
1161+
"
1162+
impl Foo for Bar {
1163+
1164+
/// Modifies the bucket pointer in place to make it point to the next slot.
1165+
pub fn next(&mut self) {
1166+
// Branchless bucket
1167+
// As we reach the end of the table...
1168+
// We take the current idx: 0111111b
1169+
// Xor it by its increment: ^ 1000000b
1170+
// ------------
1171+
// 1111111b
1172+
// Then AND with the capacity: & 1000000b
1173+
// ------------
1174+
// to get the backwards offset: 1000000b
1175+
let maybe_wraparound_dist = (self.idx ^ (self.idx + 1)) & self.table.capacity();
1176+
// Finally, we obtain the offset 1 or the offset -cap + 1.
1177+
let dist = 1 - (maybe_wraparound_dist as isize);
1178+
1179+
self.idx += 1;
1180+
1181+
unsafe {
1182+
self.raw = self.raw.offset(dist);
1183+
}
1184+
}
1185+
1186+
/// Reads a bucket at a given index, returning an enum indicating whether
1187+
/// the appropriate types to call most of the other functions in
1188+
/// this module.
1189+
pub fn peek(self) {
1190+
match foo {
1191+
EMPTY_BUCKET =>
1192+
Empty(EmptyBucket {
1193+
raw: self.raw,
1194+
idx: self.idx,
1195+
table: self.table
1196+
}),
1197+
_ =>
1198+
Full(FullBucket {
1199+
raw: self.raw,
1200+
idx: self.idx,
1201+
table: self.table
1202+
})
1203+
}
1204+
}
1205+
}
1206+
"
1207+
))

rust-mode.el

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,6 @@ This is written mainly to be used as `end-of-defun-function' for Rust."
661661
(setq-local beginning-of-defun-function 'rust-beginning-of-defun)
662662
(setq-local end-of-defun-function 'rust-end-of-defun)
663663
(setq-local parse-sexp-lookup-properties t)
664-
(setq-local syntax-begin-function 'beginning-of-defun)
665664
(add-hook 'post-self-insert-hook 'rust-match-angle-bracket-hook))
666665

667666
;;;###autoload

0 commit comments

Comments
 (0)