fix(lexer): Don't require frontmatters to be escaped with indented fences

The RFC only limits hyphens at the beginning of lines and not if they
are indented or embedded in other content.

Sticking to that approach was confirmed by the T-lang liason at
https://github.com/rust-lang/rust/issues/141367#issuecomment-3202217544

There is a regression in error message quality which I'm leaving for
someone if they feel this needs improving.
This commit is contained in:
Ed Page 2025-08-22 10:46:47 -05:00
parent 1f7dcc878d
commit 142e25e356
7 changed files with 56 additions and 79 deletions

View file

@ -550,28 +550,20 @@ impl Cursor<'_> {
self.eat_while(|ch| ch != '\n' && is_whitespace(ch));
let invalid_infostring = self.first() != '\n';
let mut s = self.as_str();
let mut found = false;
let mut size = 0;
while let Some(closing) = s.find(&"-".repeat(length_opening as usize)) {
let preceding_chars_start = s[..closing].rfind("\n").map_or(0, |i| i + 1);
if s[preceding_chars_start..closing].chars().all(is_whitespace) {
// candidate found
self.bump_bytes(size + closing);
// in case like
// ---cargo
// --- blahblah
// or
// ---cargo
// ----
// combine those stuff into this frontmatter token such that it gets detected later.
self.eat_until(b'\n');
found = true;
break;
} else {
s = &s[closing + length_opening as usize..];
size += closing + length_opening as usize;
}
let nl_fence_pattern = format!("\n{:-<1$}", "", length_opening as usize);
if let Some(closing) = self.as_str().find(&nl_fence_pattern) {
// candidate found
self.bump_bytes(closing + nl_fence_pattern.len());
// in case like
// ---cargo
// --- blahblah
// or
// ---cargo
// ----
// combine those stuff into this frontmatter token such that it gets detected later.
self.eat_until(b'\n');
found = true;
}
if !found {

View file

@ -1,7 +1,7 @@
---
//~^ ERROR: invalid preceding whitespace for frontmatter opening
//~^^ ERROR: unclosed frontmatter
---
//~^ ERROR: invalid preceding whitespace for frontmatter close
#![feature(frontmatter)]

View file

@ -10,17 +10,21 @@ note: frontmatter opening should not be preceded by whitespace
LL | ---
| ^^
error: invalid preceding whitespace for frontmatter close
--> $DIR/frontmatter-whitespace-1.rs:3:1
error: unclosed frontmatter
--> $DIR/frontmatter-whitespace-1.rs:1:3
|
LL | / ---
LL | |
LL | |
LL | | ---
LL | |
| |_^
|
note: frontmatter opening here was not closed
--> $DIR/frontmatter-whitespace-1.rs:1:3
|
LL | ---
| ^^^^^
|
note: frontmatter close should not be preceded by whitespace
--> $DIR/frontmatter-whitespace-1.rs:3:1
|
LL | ---
| ^^
| ^^^
error: aborting due to 2 previous errors

View file

@ -1,4 +1,5 @@
---cargo
//~^ ERROR: unclosed frontmatter
//@ compile-flags: --crate-type lib
@ -6,10 +7,8 @@
fn foo(x: i32) -> i32 {
---x
//~^ ERROR: invalid preceding whitespace for frontmatter close
//~| ERROR: extra characters after frontmatter close are not allowed
//~^ WARNING: use of a double negation [double_negations]
}
//~^ ERROR: unexpected closing delimiter: `}`
// this test is for the weird case that valid Rust code can have three dashes
// within them and get treated as a frontmatter close.

View file

@ -1,26 +1,30 @@
error: invalid preceding whitespace for frontmatter close
--> $DIR/frontmatter-whitespace-2.rs:8:1
error: unclosed frontmatter
--> $DIR/frontmatter-whitespace-2.rs:1:1
|
LL | / ---cargo
... |
LL | |
| |_^
|
note: frontmatter opening here was not closed
--> $DIR/frontmatter-whitespace-2.rs:1:1
|
LL | ---cargo
| ^^^
warning: use of a double negation
--> $DIR/frontmatter-whitespace-2.rs:9:6
|
LL | ---x
| ^^^^^^^^
| ^^^
|
note: frontmatter close should not be preceded by whitespace
--> $DIR/frontmatter-whitespace-2.rs:8:1
= note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages
= note: use `-= 1` if you meant to decrement the value
= note: `#[warn(double_negations)]` on by default
help: add parentheses for clarity
|
LL | ---x
| ^^^^
LL | --(-x)
| + +
error: extra characters after frontmatter close are not allowed
--> $DIR/frontmatter-whitespace-2.rs:8:1
|
LL | ---x
| ^^^^^^^^
error: unexpected closing delimiter: `}`
--> $DIR/frontmatter-whitespace-2.rs:11:1
|
LL | }
| ^ unexpected closing delimiter
error: aborting due to 3 previous errors
error: aborting due to 1 previous error; 1 warning emitted

View file

@ -1,12 +1,12 @@
---
---
//~^ ERROR: invalid preceding whitespace for frontmatter close
---
//~^ ERROR: expected item, found `-`
// FIXME(frontmatter): make this diagnostic better
---
// hyphens only need to be escaped when at the start of a line
//@ check-pass
#![feature(frontmatter)]
fn main() {}

View file

@ -1,22 +0,0 @@
error: invalid preceding whitespace for frontmatter close
--> $DIR/multifrontmatter-2.rs:2:1
|
LL | ---
| ^^^^
|
note: frontmatter close should not be preceded by whitespace
--> $DIR/multifrontmatter-2.rs:2:1
|
LL | ---
| ^
error: expected item, found `-`
--> $DIR/multifrontmatter-2.rs:5:2
|
LL | ---
| ^ expected item
|
= note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>
error: aborting due to 2 previous errors