Commit 8401398

Browse files
committed
Auto merge of #148762 - matthiaskrgr:rollup-4oifvkr, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #148248 (Constify `ControlFlow` methods without unstable bounds) - #148285 (Constify `ControlFlow` methods with unstable bounds) - #148510 (compiletest: Do the known-directives check only once, and improve its error message) - #148655 (Fix invalid macro tag generation for keywords which can be followed by values) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 6647be9 + 5430082 commit 8401398

8 files changed

Lines changed: 177 additions & 98 deletions

File tree

‎library/core/src/ops/control_flow.rs‎

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
usecrate::marker::Destruct;
12
usecrate::{convert, ops};
23

34
/// Used to tell an operation whether it should exit early or go on as usual.
@@ -150,7 +151,8 @@ impl<B, C> ControlFlow<B, C> {
150151
/// ```
151152
#[inline]
152153
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
153-
pubfnis_break(&self) -> bool{
154+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
155+
pubconstfnis_break(&self) -> bool{
154156
matches!(*self,ControlFlow::Break(_))
155157
}
156158

@@ -166,7 +168,8 @@ impl<B, C> ControlFlow<B, C> {
166168
/// ```
167169
#[inline]
168170
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
169-
pubfnis_continue(&self) -> bool{
171+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
172+
pubconstfnis_continue(&self) -> bool{
170173
matches!(*self,ControlFlow::Continue(_))
171174
}
172175

@@ -183,7 +186,11 @@ impl<B, C> ControlFlow<B, C> {
183186
/// ```
184187
#[inline]
185188
#[stable(feature = "control_flow_enum", since = "1.83.0")]
186-
pubfnbreak_value(self) -> Option<B>{
189+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
190+
pubconstfnbreak_value(self) -> Option<B>
191+
where
192+
Self:[const]Destruct,
193+
{
187194
matchself{
188195
ControlFlow::Continue(..) => None,
189196
ControlFlow::Break(x) => Some(x),
@@ -257,7 +264,8 @@ impl<B, C> ControlFlow<B, C> {
257264
/// ```
258265
#[inline]
259266
#[unstable(feature = "control_flow_ok", issue = "140266")]
260-
pubfnbreak_ok(self) -> Result<B,C>{
267+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
268+
pubconstfnbreak_ok(self) -> Result<B,C>{
261269
matchself{
262270
ControlFlow::Continue(c) => Err(c),
263271
ControlFlow::Break(b) => Ok(b),
@@ -268,7 +276,11 @@ impl<B, C> ControlFlow<B, C> {
268276
/// to the break value in case it exists.
269277
#[inline]
270278
#[stable(feature = "control_flow_enum", since = "1.83.0")]
271-
pubfnmap_break<T>(self,f:implFnOnce(B) -> T) -> ControlFlow<T,C>{
279+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
280+
pubconstfn map_break<T,F>(self,f:F) -> ControlFlow<T,C>
281+
where
282+
F:[const]FnOnce(B) -> T + [const]Destruct,
283+
{
272284
matchself{
273285
ControlFlow::Continue(x) => ControlFlow::Continue(x),
274286
ControlFlow::Break(x) => ControlFlow::Break(f(x)),
@@ -288,7 +300,11 @@ impl<B, C> ControlFlow<B, C> {
288300
/// ```
289301
#[inline]
290302
#[stable(feature = "control_flow_enum", since = "1.83.0")]
291-
pubfncontinue_value(self) -> Option<C>{
303+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
304+
pub constfncontinue_value(self) -> Option<C>
305+
where
306+
Self:[const]Destruct,
307+
{
292308
matchself{
293309
ControlFlow::Continue(x) => Some(x),
294310
ControlFlow::Break(..) => None,
@@ -361,7 +377,8 @@ impl<B, C> ControlFlow<B, C> {
361377
/// ```
362378
#[inline]
363379
#[unstable(feature = "control_flow_ok", issue = "140266")]
364-
pubfncontinue_ok(self) -> Result<C,B>{
380+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
381+
pub constfncontinue_ok(self) -> Result<C,B>{
365382
matchself{
366383
ControlFlow::Continue(c) => Ok(c),
367384
ControlFlow::Break(b) => Err(b),
@@ -372,7 +389,11 @@ impl<B, C> ControlFlow<B, C> {
372389
/// to the continue value in case it exists.
373390
#[inline]
374391
#[stable(feature = "control_flow_enum", since = "1.83.0")]
375-
pubfnmap_continue<T>(self,f:implFnOnce(C) -> T) -> ControlFlow<B,T>{
392+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
393+
pub constfnmap_continue<T,F>(self,f:F) -> ControlFlow<B,T>
394+
where
395+
F:[const]FnOnce(C) -> T + [const]Destruct,
396+
{
376397
matchself{
377398
ControlFlow::Continue(x) => ControlFlow::Continue(f(x)),
378399
ControlFlow::Break(x) => ControlFlow::Break(x),

‎src/librustdoc/html/highlight.rs‎

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,9 @@ impl<'a> Iterator for TokenIter<'a> {
789789
}
790790
}
791791

792+
/// Used to know if a keyword followed by a `!` should never be treated as a macro.
793+
constNON_MACRO_KEYWORDS:&[&str] = &["if","while","match","break","return","impl"];
794+
792795
/// This iterator comes from the same idea than "Peekable" except that it allows to "peek" more than
793796
/// just the next item by using `peek_next`. The `peek` method always returns the next item after
794797
/// the current one whereas `peek_next` will return the next item after the last one peeked.
@@ -1010,6 +1013,19 @@ impl<'src> Classifier<'src> {
10101013
}
10111014
}
10121015

1016+
fnnew_macro_span(
1017+
&mutself,
1018+
text:&'srcstr,
1019+
sink:&mutdynFnMut(Span,Highlight<'src>),
1020+
before:u32,
1021+
file_span:Span,
1022+
){
1023+
self.in_macro = true;
1024+
let span = new_span(before, text, file_span);
1025+
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1026+
sink(span,Highlight::Token{ text,class:None});
1027+
}
1028+
10131029
/// Single step of highlighting. This will classify `token`, but maybe also a couple of
10141030
/// following ones as well.
10151031
///
@@ -1216,16 +1232,46 @@ impl<'src> Classifier<'src> {
12161232
LiteralKind::Float{ .. } | LiteralKind::Int{ .. } => Class::Number,
12171233
},
12181234
TokenKind::GuardedStrPrefix => returnno_highlight(sink),
1219-
TokenKind::Ident | TokenKind::RawIdent
1220-
ifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() =>
1221-
{
1222-
self.in_macro = true;
1223-
let span = new_span(before, text, file_span);
1224-
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1225-
sink(span,Highlight::Token{ text,class:None});
1235+
TokenKind::RawIdentifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() => {
1236+
self.new_macro_span(text, sink, before, file_span);
12261237
return;
12271238
}
1228-
TokenKind::Ident => self.classify_ident(before, text),
1239+
// Macro non-terminals (meta vars) take precedence.
1240+
TokenKind::Identifself.in_macro_nonterminal => {
1241+
self.in_macro_nonterminal = false;
1242+
Class::MacroNonTerminal
1243+
}
1244+
TokenKind::Ident => {
1245+
let file_span = self.file_span;
1246+
let span = || new_span(before, text, file_span);
1247+
1248+
match text {
1249+
"ref" | "mut" => Class::RefKeyWord,
1250+
"false" | "true" => Class::Bool,
1251+
"self" | "Self" => Class::Self_(span()),
1252+
"Option" | "Result" => Class::PreludeTy(span()),
1253+
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1254+
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => {
1255+
// So if it's not a keyword which can be followed by a value (like `if` or
1256+
// `return`) and the next non-whitespace token is a `!`, then we consider
1257+
// it's a macro.
1258+
if !NON_MACRO_KEYWORDS.contains(&text)
1259+
&& matches!(self.peek_non_trivia(),Some((TokenKind::Bang, _)))
1260+
{
1261+
self.new_macro_span(text, sink, before, file_span);
1262+
return;
1263+
}
1264+
Class::KeyWord
1265+
}
1266+
// If it's not a keyword and the next non whitespace token is a `!`, then
1267+
// we consider it's a macro.
1268+
_ ifmatches!(self.peek_non_trivia(),Some((TokenKind::Bang, _))) => {
1269+
self.new_macro_span(text, sink, before, file_span);
1270+
return;
1271+
}
1272+
_ => Class::Ident(span()),
1273+
}
1274+
}
12291275
TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
12301276
Class::Ident(new_span(before, text, file_span))
12311277
}
@@ -1246,27 +1292,6 @@ impl<'src> Classifier<'src> {
12461292
}
12471293
}
12481294

1249-
fnclassify_ident(&mutself,before:u32,text:&'srcstr) -> Class{
1250-
// Macro non-terminals (meta vars) take precedence.
1251-
ifself.in_macro_nonterminal{
1252-
self.in_macro_nonterminal = false;
1253-
returnClass::MacroNonTerminal;
1254-
}
1255-
1256-
let file_span = self.file_span;
1257-
let span = || new_span(before, text, file_span);
1258-
1259-
match text {
1260-
"ref" | "mut" => Class::RefKeyWord,
1261-
"false" | "true" => Class::Bool,
1262-
"self" | "Self" => Class::Self_(span()),
1263-
"Option" | "Result" => Class::PreludeTy(span()),
1264-
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1265-
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => Class::KeyWord,
1266-
_ => Class::Ident(span()),
1267-
}
1268-
}
1269-
12701295
fnis_weak_keyword(&mutself,text:&str) -> bool{
12711296
// NOTE: `yeet` (`do yeet $expr`), `catch` (`do catch $block`), `default` (specialization),
12721297
// `contract_{ensures,requires}`, `builtin` (builtin_syntax) & `reuse` (fn_delegation) are

‎src/tools/compiletest/src/directives.rs‎

Lines changed: 33 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::debuggers::{extract_cdb_version, extract_gdb_version};
1111
pub(crate)usecrate::directives::auxiliary::AuxProps;
1212
usecrate::directives::auxiliary::parse_and_update_aux;
1313
usecrate::directives::directive_names::{
14-
KNOWN_DIRECTIVE_NAMES,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
14+
KNOWN_DIRECTIVE_NAMES_SET,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
1515
};
1616
pub(crate)usecrate::directives::file::FileDirectives;
1717
usecrate::directives::line::{DirectiveLine, line_directive};
@@ -53,25 +53,17 @@ impl EarlyProps {
5353
config:&Config,
5454
file_directives:&FileDirectives<'_>,
5555
) -> Self{
56-
let testfile = file_directives.path;
5756
letmut props = EarlyProps::default();
58-
letmut poisoned = false;
5957

6058
iter_directives(
6159
config.mode,
62-
&mut poisoned,
6360
file_directives,
6461
// (dummy comment to force args into vertical layout)
6562
&mut |ln:&DirectiveLine<'_>| {
6663
config.parse_and_update_revisions(ln,&mut props.revisions);
6764
},
6865
);
6966

70-
if poisoned {
71-
eprintln!("errors encountered during EarlyProps parsing: {}", testfile);
72-
panic!("errors encountered during EarlyProps parsing");
73-
}
74-
7567
props
7668
}
7769
}
@@ -358,12 +350,10 @@ impl TestProps {
358350
let file_contents = fs::read_to_string(testfile).unwrap();
359351
let file_directives = FileDirectives::from_file_contents(testfile,&file_contents);
360352

361-
letmut poisoned = false;
362-
363353
iter_directives(
364354
config.mode,
365-
&mut poisoned,
366355
&file_directives,
356+
// (dummy comment to force args into vertical layout)
367357
&mut |ln:&DirectiveLine<'_>| {
368358
if !ln.applies_to_test_revision(test_revision){
369359
return;
@@ -634,11 +624,6 @@ impl TestProps {
634624
);
635625
},
636626
);
637-
638-
if poisoned {
639-
eprintln!("errors encountered during TestProps parsing: {}", testfile);
640-
panic!("errors encountered during TestProps parsing");
641-
}
642627
}
643628

644629
ifself.should_ice{
@@ -775,6 +760,34 @@ impl TestProps {
775760
}
776761
}
777762

763+
pub(crate)fndo_early_directives_check(
764+
mode:TestMode,
765+
file_directives:&FileDirectives<'_>,
766+
) -> Result<(),String>{
767+
let testfile = file_directives.path;
768+
769+
for directive_line @ DirectiveLine{ line_number, .. }in&file_directives.lines{
770+
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
771+
check_directive(directive_line, mode);
772+
773+
if !is_known_directive {
774+
returnErr(format!(
775+
"ERROR: unknown compiletest directive `{directive}` at {testfile}:{line_number}",
776+
directive = directive_line.display(),
777+
));
778+
}
779+
780+
ifletSome(trailing_directive) = &trailing_directive {
781+
returnErr(format!(
782+
"ERROR: detected trailing compiletest directive `{trailing_directive}` at {testfile}:{line_number}\n\
783+
HELP: put the directive on its own line: `//@ {trailing_directive}`"
784+
));
785+
}
786+
}
787+
788+
Ok(())
789+
}
790+
778791
pub(crate)structCheckDirectiveResult<'ln>{
779792
is_known_directive:bool,
780793
trailing_directive:Option<&'lnstr>,
@@ -786,7 +799,7 @@ fn check_directive<'a>(
786799
) -> CheckDirectiveResult<'a>{
787800
let&DirectiveLine{name: directive_name, .. } = directive_ln;
788801

789-
let is_known_directive = KNOWN_DIRECTIVE_NAMES.contains(&directive_name)
802+
let is_known_directive = KNOWN_DIRECTIVE_NAMES_SET.contains(&directive_name)
790803
|| match mode {
791804
TestMode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
792805
TestMode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
@@ -799,7 +812,7 @@ fn check_directive<'a>(
799812
let trailing_directive = directive_ln
800813
.remark_after_space()
801814
.map(|remark| remark.trim_start().split(' ').next().unwrap())
802-
.filter(|token| KNOWN_DIRECTIVE_NAMES.contains(token));
815+
.filter(|token| KNOWN_DIRECTIVE_NAMES_SET.contains(token));
803816

804817
// FIXME(Zalathar): Consider emitting specialized error/help messages for
805818
// bogus directive names that are similar to real ones, e.g.:
@@ -811,7 +824,6 @@ fn check_directive<'a>(
811824

812825
fniter_directives(
813826
mode:TestMode,
814-
poisoned:&mutbool,
815827
file_directives:&FileDirectives<'_>,
816828
it:&mutdynFnMut(&DirectiveLine<'_>),
817829
){
@@ -837,36 +849,7 @@ fn iter_directives(
837849
}
838850
}
839851

840-
for directive_line @ &DirectiveLine{ line_number, .. }in&file_directives.lines{
841-
// Perform unknown directive check on Rust files.
842-
if testfile.extension() == Some("rs"){
843-
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
844-
check_directive(directive_line, mode);
845-
846-
if !is_known_directive {
847-
*poisoned = true;
848-
849-
error!(
850-
"{testfile}:{line_number}: detected unknown compiletest test directive `{}`",
851-
directive_line.display(),
852-
);
853-
854-
return;
855-
}
856-
857-
ifletSome(trailing_directive) = &trailing_directive {
858-
*poisoned = true;
859-
860-
error!(
861-
"{testfile}:{line_number}: detected trailing compiletest test directive `{}`",
862-
trailing_directive,
863-
);
864-
help!("put the trailing directive in its own line: `//@ {}`", trailing_directive);
865-
866-
return;
867-
}
868-
}
869-
852+
for directive_line in&file_directives.lines{
870853
it(directive_line);
871854
}
872855
}
@@ -1304,12 +1287,9 @@ pub(crate) fn make_test_description(
13041287
letmut ignore_message = None;
13051288
letmut should_fail = false;
13061289

1307-
letmut local_poisoned = false;
1308-
13091290
// Scan through the test file to handle `ignore-*`, `only-*`, and `needs-*` directives.
13101291
iter_directives(
13111292
config.mode,
1312-
&mut local_poisoned,
13131293
file_directives,
13141294
&mut |ln @ &DirectiveLine{ line_number, .. }| {
13151295
if !ln.applies_to_test_revision(test_revision){
@@ -1358,11 +1338,6 @@ pub(crate) fn make_test_description(
13581338
},
13591339
);
13601340

1361-
if local_poisoned {
1362-
eprintln!("errors encountered when trying to make test description: {}", path);
1363-
panic!("errors encountered when trying to make test description");
1364-
}
1365-
13661341
// The `should-fail` annotation doesn't apply to pretty tests,
13671342
// since we run the pretty printer across all tests by default.
13681343
// If desired, we could add a `should-fail-pretty` annotation.

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Commit 8401398

Browse files
committed
Auto merge of #148762 - matthiaskrgr:rollup-4oifvkr, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #148248 (Constify `ControlFlow` methods without unstable bounds) - #148285 (Constify `ControlFlow` methods with unstable bounds) - #148510 (compiletest: Do the known-directives check only once, and improve its error message) - #148655 (Fix invalid macro tag generation for keywords which can be followed by values) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 6647be9 + 5430082 commit 8401398

8 files changed

Lines changed: 177 additions & 98 deletions

File tree

‎library/core/src/ops/control_flow.rs‎

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
usecrate::marker::Destruct;
12
usecrate::{convert, ops};
23

34
/// Used to tell an operation whether it should exit early or go on as usual.
@@ -150,7 +151,8 @@ impl<B, C> ControlFlow<B, C> {
150151
/// ```
151152
#[inline]
152153
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
153-
pubfnis_break(&self) -> bool{
154+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
155+
pubconstfnis_break(&self) -> bool{
154156
matches!(*self,ControlFlow::Break(_))
155157
}
156158

@@ -166,7 +168,8 @@ impl<B, C> ControlFlow<B, C> {
166168
/// ```
167169
#[inline]
168170
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
169-
pubfnis_continue(&self) -> bool{
171+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
172+
pubconstfnis_continue(&self) -> bool{
170173
matches!(*self,ControlFlow::Continue(_))
171174
}
172175

@@ -183,7 +186,11 @@ impl<B, C> ControlFlow<B, C> {
183186
/// ```
184187
#[inline]
185188
#[stable(feature = "control_flow_enum", since = "1.83.0")]
186-
pubfnbreak_value(self) -> Option<B>{
189+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
190+
pubconstfnbreak_value(self) -> Option<B>
191+
where
192+
Self:[const]Destruct,
193+
{
187194
matchself{
188195
ControlFlow::Continue(..) => None,
189196
ControlFlow::Break(x) => Some(x),
@@ -257,7 +264,8 @@ impl<B, C> ControlFlow<B, C> {
257264
/// ```
258265
#[inline]
259266
#[unstable(feature = "control_flow_ok", issue = "140266")]
260-
pubfnbreak_ok(self) -> Result<B,C>{
267+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
268+
pubconstfnbreak_ok(self) -> Result<B,C>{
261269
matchself{
262270
ControlFlow::Continue(c) => Err(c),
263271
ControlFlow::Break(b) => Ok(b),
@@ -268,7 +276,11 @@ impl<B, C> ControlFlow<B, C> {
268276
/// to the break value in case it exists.
269277
#[inline]
270278
#[stable(feature = "control_flow_enum", since = "1.83.0")]
271-
pubfnmap_break<T>(self,f:implFnOnce(B) -> T) -> ControlFlow<T,C>{
279+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
280+
pubconstfn map_break<T,F>(self,f:F) -> ControlFlow<T,C>
281+
where
282+
F:[const]FnOnce(B) -> T + [const]Destruct,
283+
{
272284
matchself{
273285
ControlFlow::Continue(x) => ControlFlow::Continue(x),
274286
ControlFlow::Break(x) => ControlFlow::Break(f(x)),
@@ -288,7 +300,11 @@ impl<B, C> ControlFlow<B, C> {
288300
/// ```
289301
#[inline]
290302
#[stable(feature = "control_flow_enum", since = "1.83.0")]
291-
pubfncontinue_value(self) -> Option<C>{
303+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
304+
pub constfncontinue_value(self) -> Option<C>
305+
where
306+
Self:[const]Destruct,
307+
{
292308
matchself{
293309
ControlFlow::Continue(x) => Some(x),
294310
ControlFlow::Break(..) => None,
@@ -361,7 +377,8 @@ impl<B, C> ControlFlow<B, C> {
361377
/// ```
362378
#[inline]
363379
#[unstable(feature = "control_flow_ok", issue = "140266")]
364-
pubfncontinue_ok(self) -> Result<C,B>{
380+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
381+
pub constfncontinue_ok(self) -> Result<C,B>{
365382
matchself{
366383
ControlFlow::Continue(c) => Ok(c),
367384
ControlFlow::Break(b) => Err(b),
@@ -372,7 +389,11 @@ impl<B, C> ControlFlow<B, C> {
372389
/// to the continue value in case it exists.
373390
#[inline]
374391
#[stable(feature = "control_flow_enum", since = "1.83.0")]
375-
pubfnmap_continue<T>(self,f:implFnOnce(C) -> T) -> ControlFlow<B,T>{
392+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
393+
pub constfnmap_continue<T,F>(self,f:F) -> ControlFlow<B,T>
394+
where
395+
F:[const]FnOnce(C) -> T + [const]Destruct,
396+
{
376397
matchself{
377398
ControlFlow::Continue(x) => ControlFlow::Continue(f(x)),
378399
ControlFlow::Break(x) => ControlFlow::Break(x),

‎src/librustdoc/html/highlight.rs‎

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,9 @@ impl<'a> Iterator for TokenIter<'a> {
789789
}
790790
}
791791

792+
/// Used to know if a keyword followed by a `!` should never be treated as a macro.
793+
constNON_MACRO_KEYWORDS:&[&str] = &["if","while","match","break","return","impl"];
794+
792795
/// This iterator comes from the same idea than "Peekable" except that it allows to "peek" more than
793796
/// just the next item by using `peek_next`. The `peek` method always returns the next item after
794797
/// the current one whereas `peek_next` will return the next item after the last one peeked.
@@ -1010,6 +1013,19 @@ impl<'src> Classifier<'src> {
10101013
}
10111014
}
10121015

1016+
fnnew_macro_span(
1017+
&mutself,
1018+
text:&'srcstr,
1019+
sink:&mutdynFnMut(Span,Highlight<'src>),
1020+
before:u32,
1021+
file_span:Span,
1022+
){
1023+
self.in_macro = true;
1024+
let span = new_span(before, text, file_span);
1025+
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1026+
sink(span,Highlight::Token{ text,class:None});
1027+
}
1028+
10131029
/// Single step of highlighting. This will classify `token`, but maybe also a couple of
10141030
/// following ones as well.
10151031
///
@@ -1216,16 +1232,46 @@ impl<'src> Classifier<'src> {
12161232
LiteralKind::Float{ .. } | LiteralKind::Int{ .. } => Class::Number,
12171233
},
12181234
TokenKind::GuardedStrPrefix => returnno_highlight(sink),
1219-
TokenKind::Ident | TokenKind::RawIdent
1220-
ifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() =>
1221-
{
1222-
self.in_macro = true;
1223-
let span = new_span(before, text, file_span);
1224-
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1225-
sink(span,Highlight::Token{ text,class:None});
1235+
TokenKind::RawIdentifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() => {
1236+
self.new_macro_span(text, sink, before, file_span);
12261237
return;
12271238
}
1228-
TokenKind::Ident => self.classify_ident(before, text),
1239+
// Macro non-terminals (meta vars) take precedence.
1240+
TokenKind::Identifself.in_macro_nonterminal => {
1241+
self.in_macro_nonterminal = false;
1242+
Class::MacroNonTerminal
1243+
}
1244+
TokenKind::Ident => {
1245+
let file_span = self.file_span;
1246+
let span = || new_span(before, text, file_span);
1247+
1248+
match text {
1249+
"ref" | "mut" => Class::RefKeyWord,
1250+
"false" | "true" => Class::Bool,
1251+
"self" | "Self" => Class::Self_(span()),
1252+
"Option" | "Result" => Class::PreludeTy(span()),
1253+
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1254+
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => {
1255+
// So if it's not a keyword which can be followed by a value (like `if` or
1256+
// `return`) and the next non-whitespace token is a `!`, then we consider
1257+
// it's a macro.
1258+
if !NON_MACRO_KEYWORDS.contains(&text)
1259+
&& matches!(self.peek_non_trivia(),Some((TokenKind::Bang, _)))
1260+
{
1261+
self.new_macro_span(text, sink, before, file_span);
1262+
return;
1263+
}
1264+
Class::KeyWord
1265+
}
1266+
// If it's not a keyword and the next non whitespace token is a `!`, then
1267+
// we consider it's a macro.
1268+
_ ifmatches!(self.peek_non_trivia(),Some((TokenKind::Bang, _))) => {
1269+
self.new_macro_span(text, sink, before, file_span);
1270+
return;
1271+
}
1272+
_ => Class::Ident(span()),
1273+
}
1274+
}
12291275
TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
12301276
Class::Ident(new_span(before, text, file_span))
12311277
}
@@ -1246,27 +1292,6 @@ impl<'src> Classifier<'src> {
12461292
}
12471293
}
12481294

1249-
fnclassify_ident(&mutself,before:u32,text:&'srcstr) -> Class{
1250-
// Macro non-terminals (meta vars) take precedence.
1251-
ifself.in_macro_nonterminal{
1252-
self.in_macro_nonterminal = false;
1253-
returnClass::MacroNonTerminal;
1254-
}
1255-
1256-
let file_span = self.file_span;
1257-
let span = || new_span(before, text, file_span);
1258-
1259-
match text {
1260-
"ref" | "mut" => Class::RefKeyWord,
1261-
"false" | "true" => Class::Bool,
1262-
"self" | "Self" => Class::Self_(span()),
1263-
"Option" | "Result" => Class::PreludeTy(span()),
1264-
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1265-
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => Class::KeyWord,
1266-
_ => Class::Ident(span()),
1267-
}
1268-
}
1269-
12701295
fnis_weak_keyword(&mutself,text:&str) -> bool{
12711296
// NOTE: `yeet` (`do yeet $expr`), `catch` (`do catch $block`), `default` (specialization),
12721297
// `contract_{ensures,requires}`, `builtin` (builtin_syntax) & `reuse` (fn_delegation) are

‎src/tools/compiletest/src/directives.rs‎

Lines changed: 33 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::debuggers::{extract_cdb_version, extract_gdb_version};
1111
pub(crate)usecrate::directives::auxiliary::AuxProps;
1212
usecrate::directives::auxiliary::parse_and_update_aux;
1313
usecrate::directives::directive_names::{
14-
KNOWN_DIRECTIVE_NAMES,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
14+
KNOWN_DIRECTIVE_NAMES_SET,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
1515
};
1616
pub(crate)usecrate::directives::file::FileDirectives;
1717
usecrate::directives::line::{DirectiveLine, line_directive};
@@ -53,25 +53,17 @@ impl EarlyProps {
5353
config:&Config,
5454
file_directives:&FileDirectives<'_>,
5555
) -> Self{
56-
let testfile = file_directives.path;
5756
letmut props = EarlyProps::default();
58-
letmut poisoned = false;
5957

6058
iter_directives(
6159
config.mode,
62-
&mut poisoned,
6360
file_directives,
6461
// (dummy comment to force args into vertical layout)
6562
&mut |ln:&DirectiveLine<'_>| {
6663
config.parse_and_update_revisions(ln,&mut props.revisions);
6764
},
6865
);
6966

70-
if poisoned {
71-
eprintln!("errors encountered during EarlyProps parsing: {}", testfile);
72-
panic!("errors encountered during EarlyProps parsing");
73-
}
74-
7567
props
7668
}
7769
}
@@ -358,12 +350,10 @@ impl TestProps {
358350
let file_contents = fs::read_to_string(testfile).unwrap();
359351
let file_directives = FileDirectives::from_file_contents(testfile,&file_contents);
360352

361-
letmut poisoned = false;
362-
363353
iter_directives(
364354
config.mode,
365-
&mut poisoned,
366355
&file_directives,
356+
// (dummy comment to force args into vertical layout)
367357
&mut |ln:&DirectiveLine<'_>| {
368358
if !ln.applies_to_test_revision(test_revision){
369359
return;
@@ -634,11 +624,6 @@ impl TestProps {
634624
);
635625
},
636626
);
637-
638-
if poisoned {
639-
eprintln!("errors encountered during TestProps parsing: {}", testfile);
640-
panic!("errors encountered during TestProps parsing");
641-
}
642627
}
643628

644629
ifself.should_ice{
@@ -775,6 +760,34 @@ impl TestProps {
775760
}
776761
}
777762

763+
pub(crate)fndo_early_directives_check(
764+
mode:TestMode,
765+
file_directives:&FileDirectives<'_>,
766+
) -> Result<(),String>{
767+
let testfile = file_directives.path;
768+
769+
for directive_line @ DirectiveLine{ line_number, .. }in&file_directives.lines{
770+
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
771+
check_directive(directive_line, mode);
772+
773+
if !is_known_directive {
774+
returnErr(format!(
775+
"ERROR: unknown compiletest directive `{directive}` at {testfile}:{line_number}",
776+
directive = directive_line.display(),
777+
));
778+
}
779+
780+
ifletSome(trailing_directive) = &trailing_directive {
781+
returnErr(format!(
782+
"ERROR: detected trailing compiletest directive `{trailing_directive}` at {testfile}:{line_number}\n\
783+
HELP: put the directive on its own line: `//@ {trailing_directive}`"
784+
));
785+
}
786+
}
787+
788+
Ok(())
789+
}
790+
778791
pub(crate)structCheckDirectiveResult<'ln>{
779792
is_known_directive:bool,
780793
trailing_directive:Option<&'lnstr>,
@@ -786,7 +799,7 @@ fn check_directive<'a>(
786799
) -> CheckDirectiveResult<'a>{
787800
let&DirectiveLine{name: directive_name, .. } = directive_ln;
788801

789-
let is_known_directive = KNOWN_DIRECTIVE_NAMES.contains(&directive_name)
802+
let is_known_directive = KNOWN_DIRECTIVE_NAMES_SET.contains(&directive_name)
790803
|| match mode {
791804
TestMode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
792805
TestMode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
@@ -799,7 +812,7 @@ fn check_directive<'a>(
799812
let trailing_directive = directive_ln
800813
.remark_after_space()
801814
.map(|remark| remark.trim_start().split(' ').next().unwrap())
802-
.filter(|token| KNOWN_DIRECTIVE_NAMES.contains(token));
815+
.filter(|token| KNOWN_DIRECTIVE_NAMES_SET.contains(token));
803816

804817
// FIXME(Zalathar): Consider emitting specialized error/help messages for
805818
// bogus directive names that are similar to real ones, e.g.:
@@ -811,7 +824,6 @@ fn check_directive<'a>(
811824

812825
fniter_directives(
813826
mode:TestMode,
814-
poisoned:&mutbool,
815827
file_directives:&FileDirectives<'_>,
816828
it:&mutdynFnMut(&DirectiveLine<'_>),
817829
){
@@ -837,36 +849,7 @@ fn iter_directives(
837849
}
838850
}
839851

840-
for directive_line @ &DirectiveLine{ line_number, .. }in&file_directives.lines{
841-
// Perform unknown directive check on Rust files.
842-
if testfile.extension() == Some("rs"){
843-
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
844-
check_directive(directive_line, mode);
845-
846-
if !is_known_directive {
847-
*poisoned = true;
848-
849-
error!(
850-
"{testfile}:{line_number}: detected unknown compiletest test directive `{}`",
851-
directive_line.display(),
852-
);
853-
854-
return;
855-
}
856-
857-
ifletSome(trailing_directive) = &trailing_directive {
858-
*poisoned = true;
859-
860-
error!(
861-
"{testfile}:{line_number}: detected trailing compiletest test directive `{}`",
862-
trailing_directive,
863-
);
864-
help!("put the trailing directive in its own line: `//@ {}`", trailing_directive);
865-
866-
return;
867-
}
868-
}
869-
852+
for directive_line in&file_directives.lines{
870853
it(directive_line);
871854
}
872855
}
@@ -1304,12 +1287,9 @@ pub(crate) fn make_test_description(
13041287
letmut ignore_message = None;
13051288
letmut should_fail = false;
13061289

1307-
letmut local_poisoned = false;
1308-
13091290
// Scan through the test file to handle `ignore-*`, `only-*`, and `needs-*` directives.
13101291
iter_directives(
13111292
config.mode,
1312-
&mut local_poisoned,
13131293
file_directives,
13141294
&mut |ln @ &DirectiveLine{ line_number, .. }| {
13151295
if !ln.applies_to_test_revision(test_revision){
@@ -1358,11 +1338,6 @@ pub(crate) fn make_test_description(
13581338
},
13591339
);
13601340

1361-
if local_poisoned {
1362-
eprintln!("errors encountered when trying to make test description: {}", path);
1363-
panic!("errors encountered when trying to make test description");
1364-
}
1365-
13661341
// The `should-fail` annotation doesn't apply to pretty tests,
13671342
// since we run the pretty printer across all tests by default.
13681343
// If desired, we could add a `should-fail-pretty` annotation.

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Commit 8401398

Browse files
committed
Auto merge of #148762 - matthiaskrgr:rollup-4oifvkr, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #148248 (Constify `ControlFlow` methods without unstable bounds) - #148285 (Constify `ControlFlow` methods with unstable bounds) - #148510 (compiletest: Do the known-directives check only once, and improve its error message) - #148655 (Fix invalid macro tag generation for keywords which can be followed by values) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 6647be9 + 5430082 commit 8401398

8 files changed

Lines changed: 177 additions & 98 deletions

File tree

‎library/core/src/ops/control_flow.rs‎

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
usecrate::marker::Destruct;
12
usecrate::{convert, ops};
23

34
/// Used to tell an operation whether it should exit early or go on as usual.
@@ -150,7 +151,8 @@ impl<B, C> ControlFlow<B, C> {
150151
/// ```
151152
#[inline]
152153
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
153-
pubfnis_break(&self) -> bool{
154+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
155+
pubconstfnis_break(&self) -> bool{
154156
matches!(*self,ControlFlow::Break(_))
155157
}
156158

@@ -166,7 +168,8 @@ impl<B, C> ControlFlow<B, C> {
166168
/// ```
167169
#[inline]
168170
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
169-
pubfnis_continue(&self) -> bool{
171+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
172+
pubconstfnis_continue(&self) -> bool{
170173
matches!(*self,ControlFlow::Continue(_))
171174
}
172175

@@ -183,7 +186,11 @@ impl<B, C> ControlFlow<B, C> {
183186
/// ```
184187
#[inline]
185188
#[stable(feature = "control_flow_enum", since = "1.83.0")]
186-
pubfnbreak_value(self) -> Option<B>{
189+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
190+
pubconstfnbreak_value(self) -> Option<B>
191+
where
192+
Self:[const]Destruct,
193+
{
187194
matchself{
188195
ControlFlow::Continue(..) => None,
189196
ControlFlow::Break(x) => Some(x),
@@ -257,7 +264,8 @@ impl<B, C> ControlFlow<B, C> {
257264
/// ```
258265
#[inline]
259266
#[unstable(feature = "control_flow_ok", issue = "140266")]
260-
pubfnbreak_ok(self) -> Result<B,C>{
267+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
268+
pubconstfnbreak_ok(self) -> Result<B,C>{
261269
matchself{
262270
ControlFlow::Continue(c) => Err(c),
263271
ControlFlow::Break(b) => Ok(b),
@@ -268,7 +276,11 @@ impl<B, C> ControlFlow<B, C> {
268276
/// to the break value in case it exists.
269277
#[inline]
270278
#[stable(feature = "control_flow_enum", since = "1.83.0")]
271-
pubfnmap_break<T>(self,f:implFnOnce(B) -> T) -> ControlFlow<T,C>{
279+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
280+
pubconstfn map_break<T,F>(self,f:F) -> ControlFlow<T,C>
281+
where
282+
F:[const]FnOnce(B) -> T + [const]Destruct,
283+
{
272284
matchself{
273285
ControlFlow::Continue(x) => ControlFlow::Continue(x),
274286
ControlFlow::Break(x) => ControlFlow::Break(f(x)),
@@ -288,7 +300,11 @@ impl<B, C> ControlFlow<B, C> {
288300
/// ```
289301
#[inline]
290302
#[stable(feature = "control_flow_enum", since = "1.83.0")]
291-
pubfncontinue_value(self) -> Option<C>{
303+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
304+
pub constfncontinue_value(self) -> Option<C>
305+
where
306+
Self:[const]Destruct,
307+
{
292308
matchself{
293309
ControlFlow::Continue(x) => Some(x),
294310
ControlFlow::Break(..) => None,
@@ -361,7 +377,8 @@ impl<B, C> ControlFlow<B, C> {
361377
/// ```
362378
#[inline]
363379
#[unstable(feature = "control_flow_ok", issue = "140266")]
364-
pubfncontinue_ok(self) -> Result<C,B>{
380+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
381+
pub constfncontinue_ok(self) -> Result<C,B>{
365382
matchself{
366383
ControlFlow::Continue(c) => Ok(c),
367384
ControlFlow::Break(b) => Err(b),
@@ -372,7 +389,11 @@ impl<B, C> ControlFlow<B, C> {
372389
/// to the continue value in case it exists.
373390
#[inline]
374391
#[stable(feature = "control_flow_enum", since = "1.83.0")]
375-
pubfnmap_continue<T>(self,f:implFnOnce(C) -> T) -> ControlFlow<B,T>{
392+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
393+
pub constfnmap_continue<T,F>(self,f:F) -> ControlFlow<B,T>
394+
where
395+
F:[const]FnOnce(C) -> T + [const]Destruct,
396+
{
376397
matchself{
377398
ControlFlow::Continue(x) => ControlFlow::Continue(f(x)),
378399
ControlFlow::Break(x) => ControlFlow::Break(x),

‎src/librustdoc/html/highlight.rs‎

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,9 @@ impl<'a> Iterator for TokenIter<'a> {
789789
}
790790
}
791791

792+
/// Used to know if a keyword followed by a `!` should never be treated as a macro.
793+
constNON_MACRO_KEYWORDS:&[&str] = &["if","while","match","break","return","impl"];
794+
792795
/// This iterator comes from the same idea than "Peekable" except that it allows to "peek" more than
793796
/// just the next item by using `peek_next`. The `peek` method always returns the next item after
794797
/// the current one whereas `peek_next` will return the next item after the last one peeked.
@@ -1010,6 +1013,19 @@ impl<'src> Classifier<'src> {
10101013
}
10111014
}
10121015

1016+
fnnew_macro_span(
1017+
&mutself,
1018+
text:&'srcstr,
1019+
sink:&mutdynFnMut(Span,Highlight<'src>),
1020+
before:u32,
1021+
file_span:Span,
1022+
){
1023+
self.in_macro = true;
1024+
let span = new_span(before, text, file_span);
1025+
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1026+
sink(span,Highlight::Token{ text,class:None});
1027+
}
1028+
10131029
/// Single step of highlighting. This will classify `token`, but maybe also a couple of
10141030
/// following ones as well.
10151031
///
@@ -1216,16 +1232,46 @@ impl<'src> Classifier<'src> {
12161232
LiteralKind::Float{ .. } | LiteralKind::Int{ .. } => Class::Number,
12171233
},
12181234
TokenKind::GuardedStrPrefix => returnno_highlight(sink),
1219-
TokenKind::Ident | TokenKind::RawIdent
1220-
ifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() =>
1221-
{
1222-
self.in_macro = true;
1223-
let span = new_span(before, text, file_span);
1224-
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1225-
sink(span,Highlight::Token{ text,class:None});
1235+
TokenKind::RawIdentifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() => {
1236+
self.new_macro_span(text, sink, before, file_span);
12261237
return;
12271238
}
1228-
TokenKind::Ident => self.classify_ident(before, text),
1239+
// Macro non-terminals (meta vars) take precedence.
1240+
TokenKind::Identifself.in_macro_nonterminal => {
1241+
self.in_macro_nonterminal = false;
1242+
Class::MacroNonTerminal
1243+
}
1244+
TokenKind::Ident => {
1245+
let file_span = self.file_span;
1246+
let span = || new_span(before, text, file_span);
1247+
1248+
match text {
1249+
"ref" | "mut" => Class::RefKeyWord,
1250+
"false" | "true" => Class::Bool,
1251+
"self" | "Self" => Class::Self_(span()),
1252+
"Option" | "Result" => Class::PreludeTy(span()),
1253+
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1254+
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => {
1255+
// So if it's not a keyword which can be followed by a value (like `if` or
1256+
// `return`) and the next non-whitespace token is a `!`, then we consider
1257+
// it's a macro.
1258+
if !NON_MACRO_KEYWORDS.contains(&text)
1259+
&& matches!(self.peek_non_trivia(),Some((TokenKind::Bang, _)))
1260+
{
1261+
self.new_macro_span(text, sink, before, file_span);
1262+
return;
1263+
}
1264+
Class::KeyWord
1265+
}
1266+
// If it's not a keyword and the next non whitespace token is a `!`, then
1267+
// we consider it's a macro.
1268+
_ ifmatches!(self.peek_non_trivia(),Some((TokenKind::Bang, _))) => {
1269+
self.new_macro_span(text, sink, before, file_span);
1270+
return;
1271+
}
1272+
_ => Class::Ident(span()),
1273+
}
1274+
}
12291275
TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
12301276
Class::Ident(new_span(before, text, file_span))
12311277
}
@@ -1246,27 +1292,6 @@ impl<'src> Classifier<'src> {
12461292
}
12471293
}
12481294

1249-
fnclassify_ident(&mutself,before:u32,text:&'srcstr) -> Class{
1250-
// Macro non-terminals (meta vars) take precedence.
1251-
ifself.in_macro_nonterminal{
1252-
self.in_macro_nonterminal = false;
1253-
returnClass::MacroNonTerminal;
1254-
}
1255-
1256-
let file_span = self.file_span;
1257-
let span = || new_span(before, text, file_span);
1258-
1259-
match text {
1260-
"ref" | "mut" => Class::RefKeyWord,
1261-
"false" | "true" => Class::Bool,
1262-
"self" | "Self" => Class::Self_(span()),
1263-
"Option" | "Result" => Class::PreludeTy(span()),
1264-
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1265-
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => Class::KeyWord,
1266-
_ => Class::Ident(span()),
1267-
}
1268-
}
1269-
12701295
fnis_weak_keyword(&mutself,text:&str) -> bool{
12711296
// NOTE: `yeet` (`do yeet $expr`), `catch` (`do catch $block`), `default` (specialization),
12721297
// `contract_{ensures,requires}`, `builtin` (builtin_syntax) & `reuse` (fn_delegation) are

‎src/tools/compiletest/src/directives.rs‎

Lines changed: 33 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::debuggers::{extract_cdb_version, extract_gdb_version};
1111
pub(crate)usecrate::directives::auxiliary::AuxProps;
1212
usecrate::directives::auxiliary::parse_and_update_aux;
1313
usecrate::directives::directive_names::{
14-
KNOWN_DIRECTIVE_NAMES,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
14+
KNOWN_DIRECTIVE_NAMES_SET,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
1515
};
1616
pub(crate)usecrate::directives::file::FileDirectives;
1717
usecrate::directives::line::{DirectiveLine, line_directive};
@@ -53,25 +53,17 @@ impl EarlyProps {
5353
config:&Config,
5454
file_directives:&FileDirectives<'_>,
5555
) -> Self{
56-
let testfile = file_directives.path;
5756
letmut props = EarlyProps::default();
58-
letmut poisoned = false;
5957

6058
iter_directives(
6159
config.mode,
62-
&mut poisoned,
6360
file_directives,
6461
// (dummy comment to force args into vertical layout)
6562
&mut |ln:&DirectiveLine<'_>| {
6663
config.parse_and_update_revisions(ln,&mut props.revisions);
6764
},
6865
);
6966

70-
if poisoned {
71-
eprintln!("errors encountered during EarlyProps parsing: {}", testfile);
72-
panic!("errors encountered during EarlyProps parsing");
73-
}
74-
7567
props
7668
}
7769
}
@@ -358,12 +350,10 @@ impl TestProps {
358350
let file_contents = fs::read_to_string(testfile).unwrap();
359351
let file_directives = FileDirectives::from_file_contents(testfile,&file_contents);
360352

361-
letmut poisoned = false;
362-
363353
iter_directives(
364354
config.mode,
365-
&mut poisoned,
366355
&file_directives,
356+
// (dummy comment to force args into vertical layout)
367357
&mut |ln:&DirectiveLine<'_>| {
368358
if !ln.applies_to_test_revision(test_revision){
369359
return;
@@ -634,11 +624,6 @@ impl TestProps {
634624
);
635625
},
636626
);
637-
638-
if poisoned {
639-
eprintln!("errors encountered during TestProps parsing: {}", testfile);
640-
panic!("errors encountered during TestProps parsing");
641-
}
642627
}
643628

644629
ifself.should_ice{
@@ -775,6 +760,34 @@ impl TestProps {
775760
}
776761
}
777762

763+
pub(crate)fndo_early_directives_check(
764+
mode:TestMode,
765+
file_directives:&FileDirectives<'_>,
766+
) -> Result<(),String>{
767+
let testfile = file_directives.path;
768+
769+
for directive_line @ DirectiveLine{ line_number, .. }in&file_directives.lines{
770+
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
771+
check_directive(directive_line, mode);
772+
773+
if !is_known_directive {
774+
returnErr(format!(
775+
"ERROR: unknown compiletest directive `{directive}` at {testfile}:{line_number}",
776+
directive = directive_line.display(),
777+
));
778+
}
779+
780+
ifletSome(trailing_directive) = &trailing_directive {
781+
returnErr(format!(
782+
"ERROR: detected trailing compiletest directive `{trailing_directive}` at {testfile}:{line_number}\n\
783+
HELP: put the directive on its own line: `//@ {trailing_directive}`"
784+
));
785+
}
786+
}
787+
788+
Ok(())
789+
}
790+
778791
pub(crate)structCheckDirectiveResult<'ln>{
779792
is_known_directive:bool,
780793
trailing_directive:Option<&'lnstr>,
@@ -786,7 +799,7 @@ fn check_directive<'a>(
786799
) -> CheckDirectiveResult<'a>{
787800
let&DirectiveLine{name: directive_name, .. } = directive_ln;
788801

789-
let is_known_directive = KNOWN_DIRECTIVE_NAMES.contains(&directive_name)
802+
let is_known_directive = KNOWN_DIRECTIVE_NAMES_SET.contains(&directive_name)
790803
|| match mode {
791804
TestMode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
792805
TestMode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
@@ -799,7 +812,7 @@ fn check_directive<'a>(
799812
let trailing_directive = directive_ln
800813
.remark_after_space()
801814
.map(|remark| remark.trim_start().split(' ').next().unwrap())
802-
.filter(|token| KNOWN_DIRECTIVE_NAMES.contains(token));
815+
.filter(|token| KNOWN_DIRECTIVE_NAMES_SET.contains(token));
803816

804817
// FIXME(Zalathar): Consider emitting specialized error/help messages for
805818
// bogus directive names that are similar to real ones, e.g.:
@@ -811,7 +824,6 @@ fn check_directive<'a>(
811824

812825
fniter_directives(
813826
mode:TestMode,
814-
poisoned:&mutbool,
815827
file_directives:&FileDirectives<'_>,
816828
it:&mutdynFnMut(&DirectiveLine<'_>),
817829
){
@@ -837,36 +849,7 @@ fn iter_directives(
837849
}
838850
}
839851

840-
for directive_line @ &DirectiveLine{ line_number, .. }in&file_directives.lines{
841-
// Perform unknown directive check on Rust files.
842-
if testfile.extension() == Some("rs"){
843-
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
844-
check_directive(directive_line, mode);
845-
846-
if !is_known_directive {
847-
*poisoned = true;
848-
849-
error!(
850-
"{testfile}:{line_number}: detected unknown compiletest test directive `{}`",
851-
directive_line.display(),
852-
);
853-
854-
return;
855-
}
856-
857-
ifletSome(trailing_directive) = &trailing_directive {
858-
*poisoned = true;
859-
860-
error!(
861-
"{testfile}:{line_number}: detected trailing compiletest test directive `{}`",
862-
trailing_directive,
863-
);
864-
help!("put the trailing directive in its own line: `//@ {}`", trailing_directive);
865-
866-
return;
867-
}
868-
}
869-
852+
for directive_line in&file_directives.lines{
870853
it(directive_line);
871854
}
872855
}
@@ -1304,12 +1287,9 @@ pub(crate) fn make_test_description(
13041287
letmut ignore_message = None;
13051288
letmut should_fail = false;
13061289

1307-
letmut local_poisoned = false;
1308-
13091290
// Scan through the test file to handle `ignore-*`, `only-*`, and `needs-*` directives.
13101291
iter_directives(
13111292
config.mode,
1312-
&mut local_poisoned,
13131293
file_directives,
13141294
&mut |ln @ &DirectiveLine{ line_number, .. }| {
13151295
if !ln.applies_to_test_revision(test_revision){
@@ -1358,11 +1338,6 @@ pub(crate) fn make_test_description(
13581338
},
13591339
);
13601340

1361-
if local_poisoned {
1362-
eprintln!("errors encountered when trying to make test description: {}", path);
1363-
panic!("errors encountered when trying to make test description");
1364-
}
1365-
13661341
// The `should-fail` annotation doesn't apply to pretty tests,
13671342
// since we run the pretty printer across all tests by default.
13681343
// If desired, we could add a `should-fail-pretty` annotation.

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Commit 8401398

Browse files
committed
Auto merge of #148762 - matthiaskrgr:rollup-4oifvkr, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #148248 (Constify `ControlFlow` methods without unstable bounds) - #148285 (Constify `ControlFlow` methods with unstable bounds) - #148510 (compiletest: Do the known-directives check only once, and improve its error message) - #148655 (Fix invalid macro tag generation for keywords which can be followed by values) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 6647be9 + 5430082 commit 8401398

8 files changed

Lines changed: 177 additions & 98 deletions

File tree

‎library/core/src/ops/control_flow.rs‎

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
usecrate::marker::Destruct;
12
usecrate::{convert, ops};
23

34
/// Used to tell an operation whether it should exit early or go on as usual.
@@ -150,7 +151,8 @@ impl<B, C> ControlFlow<B, C> {
150151
/// ```
151152
#[inline]
152153
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
153-
pubfnis_break(&self) -> bool{
154+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
155+
pubconstfnis_break(&self) -> bool{
154156
matches!(*self,ControlFlow::Break(_))
155157
}
156158

@@ -166,7 +168,8 @@ impl<B, C> ControlFlow<B, C> {
166168
/// ```
167169
#[inline]
168170
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
169-
pubfnis_continue(&self) -> bool{
171+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
172+
pubconstfnis_continue(&self) -> bool{
170173
matches!(*self,ControlFlow::Continue(_))
171174
}
172175

@@ -183,7 +186,11 @@ impl<B, C> ControlFlow<B, C> {
183186
/// ```
184187
#[inline]
185188
#[stable(feature = "control_flow_enum", since = "1.83.0")]
186-
pubfnbreak_value(self) -> Option<B>{
189+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
190+
pubconstfnbreak_value(self) -> Option<B>
191+
where
192+
Self:[const]Destruct,
193+
{
187194
matchself{
188195
ControlFlow::Continue(..) => None,
189196
ControlFlow::Break(x) => Some(x),
@@ -257,7 +264,8 @@ impl<B, C> ControlFlow<B, C> {
257264
/// ```
258265
#[inline]
259266
#[unstable(feature = "control_flow_ok", issue = "140266")]
260-
pubfnbreak_ok(self) -> Result<B,C>{
267+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
268+
pubconstfnbreak_ok(self) -> Result<B,C>{
261269
matchself{
262270
ControlFlow::Continue(c) => Err(c),
263271
ControlFlow::Break(b) => Ok(b),
@@ -268,7 +276,11 @@ impl<B, C> ControlFlow<B, C> {
268276
/// to the break value in case it exists.
269277
#[inline]
270278
#[stable(feature = "control_flow_enum", since = "1.83.0")]
271-
pubfnmap_break<T>(self,f:implFnOnce(B) -> T) -> ControlFlow<T,C>{
279+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
280+
pubconstfn map_break<T,F>(self,f:F) -> ControlFlow<T,C>
281+
where
282+
F:[const]FnOnce(B) -> T + [const]Destruct,
283+
{
272284
matchself{
273285
ControlFlow::Continue(x) => ControlFlow::Continue(x),
274286
ControlFlow::Break(x) => ControlFlow::Break(f(x)),
@@ -288,7 +300,11 @@ impl<B, C> ControlFlow<B, C> {
288300
/// ```
289301
#[inline]
290302
#[stable(feature = "control_flow_enum", since = "1.83.0")]
291-
pubfncontinue_value(self) -> Option<C>{
303+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
304+
pub constfncontinue_value(self) -> Option<C>
305+
where
306+
Self:[const]Destruct,
307+
{
292308
matchself{
293309
ControlFlow::Continue(x) => Some(x),
294310
ControlFlow::Break(..) => None,
@@ -361,7 +377,8 @@ impl<B, C> ControlFlow<B, C> {
361377
/// ```
362378
#[inline]
363379
#[unstable(feature = "control_flow_ok", issue = "140266")]
364-
pubfncontinue_ok(self) -> Result<C,B>{
380+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
381+
pub constfncontinue_ok(self) -> Result<C,B>{
365382
matchself{
366383
ControlFlow::Continue(c) => Ok(c),
367384
ControlFlow::Break(b) => Err(b),
@@ -372,7 +389,11 @@ impl<B, C> ControlFlow<B, C> {
372389
/// to the continue value in case it exists.
373390
#[inline]
374391
#[stable(feature = "control_flow_enum", since = "1.83.0")]
375-
pubfnmap_continue<T>(self,f:implFnOnce(C) -> T) -> ControlFlow<B,T>{
392+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
393+
pub constfnmap_continue<T,F>(self,f:F) -> ControlFlow<B,T>
394+
where
395+
F:[const]FnOnce(C) -> T + [const]Destruct,
396+
{
376397
matchself{
377398
ControlFlow::Continue(x) => ControlFlow::Continue(f(x)),
378399
ControlFlow::Break(x) => ControlFlow::Break(x),

‎src/librustdoc/html/highlight.rs‎

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,9 @@ impl<'a> Iterator for TokenIter<'a> {
789789
}
790790
}
791791

792+
/// Used to know if a keyword followed by a `!` should never be treated as a macro.
793+
constNON_MACRO_KEYWORDS:&[&str] = &["if","while","match","break","return","impl"];
794+
792795
/// This iterator comes from the same idea than "Peekable" except that it allows to "peek" more than
793796
/// just the next item by using `peek_next`. The `peek` method always returns the next item after
794797
/// the current one whereas `peek_next` will return the next item after the last one peeked.
@@ -1010,6 +1013,19 @@ impl<'src> Classifier<'src> {
10101013
}
10111014
}
10121015

1016+
fnnew_macro_span(
1017+
&mutself,
1018+
text:&'srcstr,
1019+
sink:&mutdynFnMut(Span,Highlight<'src>),
1020+
before:u32,
1021+
file_span:Span,
1022+
){
1023+
self.in_macro = true;
1024+
let span = new_span(before, text, file_span);
1025+
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1026+
sink(span,Highlight::Token{ text,class:None});
1027+
}
1028+
10131029
/// Single step of highlighting. This will classify `token`, but maybe also a couple of
10141030
/// following ones as well.
10151031
///
@@ -1216,16 +1232,46 @@ impl<'src> Classifier<'src> {
12161232
LiteralKind::Float{ .. } | LiteralKind::Int{ .. } => Class::Number,
12171233
},
12181234
TokenKind::GuardedStrPrefix => returnno_highlight(sink),
1219-
TokenKind::Ident | TokenKind::RawIdent
1220-
ifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() =>
1221-
{
1222-
self.in_macro = true;
1223-
let span = new_span(before, text, file_span);
1224-
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1225-
sink(span,Highlight::Token{ text,class:None});
1235+
TokenKind::RawIdentifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() => {
1236+
self.new_macro_span(text, sink, before, file_span);
12261237
return;
12271238
}
1228-
TokenKind::Ident => self.classify_ident(before, text),
1239+
// Macro non-terminals (meta vars) take precedence.
1240+
TokenKind::Identifself.in_macro_nonterminal => {
1241+
self.in_macro_nonterminal = false;
1242+
Class::MacroNonTerminal
1243+
}
1244+
TokenKind::Ident => {
1245+
let file_span = self.file_span;
1246+
let span = || new_span(before, text, file_span);
1247+
1248+
match text {
1249+
"ref" | "mut" => Class::RefKeyWord,
1250+
"false" | "true" => Class::Bool,
1251+
"self" | "Self" => Class::Self_(span()),
1252+
"Option" | "Result" => Class::PreludeTy(span()),
1253+
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1254+
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => {
1255+
// So if it's not a keyword which can be followed by a value (like `if` or
1256+
// `return`) and the next non-whitespace token is a `!`, then we consider
1257+
// it's a macro.
1258+
if !NON_MACRO_KEYWORDS.contains(&text)
1259+
&& matches!(self.peek_non_trivia(),Some((TokenKind::Bang, _)))
1260+
{
1261+
self.new_macro_span(text, sink, before, file_span);
1262+
return;
1263+
}
1264+
Class::KeyWord
1265+
}
1266+
// If it's not a keyword and the next non whitespace token is a `!`, then
1267+
// we consider it's a macro.
1268+
_ ifmatches!(self.peek_non_trivia(),Some((TokenKind::Bang, _))) => {
1269+
self.new_macro_span(text, sink, before, file_span);
1270+
return;
1271+
}
1272+
_ => Class::Ident(span()),
1273+
}
1274+
}
12291275
TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
12301276
Class::Ident(new_span(before, text, file_span))
12311277
}
@@ -1246,27 +1292,6 @@ impl<'src> Classifier<'src> {
12461292
}
12471293
}
12481294

1249-
fnclassify_ident(&mutself,before:u32,text:&'srcstr) -> Class{
1250-
// Macro non-terminals (meta vars) take precedence.
1251-
ifself.in_macro_nonterminal{
1252-
self.in_macro_nonterminal = false;
1253-
returnClass::MacroNonTerminal;
1254-
}
1255-
1256-
let file_span = self.file_span;
1257-
let span = || new_span(before, text, file_span);
1258-
1259-
match text {
1260-
"ref" | "mut" => Class::RefKeyWord,
1261-
"false" | "true" => Class::Bool,
1262-
"self" | "Self" => Class::Self_(span()),
1263-
"Option" | "Result" => Class::PreludeTy(span()),
1264-
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1265-
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => Class::KeyWord,
1266-
_ => Class::Ident(span()),
1267-
}
1268-
}
1269-
12701295
fnis_weak_keyword(&mutself,text:&str) -> bool{
12711296
// NOTE: `yeet` (`do yeet $expr`), `catch` (`do catch $block`), `default` (specialization),
12721297
// `contract_{ensures,requires}`, `builtin` (builtin_syntax) & `reuse` (fn_delegation) are

‎src/tools/compiletest/src/directives.rs‎

Lines changed: 33 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::debuggers::{extract_cdb_version, extract_gdb_version};
1111
pub(crate)usecrate::directives::auxiliary::AuxProps;
1212
usecrate::directives::auxiliary::parse_and_update_aux;
1313
usecrate::directives::directive_names::{
14-
KNOWN_DIRECTIVE_NAMES,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
14+
KNOWN_DIRECTIVE_NAMES_SET,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
1515
};
1616
pub(crate)usecrate::directives::file::FileDirectives;
1717
usecrate::directives::line::{DirectiveLine, line_directive};
@@ -53,25 +53,17 @@ impl EarlyProps {
5353
config:&Config,
5454
file_directives:&FileDirectives<'_>,
5555
) -> Self{
56-
let testfile = file_directives.path;
5756
letmut props = EarlyProps::default();
58-
letmut poisoned = false;
5957

6058
iter_directives(
6159
config.mode,
62-
&mut poisoned,
6360
file_directives,
6461
// (dummy comment to force args into vertical layout)
6562
&mut |ln:&DirectiveLine<'_>| {
6663
config.parse_and_update_revisions(ln,&mut props.revisions);
6764
},
6865
);
6966

70-
if poisoned {
71-
eprintln!("errors encountered during EarlyProps parsing: {}", testfile);
72-
panic!("errors encountered during EarlyProps parsing");
73-
}
74-
7567
props
7668
}
7769
}
@@ -358,12 +350,10 @@ impl TestProps {
358350
let file_contents = fs::read_to_string(testfile).unwrap();
359351
let file_directives = FileDirectives::from_file_contents(testfile,&file_contents);
360352

361-
letmut poisoned = false;
362-
363353
iter_directives(
364354
config.mode,
365-
&mut poisoned,
366355
&file_directives,
356+
// (dummy comment to force args into vertical layout)
367357
&mut |ln:&DirectiveLine<'_>| {
368358
if !ln.applies_to_test_revision(test_revision){
369359
return;
@@ -634,11 +624,6 @@ impl TestProps {
634624
);
635625
},
636626
);
637-
638-
if poisoned {
639-
eprintln!("errors encountered during TestProps parsing: {}", testfile);
640-
panic!("errors encountered during TestProps parsing");
641-
}
642627
}
643628

644629
ifself.should_ice{
@@ -775,6 +760,34 @@ impl TestProps {
775760
}
776761
}
777762

763+
pub(crate)fndo_early_directives_check(
764+
mode:TestMode,
765+
file_directives:&FileDirectives<'_>,
766+
) -> Result<(),String>{
767+
let testfile = file_directives.path;
768+
769+
for directive_line @ DirectiveLine{ line_number, .. }in&file_directives.lines{
770+
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
771+
check_directive(directive_line, mode);
772+
773+
if !is_known_directive {
774+
returnErr(format!(
775+
"ERROR: unknown compiletest directive `{directive}` at {testfile}:{line_number}",
776+
directive = directive_line.display(),
777+
));
778+
}
779+
780+
ifletSome(trailing_directive) = &trailing_directive {
781+
returnErr(format!(
782+
"ERROR: detected trailing compiletest directive `{trailing_directive}` at {testfile}:{line_number}\n\
783+
HELP: put the directive on its own line: `//@ {trailing_directive}`"
784+
));
785+
}
786+
}
787+
788+
Ok(())
789+
}
790+
778791
pub(crate)structCheckDirectiveResult<'ln>{
779792
is_known_directive:bool,
780793
trailing_directive:Option<&'lnstr>,
@@ -786,7 +799,7 @@ fn check_directive<'a>(
786799
) -> CheckDirectiveResult<'a>{
787800
let&DirectiveLine{name: directive_name, .. } = directive_ln;
788801

789-
let is_known_directive = KNOWN_DIRECTIVE_NAMES.contains(&directive_name)
802+
let is_known_directive = KNOWN_DIRECTIVE_NAMES_SET.contains(&directive_name)
790803
|| match mode {
791804
TestMode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
792805
TestMode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
@@ -799,7 +812,7 @@ fn check_directive<'a>(
799812
let trailing_directive = directive_ln
800813
.remark_after_space()
801814
.map(|remark| remark.trim_start().split(' ').next().unwrap())
802-
.filter(|token| KNOWN_DIRECTIVE_NAMES.contains(token));
815+
.filter(|token| KNOWN_DIRECTIVE_NAMES_SET.contains(token));
803816

804817
// FIXME(Zalathar): Consider emitting specialized error/help messages for
805818
// bogus directive names that are similar to real ones, e.g.:
@@ -811,7 +824,6 @@ fn check_directive<'a>(
811824

812825
fniter_directives(
813826
mode:TestMode,
814-
poisoned:&mutbool,
815827
file_directives:&FileDirectives<'_>,
816828
it:&mutdynFnMut(&DirectiveLine<'_>),
817829
){
@@ -837,36 +849,7 @@ fn iter_directives(
837849
}
838850
}
839851

840-
for directive_line @ &DirectiveLine{ line_number, .. }in&file_directives.lines{
841-
// Perform unknown directive check on Rust files.
842-
if testfile.extension() == Some("rs"){
843-
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
844-
check_directive(directive_line, mode);
845-
846-
if !is_known_directive {
847-
*poisoned = true;
848-
849-
error!(
850-
"{testfile}:{line_number}: detected unknown compiletest test directive `{}`",
851-
directive_line.display(),
852-
);
853-
854-
return;
855-
}
856-
857-
ifletSome(trailing_directive) = &trailing_directive {
858-
*poisoned = true;
859-
860-
error!(
861-
"{testfile}:{line_number}: detected trailing compiletest test directive `{}`",
862-
trailing_directive,
863-
);
864-
help!("put the trailing directive in its own line: `//@ {}`", trailing_directive);
865-
866-
return;
867-
}
868-
}
869-
852+
for directive_line in&file_directives.lines{
870853
it(directive_line);
871854
}
872855
}
@@ -1304,12 +1287,9 @@ pub(crate) fn make_test_description(
13041287
letmut ignore_message = None;
13051288
letmut should_fail = false;
13061289

1307-
letmut local_poisoned = false;
1308-
13091290
// Scan through the test file to handle `ignore-*`, `only-*`, and `needs-*` directives.
13101291
iter_directives(
13111292
config.mode,
1312-
&mut local_poisoned,
13131293
file_directives,
13141294
&mut |ln @ &DirectiveLine{ line_number, .. }| {
13151295
if !ln.applies_to_test_revision(test_revision){
@@ -1358,11 +1338,6 @@ pub(crate) fn make_test_description(
13581338
},
13591339
);
13601340

1361-
if local_poisoned {
1362-
eprintln!("errors encountered when trying to make test description: {}", path);
1363-
panic!("errors encountered when trying to make test description");
1364-
}
1365-
13661341
// The `should-fail` annotation doesn't apply to pretty tests,
13671342
// since we run the pretty printer across all tests by default.
13681343
// If desired, we could add a `should-fail-pretty` annotation.

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Commit 8401398

Browse files
committed
Auto merge of #148762 - matthiaskrgr:rollup-4oifvkr, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #148248 (Constify `ControlFlow` methods without unstable bounds) - #148285 (Constify `ControlFlow` methods with unstable bounds) - #148510 (compiletest: Do the known-directives check only once, and improve its error message) - #148655 (Fix invalid macro tag generation for keywords which can be followed by values) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 6647be9 + 5430082 commit 8401398

8 files changed

Lines changed: 177 additions & 98 deletions

File tree

‎library/core/src/ops/control_flow.rs‎

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
usecrate::marker::Destruct;
12
usecrate::{convert, ops};
23

34
/// Used to tell an operation whether it should exit early or go on as usual.
@@ -150,7 +151,8 @@ impl<B, C> ControlFlow<B, C> {
150151
/// ```
151152
#[inline]
152153
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
153-
pubfnis_break(&self) -> bool{
154+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
155+
pubconstfnis_break(&self) -> bool{
154156
matches!(*self,ControlFlow::Break(_))
155157
}
156158

@@ -166,7 +168,8 @@ impl<B, C> ControlFlow<B, C> {
166168
/// ```
167169
#[inline]
168170
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
169-
pubfnis_continue(&self) -> bool{
171+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
172+
pubconstfnis_continue(&self) -> bool{
170173
matches!(*self,ControlFlow::Continue(_))
171174
}
172175

@@ -183,7 +186,11 @@ impl<B, C> ControlFlow<B, C> {
183186
/// ```
184187
#[inline]
185188
#[stable(feature = "control_flow_enum", since = "1.83.0")]
186-
pubfnbreak_value(self) -> Option<B>{
189+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
190+
pubconstfnbreak_value(self) -> Option<B>
191+
where
192+
Self:[const]Destruct,
193+
{
187194
matchself{
188195
ControlFlow::Continue(..) => None,
189196
ControlFlow::Break(x) => Some(x),
@@ -257,7 +264,8 @@ impl<B, C> ControlFlow<B, C> {
257264
/// ```
258265
#[inline]
259266
#[unstable(feature = "control_flow_ok", issue = "140266")]
260-
pubfnbreak_ok(self) -> Result<B,C>{
267+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
268+
pubconstfnbreak_ok(self) -> Result<B,C>{
261269
matchself{
262270
ControlFlow::Continue(c) => Err(c),
263271
ControlFlow::Break(b) => Ok(b),
@@ -268,7 +276,11 @@ impl<B, C> ControlFlow<B, C> {
268276
/// to the break value in case it exists.
269277
#[inline]
270278
#[stable(feature = "control_flow_enum", since = "1.83.0")]
271-
pubfnmap_break<T>(self,f:implFnOnce(B) -> T) -> ControlFlow<T,C>{
279+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
280+
pubconstfn map_break<T,F>(self,f:F) -> ControlFlow<T,C>
281+
where
282+
F:[const]FnOnce(B) -> T + [const]Destruct,
283+
{
272284
matchself{
273285
ControlFlow::Continue(x) => ControlFlow::Continue(x),
274286
ControlFlow::Break(x) => ControlFlow::Break(f(x)),
@@ -288,7 +300,11 @@ impl<B, C> ControlFlow<B, C> {
288300
/// ```
289301
#[inline]
290302
#[stable(feature = "control_flow_enum", since = "1.83.0")]
291-
pubfncontinue_value(self) -> Option<C>{
303+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
304+
pub constfncontinue_value(self) -> Option<C>
305+
where
306+
Self:[const]Destruct,
307+
{
292308
matchself{
293309
ControlFlow::Continue(x) => Some(x),
294310
ControlFlow::Break(..) => None,
@@ -361,7 +377,8 @@ impl<B, C> ControlFlow<B, C> {
361377
/// ```
362378
#[inline]
363379
#[unstable(feature = "control_flow_ok", issue = "140266")]
364-
pubfncontinue_ok(self) -> Result<C,B>{
380+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
381+
pub constfncontinue_ok(self) -> Result<C,B>{
365382
matchself{
366383
ControlFlow::Continue(c) => Ok(c),
367384
ControlFlow::Break(b) => Err(b),
@@ -372,7 +389,11 @@ impl<B, C> ControlFlow<B, C> {
372389
/// to the continue value in case it exists.
373390
#[inline]
374391
#[stable(feature = "control_flow_enum", since = "1.83.0")]
375-
pubfnmap_continue<T>(self,f:implFnOnce(C) -> T) -> ControlFlow<B,T>{
392+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
393+
pub constfnmap_continue<T,F>(self,f:F) -> ControlFlow<B,T>
394+
where
395+
F:[const]FnOnce(C) -> T + [const]Destruct,
396+
{
376397
matchself{
377398
ControlFlow::Continue(x) => ControlFlow::Continue(f(x)),
378399
ControlFlow::Break(x) => ControlFlow::Break(x),

‎src/librustdoc/html/highlight.rs‎

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,9 @@ impl<'a> Iterator for TokenIter<'a> {
789789
}
790790
}
791791

792+
/// Used to know if a keyword followed by a `!` should never be treated as a macro.
793+
constNON_MACRO_KEYWORDS:&[&str] = &["if","while","match","break","return","impl"];
794+
792795
/// This iterator comes from the same idea than "Peekable" except that it allows to "peek" more than
793796
/// just the next item by using `peek_next`. The `peek` method always returns the next item after
794797
/// the current one whereas `peek_next` will return the next item after the last one peeked.
@@ -1010,6 +1013,19 @@ impl<'src> Classifier<'src> {
10101013
}
10111014
}
10121015

1016+
fnnew_macro_span(
1017+
&mutself,
1018+
text:&'srcstr,
1019+
sink:&mutdynFnMut(Span,Highlight<'src>),
1020+
before:u32,
1021+
file_span:Span,
1022+
){
1023+
self.in_macro = true;
1024+
let span = new_span(before, text, file_span);
1025+
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1026+
sink(span,Highlight::Token{ text,class:None});
1027+
}
1028+
10131029
/// Single step of highlighting. This will classify `token`, but maybe also a couple of
10141030
/// following ones as well.
10151031
///
@@ -1216,16 +1232,46 @@ impl<'src> Classifier<'src> {
12161232
LiteralKind::Float{ .. } | LiteralKind::Int{ .. } => Class::Number,
12171233
},
12181234
TokenKind::GuardedStrPrefix => returnno_highlight(sink),
1219-
TokenKind::Ident | TokenKind::RawIdent
1220-
ifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() =>
1221-
{
1222-
self.in_macro = true;
1223-
let span = new_span(before, text, file_span);
1224-
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1225-
sink(span,Highlight::Token{ text,class:None});
1235+
TokenKind::RawIdentifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() => {
1236+
self.new_macro_span(text, sink, before, file_span);
12261237
return;
12271238
}
1228-
TokenKind::Ident => self.classify_ident(before, text),
1239+
// Macro non-terminals (meta vars) take precedence.
1240+
TokenKind::Identifself.in_macro_nonterminal => {
1241+
self.in_macro_nonterminal = false;
1242+
Class::MacroNonTerminal
1243+
}
1244+
TokenKind::Ident => {
1245+
let file_span = self.file_span;
1246+
let span = || new_span(before, text, file_span);
1247+
1248+
match text {
1249+
"ref" | "mut" => Class::RefKeyWord,
1250+
"false" | "true" => Class::Bool,
1251+
"self" | "Self" => Class::Self_(span()),
1252+
"Option" | "Result" => Class::PreludeTy(span()),
1253+
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1254+
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => {
1255+
// So if it's not a keyword which can be followed by a value (like `if` or
1256+
// `return`) and the next non-whitespace token is a `!`, then we consider
1257+
// it's a macro.
1258+
if !NON_MACRO_KEYWORDS.contains(&text)
1259+
&& matches!(self.peek_non_trivia(),Some((TokenKind::Bang, _)))
1260+
{
1261+
self.new_macro_span(text, sink, before, file_span);
1262+
return;
1263+
}
1264+
Class::KeyWord
1265+
}
1266+
// If it's not a keyword and the next non whitespace token is a `!`, then
1267+
// we consider it's a macro.
1268+
_ ifmatches!(self.peek_non_trivia(),Some((TokenKind::Bang, _))) => {
1269+
self.new_macro_span(text, sink, before, file_span);
1270+
return;
1271+
}
1272+
_ => Class::Ident(span()),
1273+
}
1274+
}
12291275
TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
12301276
Class::Ident(new_span(before, text, file_span))
12311277
}
@@ -1246,27 +1292,6 @@ impl<'src> Classifier<'src> {
12461292
}
12471293
}
12481294

1249-
fnclassify_ident(&mutself,before:u32,text:&'srcstr) -> Class{
1250-
// Macro non-terminals (meta vars) take precedence.
1251-
ifself.in_macro_nonterminal{
1252-
self.in_macro_nonterminal = false;
1253-
returnClass::MacroNonTerminal;
1254-
}
1255-
1256-
let file_span = self.file_span;
1257-
let span = || new_span(before, text, file_span);
1258-
1259-
match text {
1260-
"ref" | "mut" => Class::RefKeyWord,
1261-
"false" | "true" => Class::Bool,
1262-
"self" | "Self" => Class::Self_(span()),
1263-
"Option" | "Result" => Class::PreludeTy(span()),
1264-
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1265-
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => Class::KeyWord,
1266-
_ => Class::Ident(span()),
1267-
}
1268-
}
1269-
12701295
fnis_weak_keyword(&mutself,text:&str) -> bool{
12711296
// NOTE: `yeet` (`do yeet $expr`), `catch` (`do catch $block`), `default` (specialization),
12721297
// `contract_{ensures,requires}`, `builtin` (builtin_syntax) & `reuse` (fn_delegation) are

‎src/tools/compiletest/src/directives.rs‎

Lines changed: 33 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::debuggers::{extract_cdb_version, extract_gdb_version};
1111
pub(crate)usecrate::directives::auxiliary::AuxProps;
1212
usecrate::directives::auxiliary::parse_and_update_aux;
1313
usecrate::directives::directive_names::{
14-
KNOWN_DIRECTIVE_NAMES,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
14+
KNOWN_DIRECTIVE_NAMES_SET,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
1515
};
1616
pub(crate)usecrate::directives::file::FileDirectives;
1717
usecrate::directives::line::{DirectiveLine, line_directive};
@@ -53,25 +53,17 @@ impl EarlyProps {
5353
config:&Config,
5454
file_directives:&FileDirectives<'_>,
5555
) -> Self{
56-
let testfile = file_directives.path;
5756
letmut props = EarlyProps::default();
58-
letmut poisoned = false;
5957

6058
iter_directives(
6159
config.mode,
62-
&mut poisoned,
6360
file_directives,
6461
// (dummy comment to force args into vertical layout)
6562
&mut |ln:&DirectiveLine<'_>| {
6663
config.parse_and_update_revisions(ln,&mut props.revisions);
6764
},
6865
);
6966

70-
if poisoned {
71-
eprintln!("errors encountered during EarlyProps parsing: {}", testfile);
72-
panic!("errors encountered during EarlyProps parsing");
73-
}
74-
7567
props
7668
}
7769
}
@@ -358,12 +350,10 @@ impl TestProps {
358350
let file_contents = fs::read_to_string(testfile).unwrap();
359351
let file_directives = FileDirectives::from_file_contents(testfile,&file_contents);
360352

361-
letmut poisoned = false;
362-
363353
iter_directives(
364354
config.mode,
365-
&mut poisoned,
366355
&file_directives,
356+
// (dummy comment to force args into vertical layout)
367357
&mut |ln:&DirectiveLine<'_>| {
368358
if !ln.applies_to_test_revision(test_revision){
369359
return;
@@ -634,11 +624,6 @@ impl TestProps {
634624
);
635625
},
636626
);
637-
638-
if poisoned {
639-
eprintln!("errors encountered during TestProps parsing: {}", testfile);
640-
panic!("errors encountered during TestProps parsing");
641-
}
642627
}
643628

644629
ifself.should_ice{
@@ -775,6 +760,34 @@ impl TestProps {
775760
}
776761
}
777762

763+
pub(crate)fndo_early_directives_check(
764+
mode:TestMode,
765+
file_directives:&FileDirectives<'_>,
766+
) -> Result<(),String>{
767+
let testfile = file_directives.path;
768+
769+
for directive_line @ DirectiveLine{ line_number, .. }in&file_directives.lines{
770+
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
771+
check_directive(directive_line, mode);
772+
773+
if !is_known_directive {
774+
returnErr(format!(
775+
"ERROR: unknown compiletest directive `{directive}` at {testfile}:{line_number}",
776+
directive = directive_line.display(),
777+
));
778+
}
779+
780+
ifletSome(trailing_directive) = &trailing_directive {
781+
returnErr(format!(
782+
"ERROR: detected trailing compiletest directive `{trailing_directive}` at {testfile}:{line_number}\n\
783+
HELP: put the directive on its own line: `//@ {trailing_directive}`"
784+
));
785+
}
786+
}
787+
788+
Ok(())
789+
}
790+
778791
pub(crate)structCheckDirectiveResult<'ln>{
779792
is_known_directive:bool,
780793
trailing_directive:Option<&'lnstr>,
@@ -786,7 +799,7 @@ fn check_directive<'a>(
786799
) -> CheckDirectiveResult<'a>{
787800
let&DirectiveLine{name: directive_name, .. } = directive_ln;
788801

789-
let is_known_directive = KNOWN_DIRECTIVE_NAMES.contains(&directive_name)
802+
let is_known_directive = KNOWN_DIRECTIVE_NAMES_SET.contains(&directive_name)
790803
|| match mode {
791804
TestMode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
792805
TestMode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
@@ -799,7 +812,7 @@ fn check_directive<'a>(
799812
let trailing_directive = directive_ln
800813
.remark_after_space()
801814
.map(|remark| remark.trim_start().split(' ').next().unwrap())
802-
.filter(|token| KNOWN_DIRECTIVE_NAMES.contains(token));
815+
.filter(|token| KNOWN_DIRECTIVE_NAMES_SET.contains(token));
803816

804817
// FIXME(Zalathar): Consider emitting specialized error/help messages for
805818
// bogus directive names that are similar to real ones, e.g.:
@@ -811,7 +824,6 @@ fn check_directive<'a>(
811824

812825
fniter_directives(
813826
mode:TestMode,
814-
poisoned:&mutbool,
815827
file_directives:&FileDirectives<'_>,
816828
it:&mutdynFnMut(&DirectiveLine<'_>),
817829
){
@@ -837,36 +849,7 @@ fn iter_directives(
837849
}
838850
}
839851

840-
for directive_line @ &DirectiveLine{ line_number, .. }in&file_directives.lines{
841-
// Perform unknown directive check on Rust files.
842-
if testfile.extension() == Some("rs"){
843-
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
844-
check_directive(directive_line, mode);
845-
846-
if !is_known_directive {
847-
*poisoned = true;
848-
849-
error!(
850-
"{testfile}:{line_number}: detected unknown compiletest test directive `{}`",
851-
directive_line.display(),
852-
);
853-
854-
return;
855-
}
856-
857-
ifletSome(trailing_directive) = &trailing_directive {
858-
*poisoned = true;
859-
860-
error!(
861-
"{testfile}:{line_number}: detected trailing compiletest test directive `{}`",
862-
trailing_directive,
863-
);
864-
help!("put the trailing directive in its own line: `//@ {}`", trailing_directive);
865-
866-
return;
867-
}
868-
}
869-
852+
for directive_line in&file_directives.lines{
870853
it(directive_line);
871854
}
872855
}
@@ -1304,12 +1287,9 @@ pub(crate) fn make_test_description(
13041287
letmut ignore_message = None;
13051288
letmut should_fail = false;
13061289

1307-
letmut local_poisoned = false;
1308-
13091290
// Scan through the test file to handle `ignore-*`, `only-*`, and `needs-*` directives.
13101291
iter_directives(
13111292
config.mode,
1312-
&mut local_poisoned,
13131293
file_directives,
13141294
&mut |ln @ &DirectiveLine{ line_number, .. }| {
13151295
if !ln.applies_to_test_revision(test_revision){
@@ -1358,11 +1338,6 @@ pub(crate) fn make_test_description(
13581338
},
13591339
);
13601340

1361-
if local_poisoned {
1362-
eprintln!("errors encountered when trying to make test description: {}", path);
1363-
panic!("errors encountered when trying to make test description");
1364-
}
1365-
13661341
// The `should-fail` annotation doesn't apply to pretty tests,
13671342
// since we run the pretty printer across all tests by default.
13681343
// If desired, we could add a `should-fail-pretty` annotation.

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Commit 8401398

Browse files
committed
Auto merge of #148762 - matthiaskrgr:rollup-4oifvkr, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #148248 (Constify `ControlFlow` methods without unstable bounds) - #148285 (Constify `ControlFlow` methods with unstable bounds) - #148510 (compiletest: Do the known-directives check only once, and improve its error message) - #148655 (Fix invalid macro tag generation for keywords which can be followed by values) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 6647be9 + 5430082 commit 8401398

8 files changed

Lines changed: 177 additions & 98 deletions

File tree

‎library/core/src/ops/control_flow.rs‎

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
usecrate::marker::Destruct;
12
usecrate::{convert, ops};
23

34
/// Used to tell an operation whether it should exit early or go on as usual.
@@ -150,7 +151,8 @@ impl<B, C> ControlFlow<B, C> {
150151
/// ```
151152
#[inline]
152153
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
153-
pubfnis_break(&self) -> bool{
154+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
155+
pubconstfnis_break(&self) -> bool{
154156
matches!(*self,ControlFlow::Break(_))
155157
}
156158

@@ -166,7 +168,8 @@ impl<B, C> ControlFlow<B, C> {
166168
/// ```
167169
#[inline]
168170
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
169-
pubfnis_continue(&self) -> bool{
171+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
172+
pubconstfnis_continue(&self) -> bool{
170173
matches!(*self,ControlFlow::Continue(_))
171174
}
172175

@@ -183,7 +186,11 @@ impl<B, C> ControlFlow<B, C> {
183186
/// ```
184187
#[inline]
185188
#[stable(feature = "control_flow_enum", since = "1.83.0")]
186-
pubfnbreak_value(self) -> Option<B>{
189+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
190+
pubconstfnbreak_value(self) -> Option<B>
191+
where
192+
Self:[const]Destruct,
193+
{
187194
matchself{
188195
ControlFlow::Continue(..) => None,
189196
ControlFlow::Break(x) => Some(x),
@@ -257,7 +264,8 @@ impl<B, C> ControlFlow<B, C> {
257264
/// ```
258265
#[inline]
259266
#[unstable(feature = "control_flow_ok", issue = "140266")]
260-
pubfnbreak_ok(self) -> Result<B,C>{
267+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
268+
pubconstfnbreak_ok(self) -> Result<B,C>{
261269
matchself{
262270
ControlFlow::Continue(c) => Err(c),
263271
ControlFlow::Break(b) => Ok(b),
@@ -268,7 +276,11 @@ impl<B, C> ControlFlow<B, C> {
268276
/// to the break value in case it exists.
269277
#[inline]
270278
#[stable(feature = "control_flow_enum", since = "1.83.0")]
271-
pubfnmap_break<T>(self,f:implFnOnce(B) -> T) -> ControlFlow<T,C>{
279+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
280+
pubconstfn map_break<T,F>(self,f:F) -> ControlFlow<T,C>
281+
where
282+
F:[const]FnOnce(B) -> T + [const]Destruct,
283+
{
272284
matchself{
273285
ControlFlow::Continue(x) => ControlFlow::Continue(x),
274286
ControlFlow::Break(x) => ControlFlow::Break(f(x)),
@@ -288,7 +300,11 @@ impl<B, C> ControlFlow<B, C> {
288300
/// ```
289301
#[inline]
290302
#[stable(feature = "control_flow_enum", since = "1.83.0")]
291-
pubfncontinue_value(self) -> Option<C>{
303+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
304+
pub constfncontinue_value(self) -> Option<C>
305+
where
306+
Self:[const]Destruct,
307+
{
292308
matchself{
293309
ControlFlow::Continue(x) => Some(x),
294310
ControlFlow::Break(..) => None,
@@ -361,7 +377,8 @@ impl<B, C> ControlFlow<B, C> {
361377
/// ```
362378
#[inline]
363379
#[unstable(feature = "control_flow_ok", issue = "140266")]
364-
pubfncontinue_ok(self) -> Result<C,B>{
380+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
381+
pub constfncontinue_ok(self) -> Result<C,B>{
365382
matchself{
366383
ControlFlow::Continue(c) => Ok(c),
367384
ControlFlow::Break(b) => Err(b),
@@ -372,7 +389,11 @@ impl<B, C> ControlFlow<B, C> {
372389
/// to the continue value in case it exists.
373390
#[inline]
374391
#[stable(feature = "control_flow_enum", since = "1.83.0")]
375-
pubfnmap_continue<T>(self,f:implFnOnce(C) -> T) -> ControlFlow<B,T>{
392+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
393+
pub constfnmap_continue<T,F>(self,f:F) -> ControlFlow<B,T>
394+
where
395+
F:[const]FnOnce(C) -> T + [const]Destruct,
396+
{
376397
matchself{
377398
ControlFlow::Continue(x) => ControlFlow::Continue(f(x)),
378399
ControlFlow::Break(x) => ControlFlow::Break(x),

‎src/librustdoc/html/highlight.rs‎

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,9 @@ impl<'a> Iterator for TokenIter<'a> {
789789
}
790790
}
791791

792+
/// Used to know if a keyword followed by a `!` should never be treated as a macro.
793+
constNON_MACRO_KEYWORDS:&[&str] = &["if","while","match","break","return","impl"];
794+
792795
/// This iterator comes from the same idea than "Peekable" except that it allows to "peek" more than
793796
/// just the next item by using `peek_next`. The `peek` method always returns the next item after
794797
/// the current one whereas `peek_next` will return the next item after the last one peeked.
@@ -1010,6 +1013,19 @@ impl<'src> Classifier<'src> {
10101013
}
10111014
}
10121015

1016+
fnnew_macro_span(
1017+
&mutself,
1018+
text:&'srcstr,
1019+
sink:&mutdynFnMut(Span,Highlight<'src>),
1020+
before:u32,
1021+
file_span:Span,
1022+
){
1023+
self.in_macro = true;
1024+
let span = new_span(before, text, file_span);
1025+
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1026+
sink(span,Highlight::Token{ text,class:None});
1027+
}
1028+
10131029
/// Single step of highlighting. This will classify `token`, but maybe also a couple of
10141030
/// following ones as well.
10151031
///
@@ -1216,16 +1232,46 @@ impl<'src> Classifier<'src> {
12161232
LiteralKind::Float{ .. } | LiteralKind::Int{ .. } => Class::Number,
12171233
},
12181234
TokenKind::GuardedStrPrefix => returnno_highlight(sink),
1219-
TokenKind::Ident | TokenKind::RawIdent
1220-
ifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() =>
1221-
{
1222-
self.in_macro = true;
1223-
let span = new_span(before, text, file_span);
1224-
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1225-
sink(span,Highlight::Token{ text,class:None});
1235+
TokenKind::RawIdentifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() => {
1236+
self.new_macro_span(text, sink, before, file_span);
12261237
return;
12271238
}
1228-
TokenKind::Ident => self.classify_ident(before, text),
1239+
// Macro non-terminals (meta vars) take precedence.
1240+
TokenKind::Identifself.in_macro_nonterminal => {
1241+
self.in_macro_nonterminal = false;
1242+
Class::MacroNonTerminal
1243+
}
1244+
TokenKind::Ident => {
1245+
let file_span = self.file_span;
1246+
let span = || new_span(before, text, file_span);
1247+
1248+
match text {
1249+
"ref" | "mut" => Class::RefKeyWord,
1250+
"false" | "true" => Class::Bool,
1251+
"self" | "Self" => Class::Self_(span()),
1252+
"Option" | "Result" => Class::PreludeTy(span()),
1253+
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1254+
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => {
1255+
// So if it's not a keyword which can be followed by a value (like `if` or
1256+
// `return`) and the next non-whitespace token is a `!`, then we consider
1257+
// it's a macro.
1258+
if !NON_MACRO_KEYWORDS.contains(&text)
1259+
&& matches!(self.peek_non_trivia(),Some((TokenKind::Bang, _)))
1260+
{
1261+
self.new_macro_span(text, sink, before, file_span);
1262+
return;
1263+
}
1264+
Class::KeyWord
1265+
}
1266+
// If it's not a keyword and the next non whitespace token is a `!`, then
1267+
// we consider it's a macro.
1268+
_ ifmatches!(self.peek_non_trivia(),Some((TokenKind::Bang, _))) => {
1269+
self.new_macro_span(text, sink, before, file_span);
1270+
return;
1271+
}
1272+
_ => Class::Ident(span()),
1273+
}
1274+
}
12291275
TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
12301276
Class::Ident(new_span(before, text, file_span))
12311277
}
@@ -1246,27 +1292,6 @@ impl<'src> Classifier<'src> {
12461292
}
12471293
}
12481294

1249-
fnclassify_ident(&mutself,before:u32,text:&'srcstr) -> Class{
1250-
// Macro non-terminals (meta vars) take precedence.
1251-
ifself.in_macro_nonterminal{
1252-
self.in_macro_nonterminal = false;
1253-
returnClass::MacroNonTerminal;
1254-
}
1255-
1256-
let file_span = self.file_span;
1257-
let span = || new_span(before, text, file_span);
1258-
1259-
match text {
1260-
"ref" | "mut" => Class::RefKeyWord,
1261-
"false" | "true" => Class::Bool,
1262-
"self" | "Self" => Class::Self_(span()),
1263-
"Option" | "Result" => Class::PreludeTy(span()),
1264-
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1265-
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => Class::KeyWord,
1266-
_ => Class::Ident(span()),
1267-
}
1268-
}
1269-
12701295
fnis_weak_keyword(&mutself,text:&str) -> bool{
12711296
// NOTE: `yeet` (`do yeet $expr`), `catch` (`do catch $block`), `default` (specialization),
12721297
// `contract_{ensures,requires}`, `builtin` (builtin_syntax) & `reuse` (fn_delegation) are

‎src/tools/compiletest/src/directives.rs‎

Lines changed: 33 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::debuggers::{extract_cdb_version, extract_gdb_version};
1111
pub(crate)usecrate::directives::auxiliary::AuxProps;
1212
usecrate::directives::auxiliary::parse_and_update_aux;
1313
usecrate::directives::directive_names::{
14-
KNOWN_DIRECTIVE_NAMES,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
14+
KNOWN_DIRECTIVE_NAMES_SET,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
1515
};
1616
pub(crate)usecrate::directives::file::FileDirectives;
1717
usecrate::directives::line::{DirectiveLine, line_directive};
@@ -53,25 +53,17 @@ impl EarlyProps {
5353
config:&Config,
5454
file_directives:&FileDirectives<'_>,
5555
) -> Self{
56-
let testfile = file_directives.path;
5756
letmut props = EarlyProps::default();
58-
letmut poisoned = false;
5957

6058
iter_directives(
6159
config.mode,
62-
&mut poisoned,
6360
file_directives,
6461
// (dummy comment to force args into vertical layout)
6562
&mut |ln:&DirectiveLine<'_>| {
6663
config.parse_and_update_revisions(ln,&mut props.revisions);
6764
},
6865
);
6966

70-
if poisoned {
71-
eprintln!("errors encountered during EarlyProps parsing: {}", testfile);
72-
panic!("errors encountered during EarlyProps parsing");
73-
}
74-
7567
props
7668
}
7769
}
@@ -358,12 +350,10 @@ impl TestProps {
358350
let file_contents = fs::read_to_string(testfile).unwrap();
359351
let file_directives = FileDirectives::from_file_contents(testfile,&file_contents);
360352

361-
letmut poisoned = false;
362-
363353
iter_directives(
364354
config.mode,
365-
&mut poisoned,
366355
&file_directives,
356+
// (dummy comment to force args into vertical layout)
367357
&mut |ln:&DirectiveLine<'_>| {
368358
if !ln.applies_to_test_revision(test_revision){
369359
return;
@@ -634,11 +624,6 @@ impl TestProps {
634624
);
635625
},
636626
);
637-
638-
if poisoned {
639-
eprintln!("errors encountered during TestProps parsing: {}", testfile);
640-
panic!("errors encountered during TestProps parsing");
641-
}
642627
}
643628

644629
ifself.should_ice{
@@ -775,6 +760,34 @@ impl TestProps {
775760
}
776761
}
777762

763+
pub(crate)fndo_early_directives_check(
764+
mode:TestMode,
765+
file_directives:&FileDirectives<'_>,
766+
) -> Result<(),String>{
767+
let testfile = file_directives.path;
768+
769+
for directive_line @ DirectiveLine{ line_number, .. }in&file_directives.lines{
770+
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
771+
check_directive(directive_line, mode);
772+
773+
if !is_known_directive {
774+
returnErr(format!(
775+
"ERROR: unknown compiletest directive `{directive}` at {testfile}:{line_number}",
776+
directive = directive_line.display(),
777+
));
778+
}
779+
780+
ifletSome(trailing_directive) = &trailing_directive {
781+
returnErr(format!(
782+
"ERROR: detected trailing compiletest directive `{trailing_directive}` at {testfile}:{line_number}\n\
783+
HELP: put the directive on its own line: `//@ {trailing_directive}`"
784+
));
785+
}
786+
}
787+
788+
Ok(())
789+
}
790+
778791
pub(crate)structCheckDirectiveResult<'ln>{
779792
is_known_directive:bool,
780793
trailing_directive:Option<&'lnstr>,
@@ -786,7 +799,7 @@ fn check_directive<'a>(
786799
) -> CheckDirectiveResult<'a>{
787800
let&DirectiveLine{name: directive_name, .. } = directive_ln;
788801

789-
let is_known_directive = KNOWN_DIRECTIVE_NAMES.contains(&directive_name)
802+
let is_known_directive = KNOWN_DIRECTIVE_NAMES_SET.contains(&directive_name)
790803
|| match mode {
791804
TestMode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
792805
TestMode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
@@ -799,7 +812,7 @@ fn check_directive<'a>(
799812
let trailing_directive = directive_ln
800813
.remark_after_space()
801814
.map(|remark| remark.trim_start().split(' ').next().unwrap())
802-
.filter(|token| KNOWN_DIRECTIVE_NAMES.contains(token));
815+
.filter(|token| KNOWN_DIRECTIVE_NAMES_SET.contains(token));
803816

804817
// FIXME(Zalathar): Consider emitting specialized error/help messages for
805818
// bogus directive names that are similar to real ones, e.g.:
@@ -811,7 +824,6 @@ fn check_directive<'a>(
811824

812825
fniter_directives(
813826
mode:TestMode,
814-
poisoned:&mutbool,
815827
file_directives:&FileDirectives<'_>,
816828
it:&mutdynFnMut(&DirectiveLine<'_>),
817829
){
@@ -837,36 +849,7 @@ fn iter_directives(
837849
}
838850
}
839851

840-
for directive_line @ &DirectiveLine{ line_number, .. }in&file_directives.lines{
841-
// Perform unknown directive check on Rust files.
842-
if testfile.extension() == Some("rs"){
843-
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
844-
check_directive(directive_line, mode);
845-
846-
if !is_known_directive {
847-
*poisoned = true;
848-
849-
error!(
850-
"{testfile}:{line_number}: detected unknown compiletest test directive `{}`",
851-
directive_line.display(),
852-
);
853-
854-
return;
855-
}
856-
857-
ifletSome(trailing_directive) = &trailing_directive {
858-
*poisoned = true;
859-
860-
error!(
861-
"{testfile}:{line_number}: detected trailing compiletest test directive `{}`",
862-
trailing_directive,
863-
);
864-
help!("put the trailing directive in its own line: `//@ {}`", trailing_directive);
865-
866-
return;
867-
}
868-
}
869-
852+
for directive_line in&file_directives.lines{
870853
it(directive_line);
871854
}
872855
}
@@ -1304,12 +1287,9 @@ pub(crate) fn make_test_description(
13041287
letmut ignore_message = None;
13051288
letmut should_fail = false;
13061289

1307-
letmut local_poisoned = false;
1308-
13091290
// Scan through the test file to handle `ignore-*`, `only-*`, and `needs-*` directives.
13101291
iter_directives(
13111292
config.mode,
1312-
&mut local_poisoned,
13131293
file_directives,
13141294
&mut |ln @ &DirectiveLine{ line_number, .. }| {
13151295
if !ln.applies_to_test_revision(test_revision){
@@ -1358,11 +1338,6 @@ pub(crate) fn make_test_description(
13581338
},
13591339
);
13601340

1361-
if local_poisoned {
1362-
eprintln!("errors encountered when trying to make test description: {}", path);
1363-
panic!("errors encountered when trying to make test description");
1364-
}
1365-
13661341
// The `should-fail` annotation doesn't apply to pretty tests,
13671342
// since we run the pretty printer across all tests by default.
13681343
// If desired, we could add a `should-fail-pretty` annotation.

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Commit 8401398

Browse files
committed
Auto merge of #148762 - matthiaskrgr:rollup-4oifvkr, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #148248 (Constify `ControlFlow` methods without unstable bounds) - #148285 (Constify `ControlFlow` methods with unstable bounds) - #148510 (compiletest: Do the known-directives check only once, and improve its error message) - #148655 (Fix invalid macro tag generation for keywords which can be followed by values) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 6647be9 + 5430082 commit 8401398

8 files changed

Lines changed: 177 additions & 98 deletions

File tree

‎library/core/src/ops/control_flow.rs‎

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
usecrate::marker::Destruct;
12
usecrate::{convert, ops};
23

34
/// Used to tell an operation whether it should exit early or go on as usual.
@@ -150,7 +151,8 @@ impl<B, C> ControlFlow<B, C> {
150151
/// ```
151152
#[inline]
152153
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
153-
pubfnis_break(&self) -> bool{
154+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
155+
pubconstfnis_break(&self) -> bool{
154156
matches!(*self,ControlFlow::Break(_))
155157
}
156158

@@ -166,7 +168,8 @@ impl<B, C> ControlFlow<B, C> {
166168
/// ```
167169
#[inline]
168170
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
169-
pubfnis_continue(&self) -> bool{
171+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
172+
pubconstfnis_continue(&self) -> bool{
170173
matches!(*self,ControlFlow::Continue(_))
171174
}
172175

@@ -183,7 +186,11 @@ impl<B, C> ControlFlow<B, C> {
183186
/// ```
184187
#[inline]
185188
#[stable(feature = "control_flow_enum", since = "1.83.0")]
186-
pubfnbreak_value(self) -> Option<B>{
189+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
190+
pubconstfnbreak_value(self) -> Option<B>
191+
where
192+
Self:[const]Destruct,
193+
{
187194
matchself{
188195
ControlFlow::Continue(..) => None,
189196
ControlFlow::Break(x) => Some(x),
@@ -257,7 +264,8 @@ impl<B, C> ControlFlow<B, C> {
257264
/// ```
258265
#[inline]
259266
#[unstable(feature = "control_flow_ok", issue = "140266")]
260-
pubfnbreak_ok(self) -> Result<B,C>{
267+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
268+
pubconstfnbreak_ok(self) -> Result<B,C>{
261269
matchself{
262270
ControlFlow::Continue(c) => Err(c),
263271
ControlFlow::Break(b) => Ok(b),
@@ -268,7 +276,11 @@ impl<B, C> ControlFlow<B, C> {
268276
/// to the break value in case it exists.
269277
#[inline]
270278
#[stable(feature = "control_flow_enum", since = "1.83.0")]
271-
pubfnmap_break<T>(self,f:implFnOnce(B) -> T) -> ControlFlow<T,C>{
279+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
280+
pubconstfn map_break<T,F>(self,f:F) -> ControlFlow<T,C>
281+
where
282+
F:[const]FnOnce(B) -> T + [const]Destruct,
283+
{
272284
matchself{
273285
ControlFlow::Continue(x) => ControlFlow::Continue(x),
274286
ControlFlow::Break(x) => ControlFlow::Break(f(x)),
@@ -288,7 +300,11 @@ impl<B, C> ControlFlow<B, C> {
288300
/// ```
289301
#[inline]
290302
#[stable(feature = "control_flow_enum", since = "1.83.0")]
291-
pubfncontinue_value(self) -> Option<C>{
303+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
304+
pub constfncontinue_value(self) -> Option<C>
305+
where
306+
Self:[const]Destruct,
307+
{
292308
matchself{
293309
ControlFlow::Continue(x) => Some(x),
294310
ControlFlow::Break(..) => None,
@@ -361,7 +377,8 @@ impl<B, C> ControlFlow<B, C> {
361377
/// ```
362378
#[inline]
363379
#[unstable(feature = "control_flow_ok", issue = "140266")]
364-
pubfncontinue_ok(self) -> Result<C,B>{
380+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
381+
pub constfncontinue_ok(self) -> Result<C,B>{
365382
matchself{
366383
ControlFlow::Continue(c) => Ok(c),
367384
ControlFlow::Break(b) => Err(b),
@@ -372,7 +389,11 @@ impl<B, C> ControlFlow<B, C> {
372389
/// to the continue value in case it exists.
373390
#[inline]
374391
#[stable(feature = "control_flow_enum", since = "1.83.0")]
375-
pubfnmap_continue<T>(self,f:implFnOnce(C) -> T) -> ControlFlow<B,T>{
392+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
393+
pub constfnmap_continue<T,F>(self,f:F) -> ControlFlow<B,T>
394+
where
395+
F:[const]FnOnce(C) -> T + [const]Destruct,
396+
{
376397
matchself{
377398
ControlFlow::Continue(x) => ControlFlow::Continue(f(x)),
378399
ControlFlow::Break(x) => ControlFlow::Break(x),

‎src/librustdoc/html/highlight.rs‎

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,9 @@ impl<'a> Iterator for TokenIter<'a> {
789789
}
790790
}
791791

792+
/// Used to know if a keyword followed by a `!` should never be treated as a macro.
793+
constNON_MACRO_KEYWORDS:&[&str] = &["if","while","match","break","return","impl"];
794+
792795
/// This iterator comes from the same idea than "Peekable" except that it allows to "peek" more than
793796
/// just the next item by using `peek_next`. The `peek` method always returns the next item after
794797
/// the current one whereas `peek_next` will return the next item after the last one peeked.
@@ -1010,6 +1013,19 @@ impl<'src> Classifier<'src> {
10101013
}
10111014
}
10121015

1016+
fnnew_macro_span(
1017+
&mutself,
1018+
text:&'srcstr,
1019+
sink:&mutdynFnMut(Span,Highlight<'src>),
1020+
before:u32,
1021+
file_span:Span,
1022+
){
1023+
self.in_macro = true;
1024+
let span = new_span(before, text, file_span);
1025+
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1026+
sink(span,Highlight::Token{ text,class:None});
1027+
}
1028+
10131029
/// Single step of highlighting. This will classify `token`, but maybe also a couple of
10141030
/// following ones as well.
10151031
///
@@ -1216,16 +1232,46 @@ impl<'src> Classifier<'src> {
12161232
LiteralKind::Float{ .. } | LiteralKind::Int{ .. } => Class::Number,
12171233
},
12181234
TokenKind::GuardedStrPrefix => returnno_highlight(sink),
1219-
TokenKind::Ident | TokenKind::RawIdent
1220-
ifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() =>
1221-
{
1222-
self.in_macro = true;
1223-
let span = new_span(before, text, file_span);
1224-
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1225-
sink(span,Highlight::Token{ text,class:None});
1235+
TokenKind::RawIdentifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() => {
1236+
self.new_macro_span(text, sink, before, file_span);
12261237
return;
12271238
}
1228-
TokenKind::Ident => self.classify_ident(before, text),
1239+
// Macro non-terminals (meta vars) take precedence.
1240+
TokenKind::Identifself.in_macro_nonterminal => {
1241+
self.in_macro_nonterminal = false;
1242+
Class::MacroNonTerminal
1243+
}
1244+
TokenKind::Ident => {
1245+
let file_span = self.file_span;
1246+
let span = || new_span(before, text, file_span);
1247+
1248+
match text {
1249+
"ref" | "mut" => Class::RefKeyWord,
1250+
"false" | "true" => Class::Bool,
1251+
"self" | "Self" => Class::Self_(span()),
1252+
"Option" | "Result" => Class::PreludeTy(span()),
1253+
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1254+
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => {
1255+
// So if it's not a keyword which can be followed by a value (like `if` or
1256+
// `return`) and the next non-whitespace token is a `!`, then we consider
1257+
// it's a macro.
1258+
if !NON_MACRO_KEYWORDS.contains(&text)
1259+
&& matches!(self.peek_non_trivia(),Some((TokenKind::Bang, _)))
1260+
{
1261+
self.new_macro_span(text, sink, before, file_span);
1262+
return;
1263+
}
1264+
Class::KeyWord
1265+
}
1266+
// If it's not a keyword and the next non whitespace token is a `!`, then
1267+
// we consider it's a macro.
1268+
_ ifmatches!(self.peek_non_trivia(),Some((TokenKind::Bang, _))) => {
1269+
self.new_macro_span(text, sink, before, file_span);
1270+
return;
1271+
}
1272+
_ => Class::Ident(span()),
1273+
}
1274+
}
12291275
TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
12301276
Class::Ident(new_span(before, text, file_span))
12311277
}
@@ -1246,27 +1292,6 @@ impl<'src> Classifier<'src> {
12461292
}
12471293
}
12481294

1249-
fnclassify_ident(&mutself,before:u32,text:&'srcstr) -> Class{
1250-
// Macro non-terminals (meta vars) take precedence.
1251-
ifself.in_macro_nonterminal{
1252-
self.in_macro_nonterminal = false;
1253-
returnClass::MacroNonTerminal;
1254-
}
1255-
1256-
let file_span = self.file_span;
1257-
let span = || new_span(before, text, file_span);
1258-
1259-
match text {
1260-
"ref" | "mut" => Class::RefKeyWord,
1261-
"false" | "true" => Class::Bool,
1262-
"self" | "Self" => Class::Self_(span()),
1263-
"Option" | "Result" => Class::PreludeTy(span()),
1264-
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1265-
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => Class::KeyWord,
1266-
_ => Class::Ident(span()),
1267-
}
1268-
}
1269-
12701295
fnis_weak_keyword(&mutself,text:&str) -> bool{
12711296
// NOTE: `yeet` (`do yeet $expr`), `catch` (`do catch $block`), `default` (specialization),
12721297
// `contract_{ensures,requires}`, `builtin` (builtin_syntax) & `reuse` (fn_delegation) are

‎src/tools/compiletest/src/directives.rs‎

Lines changed: 33 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::debuggers::{extract_cdb_version, extract_gdb_version};
1111
pub(crate)usecrate::directives::auxiliary::AuxProps;
1212
usecrate::directives::auxiliary::parse_and_update_aux;
1313
usecrate::directives::directive_names::{
14-
KNOWN_DIRECTIVE_NAMES,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
14+
KNOWN_DIRECTIVE_NAMES_SET,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
1515
};
1616
pub(crate)usecrate::directives::file::FileDirectives;
1717
usecrate::directives::line::{DirectiveLine, line_directive};
@@ -53,25 +53,17 @@ impl EarlyProps {
5353
config:&Config,
5454
file_directives:&FileDirectives<'_>,
5555
) -> Self{
56-
let testfile = file_directives.path;
5756
letmut props = EarlyProps::default();
58-
letmut poisoned = false;
5957

6058
iter_directives(
6159
config.mode,
62-
&mut poisoned,
6360
file_directives,
6461
// (dummy comment to force args into vertical layout)
6562
&mut |ln:&DirectiveLine<'_>| {
6663
config.parse_and_update_revisions(ln,&mut props.revisions);
6764
},
6865
);
6966

70-
if poisoned {
71-
eprintln!("errors encountered during EarlyProps parsing: {}", testfile);
72-
panic!("errors encountered during EarlyProps parsing");
73-
}
74-
7567
props
7668
}
7769
}
@@ -358,12 +350,10 @@ impl TestProps {
358350
let file_contents = fs::read_to_string(testfile).unwrap();
359351
let file_directives = FileDirectives::from_file_contents(testfile,&file_contents);
360352

361-
letmut poisoned = false;
362-
363353
iter_directives(
364354
config.mode,
365-
&mut poisoned,
366355
&file_directives,
356+
// (dummy comment to force args into vertical layout)
367357
&mut |ln:&DirectiveLine<'_>| {
368358
if !ln.applies_to_test_revision(test_revision){
369359
return;
@@ -634,11 +624,6 @@ impl TestProps {
634624
);
635625
},
636626
);
637-
638-
if poisoned {
639-
eprintln!("errors encountered during TestProps parsing: {}", testfile);
640-
panic!("errors encountered during TestProps parsing");
641-
}
642627
}
643628

644629
ifself.should_ice{
@@ -775,6 +760,34 @@ impl TestProps {
775760
}
776761
}
777762

763+
pub(crate)fndo_early_directives_check(
764+
mode:TestMode,
765+
file_directives:&FileDirectives<'_>,
766+
) -> Result<(),String>{
767+
let testfile = file_directives.path;
768+
769+
for directive_line @ DirectiveLine{ line_number, .. }in&file_directives.lines{
770+
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
771+
check_directive(directive_line, mode);
772+
773+
if !is_known_directive {
774+
returnErr(format!(
775+
"ERROR: unknown compiletest directive `{directive}` at {testfile}:{line_number}",
776+
directive = directive_line.display(),
777+
));
778+
}
779+
780+
ifletSome(trailing_directive) = &trailing_directive {
781+
returnErr(format!(
782+
"ERROR: detected trailing compiletest directive `{trailing_directive}` at {testfile}:{line_number}\n\
783+
HELP: put the directive on its own line: `//@ {trailing_directive}`"
784+
));
785+
}
786+
}
787+
788+
Ok(())
789+
}
790+
778791
pub(crate)structCheckDirectiveResult<'ln>{
779792
is_known_directive:bool,
780793
trailing_directive:Option<&'lnstr>,
@@ -786,7 +799,7 @@ fn check_directive<'a>(
786799
) -> CheckDirectiveResult<'a>{
787800
let&DirectiveLine{name: directive_name, .. } = directive_ln;
788801

789-
let is_known_directive = KNOWN_DIRECTIVE_NAMES.contains(&directive_name)
802+
let is_known_directive = KNOWN_DIRECTIVE_NAMES_SET.contains(&directive_name)
790803
|| match mode {
791804
TestMode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
792805
TestMode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
@@ -799,7 +812,7 @@ fn check_directive<'a>(
799812
let trailing_directive = directive_ln
800813
.remark_after_space()
801814
.map(|remark| remark.trim_start().split(' ').next().unwrap())
802-
.filter(|token| KNOWN_DIRECTIVE_NAMES.contains(token));
815+
.filter(|token| KNOWN_DIRECTIVE_NAMES_SET.contains(token));
803816

804817
// FIXME(Zalathar): Consider emitting specialized error/help messages for
805818
// bogus directive names that are similar to real ones, e.g.:
@@ -811,7 +824,6 @@ fn check_directive<'a>(
811824

812825
fniter_directives(
813826
mode:TestMode,
814-
poisoned:&mutbool,
815827
file_directives:&FileDirectives<'_>,
816828
it:&mutdynFnMut(&DirectiveLine<'_>),
817829
){
@@ -837,36 +849,7 @@ fn iter_directives(
837849
}
838850
}
839851

840-
for directive_line @ &DirectiveLine{ line_number, .. }in&file_directives.lines{
841-
// Perform unknown directive check on Rust files.
842-
if testfile.extension() == Some("rs"){
843-
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
844-
check_directive(directive_line, mode);
845-
846-
if !is_known_directive {
847-
*poisoned = true;
848-
849-
error!(
850-
"{testfile}:{line_number}: detected unknown compiletest test directive `{}`",
851-
directive_line.display(),
852-
);
853-
854-
return;
855-
}
856-
857-
ifletSome(trailing_directive) = &trailing_directive {
858-
*poisoned = true;
859-
860-
error!(
861-
"{testfile}:{line_number}: detected trailing compiletest test directive `{}`",
862-
trailing_directive,
863-
);
864-
help!("put the trailing directive in its own line: `//@ {}`", trailing_directive);
865-
866-
return;
867-
}
868-
}
869-
852+
for directive_line in&file_directives.lines{
870853
it(directive_line);
871854
}
872855
}
@@ -1304,12 +1287,9 @@ pub(crate) fn make_test_description(
13041287
letmut ignore_message = None;
13051288
letmut should_fail = false;
13061289

1307-
letmut local_poisoned = false;
1308-
13091290
// Scan through the test file to handle `ignore-*`, `only-*`, and `needs-*` directives.
13101291
iter_directives(
13111292
config.mode,
1312-
&mut local_poisoned,
13131293
file_directives,
13141294
&mut |ln @ &DirectiveLine{ line_number, .. }| {
13151295
if !ln.applies_to_test_revision(test_revision){
@@ -1358,11 +1338,6 @@ pub(crate) fn make_test_description(
13581338
},
13591339
);
13601340

1361-
if local_poisoned {
1362-
eprintln!("errors encountered when trying to make test description: {}", path);
1363-
panic!("errors encountered when trying to make test description");
1364-
}
1365-
13661341
// The `should-fail` annotation doesn't apply to pretty tests,
13671342
// since we run the pretty printer across all tests by default.
13681343
// If desired, we could add a `should-fail-pretty` annotation.

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Commit 8401398

Browse files
committed
Auto merge of #148762 - matthiaskrgr:rollup-4oifvkr, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #148248 (Constify `ControlFlow` methods without unstable bounds) - #148285 (Constify `ControlFlow` methods with unstable bounds) - #148510 (compiletest: Do the known-directives check only once, and improve its error message) - #148655 (Fix invalid macro tag generation for keywords which can be followed by values) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 6647be9 + 5430082 commit 8401398

8 files changed

Lines changed: 177 additions & 98 deletions

File tree

‎library/core/src/ops/control_flow.rs‎

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
usecrate::marker::Destruct;
12
usecrate::{convert, ops};
23

34
/// Used to tell an operation whether it should exit early or go on as usual.
@@ -150,7 +151,8 @@ impl<B, C> ControlFlow<B, C> {
150151
/// ```
151152
#[inline]
152153
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
153-
pubfnis_break(&self) -> bool{
154+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
155+
pubconstfnis_break(&self) -> bool{
154156
matches!(*self,ControlFlow::Break(_))
155157
}
156158

@@ -166,7 +168,8 @@ impl<B, C> ControlFlow<B, C> {
166168
/// ```
167169
#[inline]
168170
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
169-
pubfnis_continue(&self) -> bool{
171+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
172+
pubconstfnis_continue(&self) -> bool{
170173
matches!(*self,ControlFlow::Continue(_))
171174
}
172175

@@ -183,7 +186,11 @@ impl<B, C> ControlFlow<B, C> {
183186
/// ```
184187
#[inline]
185188
#[stable(feature = "control_flow_enum", since = "1.83.0")]
186-
pubfnbreak_value(self) -> Option<B>{
189+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
190+
pubconstfnbreak_value(self) -> Option<B>
191+
where
192+
Self:[const]Destruct,
193+
{
187194
matchself{
188195
ControlFlow::Continue(..) => None,
189196
ControlFlow::Break(x) => Some(x),
@@ -257,7 +264,8 @@ impl<B, C> ControlFlow<B, C> {
257264
/// ```
258265
#[inline]
259266
#[unstable(feature = "control_flow_ok", issue = "140266")]
260-
pubfnbreak_ok(self) -> Result<B,C>{
267+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
268+
pubconstfnbreak_ok(self) -> Result<B,C>{
261269
matchself{
262270
ControlFlow::Continue(c) => Err(c),
263271
ControlFlow::Break(b) => Ok(b),
@@ -268,7 +276,11 @@ impl<B, C> ControlFlow<B, C> {
268276
/// to the break value in case it exists.
269277
#[inline]
270278
#[stable(feature = "control_flow_enum", since = "1.83.0")]
271-
pubfnmap_break<T>(self,f:implFnOnce(B) -> T) -> ControlFlow<T,C>{
279+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
280+
pubconstfn map_break<T,F>(self,f:F) -> ControlFlow<T,C>
281+
where
282+
F:[const]FnOnce(B) -> T + [const]Destruct,
283+
{
272284
matchself{
273285
ControlFlow::Continue(x) => ControlFlow::Continue(x),
274286
ControlFlow::Break(x) => ControlFlow::Break(f(x)),
@@ -288,7 +300,11 @@ impl<B, C> ControlFlow<B, C> {
288300
/// ```
289301
#[inline]
290302
#[stable(feature = "control_flow_enum", since = "1.83.0")]
291-
pubfncontinue_value(self) -> Option<C>{
303+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
304+
pub constfncontinue_value(self) -> Option<C>
305+
where
306+
Self:[const]Destruct,
307+
{
292308
matchself{
293309
ControlFlow::Continue(x) => Some(x),
294310
ControlFlow::Break(..) => None,
@@ -361,7 +377,8 @@ impl<B, C> ControlFlow<B, C> {
361377
/// ```
362378
#[inline]
363379
#[unstable(feature = "control_flow_ok", issue = "140266")]
364-
pubfncontinue_ok(self) -> Result<C,B>{
380+
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
381+
pub constfncontinue_ok(self) -> Result<C,B>{
365382
matchself{
366383
ControlFlow::Continue(c) => Ok(c),
367384
ControlFlow::Break(b) => Err(b),
@@ -372,7 +389,11 @@ impl<B, C> ControlFlow<B, C> {
372389
/// to the continue value in case it exists.
373390
#[inline]
374391
#[stable(feature = "control_flow_enum", since = "1.83.0")]
375-
pubfnmap_continue<T>(self,f:implFnOnce(C) -> T) -> ControlFlow<B,T>{
392+
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
393+
pub constfnmap_continue<T,F>(self,f:F) -> ControlFlow<B,T>
394+
where
395+
F:[const]FnOnce(C) -> T + [const]Destruct,
396+
{
376397
matchself{
377398
ControlFlow::Continue(x) => ControlFlow::Continue(f(x)),
378399
ControlFlow::Break(x) => ControlFlow::Break(x),

‎src/librustdoc/html/highlight.rs‎

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,9 @@ impl<'a> Iterator for TokenIter<'a> {
789789
}
790790
}
791791

792+
/// Used to know if a keyword followed by a `!` should never be treated as a macro.
793+
constNON_MACRO_KEYWORDS:&[&str] = &["if","while","match","break","return","impl"];
794+
792795
/// This iterator comes from the same idea than "Peekable" except that it allows to "peek" more than
793796
/// just the next item by using `peek_next`. The `peek` method always returns the next item after
794797
/// the current one whereas `peek_next` will return the next item after the last one peeked.
@@ -1010,6 +1013,19 @@ impl<'src> Classifier<'src> {
10101013
}
10111014
}
10121015

1016+
fnnew_macro_span(
1017+
&mutself,
1018+
text:&'srcstr,
1019+
sink:&mutdynFnMut(Span,Highlight<'src>),
1020+
before:u32,
1021+
file_span:Span,
1022+
){
1023+
self.in_macro = true;
1024+
let span = new_span(before, text, file_span);
1025+
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1026+
sink(span,Highlight::Token{ text,class:None});
1027+
}
1028+
10131029
/// Single step of highlighting. This will classify `token`, but maybe also a couple of
10141030
/// following ones as well.
10151031
///
@@ -1216,16 +1232,46 @@ impl<'src> Classifier<'src> {
12161232
LiteralKind::Float{ .. } | LiteralKind::Int{ .. } => Class::Number,
12171233
},
12181234
TokenKind::GuardedStrPrefix => returnno_highlight(sink),
1219-
TokenKind::Ident | TokenKind::RawIdent
1220-
ifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() =>
1221-
{
1222-
self.in_macro = true;
1223-
let span = new_span(before, text, file_span);
1224-
sink(DUMMY_SP,Highlight::EnterSpan{class:Class::Macro(span)});
1225-
sink(span,Highlight::Token{ text,class:None});
1235+
TokenKind::RawIdentifletSome((TokenKind::Bang, _)) = self.peek_non_trivia() => {
1236+
self.new_macro_span(text, sink, before, file_span);
12261237
return;
12271238
}
1228-
TokenKind::Ident => self.classify_ident(before, text),
1239+
// Macro non-terminals (meta vars) take precedence.
1240+
TokenKind::Identifself.in_macro_nonterminal => {
1241+
self.in_macro_nonterminal = false;
1242+
Class::MacroNonTerminal
1243+
}
1244+
TokenKind::Ident => {
1245+
let file_span = self.file_span;
1246+
let span = || new_span(before, text, file_span);
1247+
1248+
match text {
1249+
"ref" | "mut" => Class::RefKeyWord,
1250+
"false" | "true" => Class::Bool,
1251+
"self" | "Self" => Class::Self_(span()),
1252+
"Option" | "Result" => Class::PreludeTy(span()),
1253+
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1254+
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => {
1255+
// So if it's not a keyword which can be followed by a value (like `if` or
1256+
// `return`) and the next non-whitespace token is a `!`, then we consider
1257+
// it's a macro.
1258+
if !NON_MACRO_KEYWORDS.contains(&text)
1259+
&& matches!(self.peek_non_trivia(),Some((TokenKind::Bang, _)))
1260+
{
1261+
self.new_macro_span(text, sink, before, file_span);
1262+
return;
1263+
}
1264+
Class::KeyWord
1265+
}
1266+
// If it's not a keyword and the next non whitespace token is a `!`, then
1267+
// we consider it's a macro.
1268+
_ ifmatches!(self.peek_non_trivia(),Some((TokenKind::Bang, _))) => {
1269+
self.new_macro_span(text, sink, before, file_span);
1270+
return;
1271+
}
1272+
_ => Class::Ident(span()),
1273+
}
1274+
}
12291275
TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
12301276
Class::Ident(new_span(before, text, file_span))
12311277
}
@@ -1246,27 +1292,6 @@ impl<'src> Classifier<'src> {
12461292
}
12471293
}
12481294

1249-
fnclassify_ident(&mutself,before:u32,text:&'srcstr) -> Class{
1250-
// Macro non-terminals (meta vars) take precedence.
1251-
ifself.in_macro_nonterminal{
1252-
self.in_macro_nonterminal = false;
1253-
returnClass::MacroNonTerminal;
1254-
}
1255-
1256-
let file_span = self.file_span;
1257-
let span = || new_span(before, text, file_span);
1258-
1259-
match text {
1260-
"ref" | "mut" => Class::RefKeyWord,
1261-
"false" | "true" => Class::Bool,
1262-
"self" | "Self" => Class::Self_(span()),
1263-
"Option" | "Result" => Class::PreludeTy(span()),
1264-
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1265-
_ ifself.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => Class::KeyWord,
1266-
_ => Class::Ident(span()),
1267-
}
1268-
}
1269-
12701295
fnis_weak_keyword(&mutself,text:&str) -> bool{
12711296
// NOTE: `yeet` (`do yeet $expr`), `catch` (`do catch $block`), `default` (specialization),
12721297
// `contract_{ensures,requires}`, `builtin` (builtin_syntax) & `reuse` (fn_delegation) are

‎src/tools/compiletest/src/directives.rs‎

Lines changed: 33 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::debuggers::{extract_cdb_version, extract_gdb_version};
1111
pub(crate)usecrate::directives::auxiliary::AuxProps;
1212
usecrate::directives::auxiliary::parse_and_update_aux;
1313
usecrate::directives::directive_names::{
14-
KNOWN_DIRECTIVE_NAMES,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
14+
KNOWN_DIRECTIVE_NAMES_SET,KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
1515
};
1616
pub(crate)usecrate::directives::file::FileDirectives;
1717
usecrate::directives::line::{DirectiveLine, line_directive};
@@ -53,25 +53,17 @@ impl EarlyProps {
5353
config:&Config,
5454
file_directives:&FileDirectives<'_>,
5555
) -> Self{
56-
let testfile = file_directives.path;
5756
letmut props = EarlyProps::default();
58-
letmut poisoned = false;
5957

6058
iter_directives(
6159
config.mode,
62-
&mut poisoned,
6360
file_directives,
6461
// (dummy comment to force args into vertical layout)
6562
&mut |ln:&DirectiveLine<'_>| {
6663
config.parse_and_update_revisions(ln,&mut props.revisions);
6764
},
6865
);
6966

70-
if poisoned {
71-
eprintln!("errors encountered during EarlyProps parsing: {}", testfile);
72-
panic!("errors encountered during EarlyProps parsing");
73-
}
74-
7567
props
7668
}
7769
}
@@ -358,12 +350,10 @@ impl TestProps {
358350
let file_contents = fs::read_to_string(testfile).unwrap();
359351
let file_directives = FileDirectives::from_file_contents(testfile,&file_contents);
360352

361-
letmut poisoned = false;
362-
363353
iter_directives(
364354
config.mode,
365-
&mut poisoned,
366355
&file_directives,
356+
// (dummy comment to force args into vertical layout)
367357
&mut |ln:&DirectiveLine<'_>| {
368358
if !ln.applies_to_test_revision(test_revision){
369359
return;
@@ -634,11 +624,6 @@ impl TestProps {
634624
);
635625
},
636626
);
637-
638-
if poisoned {
639-
eprintln!("errors encountered during TestProps parsing: {}", testfile);
640-
panic!("errors encountered during TestProps parsing");
641-
}
642627
}
643628

644629
ifself.should_ice{
@@ -775,6 +760,34 @@ impl TestProps {
775760
}
776761
}
777762

763+
pub(crate)fndo_early_directives_check(
764+
mode:TestMode,
765+
file_directives:&FileDirectives<'_>,
766+
) -> Result<(),String>{
767+
let testfile = file_directives.path;
768+
769+
for directive_line @ DirectiveLine{ line_number, .. }in&file_directives.lines{
770+
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
771+
check_directive(directive_line, mode);
772+
773+
if !is_known_directive {
774+
returnErr(format!(
775+
"ERROR: unknown compiletest directive `{directive}` at {testfile}:{line_number}",
776+
directive = directive_line.display(),
777+
));
778+
}
779+
780+
ifletSome(trailing_directive) = &trailing_directive {
781+
returnErr(format!(
782+
"ERROR: detected trailing compiletest directive `{trailing_directive}` at {testfile}:{line_number}\n\
783+
HELP: put the directive on its own line: `//@ {trailing_directive}`"
784+
));
785+
}
786+
}
787+
788+
Ok(())
789+
}
790+
778791
pub(crate)structCheckDirectiveResult<'ln>{
779792
is_known_directive:bool,
780793
trailing_directive:Option<&'lnstr>,
@@ -786,7 +799,7 @@ fn check_directive<'a>(
786799
) -> CheckDirectiveResult<'a>{
787800
let&DirectiveLine{name: directive_name, .. } = directive_ln;
788801

789-
let is_known_directive = KNOWN_DIRECTIVE_NAMES.contains(&directive_name)
802+
let is_known_directive = KNOWN_DIRECTIVE_NAMES_SET.contains(&directive_name)
790803
|| match mode {
791804
TestMode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
792805
TestMode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
@@ -799,7 +812,7 @@ fn check_directive<'a>(
799812
let trailing_directive = directive_ln
800813
.remark_after_space()
801814
.map(|remark| remark.trim_start().split(' ').next().unwrap())
802-
.filter(|token| KNOWN_DIRECTIVE_NAMES.contains(token));
815+
.filter(|token| KNOWN_DIRECTIVE_NAMES_SET.contains(token));
803816

804817
// FIXME(Zalathar): Consider emitting specialized error/help messages for
805818
// bogus directive names that are similar to real ones, e.g.:
@@ -811,7 +824,6 @@ fn check_directive<'a>(
811824

812825
fniter_directives(
813826
mode:TestMode,
814-
poisoned:&mutbool,
815827
file_directives:&FileDirectives<'_>,
816828
it:&mutdynFnMut(&DirectiveLine<'_>),
817829
){
@@ -837,36 +849,7 @@ fn iter_directives(
837849
}
838850
}
839851

840-
for directive_line @ &DirectiveLine{ line_number, .. }in&file_directives.lines{
841-
// Perform unknown directive check on Rust files.
842-
if testfile.extension() == Some("rs"){
843-
letCheckDirectiveResult{ is_known_directive, trailing_directive } =
844-
check_directive(directive_line, mode);
845-
846-
if !is_known_directive {
847-
*poisoned = true;
848-
849-
error!(
850-
"{testfile}:{line_number}: detected unknown compiletest test directive `{}`",
851-
directive_line.display(),
852-
);
853-
854-
return;
855-
}
856-
857-
ifletSome(trailing_directive) = &trailing_directive {
858-
*poisoned = true;
859-
860-
error!(
861-
"{testfile}:{line_number}: detected trailing compiletest test directive `{}`",
862-
trailing_directive,
863-
);
864-
help!("put the trailing directive in its own line: `//@ {}`", trailing_directive);
865-
866-
return;
867-
}
868-
}
869-
852+
for directive_line in&file_directives.lines{
870853
it(directive_line);
871854
}
872855
}
@@ -1304,12 +1287,9 @@ pub(crate) fn make_test_description(
13041287
letmut ignore_message = None;
13051288
letmut should_fail = false;
13061289

1307-
letmut local_poisoned = false;
1308-
13091290
// Scan through the test file to handle `ignore-*`, `only-*`, and `needs-*` directives.
13101291
iter_directives(
13111292
config.mode,
1312-
&mut local_poisoned,
13131293
file_directives,
13141294
&mut |ln @ &DirectiveLine{ line_number, .. }| {
13151295
if !ln.applies_to_test_revision(test_revision){
@@ -1358,11 +1338,6 @@ pub(crate) fn make_test_description(
13581338
},
13591339
);
13601340

1361-
if local_poisoned {
1362-
eprintln!("errors encountered when trying to make test description: {}", path);
1363-
panic!("errors encountered when trying to make test description");
1364-
}
1365-
13661341
// The `should-fail` annotation doesn't apply to pretty tests,
13671342
// since we run the pretty printer across all tests by default.
13681343
// If desired, we could add a `should-fail-pretty` annotation.

0 commit comments

Comments
 (0)