Auto merge of #148762 - matthiaskrgr:rollup-4oifvkr, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - rust-lang/rust#148248 (Constify `ControlFlow` methods without unstable bounds) - rust-lang/rust#148285 (Constify `ControlFlow` methods with unstable bounds) - rust-lang/rust#148510 (compiletest: Do the known-directives check only once, and improve its error message) - rust-lang/rust#148655 (Fix invalid macro tag generation for keywords which can be followed by values) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
8401398e1f
8 changed files with 177 additions and 98 deletions
|
|
@ -1,3 +1,4 @@
|
|||
use crate::marker::Destruct;
|
||||
use crate::{convert, ops};
|
||||
|
||||
/// 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> {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
|
||||
pub fn is_break(&self) -> bool {
|
||||
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
|
||||
pub const fn is_break(&self) -> bool {
|
||||
matches!(*self, ControlFlow::Break(_))
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +168,8 @@ impl<B, C> ControlFlow<B, C> {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "control_flow_enum_is", since = "1.59.0")]
|
||||
pub fn is_continue(&self) -> bool {
|
||||
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
|
||||
pub const fn is_continue(&self) -> bool {
|
||||
matches!(*self, ControlFlow::Continue(_))
|
||||
}
|
||||
|
||||
|
|
@ -183,7 +186,11 @@ impl<B, C> ControlFlow<B, C> {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "control_flow_enum", since = "1.83.0")]
|
||||
pub fn break_value(self) -> Option<B> {
|
||||
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
|
||||
pub const fn break_value(self) -> Option<B>
|
||||
where
|
||||
Self: [const] Destruct,
|
||||
{
|
||||
match self {
|
||||
ControlFlow::Continue(..) => None,
|
||||
ControlFlow::Break(x) => Some(x),
|
||||
|
|
@ -257,7 +264,8 @@ impl<B, C> ControlFlow<B, C> {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "control_flow_ok", issue = "140266")]
|
||||
pub fn break_ok(self) -> Result<B, C> {
|
||||
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
|
||||
pub const fn break_ok(self) -> Result<B, C> {
|
||||
match self {
|
||||
ControlFlow::Continue(c) => Err(c),
|
||||
ControlFlow::Break(b) => Ok(b),
|
||||
|
|
@ -268,7 +276,11 @@ impl<B, C> ControlFlow<B, C> {
|
|||
/// to the break value in case it exists.
|
||||
#[inline]
|
||||
#[stable(feature = "control_flow_enum", since = "1.83.0")]
|
||||
pub fn map_break<T>(self, f: impl FnOnce(B) -> T) -> ControlFlow<T, C> {
|
||||
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
|
||||
pub const fn map_break<T, F>(self, f: F) -> ControlFlow<T, C>
|
||||
where
|
||||
F: [const] FnOnce(B) -> T + [const] Destruct,
|
||||
{
|
||||
match self {
|
||||
ControlFlow::Continue(x) => ControlFlow::Continue(x),
|
||||
ControlFlow::Break(x) => ControlFlow::Break(f(x)),
|
||||
|
|
@ -288,7 +300,11 @@ impl<B, C> ControlFlow<B, C> {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "control_flow_enum", since = "1.83.0")]
|
||||
pub fn continue_value(self) -> Option<C> {
|
||||
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
|
||||
pub const fn continue_value(self) -> Option<C>
|
||||
where
|
||||
Self: [const] Destruct,
|
||||
{
|
||||
match self {
|
||||
ControlFlow::Continue(x) => Some(x),
|
||||
ControlFlow::Break(..) => None,
|
||||
|
|
@ -361,7 +377,8 @@ impl<B, C> ControlFlow<B, C> {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "control_flow_ok", issue = "140266")]
|
||||
pub fn continue_ok(self) -> Result<C, B> {
|
||||
#[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")]
|
||||
pub const fn continue_ok(self) -> Result<C, B> {
|
||||
match self {
|
||||
ControlFlow::Continue(c) => Ok(c),
|
||||
ControlFlow::Break(b) => Err(b),
|
||||
|
|
@ -372,7 +389,11 @@ impl<B, C> ControlFlow<B, C> {
|
|||
/// to the continue value in case it exists.
|
||||
#[inline]
|
||||
#[stable(feature = "control_flow_enum", since = "1.83.0")]
|
||||
pub fn map_continue<T>(self, f: impl FnOnce(C) -> T) -> ControlFlow<B, T> {
|
||||
#[rustc_const_unstable(feature = "const_control_flow", issue = "148739")]
|
||||
pub const fn map_continue<T, F>(self, f: F) -> ControlFlow<B, T>
|
||||
where
|
||||
F: [const] FnOnce(C) -> T + [const] Destruct,
|
||||
{
|
||||
match self {
|
||||
ControlFlow::Continue(x) => ControlFlow::Continue(f(x)),
|
||||
ControlFlow::Break(x) => ControlFlow::Break(x),
|
||||
|
|
|
|||
|
|
@ -789,6 +789,9 @@ impl<'a> Iterator for TokenIter<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Used to know if a keyword followed by a `!` should never be treated as a macro.
|
||||
const NON_MACRO_KEYWORDS: &[&str] = &["if", "while", "match", "break", "return", "impl"];
|
||||
|
||||
/// This iterator comes from the same idea than "Peekable" except that it allows to "peek" more than
|
||||
/// just the next item by using `peek_next`. The `peek` method always returns the next item after
|
||||
/// the current one whereas `peek_next` will return the next item after the last one peeked.
|
||||
|
|
@ -1010,6 +1013,19 @@ impl<'src> Classifier<'src> {
|
|||
}
|
||||
}
|
||||
|
||||
fn new_macro_span(
|
||||
&mut self,
|
||||
text: &'src str,
|
||||
sink: &mut dyn FnMut(Span, Highlight<'src>),
|
||||
before: u32,
|
||||
file_span: Span,
|
||||
) {
|
||||
self.in_macro = true;
|
||||
let span = new_span(before, text, file_span);
|
||||
sink(DUMMY_SP, Highlight::EnterSpan { class: Class::Macro(span) });
|
||||
sink(span, Highlight::Token { text, class: None });
|
||||
}
|
||||
|
||||
/// Single step of highlighting. This will classify `token`, but maybe also a couple of
|
||||
/// following ones as well.
|
||||
///
|
||||
|
|
@ -1216,16 +1232,46 @@ impl<'src> Classifier<'src> {
|
|||
LiteralKind::Float { .. } | LiteralKind::Int { .. } => Class::Number,
|
||||
},
|
||||
TokenKind::GuardedStrPrefix => return no_highlight(sink),
|
||||
TokenKind::Ident | TokenKind::RawIdent
|
||||
if let Some((TokenKind::Bang, _)) = self.peek_non_trivia() =>
|
||||
{
|
||||
self.in_macro = true;
|
||||
let span = new_span(before, text, file_span);
|
||||
sink(DUMMY_SP, Highlight::EnterSpan { class: Class::Macro(span) });
|
||||
sink(span, Highlight::Token { text, class: None });
|
||||
TokenKind::RawIdent if let Some((TokenKind::Bang, _)) = self.peek_non_trivia() => {
|
||||
self.new_macro_span(text, sink, before, file_span);
|
||||
return;
|
||||
}
|
||||
TokenKind::Ident => self.classify_ident(before, text),
|
||||
// Macro non-terminals (meta vars) take precedence.
|
||||
TokenKind::Ident if self.in_macro_nonterminal => {
|
||||
self.in_macro_nonterminal = false;
|
||||
Class::MacroNonTerminal
|
||||
}
|
||||
TokenKind::Ident => {
|
||||
let file_span = self.file_span;
|
||||
let span = || new_span(before, text, file_span);
|
||||
|
||||
match text {
|
||||
"ref" | "mut" => Class::RefKeyWord,
|
||||
"false" | "true" => Class::Bool,
|
||||
"self" | "Self" => Class::Self_(span()),
|
||||
"Option" | "Result" => Class::PreludeTy(span()),
|
||||
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
|
||||
_ if self.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => {
|
||||
// So if it's not a keyword which can be followed by a value (like `if` or
|
||||
// `return`) and the next non-whitespace token is a `!`, then we consider
|
||||
// it's a macro.
|
||||
if !NON_MACRO_KEYWORDS.contains(&text)
|
||||
&& matches!(self.peek_non_trivia(), Some((TokenKind::Bang, _)))
|
||||
{
|
||||
self.new_macro_span(text, sink, before, file_span);
|
||||
return;
|
||||
}
|
||||
Class::KeyWord
|
||||
}
|
||||
// If it's not a keyword and the next non whitespace token is a `!`, then
|
||||
// we consider it's a macro.
|
||||
_ if matches!(self.peek_non_trivia(), Some((TokenKind::Bang, _))) => {
|
||||
self.new_macro_span(text, sink, before, file_span);
|
||||
return;
|
||||
}
|
||||
_ => Class::Ident(span()),
|
||||
}
|
||||
}
|
||||
TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
|
||||
Class::Ident(new_span(before, text, file_span))
|
||||
}
|
||||
|
|
@ -1246,27 +1292,6 @@ impl<'src> Classifier<'src> {
|
|||
}
|
||||
}
|
||||
|
||||
fn classify_ident(&mut self, before: u32, text: &'src str) -> Class {
|
||||
// Macro non-terminals (meta vars) take precedence.
|
||||
if self.in_macro_nonterminal {
|
||||
self.in_macro_nonterminal = false;
|
||||
return Class::MacroNonTerminal;
|
||||
}
|
||||
|
||||
let file_span = self.file_span;
|
||||
let span = || new_span(before, text, file_span);
|
||||
|
||||
match text {
|
||||
"ref" | "mut" => Class::RefKeyWord,
|
||||
"false" | "true" => Class::Bool,
|
||||
"self" | "Self" => Class::Self_(span()),
|
||||
"Option" | "Result" => Class::PreludeTy(span()),
|
||||
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
|
||||
_ if self.is_weak_keyword(text) || is_keyword(Symbol::intern(text)) => Class::KeyWord,
|
||||
_ => Class::Ident(span()),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_weak_keyword(&mut self, text: &str) -> bool {
|
||||
// NOTE: `yeet` (`do yeet $expr`), `catch` (`do catch $block`), `default` (specialization),
|
||||
// `contract_{ensures,requires}`, `builtin` (builtin_syntax) & `reuse` (fn_delegation) are
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::debuggers::{extract_cdb_version, extract_gdb_version};
|
|||
pub(crate) use crate::directives::auxiliary::AuxProps;
|
||||
use crate::directives::auxiliary::parse_and_update_aux;
|
||||
use crate::directives::directive_names::{
|
||||
KNOWN_DIRECTIVE_NAMES, KNOWN_HTMLDOCCK_DIRECTIVE_NAMES, KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
|
||||
KNOWN_DIRECTIVE_NAMES_SET, KNOWN_HTMLDOCCK_DIRECTIVE_NAMES, KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
|
||||
};
|
||||
pub(crate) use crate::directives::file::FileDirectives;
|
||||
use crate::directives::line::{DirectiveLine, line_directive};
|
||||
|
|
@ -53,13 +53,10 @@ impl EarlyProps {
|
|||
config: &Config,
|
||||
file_directives: &FileDirectives<'_>,
|
||||
) -> Self {
|
||||
let testfile = file_directives.path;
|
||||
let mut props = EarlyProps::default();
|
||||
let mut poisoned = false;
|
||||
|
||||
iter_directives(
|
||||
config.mode,
|
||||
&mut poisoned,
|
||||
file_directives,
|
||||
// (dummy comment to force args into vertical layout)
|
||||
&mut |ln: &DirectiveLine<'_>| {
|
||||
|
|
@ -67,11 +64,6 @@ impl EarlyProps {
|
|||
},
|
||||
);
|
||||
|
||||
if poisoned {
|
||||
eprintln!("errors encountered during EarlyProps parsing: {}", testfile);
|
||||
panic!("errors encountered during EarlyProps parsing");
|
||||
}
|
||||
|
||||
props
|
||||
}
|
||||
}
|
||||
|
|
@ -358,12 +350,10 @@ impl TestProps {
|
|||
let file_contents = fs::read_to_string(testfile).unwrap();
|
||||
let file_directives = FileDirectives::from_file_contents(testfile, &file_contents);
|
||||
|
||||
let mut poisoned = false;
|
||||
|
||||
iter_directives(
|
||||
config.mode,
|
||||
&mut poisoned,
|
||||
&file_directives,
|
||||
// (dummy comment to force args into vertical layout)
|
||||
&mut |ln: &DirectiveLine<'_>| {
|
||||
if !ln.applies_to_test_revision(test_revision) {
|
||||
return;
|
||||
|
|
@ -634,11 +624,6 @@ impl TestProps {
|
|||
);
|
||||
},
|
||||
);
|
||||
|
||||
if poisoned {
|
||||
eprintln!("errors encountered during TestProps parsing: {}", testfile);
|
||||
panic!("errors encountered during TestProps parsing");
|
||||
}
|
||||
}
|
||||
|
||||
if self.should_ice {
|
||||
|
|
@ -775,6 +760,34 @@ impl TestProps {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn do_early_directives_check(
|
||||
mode: TestMode,
|
||||
file_directives: &FileDirectives<'_>,
|
||||
) -> Result<(), String> {
|
||||
let testfile = file_directives.path;
|
||||
|
||||
for directive_line @ DirectiveLine { line_number, .. } in &file_directives.lines {
|
||||
let CheckDirectiveResult { is_known_directive, trailing_directive } =
|
||||
check_directive(directive_line, mode);
|
||||
|
||||
if !is_known_directive {
|
||||
return Err(format!(
|
||||
"ERROR: unknown compiletest directive `{directive}` at {testfile}:{line_number}",
|
||||
directive = directive_line.display(),
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(trailing_directive) = &trailing_directive {
|
||||
return Err(format!(
|
||||
"ERROR: detected trailing compiletest directive `{trailing_directive}` at {testfile}:{line_number}\n\
|
||||
HELP: put the directive on its own line: `//@ {trailing_directive}`"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) struct CheckDirectiveResult<'ln> {
|
||||
is_known_directive: bool,
|
||||
trailing_directive: Option<&'ln str>,
|
||||
|
|
@ -786,7 +799,7 @@ fn check_directive<'a>(
|
|||
) -> CheckDirectiveResult<'a> {
|
||||
let &DirectiveLine { name: directive_name, .. } = directive_ln;
|
||||
|
||||
let is_known_directive = KNOWN_DIRECTIVE_NAMES.contains(&directive_name)
|
||||
let is_known_directive = KNOWN_DIRECTIVE_NAMES_SET.contains(&directive_name)
|
||||
|| match mode {
|
||||
TestMode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
|
||||
TestMode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES.contains(&directive_name),
|
||||
|
|
@ -799,7 +812,7 @@ fn check_directive<'a>(
|
|||
let trailing_directive = directive_ln
|
||||
.remark_after_space()
|
||||
.map(|remark| remark.trim_start().split(' ').next().unwrap())
|
||||
.filter(|token| KNOWN_DIRECTIVE_NAMES.contains(token));
|
||||
.filter(|token| KNOWN_DIRECTIVE_NAMES_SET.contains(token));
|
||||
|
||||
// FIXME(Zalathar): Consider emitting specialized error/help messages for
|
||||
// bogus directive names that are similar to real ones, e.g.:
|
||||
|
|
@ -811,7 +824,6 @@ fn check_directive<'a>(
|
|||
|
||||
fn iter_directives(
|
||||
mode: TestMode,
|
||||
poisoned: &mut bool,
|
||||
file_directives: &FileDirectives<'_>,
|
||||
it: &mut dyn FnMut(&DirectiveLine<'_>),
|
||||
) {
|
||||
|
|
@ -837,36 +849,7 @@ fn iter_directives(
|
|||
}
|
||||
}
|
||||
|
||||
for directive_line @ &DirectiveLine { line_number, .. } in &file_directives.lines {
|
||||
// Perform unknown directive check on Rust files.
|
||||
if testfile.extension() == Some("rs") {
|
||||
let CheckDirectiveResult { is_known_directive, trailing_directive } =
|
||||
check_directive(directive_line, mode);
|
||||
|
||||
if !is_known_directive {
|
||||
*poisoned = true;
|
||||
|
||||
error!(
|
||||
"{testfile}:{line_number}: detected unknown compiletest test directive `{}`",
|
||||
directive_line.display(),
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(trailing_directive) = &trailing_directive {
|
||||
*poisoned = true;
|
||||
|
||||
error!(
|
||||
"{testfile}:{line_number}: detected trailing compiletest test directive `{}`",
|
||||
trailing_directive,
|
||||
);
|
||||
help!("put the trailing directive in its own line: `//@ {}`", trailing_directive);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for directive_line in &file_directives.lines {
|
||||
it(directive_line);
|
||||
}
|
||||
}
|
||||
|
|
@ -1304,12 +1287,9 @@ pub(crate) fn make_test_description(
|
|||
let mut ignore_message = None;
|
||||
let mut should_fail = false;
|
||||
|
||||
let mut local_poisoned = false;
|
||||
|
||||
// Scan through the test file to handle `ignore-*`, `only-*`, and `needs-*` directives.
|
||||
iter_directives(
|
||||
config.mode,
|
||||
&mut local_poisoned,
|
||||
file_directives,
|
||||
&mut |ln @ &DirectiveLine { line_number, .. }| {
|
||||
if !ln.applies_to_test_revision(test_revision) {
|
||||
|
|
@ -1358,11 +1338,6 @@ pub(crate) fn make_test_description(
|
|||
},
|
||||
);
|
||||
|
||||
if local_poisoned {
|
||||
eprintln!("errors encountered when trying to make test description: {}", path);
|
||||
panic!("errors encountered when trying to make test description");
|
||||
}
|
||||
|
||||
// The `should-fail` annotation doesn't apply to pretty tests,
|
||||
// since we run the pretty printer across all tests by default.
|
||||
// If desired, we could add a `should-fail-pretty` annotation.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
use std::collections::HashSet;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
pub(crate) static KNOWN_DIRECTIVE_NAMES_SET: LazyLock<HashSet<&str>> =
|
||||
LazyLock::new(|| KNOWN_DIRECTIVE_NAMES.iter().copied().collect());
|
||||
|
||||
/// This was originally generated by collecting directives from ui tests and then extracting their
|
||||
/// directive names. This is **not** an exhaustive list of all possible directives. Instead, this is
|
||||
/// a best-effort approximation for diagnostics. Add new directives to this list when needed.
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ use semver::Version;
|
|||
|
||||
use crate::common::{Config, Debugger, TestMode};
|
||||
use crate::directives::{
|
||||
AuxProps, DirectivesCache, EarlyProps, Edition, EditionRange, FileDirectives,
|
||||
extract_llvm_version, extract_version_range, iter_directives, line_directive, parse_edition,
|
||||
self, AuxProps, DirectivesCache, EarlyProps, Edition, EditionRange, FileDirectives,
|
||||
extract_llvm_version, extract_version_range, line_directive, parse_edition,
|
||||
parse_normalize_rule,
|
||||
};
|
||||
use crate::executor::{CollectedTestDesc, ShouldFail};
|
||||
|
|
@ -767,7 +767,10 @@ fn threads_support() {
|
|||
|
||||
fn run_path(poisoned: &mut bool, path: &Utf8Path, file_contents: &str) {
|
||||
let file_directives = FileDirectives::from_file_contents(path, file_contents);
|
||||
iter_directives(TestMode::Ui, poisoned, &file_directives, &mut |_| {});
|
||||
let result = directives::do_early_directives_check(TestMode::Ui, &file_directives);
|
||||
if result.is_err() {
|
||||
*poisoned = true;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -869,6 +869,12 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
|
|||
let file_contents =
|
||||
fs::read_to_string(&test_path).expect("reading test file for directives should succeed");
|
||||
let file_directives = FileDirectives::from_file_contents(&test_path, &file_contents);
|
||||
|
||||
if let Err(message) = directives::do_early_directives_check(cx.config.mode, &file_directives) {
|
||||
// FIXME(Zalathar): Overhaul compiletest error handling so that we
|
||||
// don't have to resort to ad-hoc panics everywhere.
|
||||
panic!("directives check failed:\n{message}");
|
||||
}
|
||||
let early_props = EarlyProps::from_file_directives(&cx.config, &file_directives);
|
||||
|
||||
// Normally we create one structure per revision, with two exceptions:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
// This code crashed because a `if` followed by a `!` was considered a macro,
|
||||
// creating an invalid class stack.
|
||||
// Regression test for <https://github.com/rust-lang/rust/issues/148617>.
|
||||
|
||||
//@ compile-flags: -Zunstable-options --generate-macro-expansion
|
||||
|
||||
enum Enum {
|
||||
Variant,
|
||||
}
|
||||
|
||||
pub fn repro() {
|
||||
if !matches!(Enum::Variant, Enum::Variant) {}
|
||||
}
|
||||
30
tests/rustdoc/source-code-pages/keyword-macros.rs
Normal file
30
tests/rustdoc/source-code-pages/keyword-macros.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// This test ensures that keywords which can be followed by values (and therefore `!`)
|
||||
// are not considered as macros.
|
||||
// This is a regression test for <https://github.com/rust-lang/rust/issues/148617>.
|
||||
|
||||
#![crate_name = "foo"]
|
||||
#![feature(negative_impls)]
|
||||
|
||||
//@ has 'src/foo/keyword-macros.rs.html'
|
||||
|
||||
//@ has - '//*[@class="rust"]//*[@class="number"]' '2'
|
||||
//@ has - '//*[@class="rust"]//*[@class="number"]' '0'
|
||||
//@ has - '//*[@class="rust"]//*[@class="number"]' '1'
|
||||
const ARR: [u8; 2] = [!0,! 1];
|
||||
|
||||
trait X {}
|
||||
|
||||
//@ has - '//*[@class="rust"]//*[@class="kw"]' 'impl'
|
||||
impl !X for i32 {}
|
||||
|
||||
fn a() {
|
||||
//@ has - '//*[@class="rust"]//*[@class="kw"]' 'if'
|
||||
if! true{}
|
||||
//@ has - '//*[@class="rust"]//*[@class="kw"]' 'match'
|
||||
match !true { _ => {} }
|
||||
//@ has - '//*[@class="rust"]//*[@class="kw"]' 'while'
|
||||
let _ = while !true {
|
||||
//@ has - '//*[@class="rust"]//*[@class="kw"]' 'break'
|
||||
break !true;
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue