diff --git a/src/tools/rust-analyzer/.github/workflows/gen-lints.yml b/src/tools/rust-analyzer/.github/workflows/gen-lints.yml index 7319b2b3263b..c978e3571c40 100644 --- a/src/tools/rust-analyzer/.github/workflows/gen-lints.yml +++ b/src/tools/rust-analyzer/.github/workflows/gen-lints.yml @@ -13,6 +13,8 @@ jobs: lints-gen: name: Generate lints runs-on: ubuntu-latest + permissions: + pull-requests: write steps: - name: Checkout repository uses: actions/checkout@v6 @@ -23,9 +25,16 @@ jobs: - name: Generate lints/feature flags run: cargo codegen lint-definitions + - uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0 + id: app-token + with: + app-id: ${{ vars.APP_CLIENT_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + - name: Submit PR uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 with: + token: ${{ steps.app-token.outputs.token }} commit-message: "internal: update generated lints" branch: "ci/gen-lints" delete-branch: true diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 770f8cb94095..da530b3a9304 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -234,7 +234,6 @@ dependencies = [ "intern", "oorandom", "rustc-hash 2.1.1", - "span", "syntax", "syntax-bridge", "tracing", @@ -846,7 +845,6 @@ dependencies = [ name = "hir-expand" version = "0.0.0" dependencies = [ - "arrayvec", "base-db", "cfg", "cov-mark", @@ -2733,6 +2731,7 @@ dependencies = [ "rustc-hash 2.1.1", "rustc-literal-escaper 0.0.4", "rustc_apfloat", + "smallvec", "smol_str 0.3.2", "stdx", "test-utils", diff --git a/src/tools/rust-analyzer/crates/cfg/Cargo.toml b/src/tools/rust-analyzer/crates/cfg/Cargo.toml index cf2a7607b019..15de1f329385 100644 --- a/src/tools/rust-analyzer/crates/cfg/Cargo.toml +++ b/src/tools/rust-analyzer/crates/cfg/Cargo.toml @@ -19,7 +19,6 @@ tracing.workspace = true # locals deps tt = { workspace = true, optional = true } syntax = { workspace = true, optional = true } -span = { path = "../span", version = "0.0", optional = true } intern.workspace = true [dev-dependencies] @@ -36,7 +35,7 @@ cfg = { path = ".", default-features = false, features = ["tt"] } [features] default = [] -syntax = ["dep:syntax", "dep:span"] +syntax = ["dep:syntax"] tt = ["dep:tt"] in-rust-tree = [] diff --git a/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs b/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs index d253f6f492c7..7af3ed5dc9a6 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs @@ -106,10 +106,54 @@ pub fn parse_from_iter(tt: &mut tt::iter::TtIter<'_>) -> CfgExpr { } #[cfg(feature = "syntax")] - pub fn parse_from_ast( - ast: &mut std::iter::Peekable, - ) -> CfgExpr { - next_cfg_expr_from_ast(ast).unwrap_or(CfgExpr::Invalid) + pub fn parse_from_ast(ast: syntax::ast::CfgPredicate) -> CfgExpr { + use intern::sym; + use syntax::ast::{self, AstToken}; + + match ast { + ast::CfgPredicate::CfgAtom(atom) => { + let atom = match atom.key() { + Some(ast::CfgAtomKey::True) => CfgAtom::Flag(sym::true_), + Some(ast::CfgAtomKey::False) => CfgAtom::Flag(sym::false_), + Some(ast::CfgAtomKey::Ident(key)) => { + let key = Symbol::intern(key.text()); + match atom.string_token().and_then(ast::String::cast) { + Some(value) => { + if let Ok(value) = value.value() { + CfgAtom::KeyValue { key, value: Symbol::intern(&value) } + } else { + return CfgExpr::Invalid; + } + } + None => CfgAtom::Flag(key), + } + } + None => return CfgExpr::Invalid, + }; + CfgExpr::Atom(atom) + } + ast::CfgPredicate::CfgComposite(composite) => { + let Some(keyword) = composite.keyword() else { + return CfgExpr::Invalid; + }; + match keyword.text() { + "all" => CfgExpr::All( + composite.cfg_predicates().map(CfgExpr::parse_from_ast).collect(), + ), + "any" => CfgExpr::Any( + composite.cfg_predicates().map(CfgExpr::parse_from_ast).collect(), + ), + "not" => { + let mut inner = composite.cfg_predicates(); + let (Some(inner), None) = (inner.next(), inner.next()) else { + return CfgExpr::Invalid; + }; + CfgExpr::Not(Box::new(CfgExpr::parse_from_ast(inner))) + } + _ => CfgExpr::Invalid, + } + } + } } /// Fold the cfg by querying all basic `Atom` and `KeyValue` predicates. @@ -128,65 +172,6 @@ pub fn fold(&self, query: &dyn Fn(&CfgAtom) -> bool) -> Option { } } -#[cfg(feature = "syntax")] -fn next_cfg_expr_from_ast( - it: &mut std::iter::Peekable, -) -> Option { - use intern::sym; - use syntax::{NodeOrToken, SyntaxKind, T, ast}; - - let name = match it.next() { - None => return None, - Some(NodeOrToken::Token(ident)) if ident.kind().is_any_identifier() => { - Symbol::intern(ident.text()) - } - Some(_) => return Some(CfgExpr::Invalid), - }; - - let ret = match it.peek() { - Some(NodeOrToken::Token(eq)) if eq.kind() == T![=] => { - it.next(); - if let Some(NodeOrToken::Token(literal)) = it.peek() - && matches!(literal.kind(), SyntaxKind::STRING) - { - let dummy_span = span::Span { - range: span::TextRange::empty(span::TextSize::new(0)), - anchor: span::SpanAnchor { - file_id: span::EditionedFileId::from_raw(0), - ast_id: span::FIXUP_ERASED_FILE_AST_ID_MARKER, - }, - ctx: span::SyntaxContext::root(span::Edition::Edition2015), - }; - let literal = - Symbol::intern(tt::token_to_literal(literal.text(), dummy_span).text()); - it.next(); - CfgAtom::KeyValue { key: name, value: literal.clone() }.into() - } else { - return Some(CfgExpr::Invalid); - } - } - Some(NodeOrToken::Node(subtree)) => { - let mut subtree_iter = ast::TokenTreeChildren::new(subtree).peekable(); - it.next(); - let mut subs = std::iter::from_fn(|| next_cfg_expr_from_ast(&mut subtree_iter)); - match name { - s if s == sym::all => CfgExpr::All(subs.collect()), - s if s == sym::any => CfgExpr::Any(subs.collect()), - s if s == sym::not => { - CfgExpr::Not(Box::new(subs.next().unwrap_or(CfgExpr::Invalid))) - } - _ => CfgExpr::Invalid, - } - } - _ => CfgAtom::Flag(name).into(), - }; - - // Eat comma separator - while it.next().is_some_and(|it| it.as_token().is_none_or(|it| it.kind() != T![,])) {} - - Some(ret) -} - #[cfg(feature = "tt")] fn next_cfg_expr(it: &mut tt::iter::TtIter<'_>) -> Option { use intern::sym; diff --git a/src/tools/rust-analyzer/crates/cfg/src/tests.rs b/src/tools/rust-analyzer/crates/cfg/src/tests.rs index 52c581dbbd3a..bfc9220a05d9 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/tests.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/tests.rs @@ -1,10 +1,7 @@ use arbitrary::{Arbitrary, Unstructured}; use expect_test::{Expect, expect}; use intern::Symbol; -use syntax::{ - AstNode, Edition, - ast::{self, TokenTreeChildren}, -}; +use syntax::{AstNode, Edition, ast}; use syntax_bridge::{ DocCommentDesugarMode, dummy_test_span_utils::{DUMMY, DummyTestSpanMap}, @@ -14,32 +11,32 @@ use crate::{CfgAtom, CfgExpr, CfgOptions, DnfExpr}; #[track_caller] -fn parse_ast_cfg(tt: &ast::TokenTree) -> CfgExpr { - CfgExpr::parse_from_ast(&mut TokenTreeChildren::new(tt).peekable()) +fn parse_ast_cfg(pred: ast::CfgPredicate) -> CfgExpr { + CfgExpr::parse_from_ast(pred) } #[track_caller] fn assert_parse_result(input: &str, expected: CfgExpr) { - let source_file = ast::SourceFile::parse(input, Edition::CURRENT).ok().unwrap(); - let tt_ast = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); + let source_file = ast::SourceFile::parse(input, Edition::CURRENT).syntax_node(); + let pred_ast = source_file.descendants().find_map(ast::CfgPredicate::cast).unwrap(); let tt = syntax_node_to_token_tree( - tt_ast.syntax(), + pred_ast.syntax(), DummyTestSpanMap, DUMMY, DocCommentDesugarMode::ProcMacro, ); let cfg = CfgExpr::parse(&tt); assert_eq!(cfg, expected); - let cfg = parse_ast_cfg(&tt_ast); + let cfg = parse_ast_cfg(pred_ast); assert_eq!(cfg, expected); } #[track_caller] fn check_dnf(input: &str, expect: Expect) { let source_file = ast::SourceFile::parse(input, Edition::CURRENT).ok().unwrap(); - let tt_ast = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); + let pred_ast = source_file.syntax().descendants().find_map(ast::CfgPredicate::cast).unwrap(); let tt = syntax_node_to_token_tree( - tt_ast.syntax(), + pred_ast.syntax(), DummyTestSpanMap, DUMMY, DocCommentDesugarMode::ProcMacro, @@ -47,7 +44,7 @@ fn check_dnf(input: &str, expect: Expect) { let cfg = CfgExpr::parse(&tt); let actual = format!("#![cfg({})]", DnfExpr::new(&cfg)); expect.assert_eq(&actual); - let cfg = parse_ast_cfg(&tt_ast); + let cfg = parse_ast_cfg(pred_ast); let actual = format!("#![cfg({})]", DnfExpr::new(&cfg)); expect.assert_eq(&actual); } @@ -55,9 +52,9 @@ fn check_dnf(input: &str, expect: Expect) { #[track_caller] fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) { let source_file = ast::SourceFile::parse(input, Edition::CURRENT).ok().unwrap(); - let tt_ast = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); + let pred_ast = source_file.syntax().descendants().find_map(ast::CfgPredicate::cast).unwrap(); let tt = syntax_node_to_token_tree( - tt_ast.syntax(), + pred_ast.syntax(), DummyTestSpanMap, DUMMY, DocCommentDesugarMode::ProcMacro, @@ -66,7 +63,7 @@ fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) { let dnf = DnfExpr::new(&cfg); let why_inactive = dnf.why_inactive(opts).unwrap().to_string(); expect.assert_eq(&why_inactive); - let cfg = parse_ast_cfg(&tt_ast); + let cfg = parse_ast_cfg(pred_ast); let dnf = DnfExpr::new(&cfg); let why_inactive = dnf.why_inactive(opts).unwrap().to_string(); expect.assert_eq(&why_inactive); @@ -75,9 +72,9 @@ fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) { #[track_caller] fn check_enable_hints(input: &str, opts: &CfgOptions, expected_hints: &[&str]) { let source_file = ast::SourceFile::parse(input, Edition::CURRENT).ok().unwrap(); - let tt_ast = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); + let pred_ast = source_file.syntax().descendants().find_map(ast::CfgPredicate::cast).unwrap(); let tt = syntax_node_to_token_tree( - tt_ast.syntax(), + pred_ast.syntax(), DummyTestSpanMap, DUMMY, DocCommentDesugarMode::ProcMacro, @@ -86,7 +83,7 @@ fn check_enable_hints(input: &str, opts: &CfgOptions, expected_hints: &[&str]) { let dnf = DnfExpr::new(&cfg); let hints = dnf.compute_enable_hints(opts).map(|diff| diff.to_string()).collect::>(); assert_eq!(hints, expected_hints); - let cfg = parse_ast_cfg(&tt_ast); + let cfg = parse_ast_cfg(pred_ast); let dnf = DnfExpr::new(&cfg); let hints = dnf.compute_enable_hints(opts).map(|diff| diff.to_string()).collect::>(); assert_eq!(hints, expected_hints); @@ -119,20 +116,6 @@ fn test_cfg_expr_parser() { .into_boxed_slice(), ), ); - - assert_parse_result( - r#"#![cfg(any(not(), all(), , bar = "baz",))]"#, - CfgExpr::Any( - vec![ - CfgExpr::Not(Box::new(CfgExpr::Invalid)), - CfgExpr::All(Box::new([])), - CfgExpr::Invalid, - CfgAtom::KeyValue { key: Symbol::intern("bar"), value: Symbol::intern("baz") } - .into(), - ] - .into_boxed_slice(), - ), - ); } #[test] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-def/src/attrs.rs index dddfe8cefdaa..b560d08492ff 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attrs.rs @@ -22,7 +22,7 @@ use either::Either; use hir_expand::{ InFile, Lookup, - attrs::{Meta, expand_cfg_attr}, + attrs::{AstKeyValueMetaExt, AstPathExt, expand_cfg_attr}, }; use intern::Symbol; use itertools::Itertools; @@ -128,63 +128,89 @@ fn extract_rustc_skip_during_method_dispatch(attr_flags: &mut AttrFlags, tt: ast } #[inline] -fn match_attr_flags(attr_flags: &mut AttrFlags, attr: Meta) -> ControlFlow { +fn match_attr_flags(attr_flags: &mut AttrFlags, attr: ast::Meta) -> ControlFlow { match attr { - Meta::NamedKeyValue { name: Some(name), value, .. } => match name.text() { - "deprecated" => attr_flags.insert(AttrFlags::IS_DEPRECATED), - "ignore" => attr_flags.insert(AttrFlags::IS_IGNORE), - "lang" => attr_flags.insert(AttrFlags::LANG_ITEM), - "path" => attr_flags.insert(AttrFlags::HAS_PATH), - "unstable" => attr_flags.insert(AttrFlags::IS_UNSTABLE), - "export_name" => { - if let Some(value) = value - && let Some(value) = ast::String::cast(value) - && let Ok(value) = value.value() - && *value == *"main" - { - attr_flags.insert(AttrFlags::IS_EXPORT_NAME_MAIN); - } - } - _ => {} - }, - Meta::TokenTree { path, tt } => match path.segments.len() { - 1 => match path.segments[0].text() { + ast::Meta::CfgMeta(_) => attr_flags.insert(AttrFlags::HAS_CFG), + ast::Meta::KeyValueMeta(attr) => { + let Some(key) = attr.path().as_one_segment() else { return ControlFlow::Continue(()) }; + match &*key { "deprecated" => attr_flags.insert(AttrFlags::IS_DEPRECATED), - "cfg" => attr_flags.insert(AttrFlags::HAS_CFG), - "doc" => extract_doc_tt_attr(attr_flags, tt), - "repr" => attr_flags.insert(AttrFlags::HAS_REPR), - "target_feature" => attr_flags.insert(AttrFlags::HAS_TARGET_FEATURE), - "proc_macro_derive" | "rustc_builtin_macro" => { - attr_flags.insert(AttrFlags::IS_DERIVE_OR_BUILTIN_MACRO) - } + "ignore" => attr_flags.insert(AttrFlags::IS_IGNORE), + "lang" => attr_flags.insert(AttrFlags::LANG_ITEM), + "path" => attr_flags.insert(AttrFlags::HAS_PATH), "unstable" => attr_flags.insert(AttrFlags::IS_UNSTABLE), - "rustc_layout_scalar_valid_range_start" | "rustc_layout_scalar_valid_range_end" => { - attr_flags.insert(AttrFlags::RUSTC_LAYOUT_SCALAR_VALID_RANGE) - } - "rustc_legacy_const_generics" => { - attr_flags.insert(AttrFlags::HAS_LEGACY_CONST_GENERICS) - } - "rustc_skip_during_method_dispatch" => { - extract_rustc_skip_during_method_dispatch(attr_flags, tt) - } - "rustc_deprecated_safe_2024" => { - attr_flags.insert(AttrFlags::RUSTC_DEPRECATED_SAFE_2024) + "export_name" => { + if let Some(value) = attr.value_string() + && *value == *"main" + { + attr_flags.insert(AttrFlags::IS_EXPORT_NAME_MAIN); + } } _ => {} - }, - 2 => match path.segments[0].text() { - "rust_analyzer" => match path.segments[1].text() { - "completions" => extract_ra_completions(attr_flags, tt), - "macro_style" => extract_ra_macro_style(attr_flags, tt), + } + } + ast::Meta::TokenTreeMeta(attr) => { + let (Some((first_segment, second_segment)), Some(tt)) = + (attr.path().as_up_to_two_segment(), attr.token_tree()) + else { + return ControlFlow::Continue(()); + }; + match second_segment { + None => match &*first_segment { + "deprecated" => attr_flags.insert(AttrFlags::IS_DEPRECATED), + "doc" => extract_doc_tt_attr(attr_flags, tt), + "repr" => attr_flags.insert(AttrFlags::HAS_REPR), + "target_feature" => attr_flags.insert(AttrFlags::HAS_TARGET_FEATURE), + "proc_macro_derive" | "rustc_builtin_macro" => { + attr_flags.insert(AttrFlags::IS_DERIVE_OR_BUILTIN_MACRO) + } + "unstable" => attr_flags.insert(AttrFlags::IS_UNSTABLE), + "rustc_layout_scalar_valid_range_start" + | "rustc_layout_scalar_valid_range_end" => { + attr_flags.insert(AttrFlags::RUSTC_LAYOUT_SCALAR_VALID_RANGE) + } + "rustc_legacy_const_generics" => { + attr_flags.insert(AttrFlags::HAS_LEGACY_CONST_GENERICS) + } + "rustc_skip_during_method_dispatch" => { + extract_rustc_skip_during_method_dispatch(attr_flags, tt) + } + "rustc_deprecated_safe_2024" => { + attr_flags.insert(AttrFlags::RUSTC_DEPRECATED_SAFE_2024) + } _ => {} }, - _ => {} - }, - _ => {} - }, - Meta::Path { path } => { - match path.segments.len() { - 1 => match path.segments[0].text() { + Some(second_segment) => match &*first_segment { + "rust_analyzer" => match &*second_segment { + "completions" => extract_ra_completions(attr_flags, tt), + "macro_style" => extract_ra_macro_style(attr_flags, tt), + _ => {} + }, + _ => {} + }, + } + } + ast::Meta::PathMeta(attr) => { + let is_test = attr.path().is_some_and(|path| { + let Some(segment1) = (|| path.segment()?.name_ref())() else { return false }; + let segment2 = path.qualifier(); + let segment3 = segment2.as_ref().and_then(|it| it.qualifier()); + let segment4 = segment3.as_ref().and_then(|it| it.qualifier()); + let segment3 = segment3.and_then(|it| it.segment()?.name_ref()); + let segment4 = segment4.and_then(|it| it.segment()?.name_ref()); + segment1.text() == "test" + && segment3.is_none_or(|it| it.text() == "prelude") + && segment4.is_none_or(|it| it.text() == "core") + }); + if is_test { + attr_flags.insert(AttrFlags::IS_TEST); + } + + let Some((first_segment, second_segment)) = attr.path().as_up_to_two_segment() else { + return ControlFlow::Continue(()); + }; + match second_segment { + None => match &*first_segment { "rustc_has_incoherent_inherent_impls" => { attr_flags.insert(AttrFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) } @@ -228,18 +254,13 @@ fn match_attr_flags(attr_flags: &mut AttrFlags, attr: Meta) -> ControlFlow {} }, - 2 => match path.segments[0].text() { - "rust_analyzer" => match path.segments[1].text() { + Some(second_segment) => match &*first_segment { + "rust_analyzer" => match &*second_segment { "skip" => attr_flags.insert(AttrFlags::RUST_ANALYZER_SKIP), _ => {} }, _ => {} }, - _ => {} - } - - if path.is_test { - attr_flags.insert(AttrFlags::IS_TEST); } } _ => {} @@ -420,7 +441,7 @@ fn resolver_for_attr_def_id(db: &dyn DefDatabase, owner: AttrDefId) -> Resolver< fn collect_attrs( db: &dyn DefDatabase, owner: AttrDefId, - mut callback: impl FnMut(Meta) -> ControlFlow, + mut callback: impl FnMut(ast::Meta) -> ControlFlow, ) -> Option { let (source, outer_mod_decl, extra_crate_attrs, krate) = attrs_source(db, owner); let extra_attrs = extra_crate_attrs @@ -432,7 +453,7 @@ fn collect_attrs( expand_cfg_attr( extra_attrs.chain(ast::attrs_including_inner(&source.value)), || cfg_options.get_or_insert_with(|| krate.cfg_options(db)), - move |meta, _, _, _| callback(meta), + move |meta, _| callback(meta), ) } @@ -500,9 +521,10 @@ pub struct DeriveInfo { pub helpers: Box<[Symbol]>, } -fn extract_doc_aliases(result: &mut Vec, attr: Meta) -> ControlFlow { - if let Meta::TokenTree { path, tt } = attr - && path.is1("doc") +fn extract_doc_aliases(result: &mut Vec, attr: ast::Meta) -> ControlFlow { + if let ast::Meta::TokenTreeMeta(attr) = attr + && attr.path().is1("doc") + && let Some(tt) = attr.token_tree() { for atom in DocAtom::parse(tt) { match atom { @@ -519,11 +541,11 @@ fn extract_doc_aliases(result: &mut Vec, attr: Meta) -> ControlFlow, attr: Meta) -> ControlFlow { - if let Meta::TokenTree { path, tt } = attr - && path.is1("cfg") +fn extract_cfgs(result: &mut Vec, attr: ast::Meta) -> ControlFlow { + if let ast::Meta::CfgMeta(attr) = attr + && let Some(cfg_predicate) = attr.cfg_predicate() { - result.push(CfgExpr::parse_from_ast(&mut TokenTreeChildren::new(&tt).peekable())); + result.push(CfgExpr::parse_from_ast(cfg_predicate)); } ControlFlow::Continue(()) } @@ -554,7 +576,7 @@ fn field_attr_flags( expand_cfg_attr( field.value.attrs(), || cfg_options, - |attr, _, _, _| match_attr_flags(&mut attr_flags, attr), + |attr, _| match_attr_flags(&mut attr_flags, attr), ); attr_flags }) @@ -591,7 +613,7 @@ fn generic_params_attr_flags( let lifetimes_source = HasChildSource::::child_source(&def, db); for (lifetime_id, lifetime) in lifetimes_source.value.iter() { let mut attr_flags = AttrFlags::empty(); - expand_cfg_attr(lifetime.attrs(), &mut cfg_options, |attr, _, _, _| { + expand_cfg_attr(lifetime.attrs(), &mut cfg_options, |attr, _| { match_attr_flags(&mut attr_flags, attr) }); if !attr_flags.is_empty() { @@ -603,7 +625,7 @@ fn generic_params_attr_flags( HasChildSource::::child_source(&def, db); for (type_or_const_id, type_or_const) in type_and_consts_source.value.iter() { let mut attr_flags = AttrFlags::empty(); - expand_cfg_attr(type_or_const.attrs(), &mut cfg_options, |attr, _, _, _| { + expand_cfg_attr(type_or_const.attrs(), &mut cfg_options, |attr, _| { match_attr_flags(&mut attr_flags, attr) }); if !attr_flags.is_empty() { @@ -642,11 +664,10 @@ pub(crate) fn is_cfg_enabled_for( let result = expand_cfg_attr( attrs, || cfg_options, - |attr, _, _, _| { - if let Meta::TokenTree { path, tt } = attr - && path.is1("cfg") - && let cfg = - CfgExpr::parse_from_ast(&mut TokenTreeChildren::new(&tt).peekable()) + |attr, _| { + if let ast::Meta::CfgMeta(attr) = attr + && let Some(cfg_predicate) = attr.cfg_predicate() + && let cfg = CfgExpr::parse_from_ast(cfg_predicate) && cfg_options.check(&cfg) == Some(false) { ControlFlow::Break(cfg) @@ -678,10 +699,9 @@ pub fn lang_item_with_attrs(self, db: &dyn DefDatabase, owner: AttrDefId) -> Opt #[salsa::tracked] fn lang_item(db: &dyn DefDatabase, owner: AttrDefId) -> Option { collect_attrs(db, owner, |attr| { - if let Meta::NamedKeyValue { name: Some(name), value: Some(value), .. } = attr - && name.text() == "lang" - && let Some(value) = ast::String::cast(value) - && let Ok(value) = value.value() + if let ast::Meta::KeyValueMeta(attr) = attr + && attr.path().is1("lang") + && let Some(value) = attr.value_string() { ControlFlow::Break(Symbol::intern(&value)) } else { @@ -704,8 +724,9 @@ pub fn repr(db: &dyn DefDatabase, owner: AdtId) -> Option { fn repr(db: &dyn DefDatabase, owner: AdtId) -> Option { let mut result = None; collect_attrs::(db, owner.into(), |attr| { - if let Meta::TokenTree { path, tt } = attr - && path.is1("repr") + if let ast::Meta::TokenTreeMeta(attr) = attr + && attr.path().is1("repr") + && let Some(tt) = attr.token_tree() && let Some(repr) = parse_repr_tt(&tt) { match &mut result { @@ -726,8 +747,9 @@ pub(crate) fn legacy_const_generic_indices( owner: FunctionId, ) -> Option> { let result = collect_attrs(db, owner.into(), |attr| { - if let Meta::TokenTree { path, tt } = attr - && path.is1("rustc_legacy_const_generics") + if let ast::Meta::TokenTreeMeta(attr) = attr + && attr.path().is1("rustc_legacy_const_generics") + && let Some(tt) = attr.token_tree() { let result = parse_rustc_legacy_const_generics(tt); ControlFlow::Break(result) @@ -750,9 +772,10 @@ pub fn doc_html_root_url(db: &dyn DefDatabase, krate: Crate) -> Option expand_cfg_attr( extra_crate_attrs.chain(syntax.attrs()), || cfg_options.get_or_insert(krate.cfg_options(db)), - |attr, _, _, _| { - if let Meta::TokenTree { path, tt } = attr - && path.is1("doc") + |attr, _| { + if let ast::Meta::TokenTreeMeta(attr) = attr + && attr.path().is1("doc") + && let Some(tt) = attr.token_tree() && let Some(result) = DocAtom::parse(tt).into_iter().find_map(|atom| { if let DocAtom::KeyValue { key, value } = atom && key == "html_root_url" @@ -783,8 +806,9 @@ pub fn target_features(db: &dyn DefDatabase, owner: FunctionId) -> &FxHashSet FxHashSet { let mut result = FxHashSet::default(); collect_attrs::(db, owner.into(), |attr| { - if let Meta::TokenTree { path, tt } = attr - && path.is1("target_feature") + if let ast::Meta::TokenTreeMeta(attr) = attr + && attr.path().is1("target_feature") + && let Some(tt) = attr.token_tree() { let mut tt = TokenTreeChildren::new(&tt); while let Some(NodeOrToken::Token(enable_ident)) = tt.next() @@ -831,9 +855,11 @@ fn rustc_layout_scalar_valid_range( ) -> RustcLayoutScalarValidRange { let mut result = RustcLayoutScalarValidRange::default(); collect_attrs::(db, owner.into(), |attr| { - if let Meta::TokenTree { path, tt } = attr + if let ast::Meta::TokenTreeMeta(attr) = attr + && let path = attr.path() && (path.is1("rustc_layout_scalar_valid_range_start") || path.is1("rustc_layout_scalar_valid_range_end")) + && let Some(tt) = attr.token_tree() && let tt = TokenTreeChildren::new(&tt) && let Ok(NodeOrToken::Token(value)) = Itertools::exactly_one(tt) && let Some(value) = ast::IntNumber::cast(value) @@ -881,7 +907,7 @@ fn fields_doc_aliases( expand_cfg_attr( field.value.attrs(), || cfg_options, - |attr, _, _, _| extract_doc_aliases(&mut result, attr), + |attr, _| extract_doc_aliases(&mut result, attr), ); result.into_boxed_slice() }) @@ -923,7 +949,7 @@ fn fields_cfgs( expand_cfg_attr( field.value.attrs(), || cfg_options, - |attr, _, _, _| extract_cfgs(&mut result, attr), + |attr, _| extract_cfgs(&mut result, attr), ); match result.len() { 0 => None, @@ -944,8 +970,9 @@ pub fn doc_keyword(db: &dyn DefDatabase, owner: ModuleId) -> Option { #[salsa::tracked] fn doc_keyword(db: &dyn DefDatabase, owner: ModuleId) -> Option { collect_attrs(db, AttrDefId::ModuleId(owner), |attr| { - if let Meta::TokenTree { path, tt } = attr - && path.is1("doc") + if let ast::Meta::TokenTreeMeta(attr) = attr + && attr.path().is1("doc") + && let Some(tt) = attr.token_tree() { for atom in DocAtom::parse(tt) { if let DocAtom::KeyValue { key, value } = atom @@ -1015,12 +1042,10 @@ pub fn derive_info(db: &dyn DefDatabase, owner: MacroId) -> Option<&DeriveInfo> #[salsa::tracked(returns(ref))] fn derive_info(db: &dyn DefDatabase, owner: MacroId) -> Option { collect_attrs(db, owner.into(), |attr| { - if let Meta::TokenTree { path, tt } = attr - && path.segments.len() == 1 - && matches!( - path.segments[0].text(), - "proc_macro_derive" | "rustc_builtin_macro" - ) + if let ast::Meta::TokenTreeMeta(attr) = attr + && (attr.path().is1("proc_macro_derive") + || attr.path().is1("rustc_builtin_macro")) + && let Some(tt) = attr.token_tree() && let mut tt = TokenTreeChildren::new(&tt) && let Some(NodeOrToken::Token(trait_name)) = tt.next() && trait_name.kind().is_any_identifier() diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attrs/docs.rs b/src/tools/rust-analyzer/crates/hir-def/src/attrs/docs.rs index 8c14808c7195..9a715b19688e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attrs/docs.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attrs/docs.rs @@ -16,7 +16,7 @@ use either::Either; use hir_expand::{ AstId, ExpandTo, HirFileId, InFile, - attrs::{Meta, expand_cfg_attr_with_doc_comments}, + attrs::{AstPathExt, expand_cfg_attr_with_doc_comments}, mod_path::ModPath, span_map::SpanMap, }; @@ -182,8 +182,7 @@ fn extend_with_doc_comment(&mut self, comment: ast::Comment, indent: &mut usize) self.extend_with_doc_str(doc, comment.syntax().text_range().start() + offset, indent); } - fn extend_with_doc_attr(&mut self, value: syntax::SyntaxToken, indent: &mut usize) { - let Some(value) = ast::String::cast(value) else { return }; + fn extend_with_doc_attr(&mut self, value: ast::String, indent: &mut usize) { let Some(value_offset) = value.text_range_between_quotes() else { return }; let value_offset = value_offset.start(); let Ok(value) = value.value() else { return }; @@ -423,10 +422,6 @@ fn extend_with_attrs<'a, 'db>( // Lazily initialised when we first encounter a `#[doc = macro!()]`. let mut expander: Option<(DocMacroExpander<'db>, DocExprSourceCtx<'db>)> = None; - // FIXME: `#[cfg_attr(..., doc = macro!())]` skips macro expansion because - // `top_attr` points to the `cfg_attr` node, not the inner `doc = macro!()`. - // Fixing this is difficult as we need an `Expr` that doesn't exist here for - // the ast id and for sanely parsing the macro call. expand_cfg_attr_with_doc_comments::<_, Infallible>( AttrDocCommentIter::from_syntax_node(node).filter(|attr| match attr { Either::Left(attr) => attr.kind().is_inner() == expect_inner_attrs, @@ -439,46 +434,38 @@ fn extend_with_attrs<'a, 'db>( |attr| { match attr { Either::Right(doc_comment) => result.extend_with_doc_comment(doc_comment, indent), - Either::Left((attr, _, _, top_attr)) => match attr { - Meta::NamedKeyValue { name: Some(name), value: Some(value), .. } - if name.text() == "doc" => - { - result.extend_with_doc_attr(value, indent); - } - Meta::NamedKeyValue { name: Some(name), value: None, .. } - if name.text() == "doc" => - { - // When the doc attribute comes from inside a `cfg_attr`, - // `top_attr` points to the `cfg_attr(...)` node, not the - // inner `doc = macro!()`. In that case `top_attr.expr()` - // would not yield the macro expression we need, so skip - // expansion (see FIXME above). - let is_from_cfg_attr = - top_attr.as_simple_call().is_some_and(|(name, _)| name == "cfg_attr"); - if !is_from_cfg_attr && let Some(expr) = top_attr.expr() { - let (exp, ctx) = expander.get_or_insert_with(|| { - let resolver = make_resolver(); - let def_map = resolver.top_level_def_map(); - let recursion_limit = def_map.recursion_limit() as usize; - ( - DocMacroExpander { - db, - krate, - recursion_depth: 0, - recursion_limit, - }, - DocExprSourceCtx { - resolver, - file_id, - ast_id_map: db.ast_id_map(file_id), - span_map: db.span_map(file_id), - }, - ) - }); - if let Some(expanded) = - expand_doc_expr_via_macro_pipeline(exp, ctx, expr) + Either::Left((attr, _)) => match attr { + ast::Meta::KeyValueMeta(attr) if attr.path().is1("doc") => { + if let Some(value) = attr.expr() { + if let ast::Expr::Literal(value) = &value + && let ast::LiteralKind::String(value) = value.kind() { - result.extend_with_unmapped_doc_str(&expanded, indent); + result.extend_with_doc_attr(value, indent); + } else { + let (exp, ctx) = expander.get_or_insert_with(|| { + let resolver = make_resolver(); + let def_map = resolver.top_level_def_map(); + let recursion_limit = def_map.recursion_limit() as usize; + ( + DocMacroExpander { + db, + krate, + recursion_depth: 0, + recursion_limit, + }, + DocExprSourceCtx { + resolver, + file_id, + ast_id_map: db.ast_id_map(file_id), + span_map: db.span_map(file_id), + }, + ) + }); + if let Some(expanded) = + expand_doc_expr_via_macro_pipeline(exp, ctx, value) + { + result.extend_with_unmapped_doc_str(&expanded, indent); + } } } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs index 4308d0ef1c29..c38ceccd1fc0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs @@ -68,7 +68,7 @@ pub mod keys { pub const MACRO_CALL: Key = Key::new(); pub const ATTR_MACRO_CALL: Key = Key::new(); pub const DERIVE_MACRO_CALL: Key< - ast::Attr, + ast::Meta, ( AttrId, /* derive() */ MacroCallId, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/attrs.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/attrs.rs index 79076112847b..867d813e3f2b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/attrs.rs @@ -13,12 +13,12 @@ use cfg::{CfgExpr, CfgOptions}; use either::Either; use hir_expand::{ - attrs::{Attr, AttrId, AttrInput, Meta, collect_item_tree_attrs}, + attrs::{Attr, AttrId, AttrInput, collect_item_tree_attrs}, mod_path::ModPath, name::Name, }; use intern::{Interned, Symbol, sym}; -use syntax::{AstNode, T, ast}; +use syntax::{AstNode, ast}; use syntax_bridge::DocCommentDesugarMode; use tt::token_to_literal; @@ -51,58 +51,62 @@ pub(crate) fn lower<'a, S>( S: syntax_bridge::SpanMapper + Copy, { let mut attrs = Vec::new(); - let result = - collect_item_tree_attrs::(owner, cfg_options, |meta, container, _, _| { - // NOTE: We cannot early return from this function, *every* attribute must be pushed, otherwise we'll mess the `AttrId` - // tracking. - let (span, path_range, input) = match meta { - Meta::NamedKeyValue { path_range, name: _, value } => { - let span = span_map.span_for(path_range); - let input = value.map(|value| { - Box::new(AttrInput::Literal(token_to_literal( - value.text(), - span_map.span_for(value.text_range()), - ))) - }); - (span, path_range, input) - } - Meta::TokenTree { path, tt } => { - let span = span_map.span_for(path.range); - let tt = syntax_bridge::syntax_node_to_token_tree( - tt.syntax(), - span_map, - span, - DocCommentDesugarMode::ProcMacro, - ); - let input = Some(Box::new(AttrInput::TokenTree(tt))); - (span, path.range, input) - } - Meta::Path { path } => { - let span = span_map.span_for(path.range); - (span, path.range, None) - } - }; + let result = collect_item_tree_attrs::(owner, cfg_options, |meta, _| { + // NOTE: We cannot early return from this function, *every* attribute must be pushed, otherwise we'll mess the `AttrId` + // tracking. + let path = meta.path(); + let path_range = path + .as_ref() + .map(|path| path.syntax().text_range()) + .unwrap_or_else(|| meta.syntax().text_range()); + let (span, input) = match &meta { + ast::Meta::KeyValueMeta(meta) => { + let span = span_map.span_for(path_range); + let input = meta.expr().and_then(|value| { + if let ast::Expr::Literal(value) = value { + Some(Box::new(AttrInput::Literal(token_to_literal( + value.token().text(), + span_map.span_for(value.syntax().text_range()), + )))) + } else { + None + } + }); + (span, input) + } + ast::Meta::TokenTreeMeta(meta) => { + let span = span_map.span_for(path_range); + let tt = syntax_bridge::syntax_node_to_token_tree( + &meta + .token_tree() + .map(|it| it.syntax().clone()) + .unwrap_or_else(|| meta.syntax().clone()), + span_map, + span, + DocCommentDesugarMode::ProcMacro, + ); + let input = Some(Box::new(AttrInput::TokenTree(tt))); + (span, input) + } + ast::Meta::PathMeta(_) => { + let span = span_map.span_for(path_range); + (span, None) + } + ast::Meta::CfgMeta(_) | ast::Meta::CfgAttrMeta(_) | ast::Meta::UnsafeMeta(_) => { + unreachable!( + "`cfg`, `cfg_attr` and `unsafe(...)` are handled in `collect_item_tree_attrs()`" + ) + } + }; - let path = container.token_at_offset(path_range.start()).right_biased().and_then( - |first_path_token| { - let is_abs = matches!(first_path_token.kind(), T![:] | T![::]); - let segments = - std::iter::successors(Some(first_path_token), |it| it.next_token()) - .take_while(|it| it.text_range().end() <= path_range.end()) - .filter(|it| it.kind().is_any_identifier()); - ModPath::from_tokens( - db, - &mut |range| span_map.span_for(range).ctx, - is_abs, - segments, - ) - }, - ); - let path = path.unwrap_or_else(|| Name::missing().into()); - - attrs.push(Attr { path: Interned::new(path), input, ctxt: span.ctx }); - ControlFlow::Continue(()) + let path = path.and_then(|path| { + ModPath::from_src(db, path, &mut |range| span_map.span_for(range).ctx) }); + let path = path.unwrap_or_else(|| Name::missing().into()); + + attrs.push(Attr { path: Interned::new(path), input, ctxt: span.ctx }); + ControlFlow::Continue(()) + }); let attrs = AttrsOwned(attrs.into_boxed_slice()); match result { Some(Either::Right(cfg)) => AttrsOrCfg::CfgDisabled(Box::new((cfg, attrs))), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs index 7b5d0103e66e..e75c96b63039 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -1198,7 +1198,7 @@ macro_rules! m { macro_rules! m { ($m:meta) => ( #[$m] fn bar() {} ) } -#[cfg(target_os = "windows")] fn bar() {} +#[cfg (target_os = "windows")] fn bar() {} #[hello::world] fn bar() {} "#]], ); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs index ddabb50251a4..cac248f47fff 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs @@ -205,7 +205,7 @@ impl Clone for D3DVSHADERCAPS2_0 { *self } } -#[cfg(feature = "impl-default")] impl Default for D3DVSHADERCAPS2_0 { +#[cfg (feature = "impl-default")] impl Default for D3DVSHADERCAPS2_0 { #[inline] fn default() -> D3DVSHADERCAPS2_0 { unsafe { $crate::_core::mem::zeroed() @@ -215,7 +215,7 @@ impl Clone for D3DVSHADERCAPS2_0 { #[repr(C)] #[derive(Copy)] -#[cfg_attr(target_arch = "x86", repr(packed))] pub struct D3DCONTENTPROTECTIONCAPS { +#[cfg_attr (target_arch = "x86", repr(packed))] pub struct D3DCONTENTPROTECTIONCAPS { pub Caps: u8, } impl Clone for D3DCONTENTPROTECTIONCAPS { @@ -223,7 +223,7 @@ impl Clone for D3DCONTENTPROTECTIONCAPS { *self } } -#[cfg(feature = "impl-default")] impl Default for D3DCONTENTPROTECTIONCAPS { +#[cfg (feature = "impl-default")] impl Default for D3DCONTENTPROTECTIONCAPS { #[inline] fn default() -> D3DCONTENTPROTECTIONCAPS { unsafe { $crate::_core::mem::zeroed() @@ -1001,8 +1001,8 @@ macro_rules! with_std { ($($i:item)*) => ($(#[cfg(feature = "std")]$i)*) } -#[cfg(feature = "std")] mod m; -#[cfg(feature = "std")] mod f; +#[cfg (feature = "std")] mod m; +#[cfg (feature = "std")] mod f; "#]], ) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs index bf04a500a57d..8c91cf6793a5 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs @@ -55,8 +55,8 @@ fn bar() {} # ![doc = "123..."] # ![attr2] # ![attr3] - #[cfg_attr(true , cfg(false ))] fn foo() {} - #[cfg(true )] fn bar() {} + #[cfg_attr (true , cfg (false ))] fn foo() {} + #[cfg (true )] fn bar() {} }"##]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml index 4fa476afb64a..43b0bea891e3 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml @@ -23,7 +23,6 @@ triomphe.workspace = true query-group.workspace = true salsa.workspace = true salsa-macros.workspace = true -arrayvec.workspace = true thin-vec.workspace = true # local deps diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs index e3f10b212904..49baecb90cd5 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -4,20 +4,8 @@ //! [`expand_cfg_attr_with_doc_comments()`]. It is used to implement all attribute lowering //! in r-a. Its basic job is to list attributes; however, attributes do not necessarily map //! into [`ast::Attr`], because `cfg_attr` can map to zero, one, or more attributes -//! (`#[cfg_attr(predicate, attr1, attr2, ...)]`). To bridge this gap, this module defines -//! [`Meta`], which represents a desugared attribute. Various bits of r-a need different -//! things from [`Meta`], therefore it contains many parts. The basic idea is: -//! -//! - There are three kinds of attributes, `path = value`, `path`, and `path(token_tree)`. -//! - Most bits of rust-analyzer only need to deal with some paths. Therefore, we keep -//! the path only if it has up to 2 segments, or one segment for `path = value`. -//! We also only keep the value in `path = value` if it is a literal. However, we always -//! save the all relevant ranges of attributes (the path range, and the full attribute range) -//! for parts of r-a (e.g. name resolution) that need a faithful representation of the -//! attribute. -//! -//! [`expand_cfg_attr()`] expands `cfg_attr`s as it goes (as its name implies), to list -//! all attributes. +//! (`#[cfg_attr(predicate, attr1, attr2, ...)]`). [`expand_cfg_attr()`] expands `cfg_attr`s +//! as it goes (as its name implies), to list all attributes. //! //! Another thing to note is that we need to be able to map an attribute back to a range //! (for diagnostic purposes etc.). This is only ever needed for attributes that participate @@ -26,26 +14,18 @@ //! place (here) and one function ([`is_item_tree_filtered_attr()`]) that decides whether //! an attribute participate in name resolution. -use std::{ - borrow::Cow, cell::OnceCell, convert::Infallible, fmt, iter::Peekable, ops::ControlFlow, -}; +use std::{borrow::Cow, cell::OnceCell, convert::Infallible, fmt, ops::ControlFlow}; -use ::tt::{TextRange, TextSize}; -use arrayvec::ArrayVec; +use ::tt::TextRange; use base_db::Crate; use cfg::{CfgExpr, CfgOptions}; use either::Either; use intern::Interned; use itertools::Itertools; use mbe::{DelimiterKind, Punct}; -use parser::T; use smallvec::SmallVec; use span::{RealSpanMap, Span, SyntaxContext}; -use syntax::{ - AstNode, NodeOrToken, SyntaxNode, SyntaxToken, - ast::{self, TokenTreeChildren}, - unescape, -}; +use syntax::{AstNode, SmolStr, ast, unescape}; use syntax_bridge::DocCommentDesugarMode; use crate::{ @@ -56,207 +36,75 @@ tt::{self, TopSubtree}, }; -#[derive(Debug)] -pub struct AttrPath { - /// This can be empty if the path is not of 1 or 2 segments exactly. - pub segments: ArrayVec, - pub range: TextRange, - // FIXME: This shouldn't be textual, `#[test]` needs name resolution. - // And if textual, it shouldn't be here, it should be in hir-def/src/attrs.rs. But some macros - // fully qualify `test` as `core::prelude::vX::test`, and this is more than 2 segments, so hir-def - // attrs can't find it. But this will mean we have to push every up-to-4-segments path, which - // may impact perf. So it was easier to just hack it here. - pub is_test: bool, +pub trait AstPathExt { + fn is1(&self, segment: &str) -> bool; + + fn as_one_segment(&self) -> Option; + + fn as_up_to_two_segment(&self) -> Option<(SmolStr, Option)>; } -impl AttrPath { - #[inline] - fn extract(path: &ast::Path) -> Self { - let mut is_test = false; - let segments = (|| { - let mut segments = ArrayVec::new(); - let segment2 = path.segment()?.name_ref()?.syntax().first_token()?; - if segment2.text() == "test" { - // `#[test]` or `#[core::prelude::vX::test]`. - is_test = true; - } - let segment1 = path.qualifier(); - if let Some(segment1) = segment1 { - if segment1.qualifier().is_some() { - None - } else { - let segment1 = segment1.segment()?.name_ref()?.syntax().first_token()?; - segments.push(segment1); - segments.push(segment2); - Some(segments) - } - } else { - segments.push(segment2); - Some(segments) - } - })(); - AttrPath { - segments: segments.unwrap_or(ArrayVec::new()), - range: path.syntax().text_range(), - is_test, - } +impl AstPathExt for ast::Path { + fn is1(&self, segment: &str) -> bool { + self.as_one_segment().is_some_and(|it| it == segment) } - #[inline] - pub fn is1(&self, segment: &str) -> bool { - self.segments.len() == 1 && self.segments[0].text() == segment + fn as_one_segment(&self) -> Option { + Some(self.as_single_name_ref()?.text().into()) + } + + fn as_up_to_two_segment(&self) -> Option<(SmolStr, Option)> { + let parent = self.qualifier().as_one_segment(); + let this = self.segment()?.name_ref()?.text().into(); + if let Some(parent) = parent { Some((parent, Some(this))) } else { Some((this, None)) } } } -#[derive(Debug)] -pub enum Meta { - /// `name` is `None` if not a single token. `value` is a literal or `None`. - NamedKeyValue { - path_range: TextRange, - name: Option, - value: Option, - }, - TokenTree { - path: AttrPath, - tt: ast::TokenTree, - }, - Path { - path: AttrPath, - }, -} - -impl Meta { - #[inline] - pub fn path_range(&self) -> TextRange { - match self { - Meta::NamedKeyValue { path_range, .. } => *path_range, - Meta::TokenTree { path, .. } | Meta::Path { path } => path.range, - } +impl AstPathExt for Option { + fn is1(&self, segment: &str) -> bool { + self.as_ref().is_some_and(|it| it.is1(segment)) } - fn extract(iter: &mut Peekable) -> Option<(Self, TextSize)> { - let mut start_offset = None; - if let Some(NodeOrToken::Token(colon1)) = iter.peek() - && colon1.kind() == T![:] + fn as_one_segment(&self) -> Option { + self.as_ref().and_then(|it| it.as_one_segment()) + } + + fn as_up_to_two_segment(&self) -> Option<(SmolStr, Option)> { + self.as_ref().and_then(|it| it.as_up_to_two_segment()) + } +} + +pub trait AstKeyValueMetaExt { + fn value_string(&self) -> Option; +} + +impl AstKeyValueMetaExt for ast::KeyValueMeta { + fn value_string(&self) -> Option { + if let Some(ast::Expr::Literal(value)) = self.expr() + && let ast::LiteralKind::String(value) = value.kind() + && let Ok(value) = value.value() { - start_offset = Some(colon1.text_range().start()); - iter.next(); - iter.next_if(|it| it.as_token().is_some_and(|it| it.kind() == T![:])); - } - let first_segment = iter - .next_if(|it| it.as_token().is_some_and(|it| it.kind().is_any_identifier()))? - .into_token()?; - let mut is_test = first_segment.text() == "test"; - let start_offset = start_offset.unwrap_or_else(|| first_segment.text_range().start()); - - let mut segments_len = 1; - let mut second_segment = None; - let mut path_range = first_segment.text_range(); - while iter.peek().and_then(NodeOrToken::as_token).is_some_and(|it| it.kind() == T![:]) - && let _ = iter.next() - && iter.peek().and_then(NodeOrToken::as_token).is_some_and(|it| it.kind() == T![:]) - && let _ = iter.next() - && let Some(NodeOrToken::Token(segment)) = iter.peek() - && segment.kind().is_any_identifier() - { - segments_len += 1; - is_test = segment.text() == "test"; - second_segment = Some(segment.clone()); - path_range = TextRange::new(path_range.start(), segment.text_range().end()); - iter.next(); - } - - let segments = |first, second| { - let mut segments = ArrayVec::new(); - if segments_len <= 2 { - segments.push(first); - if let Some(second) = second { - segments.push(second); - } - } - segments - }; - let meta = match iter.peek() { - Some(NodeOrToken::Token(eq)) if eq.kind() == T![=] => { - iter.next(); - let value = match iter.peek() { - Some(NodeOrToken::Token(token)) if token.kind().is_literal() => { - // No need to consume it, it will be consumed by `extract_and_eat_comma()`. - Some(token.clone()) - } - _ => None, - }; - let name = if second_segment.is_none() { Some(first_segment) } else { None }; - Meta::NamedKeyValue { path_range, name, value } - } - Some(NodeOrToken::Node(tt)) => Meta::TokenTree { - path: AttrPath { - segments: segments(first_segment, second_segment), - range: path_range, - is_test, - }, - tt: tt.clone(), - }, - _ => Meta::Path { - path: AttrPath { - segments: segments(first_segment, second_segment), - range: path_range, - is_test, - }, - }, - }; - Some((meta, start_offset)) - } - - fn extract_possibly_unsafe( - iter: &mut Peekable, - container: &ast::TokenTree, - ) -> Option<(Self, TextRange)> { - if iter.peek().is_some_and(|it| it.as_token().is_some_and(|it| it.kind() == T![unsafe])) { - iter.next(); - let tt = iter.next()?.into_node()?; - let result = Self::extract(&mut TokenTreeChildren::new(&tt).peekable()).map( - |(meta, start_offset)| (meta, TextRange::new(start_offset, tt_end_offset(&tt))), - ); - while iter.next().is_some_and(|it| it.as_token().is_none_or(|it| it.kind() != T![,])) {} - result + Some((*value).into()) } else { - Self::extract(iter).map(|(meta, start_offset)| { - let end_offset = 'find_end_offset: { - for it in iter { - if let NodeOrToken::Token(it) = it - && it.kind() == T![,] - { - break 'find_end_offset it.text_range().start(); - } - } - tt_end_offset(container) - }; - (meta, TextRange::new(start_offset, end_offset)) - }) + None } } } -fn tt_end_offset(tt: &ast::TokenTree) -> TextSize { - tt.syntax().last_token().unwrap().text_range().start() -} - -/// The callback is passed a desugared form of the attribute ([`Meta`]), a [`SyntaxNode`] fully containing it -/// (note: it may not be the direct parent), the range within the [`SyntaxNode`] bounding the attribute, -/// and the outermost `ast::Attr`. Note that one node may map to multiple [`Meta`]s due to `cfg_attr`. +/// The callback is passed the attribute and the outermost `ast::Attr`. +/// Note that one node may map to multiple [`Meta`]s due to `cfg_attr`. +/// +/// `unsafe(attr)` are passed the inner attribute for now. #[inline] pub fn expand_cfg_attr<'a, BreakValue>( attrs: impl Iterator, cfg_options: impl FnMut() -> &'a CfgOptions, - mut callback: impl FnMut(Meta, &SyntaxNode, TextRange, &ast::Attr) -> ControlFlow, + mut callback: impl FnMut(ast::Meta, ast::Attr) -> ControlFlow, ) -> Option { expand_cfg_attr_with_doc_comments::( attrs.map(Either::Left), cfg_options, - move |Either::Left((meta, container, range, top_attr))| { - callback(meta, container, range, top_attr) - }, + move |Either::Left((meta, top_attr))| callback(meta, top_attr), ) } @@ -264,66 +112,47 @@ pub fn expand_cfg_attr<'a, BreakValue>( pub fn expand_cfg_attr_with_doc_comments<'a, DocComment, BreakValue>( mut attrs: impl Iterator>, mut cfg_options: impl FnMut() -> &'a CfgOptions, - mut callback: impl FnMut( - Either<(Meta, &SyntaxNode, TextRange, &ast::Attr), DocComment>, - ) -> ControlFlow, + mut callback: impl FnMut(Either<(ast::Meta, ast::Attr), DocComment>) -> ControlFlow, ) -> Option { let mut stack = SmallVec::<[_; 1]>::new(); - let result = attrs.try_for_each(|top_attr| { - let top_attr = match top_attr { - Either::Left(it) => it, - Either::Right(comment) => return callback(Either::Right(comment)), - }; - if let Some((attr_name, tt)) = top_attr.as_simple_call() - && attr_name == "cfg_attr" - { - let mut tt_iter = TokenTreeChildren::new(&tt).peekable(); - let cfg = cfg::CfgExpr::parse_from_ast(&mut tt_iter); - if cfg_options().check(&cfg) != Some(false) { - stack.push((tt_iter, tt)); - while let Some((tt_iter, tt)) = stack.last_mut() { - let Some((attr, range)) = Meta::extract_possibly_unsafe(tt_iter, tt) else { - stack.pop(); - continue; - }; - if let Meta::TokenTree { path, tt: nested_tt } = &attr - && path.is1("cfg_attr") - { - let mut nested_tt_iter = TokenTreeChildren::new(nested_tt).peekable(); - let cfg = cfg::CfgExpr::parse_from_ast(&mut nested_tt_iter); - if cfg_options().check(&cfg) != Some(false) { - stack.push((nested_tt_iter, nested_tt.clone())); - } - } else { - callback(Either::Left((attr, tt.syntax(), range, &top_attr)))?; + loop { + let (mut meta, top_attr) = if let Some(it) = stack.pop() { + it + } else { + let attr = attrs.next()?; + match attr { + Either::Left(attr) => { + let Some(meta) = attr.meta() else { continue }; + stack.push((meta, attr)); + } + Either::Right(doc_comment) => { + if let ControlFlow::Break(break_value) = callback(Either::Right(doc_comment)) { + return Some(break_value); } } } - } else if let Some(ast_meta) = top_attr.meta() - && let Some(path) = ast_meta.path() - { - let path = AttrPath::extract(&path); - let meta = if let Some(tt) = ast_meta.token_tree() { - Meta::TokenTree { path, tt } - } else if let Some(value) = ast_meta.expr() { - let value = - if let ast::Expr::Literal(value) = value { Some(value.token()) } else { None }; - let name = - if path.segments.len() == 1 { Some(path.segments[0].clone()) } else { None }; - Meta::NamedKeyValue { name, value, path_range: path.range } - } else { - Meta::Path { path } - }; - callback(Either::Left(( - meta, - ast_meta.syntax(), - ast_meta.syntax().text_range(), - &top_attr, - )))?; + continue; + }; + + while let ast::Meta::UnsafeMeta(unsafe_meta) = &meta { + let Some(inner) = unsafe_meta.meta() else { continue }; + meta = inner; } - ControlFlow::Continue(()) - }); - result.break_value() + + if let ast::Meta::CfgAttrMeta(meta) = meta { + let Some(cfg_predicate) = meta.cfg_predicate() else { continue }; + let cfg_predicate = CfgExpr::parse_from_ast(cfg_predicate); + if cfg_options().check(&cfg_predicate) != Some(false) { + let prev_stack_len = stack.len(); + stack.extend(meta.metas().map(|meta| (meta, top_attr.clone()))); + stack[prev_stack_len..].reverse(); + } + } else { + if let ControlFlow::Break(break_value) = callback(Either::Left((meta, top_attr))) { + return Some(break_value); + } + } + } } #[inline] @@ -351,39 +180,33 @@ pub(crate) fn is_item_tree_filtered_attr(name: &str) -> bool { pub fn collect_item_tree_attrs<'a, BreakValue>( owner: &dyn ast::HasAttrs, cfg_options: impl Fn() -> &'a CfgOptions, - mut on_attr: impl FnMut(Meta, &SyntaxNode, &ast::Attr, TextRange) -> ControlFlow, + mut on_attr: impl FnMut(ast::Meta, ast::Attr) -> ControlFlow, ) -> Option> { let attrs = ast::attrs_including_inner(owner); expand_cfg_attr( attrs, || cfg_options(), - |attr, container, range, top_attr| { + |attr, top_attr| { // We filter builtin attributes that we don't need for nameres, because this saves memory. // I only put the most common attributes, but if some attribute becomes common feel free to add it. // Notice, however: for an attribute to be filtered out, it *must* not be shadowable with a macro! let filter = match &attr { - Meta::NamedKeyValue { name: Some(name), .. } => { - is_item_tree_filtered_attr(name.text()) - } - Meta::TokenTree { path, tt } if path.segments.len() == 1 => { - let name = path.segments[0].text(); - if name == "cfg" { - let cfg = - CfgExpr::parse_from_ast(&mut TokenTreeChildren::new(tt).peekable()); - if cfg_options().check(&cfg) == Some(false) { - return ControlFlow::Break(Either::Right(cfg)); - } - true - } else { - is_item_tree_filtered_attr(name) + ast::Meta::CfgMeta(attr) => { + let Some(cfg_predicate) = attr.cfg_predicate() else { + return ControlFlow::Continue(()); + }; + let cfg = CfgExpr::parse_from_ast(cfg_predicate); + if cfg_options().check(&cfg) == Some(false) { + return ControlFlow::Break(Either::Right(cfg)); } + true } - Meta::Path { path } => { - path.segments.len() == 1 && is_item_tree_filtered_attr(path.segments[0].text()) - } - _ => false, + _ => attr + .path() + .and_then(|path| path.as_one_segment()) + .is_some_and(|segment| is_item_tree_filtered_attr(&segment)), }; - if !filter && let ControlFlow::Break(v) = on_attr(attr, container, top_attr, range) { + if !filter && let ControlFlow::Break(v) = on_attr(attr, top_attr) { return ControlFlow::Break(Either::Left(v)); } ControlFlow::Continue(()) @@ -540,34 +363,32 @@ pub fn item_tree_index(self) -> u32 { } /// Returns the containing `ast::Attr` (note that it may contain other attributes as well due - /// to `cfg_attr`), a `SyntaxNode` guaranteed to contain the attribute, the full range of the - /// attribute, and its desugared [`Meta`]. + /// to `cfg_attr`) and its [`ast::Meta`]. pub fn find_attr_range( self, db: &dyn ExpandDatabase, krate: Crate, owner: AstId, - ) -> (ast::Attr, SyntaxNode, TextRange, Meta) { + ) -> (ast::Attr, ast::Meta) { self.find_attr_range_with_source(db, krate, &owner.to_node(db)) } /// Returns the containing `ast::Attr` (note that it may contain other attributes as well due - /// to `cfg_attr`), a `SyntaxNode` guaranteed to contain the attribute, the full range of the - /// attribute, and its desugared [`Meta`]. + /// to `cfg_attr`) and its [`ast::Meta`]. pub fn find_attr_range_with_source( self, db: &dyn ExpandDatabase, krate: Crate, owner: &dyn ast::HasAttrs, - ) -> (ast::Attr, SyntaxNode, TextRange, Meta) { + ) -> (ast::Attr, ast::Meta) { let cfg_options = OnceCell::new(); let mut index = 0; let result = collect_item_tree_attrs( owner, || cfg_options.get_or_init(|| krate.cfg_options(db)), - |meta, container, top_attr, range| { + |meta, top_attr| { if index == self.id { - return ControlFlow::Break((top_attr.clone(), container.clone(), range, meta)); + return ControlFlow::Break((top_attr, meta)); } index += 1; ControlFlow::Continue(()) @@ -588,9 +409,12 @@ pub fn find_derive_range( owner: AstId, derive_index: u32, ) -> TextRange { - let (_, _, derive_attr_range, derive_attr) = self.find_attr_range(db, krate, owner); - let Meta::TokenTree { tt, .. } = derive_attr else { - return derive_attr_range; + let (_, derive_attr) = self.find_attr_range(db, krate, owner); + let ast::Meta::TokenTreeMeta(derive_attr) = derive_attr else { + return derive_attr.syntax().text_range(); + }; + let Some(tt) = derive_attr.token_tree() else { + return derive_attr.syntax().text_range(); }; // Fake the span map, as we don't really need spans here, just the offsets of the node in the file. let span_map = RealSpanMap::absolute(span::EditionedFileId::current_edition( @@ -605,11 +429,11 @@ pub fn find_derive_range( let Some((_, _, derive_tts)) = parse_path_comma_token_tree(db, &tt).nth(derive_index as usize) else { - return derive_attr_range; + return derive_attr.syntax().text_range(); }; let (Some(first_span), Some(last_span)) = (derive_tts.first_span(), derive_tts.last_span()) else { - return derive_attr_range; + return derive_attr.syntax().text_range(); }; let start = first_span.range.start(); let end = last_span.range.end(); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs index ccef9168ac3a..6258fac0e992 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs @@ -8,12 +8,12 @@ use smallvec::SmallVec; use syntax::{ AstNode, PreorderWithTokens, SyntaxElement, SyntaxNode, SyntaxToken, WalkEvent, - ast::{self, HasAttrs, TokenTreeChildren}, + ast::{self, HasAttrs}, }; use syntax_bridge::DocCommentDesugarMode; use crate::{ - attrs::{AttrId, Meta, expand_cfg_attr, is_item_tree_filtered_attr}, + attrs::{AstPathExt, AttrId, expand_cfg_attr, is_item_tree_filtered_attr}, db::ExpandDatabase, fixup::{self, SyntaxFixupUndoInfo}, span_map::SpanMapRef, @@ -24,7 +24,7 @@ #[derive(Debug)] struct ExpandedAttrToProcess { - range: TextRange, + attr: ast::Meta, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -143,42 +143,29 @@ fn macro_input_callback( }); attrs_idx = 0; - let strip_current_item = expand_cfg_attr( - node_attrs, - &cfg_options, - |attr, _container, range, top_attr| { + let strip_current_item = + expand_cfg_attr(node_attrs, &cfg_options, |attr, top_attr| { // Find the attr. while attrs[attrs_idx].range != top_attr.syntax().text_range() { attrs_idx += 1; } let mut strip_current_attr = false; - match attr { - Meta::NamedKeyValue { name, .. } => { - if name - .is_none_or(|name| !is_item_tree_filtered_attr(name.text())) - { - strip_current_attr = should_strip_attr(); - } - } - Meta::TokenTree { path, tt } => { - if path.is1("cfg") { - let cfg_expr = CfgExpr::parse_from_ast( - &mut TokenTreeChildren::new(&tt).peekable(), - ); + match &attr { + ast::Meta::CfgMeta(attr) => { + if let Some(cfg_predicate) = attr.cfg_predicate() { + let cfg_expr = CfgExpr::parse_from_ast(cfg_predicate); if cfg_options().check(&cfg_expr) == Some(false) { return ControlFlow::Break(ItemIsCfgedOut); } strip_current_attr = true; - } else if path.segments.len() != 1 - || !is_item_tree_filtered_attr(path.segments[0].text()) - { - strip_current_attr = should_strip_attr(); } } - Meta::Path { path } => { - if path.segments.len() != 1 - || !is_item_tree_filtered_attr(path.segments[0].text()) + _ => { + if attr + .path() + .as_one_segment() + .is_none_or(|name| !is_item_tree_filtered_attr(&name)) { strip_current_attr = should_strip_attr(); } @@ -188,12 +175,11 @@ fn macro_input_callback( if !strip_current_attr { attrs[attrs_idx] .expanded_attrs - .push(ExpandedAttrToProcess { range }); + .push(ExpandedAttrToProcess { attr }); } ControlFlow::Continue(()) - }, - ); + }); attrs_idx = 0; if strip_current_item.is_some() { @@ -248,7 +234,7 @@ fn macro_input_callback( }; match ast_attr.next_expanded_attr { NextExpandedAttrState::NotStarted => { - if token_range.start() >= expanded_attr.range.start() { + if token_range.start() >= expanded_attr.attr.syntax().text_range().start() { // We started the next attribute. let mut insert_tokens = Vec::with_capacity(3); insert_tokens.push(tt::Leaf::Punct(tt::Punct { @@ -278,7 +264,7 @@ fn macro_input_callback( } } NextExpandedAttrState::InTheMiddle => { - if token_range.start() >= expanded_attr.range.end() { + if token_range.start() >= expanded_attr.attr.syntax().text_range().end() { // Finished the current attribute. let insert_tokens = vec![tt::Leaf::Punct(tt::Punct { char: ']', @@ -329,12 +315,3 @@ pub(crate) fn attr_macro_input_to_token_tree( fixups.undo_info, ) } - -pub fn check_cfg_attr_value( - db: &dyn ExpandDatabase, - attr: &ast::TokenTree, - krate: Crate, -) -> Option { - let cfg_expr = CfgExpr::parse_from_ast(&mut TokenTreeChildren::new(attr).peekable()); - krate.cfg_options(db).check(&cfg_expr) -} diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 8a6b56d93226..8dddddfabb7a 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -11,7 +11,6 @@ AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, EagerExpander, EditionedFileId, ExpandError, ExpandResult, ExpandTo, FileRange, HirFileId, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, - attrs::Meta, builtin::pseudo_derive_attr_expansion, cfg_process::attr_macro_input_to_token_tree, declarative::DeclarativeMacroExpander, @@ -239,8 +238,15 @@ pub fn expand_speculative( MacroCallKind::Attr { censored_attr_ids: attr_ids, .. } => { if loc.def.is_attribute_derive() { // for pseudo-derive expansion we actually pass the attribute itself only - ast::Attr::cast(speculative_args.clone()).and_then(|attr| attr.token_tree()).map( - |token_tree| { + ast::Attr::cast(speculative_args.clone()) + .and_then(|attr| { + if let ast::Meta::TokenTreeMeta(meta) = attr.meta()? { + meta.token_tree() + } else { + None + } + }) + .map(|token_tree| { let mut tree = syntax_node_to_token_tree( token_tree.syntax(), span_map, @@ -250,26 +256,26 @@ pub fn expand_speculative( tree.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible); tree.set_top_subtree_delimiter_span(tt::DelimSpan::from_single(span)); tree - }, - ) + }) } else { // Attributes may have an input token tree, build the subtree and map for this as well // then try finding a token id for our token if it is inside this input subtree. let item = ast::Item::cast(speculative_args.clone())?; - let (_, _, _, meta) = + let (_, meta) = attr_ids.invoc_attr().find_attr_range_with_source(db, loc.krate, &item); - match meta { - Meta::TokenTree { tt, .. } => { - let mut attr_arg = syntax_bridge::syntax_node_to_token_tree( - tt.syntax(), - span_map, - span, - DocCommentDesugarMode::ProcMacro, - ); - attr_arg.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible); - Some(attr_arg) - } - _ => None, + if let ast::Meta::TokenTreeMeta(meta) = meta + && let Some(tt) = meta.token_tree() + { + let mut attr_arg = syntax_bridge::syntax_node_to_token_tree( + tt.syntax(), + span_map, + span, + DocCommentDesugarMode::ProcMacro, + ); + attr_arg.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible); + Some(attr_arg) + } else { + None } } } @@ -501,11 +507,11 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult { } MacroCallKind::Attr { ast_id, censored_attr_ids: attr_ids, .. } => { let node = ast_id.to_ptr(db).to_node(&root); - let range = attr_ids - .invoc_attr() - .find_attr_range_with_source(db, loc.krate, &node) - .3 - .path_range(); + let (_, attr) = attr_ids.invoc_attr().find_attr_range_with_source(db, loc.krate, &node); + let range = attr + .path() + .map(|path| path.syntax().text_range()) + .unwrap_or_else(|| attr.syntax().text_range()); let span = map.span_for_range(range); let is_derive = matches!(loc.def.kind, MacroDefKind::BuiltInAttr(_, expander) if expander.is_derive()); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs index 172641227599..4b2c6e73517b 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs @@ -6,7 +6,7 @@ use span::{Edition, Span, SyntaxContext}; use stdx::TupleExt; use syntax::{ - AstNode, AstToken, + AstNode, ast::{self, HasAttrs}, }; use syntax_bridge::DocCommentDesugarMode; @@ -15,7 +15,7 @@ use crate::{ AstId, ExpandError, ExpandErrorKind, ExpandResult, HirFileId, Lookup, MacroCallId, MacroCallStyle, - attrs::{Meta, expand_cfg_attr}, + attrs::{AstKeyValueMetaExt, AstPathExt, expand_cfg_attr}, db::ExpandDatabase, hygiene::{Transparency, apply_mark}, tt, @@ -92,11 +92,10 @@ pub(crate) fn expander( expand_cfg_attr( node.attrs(), || cfg_options.get_or_init(|| def_crate.cfg_options(db)), - |attr, _, _, _| { - if let Meta::NamedKeyValue { name: Some(name), value, .. } = attr - && name.text() == "rustc_macro_transparency" - && let Some(value) = value.and_then(ast::String::cast) - && let Ok(value) = value.value() + |attr, _| { + if let ast::Meta::KeyValueMeta(attr) = attr + && attr.path().is1("rustc_macro_transparency") + && let Some(value) = attr.value_string() { match &*value { "transparent" => ControlFlow::Break(Transparency::Transparent), diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index 4b2c75ed386e..8d42a24e2fae 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -58,7 +58,6 @@ }; pub use crate::{ - cfg_process::check_cfg_attr_value, files::{AstId, ErasedAstId, FileRange, InFile, InMacroFile, InRealFile}, prettify_macro_expansion_::prettify_macro_expansion, }; @@ -635,14 +634,12 @@ pub fn to_node(&self, db: &dyn ExpandDatabase) -> InFile { ast_id.with_value(ast_id.to_node(db).syntax().clone()) } MacroCallKind::Derive { ast_id, derive_attr_index, .. } => { - // FIXME: handle `cfg_attr` - let (attr, _, _, _) = derive_attr_index.find_attr_range(db, self.krate, *ast_id); + let (_, attr) = derive_attr_index.find_attr_range(db, self.krate, *ast_id); ast_id.with_value(attr.syntax().clone()) } MacroCallKind::Attr { ast_id, censored_attr_ids: attr_ids, .. } => { if self.def.is_attribute_derive() { - let (attr, _, _, _) = - attr_ids.invoc_attr().find_attr_range(db, self.krate, *ast_id); + let (_, attr) = attr_ids.invoc_attr().find_attr_range(db, self.krate, *ast_id); ast_id.with_value(attr.syntax().clone()) } else { ast_id.with_value(ast_id.to_node(db).syntax().clone()) @@ -770,11 +767,11 @@ pub fn original_call_range(self, db: &dyn ExpandDatabase, krate: Crate) -> FileR } MacroCallKind::Derive { ast_id, derive_attr_index, .. } => { // FIXME: should be the range of the macro name, not the whole derive - derive_attr_index.find_attr_range(db, krate, ast_id).2 + derive_attr_index.find_attr_range(db, krate, ast_id).1.syntax().text_range() } // FIXME: handle `cfg_attr` MacroCallKind::Attr { ast_id, censored_attr_ids: attr_ids, .. } => { - attr_ids.invoc_attr().find_attr_range(db, krate, ast_id).2 + attr_ids.invoc_attr().find_attr_range(db, krate, ast_id).1.syntax().text_range() } }; diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 89f3cfd14098..282990203598 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -1239,11 +1239,15 @@ fn emit_def_diagnostic_<'db>( ); } DefDiagnosticKind::InvalidDeriveTarget { ast, id } => { - let derive = id.find_attr_range(db, krate, *ast).3.path_range(); + let (_, attr) = id.find_attr_range(db, krate, *ast); + let derive = attr + .path() + .map(|path| path.syntax().text_range()) + .unwrap_or_else(|| attr.syntax().text_range()); acc.push(InvalidDeriveTarget { range: ast.with_value(derive) }.into()); } DefDiagnosticKind::MalformedDerive { ast, id } => { - let derive = id.find_attr_range(db, krate, *ast).2; + let derive = id.find_attr_range(db, krate, *ast).1.syntax().text_range(); acc.push(MalformedDerive { range: ast.with_value(derive) }.into()); } DefDiagnosticKind::MacroDefError { ast, message } => { @@ -1283,7 +1287,8 @@ fn precise_macro_call_location( ast_id.with_value(range) } MacroCallKind::Attr { ast_id, censored_attr_ids: attr_ids, .. } => { - let attr_range = attr_ids.invoc_attr().find_attr_range(db, krate, *ast_id).2; + let attr_range = + attr_ids.invoc_attr().find_attr_range(db, krate, *ast_id).1.syntax().text_range(); ast_id.with_value(attr_range) } } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 9a31a08ffb52..999616248591 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -24,6 +24,7 @@ }; use hir_expand::{ EditionedFileId, ExpandResult, FileRange, HirFileId, InMacroFile, MacroCallId, + attrs::AstPathExt, builtin::{BuiltinFnLikeExpander, EagerExpander}, db::ExpandDatabase, files::{FileRangeWrapper, HirFileRange, InRealFile}, @@ -298,14 +299,15 @@ pub fn lint_attrs( hir_expand::attrs::expand_cfg_attr::( extra_crate_attrs.chain(ast::attrs_including_inner(&item)), cfg_options, - |attr, _, _, _| { - let hir_expand::attrs::Meta::TokenTree { path, tt } = attr else { + |attr, _| { + let ast::Meta::TokenTreeMeta(attr) = attr else { return ControlFlow::Continue(()); }; - if path.segments.len() != 1 { + let (Some(segment), Some(tt)) = (attr.path().as_one_segment(), attr.token_tree()) + else { return ControlFlow::Continue(()); - } - let lint_attr = match path.segments[0].text() { + }; + let lint_attr = match &*segment { "allow" => LintAttr::Allow, "expect" => LintAttr::Expect, "warn" => LintAttr::Warn, @@ -554,17 +556,6 @@ pub fn expand_macro_call(&self, macro_call: &ast::MacroCall) -> Option Option { - let file_id = self.find_file(attr.syntax()).file_id; - let krate = match file_id { - HirFileId::FileId(file_id) => { - self.file_to_module_defs(file_id.file_id(self.db)).next()?.krate(self.db).id - } - HirFileId::MacroFile(macro_file) => self.db.lookup_intern_macro_call(macro_file).krate, - }; - hir_expand::check_cfg_attr_value(self.db, attr, krate) - } - /// Expands the macro if it isn't one of the built-in ones that expand to custom syntax or dummy /// expansions. pub fn expand_allowed_builtins( @@ -608,8 +599,8 @@ pub fn expand_attr_macro(&self, item: &ast::Item) -> Option Option { - let adt = attr.syntax().parent().and_then(ast::Adt::cast)?; + pub fn expand_derive_as_pseudo_attr_macro(&self, attr: &ast::Meta) -> Option { + let adt = attr.parent_attr()?.syntax().parent().and_then(ast::Adt::cast)?; let src = self.wrap_node_infile(attr.clone()); let call_id = self.with_ctx(|ctx| { ctx.attr_to_derive_macro_call(src.with_value(&adt), src).map(|(_, it, _)| it) @@ -617,7 +608,7 @@ pub fn expand_derive_as_pseudo_attr_macro(&self, attr: &ast::Attr) -> Option Option>> { + pub fn resolve_derive_macro(&self, attr: &ast::Meta) -> Option>> { let calls = self.derive_macro_calls(attr)?; self.with_ctx(|ctx| { Some( @@ -644,7 +635,7 @@ pub fn resolve_derive_macro(&self, attr: &ast::Attr) -> Option pub fn expand_derive_macro( &self, - attr: &ast::Attr, + attr: &ast::Meta, ) -> Option>>> { let res: Vec<_> = self .derive_macro_calls(attr)? @@ -662,9 +653,9 @@ pub fn expand_derive_macro( fn derive_macro_calls( &self, - attr: &ast::Attr, + attr: &ast::Meta, ) -> Option>>> { - let adt = attr.syntax().parent().and_then(ast::Adt::cast)?; + let adt = attr.parent_attr()?.syntax().parent().and_then(ast::Adt::cast)?; let file_id = self.find_file(adt.syntax()).file_id; let adt = InFile::new(file_id, &adt); let src = InFile::new(file_id, attr.clone()); @@ -773,7 +764,11 @@ pub fn speculative_expand_derive_as_pseudo_attr_macro( let attr = self.wrap_node_infile(actual_macro_call.clone()); let adt = actual_macro_call.syntax().parent().and_then(ast::Adt::cast)?; let macro_call_id = self.with_ctx(|ctx| { - ctx.attr_to_derive_macro_call(attr.with_value(&adt), attr).map(|(_, it, _)| it) + ctx.attr_to_derive_macro_call( + attr.with_value(&adt), + attr.with_value(attr.value.meta()?), + ) + .map(|(_, it, _)| it) })?; hir_expand::db::expand_speculative( self.db, @@ -1328,7 +1323,7 @@ fn descend_into_macros_impl( // text ranges of the outer ones, and then all of the inner ones up // to the invoking attribute so that the inbetween is ignored. // FIXME: Should cfg_attr be handled differently? - let (attr, _, _, _) = attr_ids + let (attr, _) = attr_ids .invoc_attr() .find_attr_range_with_source(db, loc.krate, &item); let start = attr.syntax().text_range().start(); @@ -1435,7 +1430,7 @@ fn descend_into_macros_impl( let derive_call = ctx .attr_to_derive_macro_call( InFile::new(expansion, &adt), - InFile::new(expansion, attr.clone()), + InFile::new(expansion, meta.clone()), )? .1; diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs index f6d1bec5754c..babeb3591345 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs @@ -126,8 +126,7 @@ fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: Hi calls.for_each(|(attr_id, call_id, calls)| { // FIXME: Is this the right crate? let krate = call_id.lookup(db).krate; - // FIXME: Fix cfg_attr handling. - let (attr, _, _, _) = attr_id.find_attr_range_with_source(db, krate, &adt); + let (_, attr) = attr_id.find_attr_range_with_source(db, krate, &adt); res[keys::DERIVE_MACRO_CALL] .insert(AstPtr::new(&attr), (attr_id, call_id, calls.into())); }); diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index 59bccc22d8de..d932198b43a7 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -398,7 +398,7 @@ pub(super) fn label_ref_to_def( pub(super) fn attr_to_derive_macro_call( &mut self, item: InFile<&ast::Adt>, - src: InFile, + src: InFile, ) -> Option<(AttrId, MacroCallId, &[Option>])> { let map = self.dyn_map(item)?; map[keys::DERIVE_MACRO_CALL] @@ -423,6 +423,7 @@ impl Iterator< let dyn_map = &map[keys::DERIVE_MACRO_CALL]; adt.value .attrs() + .flat_map(|attr| attr.skip_cfg_attrs()) .filter_map(move |attr| dyn_map.get(&AstPtr::new(&attr))) .map(|&(attr_id, call_id, ref ids)| (attr_id, call_id, &**ids)) }) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs index e022a27e519a..fccc04770e89 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs @@ -279,7 +279,7 @@ fn todo_fn(f: &ast::Fn, config: &AssistConfig) -> ast::Fn { } fn cfg_attrs(node: &impl HasAttrs) -> impl Iterator { - node.attrs().filter(|attr| attr.as_simple_call().is_some_and(|(name, _arg)| name == "cfg")) + node.attrs().filter(|attr| matches!(attr.meta(), Some(ast::Meta::CfgMeta(_)))) } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs index 3ef68f06e499..7aeb5e339696 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs @@ -68,9 +68,11 @@ pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt ], ); - let delimiter = derive - .meta() - .expect("make::attr_outer was expected to have Meta") + let meta = derive.meta().expect("make::attr_outer was expected to have Meta"); + let ast::Meta::TokenTreeMeta(meta) = meta else { + unreachable!("make::attr_outer was passed a token tree meta"); + }; + let delimiter = meta .token_tree() .expect("failed to get token tree out of Meta") .r_paren_token() diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_single_field_struct_from.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_single_field_struct_from.rs index 2fc2b9efe81f..7746cdc068a1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_single_field_struct_from.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_single_field_struct_from.rs @@ -121,9 +121,8 @@ pub(crate) fn generate_single_field_struct_from( ) .indent_with_mapping(1.into(), &make); - let cfg_attrs = strukt - .attrs() - .filter(|attr| attr.as_simple_call().is_some_and(|(name, _arg)| name == "cfg")); + let cfg_attrs = + strukt.attrs().filter(|attr| matches!(attr.meta(), Some(ast::Meta::CfgMeta(_)))); let impl_ = make.impl_trait( cfg_attrs, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index 04c9d8e54de5..5e595218f6b1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -64,9 +64,10 @@ pub(crate) fn replace_derive_with_manual_impl( .filter_map(|attr| attr.path()) .collect::>(); - let adt = value.parent().and_then(ast::Adt::cast)?; - let attr = ast::Attr::cast(value)?; - let args = attr.token_tree()?; + let attr = ast::Meta::cast(value)?.parent_attr()?; + let adt = attr.syntax().parent().and_then(ast::Adt::cast)?; + let ast::Meta::TokenTreeMeta(meta) = attr.meta()? else { return None }; + let args = meta.token_tree()?; let current_module = ctx.sema.scope(adt.syntax())?.module(); let current_crate = current_module.krate(ctx.db()); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs index 36df4af31d5e..3b8988db7aae 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs @@ -19,7 +19,7 @@ // ``` // -> // ``` -// #[cfg_attr($0, derive(Debug))] +// #[cfg_attr(${0:cfg}, derive(Debug))] // struct S { // field: i32 // } @@ -147,12 +147,15 @@ pub(crate) fn wrap_unwrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>) - } }?; match option { - WrapUnwrapOption::WrapAttr(attrs) => match &attrs[..] { - [attr] if attr.simple_name().as_deref() == Some("cfg_attr") => { - unwrap_cfg_attr(acc, attrs.into_iter().next().unwrap()) + WrapUnwrapOption::WrapAttr(attrs) => { + if let [attr] = &attrs[..] + && let Some(ast::Meta::CfgAttrMeta(meta)) = attr.meta() + { + unwrap_cfg_attr(acc, meta) + } else { + wrap_cfg_attrs(acc, ctx, attrs) } - _ => wrap_cfg_attrs(acc, ctx, attrs), - }, + } WrapUnwrapOption::WrapDerive { derive, attr } => wrap_derive(acc, ctx, attr, derive), } } @@ -164,7 +167,8 @@ fn wrap_derive( derive_element: TextRange, ) -> Option<()> { let range = attr.syntax().text_range(); - let token_tree = attr.token_tree()?; + let ast::Meta::TokenTreeMeta(meta) = attr.meta()? else { return None }; + let token_tree = meta.token_tree()?; let mut path_text = String::new(); let mut cfg_derive_tokens = Vec::new(); @@ -193,20 +197,15 @@ fn wrap_derive( let new_derive = make.attr_outer( make.meta_token_tree(make.ident_path("derive"), make.token_tree(T!['('], new_derive)), ); - let meta = make.meta_token_tree( - make.ident_path("cfg_attr"), - make.token_tree( - T!['('], - vec![ - NodeOrToken::Token(make.token(T![,])), - NodeOrToken::Token(make.whitespace(" ")), - NodeOrToken::Token(make.ident("derive")), - NodeOrToken::Node(make.token_tree(T!['('], cfg_derive_tokens)), - ], - ), + let meta = make.cfg_attr_meta( + make.cfg_flag("cfg"), + [make.meta_token_tree( + make.ident_path("derive"), + make.token_tree(T!['('], cfg_derive_tokens), + )], ); - let cfg_attr = make.attr_outer(meta); + let cfg_attr = make.attr_outer(meta.clone().into()); editor.replace_with_many( attr.syntax(), vec![ @@ -217,11 +216,10 @@ fn wrap_derive( ); if let Some(snippet_cap) = ctx.config.snippet_cap - && let Some(first_meta) = - cfg_attr.meta().and_then(|meta| meta.token_tree()).and_then(|tt| tt.l_paren_token()) + && let Some(cfg_predicate) = meta.cfg_predicate() { - let tabstop = edit.make_tabstop_after(snippet_cap); - editor.add_annotation(first_meta, tabstop); + let tabstop = edit.make_placeholder_snippet(snippet_cap); + editor.add_annotation(cfg_predicate.syntax(), tabstop); } editor.add_mappings(make.finish_with_mappings()); @@ -236,58 +234,29 @@ fn wrap_derive( ); Some(()) } + fn wrap_cfg_attrs(acc: &mut Assists, ctx: &AssistContext<'_>, attrs: Vec) -> Option<()> { let (first_attr, last_attr) = (attrs.first()?, attrs.last()?); let range = first_attr.syntax().text_range().cover(last_attr.syntax().text_range()); - let path_attrs = - attrs.iter().map(|attr| Some((attr.path()?, attr.clone()))).collect::>>()?; let handle_source_change = |edit: &mut SourceChangeBuilder| { let make = SyntaxFactory::with_mappings(); let mut editor = edit.make_editor(first_attr.syntax()); - let mut raw_tokens = vec![]; - for (path, attr) in path_attrs { - raw_tokens.extend([ - NodeOrToken::Token(make.token(T![,])), - NodeOrToken::Token(make.whitespace(" ")), - ]); - path.syntax().descendants_with_tokens().for_each(|it| { - if let NodeOrToken::Token(token) = it { - raw_tokens.push(NodeOrToken::Token(token)); - } - }); - if let Some(meta) = attr.meta() { - if let (Some(eq), Some(expr)) = (meta.eq_token(), meta.expr()) { - raw_tokens.push(NodeOrToken::Token(make.whitespace(" "))); - raw_tokens.push(NodeOrToken::Token(eq)); - raw_tokens.push(NodeOrToken::Token(make.whitespace(" "))); - - expr.syntax().descendants_with_tokens().for_each(|it| { - if let NodeOrToken::Token(token) = it { - raw_tokens.push(NodeOrToken::Token(token)); - } - }); - } else if let Some(tt) = meta.token_tree() { - raw_tokens.extend(tt.token_trees_and_tokens()); - } - } - } let meta = - make.meta_token_tree(make.ident_path("cfg_attr"), make.token_tree(T!['('], raw_tokens)); + make.cfg_attr_meta(make.cfg_flag("cfg"), attrs.iter().filter_map(|attr| attr.meta())); let cfg_attr = if first_attr.excl_token().is_some() { - make.attr_inner(meta) + make.attr_inner(meta.clone().into()) } else { - make.attr_outer(meta) + make.attr_outer(meta.clone().into()) }; let syntax_range = first_attr.syntax().clone().into()..=last_attr.syntax().clone().into(); editor.replace_all(syntax_range, vec![cfg_attr.syntax().clone().into()]); if let Some(snippet_cap) = ctx.config.snippet_cap - && let Some(first_meta) = - cfg_attr.meta().and_then(|meta| meta.token_tree()).and_then(|tt| tt.l_paren_token()) + && let Some(cfg_flag) = meta.cfg_predicate() { - let tabstop = edit.make_tabstop_after(snippet_cap); - editor.add_annotation(first_meta, tabstop); + let tabstop = edit.make_placeholder_snippet(snippet_cap); + editor.add_annotation(cfg_flag.syntax(), tabstop); } editor.add_mappings(make.finish_with_mappings()); @@ -301,66 +270,28 @@ fn wrap_cfg_attrs(acc: &mut Assists, ctx: &AssistContext<'_>, attrs: Vec Option<()> { - let range = attr.syntax().text_range(); - let meta = attr.meta()?; - let meta_tt = meta.token_tree()?; - let mut inner_attrs = Vec::with_capacity(1); - let mut found_comma = false; - let mut iter = meta_tt.token_trees_and_tokens().skip(1).peekable(); - while let Some(tt) = iter.next() { - if let NodeOrToken::Token(token) = &tt { - if token.kind() == T![')'] { - break; + +fn unwrap_cfg_attr(acc: &mut Assists, meta: ast::CfgAttrMeta) -> Option<()> { + let top_attr = ast::Meta::from(meta.clone()).parent_attr()?; + let range = top_attr.syntax().text_range(); + let inner_attrs = meta + .metas() + .map(|meta| { + if top_attr.excl_token().is_some() { + make::attr_inner(meta) + } else { + make::attr_outer(meta) } - if token.kind() == T![,] { - found_comma = true; - continue; - } - } - if !found_comma { - continue; - } - let Some(attr_name) = tt.into_token().and_then(|token| { - if token.kind() == T![ident] { Some(make::ext::ident_path(token.text())) } else { None } - }) else { - continue; - }; - let next_tt = iter.next()?; - let meta = match next_tt { - NodeOrToken::Node(tt) => make::meta_token_tree(attr_name, tt), - NodeOrToken::Token(token) if token.kind() == T![,] || token.kind() == T![')'] => { - make::meta_path(attr_name) - } - NodeOrToken::Token(token) => { - let equals = algo::skip_trivia_token(token, syntax::Direction::Next)?; - if equals.kind() != T![=] { - return None; - } - let expr_token = - algo::skip_trivia_token(equals.next_token()?, syntax::Direction::Next) - .and_then(|it| { - if it.kind().is_literal() { - Some(make::expr_literal(it.text())) - } else { - None - } - })?; - make::meta_expr(attr_name, ast::Expr::Literal(expr_token)) - } - }; - if attr.excl_token().is_some() { - inner_attrs.push(make::attr_inner(meta)); - } else { - inner_attrs.push(make::attr_outer(meta)); - } - } + }) + .collect::>(); if inner_attrs.is_empty() { return None; } let handle_source_change = |f: &mut SourceChangeBuilder| { - let inner_attrs = - inner_attrs.iter().map(|it| it.to_string()).join(&format!("\n{}", attr.indent_level())); + let inner_attrs = inner_attrs + .iter() + .map(|it| it.to_string()) + .join(&format!("\n{}", top_attr.indent_level())); f.replace(range, inner_attrs); }; acc.add( @@ -388,7 +319,7 @@ pub struct Test { } "#, r#" - #[cfg_attr($0, derive(Debug))] + #[cfg_attr(${0:cfg}, derive(Debug))] pub struct Test { test: u32, } @@ -422,7 +353,7 @@ pub struct Test { "#, r#" pub struct Test { - #[cfg_attr($0, foo)] + #[cfg_attr(${0:cfg}, foo)] test: u32, } "#, @@ -456,7 +387,7 @@ pub struct Test { r#" pub struct Test { #[other_attr] - #[cfg_attr($0, foo, bar)] + #[cfg_attr(${0:cfg}, foo, bar)] #[other_attr] test: u32, } @@ -491,7 +422,7 @@ pub struct Test { "#, r#" pub struct Test { - #[cfg_attr($0, foo = "bar")] + #[cfg_attr(${0:cfg}, foo = "bar")] test: u32, } "#, @@ -520,7 +451,7 @@ fn inner_attrs() { #![no_std$0] "#, r#" - #![cfg_attr($0, no_std)] + #![cfg_attr(${0:cfg}, no_std)] "#, ); check_assist( @@ -545,7 +476,7 @@ pub struct Test { "#, r#" #[derive( Clone, Copy)] - #[cfg_attr($0, derive(Debug))] + #[cfg_attr(${0:cfg}, derive(Debug))] pub struct Test { test: u32, } @@ -561,7 +492,7 @@ pub struct Test { "#, r#" #[derive(Clone, Copy)] - #[cfg_attr($0, derive(Debug))] + #[cfg_attr(${0:cfg}, derive(Debug))] pub struct Test { test: u32, } @@ -580,7 +511,7 @@ pub struct Test { "#, r#" #[derive( Clone, Copy)] - #[cfg_attr($0, derive(std::fmt::Debug))] + #[cfg_attr(${0:cfg}, derive(std::fmt::Debug))] pub struct Test { test: u32, } @@ -596,7 +527,7 @@ pub struct Test { "#, r#" #[derive(Clone, Copy)] - #[cfg_attr($0, derive(std::fmt::Debug))] + #[cfg_attr(${0:cfg}, derive(std::fmt::Debug))] pub struct Test { test: u32, } @@ -615,7 +546,7 @@ pub struct Test { "#, r#" #[derive(std::fmt::Debug, Clone)] - #[cfg_attr($0, derive(Copy))] + #[cfg_attr(${0:cfg}, derive(Copy))] pub struct Test { test: u32, } @@ -631,7 +562,7 @@ pub struct Test { "#, r#" #[derive(Clone, Copy)] - #[cfg_attr($0, derive(std::fmt::Debug))] + #[cfg_attr(${0:cfg}, derive(std::fmt::Debug))] pub struct Test { test: u32, } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 66d5cf834f17..a499607c1f71 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -3852,7 +3852,7 @@ struct S { } "#####, r#####" -#[cfg_attr($0, derive(Debug))] +#[cfg_attr(${0:cfg}, derive(Debug))] struct S { field: i32 } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index 3de8ec7f536c..896743342c1a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -598,9 +598,7 @@ fn generate_impl_text_inner( // Copy any cfg attrs from the original adt buf.push_str("\n\n"); - let cfg_attrs = adt - .attrs() - .filter(|attr| attr.as_simple_call().map(|(name, _arg)| name == "cfg").unwrap_or(false)); + let cfg_attrs = adt.attrs().filter(|attr| matches!(attr.meta(), Some(ast::Meta::CfgMeta(_)))); cfg_attrs.for_each(|attr| buf.push_str(&format!("{attr}\n"))); // `impl{generic_params} {trait_text} for {name}{generic_params.to_generic_args()}` @@ -740,8 +738,7 @@ fn generate_impl_inner( let ty = make::ty_path(make::ext::ident_path(&adt.name().unwrap().text())); - let cfg_attrs = - adt.attrs().filter(|attr| attr.as_simple_call().is_some_and(|(name, _arg)| name == "cfg")); + let cfg_attrs = adt.attrs().filter(|attr| matches!(attr.meta(), Some(ast::Meta::CfgMeta(_)))); match trait_ { Some(trait_) => make::impl_trait( cfg_attrs, @@ -811,8 +808,7 @@ fn generate_impl_inner_with_factory( let ty: ast::Type = make.ty_path(make.ident_path(&adt.name().unwrap().text())).into(); - let cfg_attrs = - adt.attrs().filter(|attr| attr.as_simple_call().is_some_and(|(name, _arg)| name == "cfg")); + let cfg_attrs = adt.attrs().filter(|attr| matches!(attr.meta(), Some(ast::Meta::CfgMeta(_)))); match trait_ { Some(trait_) => make.impl_trait( cfg_attrs, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs index 4a94383ff4cb..9a09e9bd4a20 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs @@ -756,7 +756,7 @@ pub(super) fn complete_name_ref( match &path_ctx.kind { PathKind::Expr { expr_ctx } => { expr::complete_expr_path(acc, ctx, path_ctx, expr_ctx); - expr::complete_expr(acc, ctx); + expr::complete_expr(acc, ctx, path_ctx); dot::complete_undotted_self(acc, ctx, path_ctx, expr_ctx); item_list::complete_item_list_in_expr(acc, ctx, path_ctx, expr_ctx); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs index 20776f6c49f6..da1e664f961c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs @@ -30,6 +30,7 @@ mod macro_use; mod repr; +pub(crate) use self::cfg::complete_cfg; pub(crate) use self::derive::complete_derive_path; /// Complete inputs to known builtin attributes as well as derive attributes @@ -37,7 +38,7 @@ pub(crate) fn complete_known_attribute_input( acc: &mut Completions, ctx: &CompletionContext<'_>, &colon_prefix: &bool, - fake_attribute_under_caret: &ast::Attr, + fake_attribute_under_caret: &ast::TokenTreeMeta, extern_crate: Option<&ast::ExternCrate>, ) -> Option<()> { let attribute = fake_attribute_under_caret; @@ -70,7 +71,6 @@ pub(crate) fn complete_known_attribute_input( lint::complete_lint(acc, ctx, colon_prefix, &existing_lints, &lints); } - ["cfg"] | ["cfg_attr"] => cfg::complete_cfg(acc, ctx), ["macro_use"] => macro_use::complete_macro_use( acc, ctx, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index 8c532e0f4d04..99ca55bdaf74 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -451,7 +451,11 @@ pub(crate) fn complete_expr_path( } } -pub(crate) fn complete_expr(acc: &mut Completions, ctx: &CompletionContext<'_>) { +pub(crate) fn complete_expr( + acc: &mut Completions, + ctx: &CompletionContext<'_>, + PathCompletionCtx { qualified, .. }: &PathCompletionCtx<'_>, +) { let _p = tracing::info_span!("complete_expr").entered(); if !ctx.config.enable_term_search { @@ -462,6 +466,10 @@ pub(crate) fn complete_expr(acc: &mut Completions, ctx: &CompletionContext<'_>) return; } + if !matches!(qualified, Qualified::No) { + return; + } + if let Some(ty) = &ctx.expected_type { // Ignore unit types as they are not very interesting if ty.is_unit() || ty.is_unknown() { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs index 413830904aa8..2cf87baf3307 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs @@ -133,7 +133,8 @@ pub(crate) fn import_on_the_fly_path( let potential_import_name = import_name(ctx); let qualifier = match qualified { Qualified::With { path, .. } => Some(path.clone()), - _ => None, + Qualified::TypeAnchor { .. } => return None, + Qualified::No | Qualified::Absolute => None, }; let import_assets = import_assets_for_path( ctx, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs index ae3f71760744..485e5f0cafd7 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs @@ -408,9 +408,11 @@ pub(crate) enum CompletionAnalysis<'db> { /// Set if we are currently completing in an unexpanded attribute, this usually implies a builtin attribute like `allow($0)` UnexpandedAttrTT { colon_prefix: bool, - fake_attribute_under_caret: Option, + fake_attribute_under_caret: Option, extern_crate: Option, }, + /// Set if we are inside the predicate of a #[cfg] or #[cfg_attr]. + CfgPredicate, MacroSegment, } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs index d8f160c1005e..2a293313f2c9 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs @@ -284,9 +284,12 @@ fn expand( }; // Expand pseudo-derive expansion aka `derive(Debug$0)` - if let Some((orig_attr, spec_attr)) = attrs { + if let Some((orig_attr, spec_attr)) = attrs + && let Some(orig_meta) = orig_attr.meta() + { + // FIXME: Support speculative expansion with `cfg_attr`. if let (Some(actual_expansion), Some((fake_expansion, fake_mapped_tokens))) = ( - sema.expand_derive_as_pseudo_attr_macro(&orig_attr), + sema.expand_derive_as_pseudo_attr_macro(&orig_meta), sema.speculative_expand_derive_as_pseudo_attr_macro( &orig_attr, &spec_attr, @@ -463,7 +466,9 @@ fn analyze<'db>( } // Overwrite the path kind for derives - if let Some((original_file, file_with_fake_ident, offset, origin_attr)) = derive_ctx { + if let Some((original_file, file_with_fake_ident, offset, origin_attr)) = derive_ctx + && let Some(origin_meta) = origin_attr.meta() + { if let Some(ast::NameLike::NameRef(name_ref)) = find_node_at_offset(&file_with_fake_ident, offset) { @@ -473,7 +478,7 @@ fn analyze<'db>( if let NameRefKind::Path(path_ctx) = &mut nameref_ctx.kind { path_ctx.kind = PathKind::Derive { existing_derives: sema - .resolve_derive_macro(&origin_attr) + .resolve_derive_macro(&origin_meta) .into_iter() .flatten() .flatten() @@ -498,7 +503,7 @@ fn analyze<'db>( let token = syntax::algo::skip_trivia_token(self_token.clone(), Direction::Prev)?; let p = token.parent()?; if p.kind() == SyntaxKind::TOKEN_TREE - && p.ancestors().any(|it| it.kind() == SyntaxKind::META) + && p.ancestors().any(|it| it.kind() == SyntaxKind::TOKEN_TREE_META) { let colon_prefix = previous_non_trivia_token(self_token.clone()) .is_some_and(|it| T![:] == it.kind()); @@ -506,7 +511,7 @@ fn analyze<'db>( CompletionAnalysis::UnexpandedAttrTT { fake_attribute_under_caret: fake_ident_token .parent_ancestors() - .find_map(ast::Attr::cast), + .find_map(ast::TokenTreeMeta::cast), colon_prefix, extern_crate: p.ancestors().find_map(ast::ExternCrate::cast), } @@ -525,6 +530,13 @@ fn analyze<'db>( } else { return None; } + } else if find_node_at_offset::( + &speculative_file, + speculative_offset, + ) + .is_some() + { + CompletionAnalysis::CfgPredicate } else { return None; } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs index 69ca2af7721b..3867e65ae57e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs @@ -263,6 +263,7 @@ pub fn completions( extern_crate.as_ref(), ); } + CompletionAnalysis::CfgPredicate => completions::attribute::complete_cfg(acc, ctx), CompletionAnalysis::MacroSegment => { completions::macro_def::complete_macro_segment(acc, ctx); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index b94644199138..b6da6fba638f 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -2211,7 +2211,6 @@ fn bb()-> &'static aa { } "#, expect![[r#" - ex bb() [type] fn from_bytes(…) fn(&[u8]) -> &aa [type_could_unify] "#]], ); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index 8e50ef10eca6..4a5983097a12 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -1030,8 +1030,6 @@ fn main() { "#, expect![[r#" fn test() fn() -> Zulu - ex Zulu - ex Zulu::test() "#]], ); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs index d7db896679df..5391e6c9ce6e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs @@ -1242,6 +1242,39 @@ impl Bar for Foo { ); } +#[test] +fn no_flyimports_type_anchor() { + check( + r#" +mod m { + pub fn foo() {} +} +struct Bar; +trait Foo {} +impl Foo for Bar {} +fn main() { + ::foo$0 +} + "#, + expect![[r#""#]], + ); + + check( + r#" +mod m { + pub fn foo() {} +} +struct Bar; +trait Foo {} +impl Foo for Bar {} +fn main() { + ::foo$0 +} + "#, + expect![[r#""#]], + ); +} + #[test] fn no_inherent_candidates_proposed() { check( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs index b82b23541c5c..55059a4035e7 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs @@ -896,9 +896,6 @@ fn bar() -> Bar { "#, expect![[r#" fn foo() (as Foo) fn() -> Self - ex Bar - ex Bar::foo() - ex bar() "#]], ); } @@ -926,9 +923,6 @@ fn bar() -> Bar { expect![[r#" fn bar() fn() fn foo() (as Foo) fn() -> Self - ex Bar - ex Bar::foo() - ex bar() "#]], ); } @@ -955,9 +949,6 @@ fn bar() -> Bar { "#, expect![[r#" fn foo() (as Foo) fn() -> Self - ex Bar - ex Bar::foo() - ex bar() "#]], ); } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index 9e6d58600888..c25feceb4157 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -1,4 +1,4 @@ -//! Generated by `cargo codegen lint-definitions`, do not edit by hand. +//! Generated by `cargo xtask codegen lint-definitions`, do not edit by hand. use span::Edition; @@ -20,8 +20,8 @@ pub struct LintGroup { pub const DEFAULT_LINTS: &[Lint] = &[ Lint { - label: "abi_unsupported_vector_types", - description: r##"this function call or definition uses a vector type which is not enabled"##, + label: "aarch64_softfloat_neon", + description: r##"detects code that could be affected by ABI issues on aarch64 softfloat targets"##, default_severity: Severity::Warning, warn_since: None, deny_since: None, @@ -40,10 +40,24 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "ambiguous_derive_helpers", + description: r##"detects derive helper attributes that are ambiguous with built-in attributes"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, + Lint { + label: "ambiguous_glob_imported_traits", + description: r##"detects uses of ambiguously glob imported traits"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "ambiguous_glob_imports", description: r##"detects certain glob imports that require reporting an ambiguity error"##, - default_severity: Severity::Warning, + default_severity: Severity::Error, warn_since: None, deny_since: None, }, @@ -54,6 +68,13 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "ambiguous_import_visibilities", + description: r##"detects certain glob imports that require reporting an ambiguity error"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "ambiguous_negative_literals", description: r##"ambiguous negative literals operations"##, @@ -61,6 +82,13 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "ambiguous_panic_imports", + description: r##"detects ambiguous core and std panic imports"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "ambiguous_wide_pointer_comparisons", description: r##"detects ambiguous wide pointer comparisons"##, @@ -145,13 +173,6 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, - Lint { - label: "cenum_impl_drop_cast", - description: r##"a C-like enum implementing Drop is cast"##, - default_severity: Severity::Error, - warn_since: None, - deny_since: None, - }, Lint { label: "clashing_extern_declarations", description: r##"detects when an extern fn has been declared with the same name but different types"##, @@ -194,6 +215,13 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "const_item_interior_mutations", + description: r##"checks for calls which mutates a interior mutable const-item"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "const_item_mutation", description: r##"detects attempts to mutate a `const` item"##, @@ -201,6 +229,20 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "dangerous_implicit_autorefs", + description: r##"implicit reference to a dereference of a raw pointer"##, + default_severity: Severity::Error, + warn_since: None, + deny_since: None, + }, + Lint { + label: "dangling_pointers_from_locals", + description: r##"detects returning a pointer from a local variable"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "dangling_pointers_from_temporaries", description: r##"detects getting a pointer from a temporary"##, @@ -215,10 +257,17 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "default_overrides_default_fields", + description: r##"detect `Default` impl that should use the type's default field values"##, + default_severity: Severity::Error, + warn_since: None, + deny_since: None, + }, Lint { label: "dependency_on_unit_never_type_fallback", description: r##"never type fallback affecting unsafe function calls"##, - default_severity: Severity::Warning, + default_severity: Severity::Error, warn_since: None, deny_since: None, }, @@ -252,14 +301,21 @@ pub struct LintGroup { }, Lint { label: "deref_into_dyn_supertrait", - description: r##"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future"##, - default_severity: Severity::Warning, + description: r##"`Deref` implementation with a supertrait trait object for output is shadowed by trait upcasting"##, + default_severity: Severity::Allow, warn_since: None, deny_since: None, }, Lint { label: "deref_nullptr", description: r##"detects when an null pointer is dereferenced"##, + default_severity: Severity::Error, + warn_since: None, + deny_since: None, + }, + Lint { + label: "double_negations", + description: r##"detects expressions of the form `--x`"##, default_severity: Severity::Warning, warn_since: None, deny_since: None, @@ -285,6 +341,13 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "duplicate_features", + description: r##"duplicate features found in crate-level `#[feature]` directives"##, + default_severity: Severity::Error, + warn_since: None, + deny_since: None, + }, Lint { label: "duplicate_macro_attributes", description: r##"duplicated attribute"##, @@ -320,13 +383,6 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, - Lint { - label: "elided_named_lifetimes", - description: r##"detects when an elided lifetime gets resolved to be `'static` or some named parameter"##, - default_severity: Severity::Warning, - warn_since: None, - deny_since: None, - }, Lint { label: "ellipsis_inclusive_range_patterns", description: r##"`...` range patterns are deprecated"##, @@ -397,6 +453,13 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "function_casts_as_integer", + description: r##"casting a function into an integer"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "function_item_references", description: r##"suggest casting to a function pointer when attempting to take references to function items"##, @@ -442,7 +505,7 @@ pub struct LintGroup { Lint { label: "impl_trait_redundant_captures", description: r##"redundant precise-capturing `use<...>` syntax on an `impl Trait`"##, - default_severity: Severity::Warning, + default_severity: Severity::Allow, warn_since: None, deny_since: None, }, @@ -460,6 +523,13 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "improper_gpu_kernel_arg", + description: r##"GPU kernel entry points have a limited ABI"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "incomplete_features", description: r##"incomplete features that may function improperly in some or all cases"##, @@ -481,9 +551,30 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "inline_always_mismatching_target_features", + description: r##"detects when a function annotated with `#[inline(always)]` and `#[target_feature(enable = "..")]` is inlined into a caller without the required target feature"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "inline_no_sanitize", - description: r##"detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`"##, + description: r##"detects incompatible use of `#[inline(always)]` and `#[sanitize(... = "off")]`"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, + Lint { + label: "integer_to_ptr_transmutes", + description: r##"detects integer to pointer transmutes"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, + Lint { + label: "internal_eq_trait_method_impls", + description: r##"manual implementation of the internal `Eq::assert_receiver_is_total_eq` method"##, default_severity: Severity::Warning, warn_since: None, deny_since: None, @@ -505,7 +596,7 @@ pub struct LintGroup { Lint { label: "invalid_doc_attributes", description: r##"detects invalid `#[doc(...)]` attributes"##, - default_severity: Severity::Error, + default_severity: Severity::Warning, warn_since: None, deny_since: None, }, @@ -526,7 +617,7 @@ pub struct LintGroup { Lint { label: "invalid_macro_export_arguments", description: r##""invalid_parameter" isn't a valid argument for `#[macro_export]`"##, - default_severity: Severity::Warning, + default_severity: Severity::Error, warn_since: None, deny_since: None, }, @@ -537,6 +628,13 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "invalid_null_arguments", + description: r##"invalid null pointer in arguments"##, + default_severity: Severity::Error, + warn_since: None, + deny_since: None, + }, Lint { label: "invalid_reference_casting", description: r##"casts of `&T` to `&mut T` without interior mutability"##, @@ -596,7 +694,7 @@ pub struct LintGroup { Lint { label: "legacy_derive_helpers", description: r##"detects derive helper attributes that are used before they are introduced"##, - default_severity: Severity::Warning, + default_severity: Severity::Error, warn_since: None, deny_since: None, }, @@ -614,6 +712,20 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "linker_info", + description: r##"linker warnings known to be informational-only and not indicative of a problem"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "linker_messages", + description: r##"warnings emitted at runtime by the target-specific linker program"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, Lint { label: "long_running_const_eval", description: r##"detects long const eval operations"##, @@ -642,6 +754,20 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "malformed_diagnostic_attributes", + description: r##"detects malformed diagnostic attributes"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, + Lint { + label: "malformed_diagnostic_format_literals", + description: r##"detects diagnostic attribute with malformed diagnostic format literals"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "map_unit_fn", description: r##"`Iterator::map` call that discard the iterator's values"##, @@ -656,10 +782,24 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "mismatched_lifetime_syntaxes", + description: r##"detects when a lifetime uses different syntax between arguments and return values"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, + Lint { + label: "misplaced_diagnostic_attributes", + description: r##"detects diagnostic attributes that are placed on the wrong item"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "missing_abi", description: r##"No declared ABI for extern declaration"##, - default_severity: Severity::Allow, + default_severity: Severity::Warning, warn_since: None, deny_since: None, }, @@ -685,9 +825,9 @@ pub struct LintGroup { deny_since: None, }, Lint { - label: "missing_fragment_specifier", - description: r##"detects missing fragment specifiers in unused `macro_rules!` patterns"##, - default_severity: Severity::Error, + label: "missing_gpu_kernel_export_name", + description: r##"mangled gpu-kernel function"##, + default_severity: Severity::Warning, warn_since: None, deny_since: None, }, @@ -743,9 +883,9 @@ pub struct LintGroup { Lint { label: "never_type_fallback_flowing_into_unsafe", description: r##"never type fallback affecting unsafe function calls"##, - default_severity: Severity::Warning, + default_severity: Severity::Error, warn_since: None, - deny_since: Some(Edition::Edition2024), + deny_since: None, }, Lint { label: "no_mangle_const_items", @@ -838,17 +978,10 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, - Lint { - label: "order_dependent_trait_objects", - description: r##"trait-object types were treated as different depending on marker-trait order"##, - default_severity: Severity::Error, - warn_since: None, - deny_since: None, - }, Lint { label: "out_of_scope_macro_calls", description: r##"detects out of scope calls to `macro_rules` in key-value attributes"##, - default_severity: Severity::Warning, + default_severity: Severity::Error, warn_since: None, deny_since: None, }, @@ -901,13 +1034,6 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, - Lint { - label: "ptr_cast_add_auto_to_object", - description: r##"detects `as` casts from pointers to `dyn Trait` to pointers to `dyn Trait + Auto`"##, - default_severity: Severity::Warning, - warn_since: None, - deny_since: None, - }, Lint { label: "ptr_to_integer_transmute_in_consts", description: r##"detects pointer to integer transmutes in const functions and associated constants"##, @@ -965,8 +1091,29 @@ pub struct LintGroup { deny_since: None, }, Lint { - label: "repr_transparent_external_private_fields", + label: "repr_c_enums_larger_than_int", + description: r##"repr(C) enums with discriminant values that do not fit into a C int"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, + Lint { + label: "repr_transparent_non_zst_fields", description: r##"transparent type contains an external ZST that is marked #[non_exhaustive] or contains private fields"##, + default_severity: Severity::Error, + warn_since: None, + deny_since: None, + }, + Lint { + label: "resolving_to_items_shadowing_supertrait_items", + description: r##"detects when a supertrait item is shadowed by a subtrait item"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "rtsan_nonblocking_async", + description: r##"detects incompatible uses of `#[sanitize(realtime = "nonblocking")]` on async functions"##, default_severity: Severity::Warning, warn_since: None, deny_since: None, @@ -1030,7 +1177,14 @@ pub struct LintGroup { Lint { label: "semicolon_in_expressions_from_macros", description: r##"trailing semicolon in macro body used as expression"##, - default_severity: Severity::Warning, + default_severity: Severity::Error, + warn_since: None, + deny_since: None, + }, + Lint { + label: "shadowing_supertrait_items", + description: r##"detects when a supertrait item is shadowed by a subtrait item"##, + default_severity: Severity::Allow, warn_since: None, deny_since: None, }, @@ -1041,13 +1195,6 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, - Lint { - label: "soft_unstable", - description: r##"a feature gate that doesn't break dependent crates"##, - default_severity: Severity::Error, - warn_since: None, - deny_since: None, - }, Lint { label: "special_module_name", description: r##"module declarations for files with a special meaning"##, @@ -1064,7 +1211,7 @@ pub struct LintGroup { }, Lint { label: "static_mut_refs", - description: r##"shared references or mutable references of mutable static is discouraged"##, + description: r##"creating a shared reference to mutable static"##, default_severity: Severity::Warning, warn_since: None, deny_since: Some(Edition::Edition2024), @@ -1167,13 +1314,6 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, - Lint { - label: "undefined_naked_function_abi", - description: r##"undefined naked function ABI"##, - default_severity: Severity::Warning, - warn_since: None, - deny_since: None, - }, Lint { label: "undropped_manually_drops", description: r##"calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of it's inner value"##, @@ -1224,15 +1364,15 @@ pub struct LintGroup { deny_since: None, }, Lint { - label: "unknown_lints", - description: r##"unrecognized lint attribute"##, + label: "unknown_diagnostic_attributes", + description: r##"detects unknown diagnostic attributes"##, default_severity: Severity::Warning, warn_since: None, deny_since: None, }, Lint { - label: "unknown_or_malformed_diagnostic_attributes", - description: r##"unrecognized or malformed diagnostic attribute"##, + label: "unknown_lints", + description: r##"unrecognized lint attribute"##, default_severity: Severity::Warning, warn_since: None, deny_since: None, @@ -1251,6 +1391,20 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "unnecessary_transmutes", + description: r##"detects transmutes that can also be achieved by other operations"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, + Lint { + label: "unpredictable_function_pointer_comparisons", + description: r##"detects unpredictable function pointer comparisons"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "unqualified_local_imports", description: r##"`use` of a local item without leading `self::`, `super::`, or `crate::`"##, @@ -1258,6 +1412,13 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "unreachable_cfg_select_predicates", + description: r##"detects unreachable configuration predicates in the cfg_select macro"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "unreachable_code", description: r##"detects unreachable code paths"##, @@ -1322,8 +1483,8 @@ pub struct LintGroup { deny_since: None, }, Lint { - label: "unsupported_fn_ptr_calling_conventions", - description: r##"use of unsupported calling convention for function pointer"##, + label: "unsupported_calling_conventions", + description: r##"use of unsupported calling convention"##, default_severity: Severity::Warning, warn_since: None, deny_since: None, @@ -1489,6 +1650,13 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "unused_visibilities", + description: r##"detect visibility qualifiers on `const _` items"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "useless_deprecated", description: r##"detects deprecation attributes with no effect"##, @@ -1503,6 +1671,20 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "uses_power_alignment", + description: r##"Structs do not follow the power alignment rule under repr(C)"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, + Lint { + label: "varargs_without_pattern", + description: r##"detects usage of `...` arguments without a pattern in non-foreign items"##, + default_severity: Severity::Warning, + warn_since: None, + deny_since: None, + }, Lint { label: "variant_size_differences", description: r##"detects enums with widely varying variant sizes"##, @@ -1517,13 +1699,6 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, - Lint { - label: "wasm_c_abi", - description: r##"detects dependencies that are incompatible with the Wasm C ABI"##, - default_severity: Severity::Error, - warn_since: None, - deny_since: None, - }, Lint { label: "while_true", description: r##"suggest using `loop { }` instead of `while true { }`"##, @@ -1540,7 +1715,7 @@ pub struct LintGroup { }, Lint { label: "future_incompatible", - description: r##"lint group for: deref-into-dyn-supertrait, abi-unsupported-vector-types, ambiguous-associated-items, ambiguous-glob-imports, cenum-impl-drop-cast, coherence-leak-check, conflicting-repr-hints, const-evaluatable-unchecked, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, order-dependent-trait-objects, out-of-scope-macro-calls, patterns-in-fns-without-body, proc-macro-derive-resolution-fallback, ptr-cast-add-auto-to-object, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, self-constructor-from-outer-item, semicolon-in-expressions-from-macros, soft-unstable, uncovered-param-in-projection, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-fn-ptr-calling-conventions, wasm-c-abi"##, + description: r##"lint group for: internal-eq-trait-method-impls, aarch64-softfloat-neon, ambiguous-associated-items, ambiguous-derive-helpers, ambiguous-glob-imported-traits, ambiguous-glob-imports, ambiguous-import-visibilities, ambiguous-panic-imports, coherence-leak-check, conflicting-repr-hints, const-evaluatable-unchecked, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, invalid-macro-export-arguments, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, out-of-scope-macro-calls, patterns-in-fns-without-body, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-c-enums-larger-than-int, repr-transparent-non-zst-fields, self-constructor-from-outer-item, semicolon-in-expressions-from-macros, uncovered-param-in-projection, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, varargs-without-pattern"##, default_severity: Severity::Allow, warn_since: None, deny_since: None, @@ -1601,9 +1776,16 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, + Lint { + label: "unknown_or_malformed_diagnostic_attributes", + description: r##"lint group for: malformed-diagnostic-attributes, malformed-diagnostic-format-literals, misplaced-diagnostic-attributes, unknown-diagnostic-attributes"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, Lint { label: "unused", - description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-macro-rules, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons, map-unit-fn"##, + description: r##"lint group for: unused-imports, unused-variables, unused-visibilities, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-macro-rules, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons, map-unit-fn"##, default_severity: Severity::Allow, warn_since: None, deny_since: None, @@ -1631,44 +1813,45 @@ pub struct LintGroup { LintGroup { lint: Lint { label: "future_incompatible", - description: r##"lint group for: deref-into-dyn-supertrait, abi-unsupported-vector-types, ambiguous-associated-items, ambiguous-glob-imports, cenum-impl-drop-cast, coherence-leak-check, conflicting-repr-hints, const-evaluatable-unchecked, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, order-dependent-trait-objects, out-of-scope-macro-calls, patterns-in-fns-without-body, proc-macro-derive-resolution-fallback, ptr-cast-add-auto-to-object, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, self-constructor-from-outer-item, semicolon-in-expressions-from-macros, soft-unstable, uncovered-param-in-projection, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-fn-ptr-calling-conventions, wasm-c-abi"##, + description: r##"lint group for: internal-eq-trait-method-impls, aarch64-softfloat-neon, ambiguous-associated-items, ambiguous-derive-helpers, ambiguous-glob-imported-traits, ambiguous-glob-imports, ambiguous-import-visibilities, ambiguous-panic-imports, coherence-leak-check, conflicting-repr-hints, const-evaluatable-unchecked, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, invalid-macro-export-arguments, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, out-of-scope-macro-calls, patterns-in-fns-without-body, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-c-enums-larger-than-int, repr-transparent-non-zst-fields, self-constructor-from-outer-item, semicolon-in-expressions-from-macros, uncovered-param-in-projection, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, varargs-without-pattern"##, default_severity: Severity::Allow, warn_since: None, deny_since: None, }, children: &[ - "deref_into_dyn_supertrait", - "abi_unsupported_vector_types", + "internal_eq_trait_method_impls", + "aarch64_softfloat_neon", "ambiguous_associated_items", + "ambiguous_derive_helpers", + "ambiguous_glob_imported_traits", "ambiguous_glob_imports", - "cenum_impl_drop_cast", + "ambiguous_import_visibilities", + "ambiguous_panic_imports", "coherence_leak_check", "conflicting_repr_hints", "const_evaluatable_unchecked", "elided_lifetimes_in_associated_constant", "forbidden_lint_groups", "ill_formed_attribute_input", + "invalid_macro_export_arguments", "invalid_type_param_default", "late_bound_lifetime_arguments", "legacy_derive_helpers", "macro_expanded_macro_exports_accessed_by_absolute_paths", - "missing_fragment_specifier", - "order_dependent_trait_objects", "out_of_scope_macro_calls", "patterns_in_fns_without_body", "proc_macro_derive_resolution_fallback", - "ptr_cast_add_auto_to_object", "pub_use_of_private_extern_crate", - "repr_transparent_external_private_fields", + "repr_c_enums_larger_than_int", + "repr_transparent_non_zst_fields", "self_constructor_from_outer_item", "semicolon_in_expressions_from_macros", - "soft_unstable", "uncovered_param_in_projection", "uninhabited_static", "unstable_name_collisions", "unstable_syntax_pre_expansion", - "unsupported_fn_ptr_calling_conventions", - "wasm_c_abi", + "unsupported_calling_conventions", + "varargs_without_pattern", ], }, LintGroup { @@ -1788,10 +1971,25 @@ pub struct LintGroup { "unsafe_op_in_unsafe_fn", ], }, + LintGroup { + lint: Lint { + label: "unknown_or_malformed_diagnostic_attributes", + description: r##"lint group for: malformed-diagnostic-attributes, malformed-diagnostic-format-literals, misplaced-diagnostic-attributes, unknown-diagnostic-attributes"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + children: &[ + "malformed_diagnostic_attributes", + "malformed_diagnostic_format_literals", + "misplaced_diagnostic_attributes", + "unknown_diagnostic_attributes", + ], + }, LintGroup { lint: Lint { label: "unused", - description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-macro-rules, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons, map-unit-fn"##, + description: r##"lint group for: unused-imports, unused-variables, unused-visibilities, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-macro-rules, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons, map-unit-fn"##, default_severity: Severity::Allow, warn_since: None, deny_since: None, @@ -1799,6 +1997,7 @@ pub struct LintGroup { children: &[ "unused_imports", "unused_variables", + "unused_visibilities", "unused_assignments", "dead_code", "unused_mut", @@ -1901,16 +2100,9 @@ pub struct LintGroup { warn_since: None, deny_since: None, }, - Lint { - label: "rustdoc::unportable_markdown", - description: r##"detects markdown that is interpreted differently in different parser"##, - default_severity: Severity::Warning, - warn_since: None, - deny_since: None, - }, Lint { label: "rustdoc::all", - description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs, rustdoc::unescaped-backticks, rustdoc::redundant-explicit-links, rustdoc::unportable-markdown"##, + description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs, rustdoc::unescaped-backticks, rustdoc::redundant-explicit-links"##, default_severity: Severity::Allow, warn_since: None, deny_since: None, @@ -1920,7 +2112,7 @@ pub struct LintGroup { pub const RUSTDOC_LINT_GROUPS: &[LintGroup] = &[LintGroup { lint: Lint { label: "rustdoc::all", - description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs, rustdoc::unescaped-backticks, rustdoc::redundant-explicit-links, rustdoc::unportable-markdown"##, + description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs, rustdoc::unescaped-backticks, rustdoc::redundant-explicit-links"##, default_severity: Severity::Allow, warn_since: None, deny_since: None, @@ -1936,7 +2128,6 @@ pub struct LintGroup { "rustdoc::missing_crate_level_docs", "rustdoc::unescaped_backticks", "rustdoc::redundant_explicit_links", - "rustdoc::unportable_markdown", ], }]; @@ -1945,9 +2136,11 @@ pub struct LintGroup { label: "aarch64_unstable_target_feature", description: r##"# `aarch64_unstable_target_feature` -The tracking issue for this feature is: [#44839] +The remaining unstable target features on aarch64. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150244] + +[#150244]: https://github.com/rust-lang/rust/issues/150244 ------------------------ "##, @@ -1959,9 +2152,11 @@ pub struct LintGroup { label: "aarch64_ver_target_feature", description: r##"# `aarch64_ver_target_feature` -The tracking issue for this feature is: [#44839] +Instruction set "version" target features on aarch64. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150245] + +[#150245]: https://github.com/rust-lang/rust/issues/150245 ------------------------ "##, @@ -1973,6 +2168,8 @@ pub struct LintGroup { label: "abi_avr_interrupt", description: r##"# `abi_avr_interrupt` +Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`. + The tracking issue for this feature is: [#69664] [#69664]: https://github.com/rust-lang/rust/issues/69664 @@ -1984,8 +2181,8 @@ pub struct LintGroup { deny_since: None, }, Lint { - label: "abi_c_cmse_nonsecure_call", - description: r##"# `abi_c_cmse_nonsecure_call` + label: "abi_cmse_nonsecure_call", + description: r##"# `abi_cmse_nonsecure_call` The tracking issue for this feature is: [#81391] @@ -2001,10 +2198,9 @@ pub struct LintGroup { [support](https://developer.arm.com/documentation/ecm0359818/latest/) for the TrustZone-M feature. -One of the things provided, with this unstable feature, is the -`C-cmse-nonsecure-call` function ABI. This ABI is used on function pointers to -non-secure code to mark a non-secure function call (see [section -5.5](https://developer.arm.com/documentation/ecm0359818/latest/) for details). +One of the things provided with this unstable feature is the "cmse-nonsecure-call" function ABI. +This ABI is used on function pointers to non-secure code to mark a non-secure function call +(see [section 5.5](https://developer.arm.com/documentation/ecm0359818/latest/) for details). With this ABI, the compiler will do the following to perform the call: * save registers needed after the call to Secure memory @@ -2015,19 +2211,16 @@ pub struct LintGroup { To avoid using the non-secure stack, the compiler will constrain the number and type of parameters/return value. -The `extern "C-cmse-nonsecure-call"` ABI is otherwise equivalent to the -`extern "C"` ABI. - ``` rust,ignore #![no_std] -#![feature(abi_c_cmse_nonsecure_call)] +#![feature(abi_cmse_nonsecure_call)] #[no_mangle] pub fn call_nonsecure_function(addr: usize) -> u32 { let non_secure_function = - unsafe { core::mem::transmute:: u32>(addr) }; + unsafe { core::mem::transmute:: u32>(addr) }; non_secure_function() } ``` @@ -2073,6 +2266,38 @@ pub fn call_nonsecure_function(addr: usize) -> u32 { add sp, #16 pop {r7, pc} ``` +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "abi_custom", + description: r##"# `abi_custom` + +Allows `extern "custom" fn()`. + +The tracking issue for this feature is: [#140829] + +[#140829]: https://github.com/rust-lang/rust/issues/140829 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "abi_gpu_kernel", + description: r##"# `abi_gpu_kernel` + +Allows `extern "gpu-kernel" fn()`. + +The tracking issue for this feature is: [#135467] + +[#135467]: https://github.com/rust-lang/rust/issues/135467 + +------------------------ "##, default_severity: Severity::Allow, warn_since: None, @@ -2198,6 +2423,8 @@ pub fn device_function() { label: "abi_riscv_interrupt", description: r##"# `abi_riscv_interrupt` +Allows `extern "riscv-interrupt-m" fn()` and `extern "riscv-interrupt-s" fn()`. + The tracking issue for this feature is: [#111889] [#111889]: https://github.com/rust-lang/rust/issues/111889 @@ -2212,6 +2439,8 @@ pub fn device_function() { label: "abi_unadjusted", description: r##"# `abi_unadjusted` +Allows using the `unadjusted` ABI; perma-unstable. + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -2250,6 +2479,8 @@ fn main() { label: "abi_x86_interrupt", description: r##"# `abi_x86_interrupt` +Allows `extern "x86-interrupt" fn()`. + The tracking issue for this feature is: [#40180] [#40180]: https://github.com/rust-lang/rust/issues/40180 @@ -2264,6 +2495,8 @@ fn main() { label: "abort_unwind", description: r##"# `abort_unwind` + + The tracking issue for this feature is: [#130338] [#130338]: https://github.com/rust-lang/rust/issues/130338 @@ -2278,6 +2511,8 @@ fn main() { label: "acceptfilter", description: r##"# `acceptfilter` + + The tracking issue for this feature is: [#121891] [#121891]: https://github.com/rust-lang/rust/issues/121891 @@ -2292,6 +2527,8 @@ fn main() { label: "addr_parse_ascii", description: r##"# `addr_parse_ascii` + + The tracking issue for this feature is: [#101035] [#101035]: https://github.com/rust-lang/rust/issues/101035 @@ -2339,6 +2576,22 @@ fn is_foo_a_and_bar_true() -> bool { } } ``` +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "align_to_uninit_mut", + description: r##"# `align_to_uninit_mut` + + + +The tracking issue for this feature is: [#139062] + +[#139062]: https://github.com/rust-lang/rust/issues/139062 + +------------------------ "##, default_severity: Severity::Allow, warn_since: None, @@ -2348,6 +2601,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "alloc_error_handler", description: r##"# `alloc_error_handler` +Allows defining an `#[alloc_error_handler]`. + The tracking issue for this feature is: [#51540] [#51540]: https://github.com/rust-lang/rust/issues/51540 @@ -2362,6 +2617,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "alloc_error_hook", description: r##"# `alloc_error_hook` + + The tracking issue for this feature is: [#51245] [#51245]: https://github.com/rust-lang/rust/issues/51245 @@ -2376,6 +2633,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "alloc_internals", description: r##"# `alloc_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -2385,12 +2644,14 @@ fn is_foo_a_and_bar_true() -> bool { deny_since: None, }, Lint { - label: "alloc_layout_extra", - description: r##"# `alloc_layout_extra` + label: "alloc_slice_into_array", + description: r##"# `alloc_slice_into_array` -The tracking issue for this feature is: [#55724] -[#55724]: https://github.com/rust-lang/rust/issues/55724 + +The tracking issue for this feature is: [#148082] + +[#148082]: https://github.com/rust-lang/rust/issues/148082 ------------------------ "##, @@ -2428,6 +2689,20 @@ fn is_foo_a_and_bar_true() -> bool { detail of the `global_allocator` feature not intended for use outside the compiler. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "alloctests", + description: r##"# `alloctests` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, default_severity: Severity::Allow, @@ -2438,6 +2713,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "allow_internal_unsafe", description: r##"# `allow_internal_unsafe` +Allows using `#[allow_internal_unsafe]`. This is an attribute on `macro_rules!` and can't use the attribute handling below (it has to be checked before expansion possibly makes macros disappear). + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -2450,6 +2727,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "allow_internal_unstable", description: r##"# `allow_internal_unstable` +Allows using `#[allow_internal_unstable]`. This is an attribute on `macro_rules!` and can't use the attribute handling below (it has to be checked before expansion possibly makes macros disappear). + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -2462,6 +2741,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "anonymous_lifetime_in_impl_trait", description: r##"# `anonymous_lifetime_in_impl_trait` +Allows using anonymous lifetimes in argument-position impl-trait. + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -2471,12 +2752,14 @@ fn is_foo_a_and_bar_true() -> bool { deny_since: None, }, Lint { - label: "anonymous_pipe", - description: r##"# `anonymous_pipe` + label: "apx_target_feature", + description: r##"# `apx_target_feature` -The tracking issue for this feature is: [#127154] +The `apxf` target feature on x86 -[#127154]: https://github.com/rust-lang/rust/issues/127154 +The tracking issue for this feature is: [#139284] + +[#139284]: https://github.com/rust-lang/rust/issues/139284 ------------------------ "##, @@ -2493,6 +2776,153 @@ fn is_foo_a_and_bar_true() -> bool { [#44874]: https://github.com/rust-lang/rust/issues/44874 ------------------------ + +Allows any type implementing `core::ops::Receiver` to be used as the type +of `self` in a method belonging to `T`. + +For example, + +```rust +#![feature(arbitrary_self_types)] + +struct A; + +impl A { + fn f(self: SmartPtr) -> i32 { 1 } // note self type +} + +struct SmartPtr(T); + +impl core::ops::Receiver for SmartPtr { + type Target = T; +} + +fn main() { + let smart_ptr = SmartPtr(A); + assert_eq!(smart_ptr.f(), 1); +} +``` + +The `Receiver` trait has a blanket implementation for all `T: Deref`, so in fact +things like this work too: + +```rust +#![feature(arbitrary_self_types)] + +use std::rc::Rc; + +struct A; + +impl A { + fn f(self: Rc) -> i32 { 1 } // Rc implements Deref +} + +fn main() { + let smart_ptr = Rc::new(A); + assert_eq!(smart_ptr.f(), 1); +} +``` + +Interestingly, that works even without the `arbitrary_self_types` feature +- but that's because certain types are _effectively_ hard coded, including +`Rc`. ("Hard coding" isn't quite true; they use a lang-item called +`LegacyReceiver` to denote their special-ness in this way). With the +`arbitrary_self_types` feature, their special-ness goes away, and custom +smart pointers can achieve the same. + +## Changes to method lookup + +Method lookup previously used to work by stepping through the `Deref` +chain then using the resulting list of steps in two different ways: + +* To identify types that might contribute methods via their `impl` + blocks (inherent methods) or via traits +* To identify the types that the method receiver (`a` in the above + examples) can be converted to. + +With this feature, these lists are created by instead stepping through +the `Receiver` chain. However, a note is kept about whether the type +can be reached also via the `Deref` chain. + +The full chain (via `Receiver` hops) is used for the first purpose +(identifying relevant `impl` blocks and traits); whereas the shorter +list (reachable via `Deref`) is used for the second purpose. That's +because, to convert the method target (`a` in `a.b()`) to the self +type, Rust may need to be able to use `Deref::deref`. Type conversions, +then, can only proceed as far as the end of the `Deref` chain whereas +the longer `Receiver` chain can be used to explore more places where +useful methods might reside. + +## Types suitable for use as smart pointers + +This feature allows the creation of customised smart pointers - for example +your own equivalent to `Rc` or `Box` with whatever capabilities you like. +Those smart pointers can either implement `Deref` (if it's safe to +create a reference to the referent) or `Receiver` (if it isn't). + +Either way, smart pointer types should mostly _avoid having methods_. +Calling methods on a smart pointer leads to ambiguity about whether you're +aiming for a method on the pointer, or on the referent. + +Best practice is therefore to put smart pointer functionality into +associated functions instead - that's what's done in all the smart pointer +types within Rust's standard library which implement `Receiver`. + +If you choose to add any methods to your smart pointer type, your users +may run into errors from deshadowing, as described in the next section. + +## Avoiding shadowing + +With or without this feature, Rust emits an error if it finds two method +candidates, like this: + +```rust,compile_fail +use std::pin::Pin; +use std::pin::pin; + +struct A; + +impl A { + fn get_ref(self: Pin<&A>) {} +} + +fn main() { + let pinned_a: Pin<&A> = pin!(A).as_ref(); + let pinned_a: Pin<&A> = pinned_a.as_ref(); + pinned_a.get_ref(); // error[E0034]: multiple applicable items in scope +} +``` + +(this is why Rust's smart pointers are mostly carefully designed to avoid +having methods at all, and shouldn't add new methods in future.) + +With `arbitrary_self_types`, we take care to spot some other kinds of +conflict: + +```rust,compile_fail +#![feature(arbitrary_self_types)] + +use std::pin::Pin; +use std::pin::pin; + +struct A; + +impl A { + fn get_ref(self: &Pin<&A>) {} // note &Pin +} + +fn main() { + let pinned_a: Pin<&mut A> = pin!(A); + let pinned_a: Pin<&A> = pinned_a.as_ref(); + pinned_a.get_ref(); +} +``` + +This is to guard against the case where an inner (referent) type has a +method of a given name, taking the smart pointer by reference, and then +the smart pointer implementer adds a similar method taking self by value. +As noted in the previous section, the safe option is simply +not to add methods to smart pointers, and then these errors can't occur. "##, default_severity: Severity::Allow, warn_since: None, @@ -2504,7 +2934,73 @@ fn is_foo_a_and_bar_true() -> bool { The tracking issue for this feature is: [#44874] -[#44874]: https://github.com/rust-lang/rust/issues/44874 +[#38788]: https://github.com/rust-lang/rust/issues/44874 + +------------------------ + +This extends the [arbitrary self types] feature to allow methods to +receive `self` by pointer. For example: + +```rust +#![feature(arbitrary_self_types_pointers)] + +struct A; + +impl A { + fn m(self: *const Self) {} +} + +fn main() { + let a = A; + let a_ptr: *const A = &a as *const A; + a_ptr.m(); +} +``` + +In general this is not advised: it's thought to be better practice to wrap +raw pointers in a newtype wrapper which implements the `core::ops::Receiver` +trait, then you need "only" the `arbitrary_self_types` feature. For example: + +```rust +#![feature(arbitrary_self_types)] +#![allow(dead_code)] + +struct A; + +impl A { + fn m(self: Wrapper) {} // can extract the pointer and do + // what it needs +} + +struct Wrapper(*const T); + +impl core::ops::Receiver for Wrapper { + type Target = T; +} + +fn main() { + let a = A; + let a_ptr: *const A = &a as *const A; + let a_wrapper = Wrapper(a_ptr); + a_wrapper.m(); +} +``` + +[arbitrary self types]: arbitrary-self-types.md +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "arc_is_unique", + description: r##"# `arc_is_unique` + + + +The tracking issue for this feature is: [#138938] + +[#138938]: https://github.com/rust-lang/rust/issues/138938 ------------------------ "##, @@ -2516,23 +3012,11 @@ fn is_foo_a_and_bar_true() -> bool { label: "arm_target_feature", description: r##"# `arm_target_feature` -The tracking issue for this feature is: [#44839] +Target features on arm. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150246] ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "array_chunks", - description: r##"# `array_chunks` - -The tracking issue for this feature is: [#74985] - -[#74985]: https://github.com/rust-lang/rust/issues/74985 +[#150246]: https://github.com/rust-lang/rust/issues/150246 ------------------------ "##, @@ -2544,6 +3028,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "array_into_iter_constructors", description: r##"# `array_into_iter_constructors` + + The tracking issue for this feature is: [#91583] [#91583]: https://github.com/rust-lang/rust/issues/91583 @@ -2558,24 +3044,12 @@ fn is_foo_a_and_bar_true() -> bool { label: "array_ptr_get", description: r##"# `array_ptr_get` + + The tracking issue for this feature is: [#119834] [#119834]: https://github.com/rust-lang/rust/issues/119834 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "array_repeat", - description: r##"# `array_repeat` - -The tracking issue for this feature is: [#126695] - -[#126695]: https://github.com/rust-lang/rust/issues/126695 - ------------------------ "##, default_severity: Severity::Allow, @@ -2586,6 +3060,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "array_try_from_fn", description: r##"# `array_try_from_fn` + + The tracking issue for this feature is: [#89379] [#89379]: https://github.com/rust-lang/rust/issues/89379 @@ -2600,38 +3076,12 @@ fn is_foo_a_and_bar_true() -> bool { label: "array_try_map", description: r##"# `array_try_map` + + The tracking issue for this feature is: [#79711] [#79711]: https://github.com/rust-lang/rust/issues/79711 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "array_windows", - description: r##"# `array_windows` - -The tracking issue for this feature is: [#75027] - -[#75027]: https://github.com/rust-lang/rust/issues/75027 - ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "as_array_of_cells", - description: r##"# `as_array_of_cells` - -The tracking issue for this feature is: [#88248] - -[#88248]: https://github.com/rust-lang/rust/issues/88248 - ------------------------ "##, default_severity: Severity::Allow, @@ -2642,6 +3092,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "ascii_char", description: r##"# `ascii_char` + + The tracking issue for this feature is: [#110998] [#110998]: https://github.com/rust-lang/rust/issues/110998 @@ -2656,6 +3108,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "ascii_char_variants", description: r##"# `ascii_char_variants` + + The tracking issue for this feature is: [#110998] [#110998]: https://github.com/rust-lang/rust/issues/110998 @@ -2678,7 +3132,6 @@ fn is_foo_a_and_bar_true() -> bool { This feature tracks `asm!` and `global_asm!` support for the following architectures: - NVPTX -- PowerPC - Hexagon - MIPS32r2 and MIPS64r2 - wasm32 @@ -2701,12 +3154,6 @@ fn is_foo_a_and_bar_true() -> bool { | NVPTX | `reg64` | None\* | `l` | | Hexagon | `reg` | `r[0-28]` | `r` | | Hexagon | `preg` | `p[0-3]` | Only clobbers | -| PowerPC | `reg` | `r0`, `r[3-12]`, `r[14-28]` | `r` | -| PowerPC | `reg_nonzero` | `r[3-12]`, `r[14-28]` | `b` | -| PowerPC | `freg` | `f[0-31]` | `f` | -| PowerPC | `vreg` | `v[0-31]` | `v` | -| PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers | -| PowerPC | `xer` | `xer` | Only clobbers | | wasm32 | `local` | None\* | `r` | | BPF | `reg` | `r[0-10]` | `r` | | BPF | `wreg` | `w[0-10]` | `w` | @@ -2742,13 +3189,6 @@ fn is_foo_a_and_bar_true() -> bool { | NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` | | Hexagon | `preg` | N/A | Only clobbers | -| PowerPC | `reg` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | -| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | -| PowerPC | `freg` | None | `f32`, `f64` | -| PowerPC | `vreg` | `altivec` | `i8x16`, `i16x8`, `i32x4`, `f32x4` | -| PowerPC | `vreg` | `vsx` | `f32`, `f64`, `i64x2`, `f64x2` | -| PowerPC | `cr` | N/A | Only clobbers | -| PowerPC | `xer` | N/A | Only clobbers | | wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` | | BPF | `reg` | None | `i8` `i16` `i32` `i64` | | BPF | `wreg` | `alu32` | `i8` `i16` `i32` | @@ -2769,10 +3209,6 @@ fn is_foo_a_and_bar_true() -> bool { | Hexagon | `r29` | `sp` | | Hexagon | `r30` | `fr` | | Hexagon | `r31` | `lr` | -| PowerPC | `r1` | `sp` | -| PowerPC | `r31` | `fp` | -| PowerPC | `r[0-31]` | `[0-31]` | -| PowerPC | `f[0-31]` | `fr[0-31]`| | BPF | `r[0-10]` | `w[0-10]` | | AVR | `XH` | `r27` | | AVR | `XL` | `r26` | @@ -2811,18 +3247,14 @@ fn is_foo_a_and_bar_true() -> bool { | Architecture | Unsupported register | Reason | | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | All | `sp`, `r14`/`o6` (SPARC) | The stack pointer must be restored to its original value at the end of an asm code block. | -| All | `fr` (Hexagon), `fp` (PowerPC), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r30`/`i6` (SPARC) | The frame pointer cannot be used as an input or output. | -| All | `r19` (Hexagon), `r29` (PowerPC), `r30` (PowerPC) | These are used internally by LLVM as "base pointer" for functions with complex stack frames. | +| All | `fr` (Hexagon) `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r30`/`i6` (SPARC) | The frame pointer cannot be used as an input or output. | +| All | `r19` (Hexagon) | These are used internally by LLVM as "base pointer" for functions with complex stack frames. | | MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. | | MIPS | `$1` or `$at` | Reserved for assembler. | | MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. | | MIPS | `$28`/`$gp` | Global pointer cannot be used as inputs or outputs. | | MIPS | `$ra` | Return address cannot be used as inputs or outputs. | | Hexagon | `lr` | This is the link register which cannot be used as an input or output. | -| PowerPC | `r2`, `r13` | These are system reserved registers. | -| PowerPC | `lr` | The link register cannot be used as an input or output. | -| PowerPC | `ctr` | The counter register cannot be used as an input or output. | -| PowerPC | `vrsave` | The vrsave register cannot be used as an input or output. | | AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. | |MSP430 | `r0`, `r2`, `r3` | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to. | | M68k | `a4`, `a5` | Used internally by LLVM for the base pointer and global base pointer. | @@ -2849,10 +3281,6 @@ fn is_foo_a_and_bar_true() -> bool { | NVPTX | `reg32` | None | `r0` | None | | NVPTX | `reg64` | None | `rd0` | None | | Hexagon | `reg` | None | `r0` | None | -| PowerPC | `reg` | None | `0` | None | -| PowerPC | `reg_nonzero` | None | `3` | None | -| PowerPC | `freg` | None | `0` | None | -| PowerPC | `vreg` | None | `0` | None | | SPARC | `reg` | None | `%o0` | None | | CSKY | `reg` | None | `r0` | None | | CSKY | `freg` | None | `f0` | None | @@ -2869,6 +3297,8 @@ fn is_foo_a_and_bar_true() -> bool { - SPARC - Integer condition codes (`icc` and `xcc`) - Floating-point condition codes (`fcc[0-3]`) +- CSKY + - Condition/carry bit (C) in `PSR`. "##, default_severity: Severity::Allow, warn_since: None, @@ -2890,16 +3320,14 @@ fn is_foo_a_and_bar_true() -> bool { | Architecture | Register class | Registers | LLVM constraint code | | ------------ | -------------- | --------- | -------------------- | -| s390x | `vreg` | `v[0-31]` | `v` | - -> **Notes**: -> - s390x `vreg` is clobber-only in stable. ## Register class supported types | Architecture | Register class | Target feature | Allowed types | | ------------ | -------------- | -------------- | ------------- | -| s390x | `vreg` | `vector` | `i32`, `f32`, `i64`, `f64`, `i128`, `f128`, `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | +| x86 | `xmm_reg` | `sse` | `i128` | +| x86 | `ymm_reg` | `avx` | `i128` | +| x86 | `zmm_reg` | `avx512f` | `i128` | ## Register aliases @@ -2915,46 +3343,6 @@ fn is_foo_a_and_bar_true() -> bool { | Architecture | Register class | Modifier | Example output | LLVM modifier | | ------------ | -------------- | -------- | -------------- | ------------- | -| s390x | `vreg` | None | `%v0` | None | -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "asm_goto", - description: r##"# `asm_goto` - -The tracking issue for this feature is: [#119364] - -[#119364]: https://github.com/rust-lang/rust/issues/119364 - ------------------------- - -This feature adds a `label ` operand type to `asm!`. - -Example: -```rust,ignore (partial-example, x86-only) - -unsafe { - asm!( - "jmp {}", - label { - println!("Jumped from asm!"); - } - ); -} -``` - -The block must have unit type or diverge. The block starts a new safety context, -so despite outer `unsafe`, you need extra unsafe to perform unsafe operations -within `label `. - -When `label ` is used together with `noreturn` option, it means that the -assembly will not fallthrough. It's allowed to jump to a label within the -assembly. In this case, the entire `asm!` expression will have an unit type as -opposed to diverging, if not all label blocks diverge. The `asm!` expression -still diverges if `noreturn` option is used and all label blocks diverge. "##, default_severity: Severity::Allow, warn_since: None, @@ -2969,6 +3357,26 @@ fn is_foo_a_and_bar_true() -> bool { [#119364]: https://github.com/rust-lang/rust/issues/119364 ------------------------ + +This feature allows label operands to be used together with output operands. + +Example: +```rust,ignore (partial-example, x86-only) + +unsafe { + let a: usize; + asm!( + "mov {}, 1" + "jmp {}", + out(reg) a, + label { + println!("Jumped from asm {}!", a); + } + ); +} +``` + +The output operands are assigned before the label blocks are executed. "##, default_severity: Severity::Allow, warn_since: None, @@ -2985,34 +3393,6 @@ fn is_foo_a_and_bar_true() -> bool { ------------------------ This feature adds a `may_unwind` option to `asm!` which allows an `asm` block to unwind stack and be part of the stack unwinding process. This option is only supported by the LLVM backend right now. -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "assert_matches", - description: r##"# `assert_matches` - -The tracking issue for this feature is: [#82775] - -[#82775]: https://github.com/rust-lang/rust/issues/82775 - ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "associated_const_equality", - description: r##"# `associated_const_equality` - -The tracking issue for this feature is: [#92827] - -[#92827]: https://github.com/rust-lang/rust/issues/92827 - ------------------------- "##, default_severity: Severity::Allow, warn_since: None, @@ -3022,24 +3402,12 @@ fn is_foo_a_and_bar_true() -> bool { label: "associated_type_defaults", description: r##"# `associated_type_defaults` +Allows associated type defaults. + The tracking issue for this feature is: [#29661] [#29661]: https://github.com/rust-lang/rust/issues/29661 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "async_closure", - description: r##"# `async_closure` - -The tracking issue for this feature is: [#62290] - -[#62290]: https://github.com/rust-lang/rust/issues/62290 - ------------------------ "##, default_severity: Severity::Allow, @@ -3050,10 +3418,28 @@ fn is_foo_a_and_bar_true() -> bool { label: "async_drop", description: r##"# `async_drop` +Allows implementing `AsyncDrop`. + The tracking issue for this feature is: [#126482] [#126482]: https://github.com/rust-lang/rust/issues/126482 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "async_fn_in_dyn_trait", + description: r##"# `async_fn_in_dyn_trait` + +Allows async functions to be called from `dyn Trait`. + +The tracking issue for this feature is: [#133119] + +[#133119]: https://github.com/rust-lang/rust/issues/133119 + ------------------------ "##, default_severity: Severity::Allow, @@ -3064,6 +3450,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "async_fn_track_caller", description: r##"# `async_fn_track_caller` +Allows `#[track_caller]` on async functions. + The tracking issue for this feature is: [#110011] [#110011]: https://github.com/rust-lang/rust/issues/110011 @@ -3098,6 +3486,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "async_for_loop", description: r##"# `async_for_loop` +Allows `for await` loops. + The tracking issue for this feature is: [#118898] [#118898]: https://github.com/rust-lang/rust/issues/118898 @@ -3112,6 +3502,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "async_gen_internals", description: r##"# `async_gen_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -3124,6 +3516,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "async_iter_from_iter", description: r##"# `async_iter_from_iter` + + The tracking issue for this feature is: [#81798] [#81798]: https://github.com/rust-lang/rust/issues/81798 @@ -3138,6 +3532,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "async_iterator", description: r##"# `async_iterator` + + The tracking issue for this feature is: [#79024] [#79024]: https://github.com/rust-lang/rust/issues/79024 @@ -3152,6 +3548,8 @@ fn is_foo_a_and_bar_true() -> bool { label: "async_trait_bounds", description: r##"# `async_trait_bounds` +Allows `async` trait bound modifier. + The tracking issue for this feature is: [#62290] [#62290]: https://github.com/rust-lang/rust/issues/62290 @@ -3166,10 +3564,42 @@ fn is_foo_a_and_bar_true() -> bool { label: "atomic_from_mut", description: r##"# `atomic_from_mut` + + The tracking issue for this feature is: [#76314] [#76314]: https://github.com/rust-lang/rust/issues/76314 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "atomic_internals", + description: r##"# `atomic_internals` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "atomic_ptr_null", + description: r##"# `atomic_ptr_null` + + + +The tracking issue for this feature is: [#150733] + +[#150733]: https://github.com/rust-lang/rust/issues/150733 + ------------------------ "##, default_severity: Severity::Allow, @@ -3293,6 +3723,8 @@ trait matching, this cycle would be an error, but for an auto trait it label: "autodiff", description: r##"# `autodiff` + + The tracking issue for this feature is: [#124509] [#124509]: https://github.com/rust-lang/rust/issues/124509 @@ -3304,12 +3736,30 @@ trait matching, this cycle would be an error, but for an auto trait it deny_since: None, }, Lint { - label: "avx512_target_feature", - description: r##"# `avx512_target_feature` + label: "avr_target_feature", + description: r##"# `avr_target_feature` -The tracking issue for this feature is: [#44839] +Target features on avr. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#146889] + +[#146889]: https://github.com/rust-lang/rust/issues/146889 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "avx10_target_feature", + description: r##"# `avx10_target_feature` + +Allows using Intel AVX10 target features and intrinsics + +The tracking issue for this feature is: [#138843] + +[#138843]: https://github.com/rust-lang/rust/issues/138843 ------------------------ "##, @@ -3321,6 +3771,8 @@ trait matching, this cycle would be an error, but for an auto trait it label: "backtrace_frames", description: r##"# `backtrace_frames` + + The tracking issue for this feature is: [#79676] [#79676]: https://github.com/rust-lang/rust/issues/79676 @@ -3332,12 +3784,28 @@ trait matching, this cycle would be an error, but for an auto trait it deny_since: None, }, Lint { - label: "bigint_helper_methods", - description: r##"# `bigint_helper_methods` + label: "bikeshed_guaranteed_no_drop", + description: r##"# `bikeshed_guaranteed_no_drop` -The tracking issue for this feature is: [#85532] -[#85532]: https://github.com/rust-lang/rust/issues/85532 + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "binary_heap_as_mut_slice", + description: r##"# `binary_heap_as_mut_slice` + + + +The tracking issue for this feature is: [#154009] + +[#154009]: https://github.com/rust-lang/rust/issues/154009 ------------------------ "##, @@ -3349,10 +3817,28 @@ trait matching, this cycle would be an error, but for an auto trait it label: "binary_heap_drain_sorted", description: r##"# `binary_heap_drain_sorted` + + The tracking issue for this feature is: [#59278] [#59278]: https://github.com/rust-lang/rust/issues/59278 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "binary_heap_from_raw_vec", + description: r##"# `binary_heap_from_raw_vec` + + + +The tracking issue for this feature is: [#152500] + +[#152500]: https://github.com/rust-lang/rust/issues/152500 + ------------------------ "##, default_severity: Severity::Allow, @@ -3363,10 +3849,76 @@ trait matching, this cycle would be an error, but for an auto trait it label: "binary_heap_into_iter_sorted", description: r##"# `binary_heap_into_iter_sorted` + + The tracking issue for this feature is: [#59278] [#59278]: https://github.com/rust-lang/rust/issues/59278 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "binary_heap_peek_mut_refresh", + description: r##"# `binary_heap_peek_mut_refresh` + + + +The tracking issue for this feature is: [#138355] + +[#138355]: https://github.com/rust-lang/rust/issues/138355 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "binary_heap_pop_if", + description: r##"# `binary_heap_pop_if` + + + +The tracking issue for this feature is: [#151828] + +[#151828]: https://github.com/rust-lang/rust/issues/151828 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "bool_to_result", + description: r##"# `bool_to_result` + + + +The tracking issue for this feature is: [#142748] + +[#142748]: https://github.com/rust-lang/rust/issues/142748 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "borrowed_buf_init", + description: r##"# `borrowed_buf_init` + + + +The tracking issue for this feature is: [#78485] + +[#78485]: https://github.com/rust-lang/rust/issues/78485 + ------------------------ "##, default_severity: Severity::Allow, @@ -3377,10 +3929,28 @@ trait matching, this cycle would be an error, but for an auto trait it label: "bound_as_ref", description: r##"# `bound_as_ref` + + The tracking issue for this feature is: [#80996] [#80996]: https://github.com/rust-lang/rust/issues/80996 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "bound_copied", + description: r##"# `bound_copied` + + + +The tracking issue for this feature is: [#145966] + +[#145966]: https://github.com/rust-lang/rust/issues/145966 + ------------------------ "##, default_severity: Severity::Allow, @@ -3391,6 +3961,8 @@ trait matching, this cycle would be an error, but for an auto trait it label: "box_as_ptr", description: r##"# `box_as_ptr` + + The tracking issue for this feature is: [#129090] [#129090]: https://github.com/rust-lang/rust/issues/129090 @@ -3405,6 +3977,8 @@ trait matching, this cycle would be an error, but for an auto trait it label: "box_into_boxed_slice", description: r##"# `box_into_boxed_slice` + + The tracking issue for this feature is: [#71582] [#71582]: https://github.com/rust-lang/rust/issues/71582 @@ -3419,6 +3993,8 @@ trait matching, this cycle would be an error, but for an auto trait it label: "box_into_inner", description: r##"# `box_into_inner` + + The tracking issue for this feature is: [#80437] [#80437]: https://github.com/rust-lang/rust/issues/80437 @@ -3439,6 +4015,8 @@ trait matching, this cycle would be an error, but for an auto trait it ------------------------ +> **Note**: This feature will be superseded by [`deref_patterns`] in the future. + Box patterns let you match on `Box`s: @@ -3461,18 +4039,22 @@ fn main() { } } ``` + +[`deref_patterns`]: ./deref-patterns.md "##, default_severity: Severity::Allow, warn_since: None, deny_since: None, }, Lint { - label: "box_uninit_write", - description: r##"# `box_uninit_write` + label: "box_take", + description: r##"# `box_take` -The tracking issue for this feature is: [#129397] -[#129397]: https://github.com/rust-lang/rust/issues/129397 + +The tracking issue for this feature is: [#147212] + +[#147212]: https://github.com/rust-lang/rust/issues/147212 ------------------------ "##, @@ -3484,6 +4066,8 @@ fn main() { label: "box_vec_non_null", description: r##"# `box_vec_non_null` + + The tracking issue for this feature is: [#130364] [#130364]: https://github.com/rust-lang/rust/issues/130364 @@ -3498,9 +4082,11 @@ fn main() { label: "bpf_target_feature", description: r##"# `bpf_target_feature` -The tracking issue for this feature is: [#44839] +Target features on bpf. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150247] + +[#150247]: https://github.com/rust-lang/rust/issues/150247 ------------------------ "##, @@ -3512,10 +4098,42 @@ fn main() { label: "breakpoint", description: r##"# `breakpoint` + + The tracking issue for this feature is: [#133724] [#133724]: https://github.com/rust-lang/rust/issues/133724 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "bstr", + description: r##"# `bstr` + + + +The tracking issue for this feature is: [#134915] + +[#134915]: https://github.com/rust-lang/rust/issues/134915 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "bstr_internals", + description: r##"# `bstr_internals` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, default_severity: Severity::Allow, @@ -3526,6 +4144,8 @@ fn main() { label: "btree_cursors", description: r##"# `btree_cursors` + + The tracking issue for this feature is: [#107540] [#107540]: https://github.com/rust-lang/rust/issues/107540 @@ -3537,26 +4157,14 @@ fn main() { deny_since: None, }, Lint { - label: "btree_entry_insert", - description: r##"# `btree_entry_insert` + label: "btree_merge", + description: r##"# `btree_merge` -The tracking issue for this feature is: [#65225] -[#65225]: https://github.com/rust-lang/rust/issues/65225 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "btree_extract_if", - description: r##"# `btree_extract_if` +The tracking issue for this feature is: [#152152] -The tracking issue for this feature is: [#70530] - -[#70530]: https://github.com/rust-lang/rust/issues/70530 +[#152152]: https://github.com/rust-lang/rust/issues/152152 ------------------------ "##, @@ -3568,6 +4176,8 @@ fn main() { label: "btree_set_entry", description: r##"# `btree_set_entry` + + The tracking issue for this feature is: [#133549] [#133549]: https://github.com/rust-lang/rust/issues/133549 @@ -3582,6 +4192,8 @@ fn main() { label: "btreemap_alloc", description: r##"# `btreemap_alloc` + + The tracking issue for this feature is: [#32838] [#32838]: https://github.com/rust-lang/rust/issues/32838 @@ -3596,6 +4208,8 @@ fn main() { label: "buf_read_has_data_left", description: r##"# `buf_read_has_data_left` + + The tracking issue for this feature is: [#86423] [#86423]: https://github.com/rust-lang/rust/issues/86423 @@ -3610,6 +4224,8 @@ fn main() { label: "bufreader_peek", description: r##"# `bufreader_peek` + + The tracking issue for this feature is: [#128405] [#128405]: https://github.com/rust-lang/rust/issues/128405 @@ -3624,6 +4240,8 @@ fn main() { label: "builtin_syntax", description: r##"# `builtin_syntax` +Allows builtin # foo() syntax + The tracking issue for this feature is: [#110680] [#110680]: https://github.com/rust-lang/rust/issues/110680 @@ -3638,24 +4256,12 @@ fn main() { label: "c_size_t", description: r##"# `c_size_t` + + The tracking issue for this feature is: [#88345] [#88345]: https://github.com/rust-lang/rust/issues/88345 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "c_str_module", - description: r##"# `c_str_module` - -The tracking issue for this feature is: [#112134] - -[#112134]: https://github.com/rust-lang/rust/issues/112134 - ------------------------ "##, default_severity: Severity::Allow, @@ -3694,33 +4300,16 @@ fn main() { deny_since: None, }, Lint { - label: "c_variadic", - description: r##"# `c_variadic` + label: "c_variadic_naked_functions", + description: r##"# `c_variadic_naked_functions` -The tracking issue for this feature is: [#44930] +Allows defining c-variadic naked functions with any extern ABI that is allowed on c-variadic foreign functions. -[#44930]: https://github.com/rust-lang/rust/issues/44930 +The tracking issue for this feature is: [#148767] + +[#148767]: https://github.com/rust-lang/rust/issues/148767 ------------------------ - -The `c_variadic` library feature exposes the `VaList` structure, -Rust's analogue of C's `va_list` type. - -## Examples - -```rust -#![feature(c_variadic)] - -use std::ffi::VaList; - -pub unsafe extern "C" fn vadd(n: usize, mut args: VaList) -> usize { - let mut sum = 0; - for _ in 0..n { - sum += args.arg::(); - } - sum -} -``` "##, default_severity: Severity::Allow, warn_since: None, @@ -3742,10 +4331,60 @@ fn main() { label: "can_vector", description: r##"# `can_vector` + + The tracking issue for this feature is: [#69941] [#69941]: https://github.com/rust-lang/rust/issues/69941 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "case_ignorable", + description: r##"# `case_ignorable` + + + +The tracking issue for this feature is: [#154848] + +[#154848]: https://github.com/rust-lang/rust/issues/154848 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "cast_maybe_uninit", + description: r##"# `cast_maybe_uninit` + + + +The tracking issue for this feature is: [#145036] + +[#145036]: https://github.com/rust-lang/rust/issues/145036 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "cell_get_cloned", + description: r##"# `cell_get_cloned` + + + +The tracking issue for this feature is: [#145329] + +[#145329]: https://github.com/rust-lang/rust/issues/145329 + ------------------------ "##, default_severity: Severity::Allow, @@ -3756,24 +4395,12 @@ fn main() { label: "cell_leak", description: r##"# `cell_leak` + + The tracking issue for this feature is: [#69099] [#69099]: https://github.com/rust-lang/rust/issues/69099 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "cell_update", - description: r##"# `cell_update` - -The tracking issue for this feature is: [#50186] - -[#50186]: https://github.com/rust-lang/rust/issues/50186 - ------------------------ "##, default_severity: Severity::Allow, @@ -3784,10 +4411,42 @@ fn main() { label: "cfg_accessible", description: r##"# `cfg_accessible` + + The tracking issue for this feature is: [#64797] [#64797]: https://github.com/rust-lang/rust/issues/64797 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "cfg_contract_checks", + description: r##"# `cfg_contract_checks` + +Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled. + +The tracking issue for this feature is: [#128044] + +[#128044]: https://github.com/rust-lang/rust/issues/128044 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "cfg_emscripten_wasm_eh", + description: r##"# `cfg_emscripten_wasm_eh` + +Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, default_severity: Severity::Allow, @@ -3798,24 +4457,12 @@ fn main() { label: "cfg_eval", description: r##"# `cfg_eval` + + The tracking issue for this feature is: [#82679] [#82679]: https://github.com/rust-lang/rust/issues/82679 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "cfg_match", - description: r##"# `cfg_match` - -The tracking issue for this feature is: [#115585] - -[#115585]: https://github.com/rust-lang/rust/issues/115585 - ------------------------ "##, default_severity: Severity::Allow, @@ -3826,6 +4473,8 @@ fn main() { label: "cfg_overflow_checks", description: r##"# `cfg_overflow_checks` +Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour. + The tracking issue for this feature is: [#111466] [#111466]: https://github.com/rust-lang/rust/issues/111466 @@ -3840,6 +4489,8 @@ fn main() { label: "cfg_relocation_model", description: r##"# `cfg_relocation_model` +Provides the relocation model information as cfg entry + The tracking issue for this feature is: [#114929] [#114929]: https://github.com/rust-lang/rust/issues/114929 @@ -3895,6 +4546,8 @@ fn b() { label: "cfg_sanitizer_cfi", description: r##"# `cfg_sanitizer_cfi` +Allows `cfg(sanitizer_cfi_generalize_pointers)` and `cfg(sanitizer_cfi_normalize_integers)`. + The tracking issue for this feature is: [#89653] [#89653]: https://github.com/rust-lang/rust/issues/89653 @@ -3909,6 +4562,8 @@ fn b() { label: "cfg_target_compact", description: r##"# `cfg_target_compact` +Allows `cfg(target(abi = "..."))`. + The tracking issue for this feature is: [#96901] [#96901]: https://github.com/rust-lang/rust/issues/96901 @@ -3923,6 +4578,8 @@ fn b() { label: "cfg_target_has_atomic", description: r##"# `cfg_target_has_atomic` +Allows `cfg(target_has_atomic_load_store = "...")`. + The tracking issue for this feature is: [#94039] [#94039]: https://github.com/rust-lang/rust/issues/94039 @@ -3937,10 +4594,26 @@ fn b() { label: "cfg_target_has_atomic_equal_alignment", description: r##"# `cfg_target_has_atomic_equal_alignment` +Allows `cfg(target_has_atomic_equal_alignment = "...")`. + The tracking issue for this feature is: [#93822] [#93822]: https://github.com/rust-lang/rust/issues/93822 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "cfg_target_has_reliable_f16_f128", + description: r##"# `cfg_target_has_reliable_f16_f128` + +Allows checking whether or not the backend correctly supports unstable float types. + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, default_severity: Severity::Allow, @@ -3951,6 +4624,8 @@ fn b() { label: "cfg_target_thread_local", description: r##"# `cfg_target_thread_local` +Allows `cfg(target_thread_local)`. + The tracking issue for this feature is: [#29594] [#29594]: https://github.com/rust-lang/rust/issues/29594 @@ -3965,6 +4640,8 @@ fn b() { label: "cfg_ub_checks", description: r##"# `cfg_ub_checks` +Allows the use of `#[cfg(ub_checks)` to check if UB checks are enabled. + The tracking issue for this feature is: [#123499] [#123499]: https://github.com/rust-lang/rust/issues/123499 @@ -4053,8 +4730,58 @@ fn b() { label: "char_internals", description: r##"# `char_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "char_max_len", + description: r##"# `char_max_len` + + + +The tracking issue for this feature is: [#121714] + +[#121714]: https://github.com/rust-lang/rust/issues/121714 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "clamp_magnitude", + description: r##"# `clamp_magnitude` + + + +The tracking issue for this feature is: [#148519] + +[#148519]: https://github.com/rust-lang/rust/issues/148519 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "clone_from_ref", + description: r##"# `clone_from_ref` + + + +The tracking issue for this feature is: [#149075] + +[#149075]: https://github.com/rust-lang/rust/issues/149075 + ------------------------ "##, default_severity: Severity::Allow, @@ -4065,6 +4792,8 @@ fn b() { label: "clone_to_uninit", description: r##"# `clone_to_uninit` + + The tracking issue for this feature is: [#126799] [#126799]: https://github.com/rust-lang/rust/issues/126799 @@ -4079,6 +4808,8 @@ fn b() { label: "closure_lifetime_binder", description: r##"# `closure_lifetime_binder` +Allows `for<...>` on closures and coroutines. + The tracking issue for this feature is: [#97362] [#97362]: https://github.com/rust-lang/rust/issues/97362 @@ -4112,6 +4843,8 @@ fn b() { label: "cmp_minmax", description: r##"# `cmp_minmax` + + The tracking issue for this feature is: [#115939] [#115939]: https://github.com/rust-lang/rust/issues/115939 @@ -4140,10 +4873,9 @@ fn b() { [support](https://developer.arm.com/documentation/ecm0359818/latest/) for the TrustZone-M feature. -One of the things provided, with this unstable feature, is the -`C-cmse-nonsecure-entry` ABI. This ABI marks a Secure function as an -entry function (see [section -5.4](https://developer.arm.com/documentation/ecm0359818/latest/) for details). +One of the things provided with this unstable feature is the "cmse-nonsecure-entry" ABI. +This ABI marks a Secure function as an entry function (see +[section 5.4](https://developer.arm.com/documentation/ecm0359818/latest/) for details). With this ABI, the compiler will do the following: * add a special symbol on the function which is the `__acle_se_` prefix and the standard function name @@ -4154,9 +4886,7 @@ fn b() { Because the stack can not be used to pass parameters, there will be compilation errors if: -* the total size of all parameters is too big (for example more than four 32 - bits integers) -* the entry function is not using a C ABI +* the total size of all parameters is too big (for example, more than four 32-bit integers) The special symbol `__acle_se_` will be used by the linker to generate a secure gateway veneer. @@ -4168,7 +4898,7 @@ fn b() { #![feature(cmse_nonsecure_entry)] #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { +pub extern "cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { input + 6 } ``` @@ -4205,6 +4935,20 @@ pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { 3c: f7ff fffe bl 0 <_ZN4core9panicking5panic17h5c028258ca2fb3f5E> 40: defe udf #254 ; 0xfe ``` +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "coerce_pointee_validated", + description: r##"# `coerce_pointee_validated` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ "##, default_severity: Severity::Allow, warn_since: None, @@ -4214,10 +4958,28 @@ pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { label: "coerce_unsized", description: r##"# `coerce_unsized` + + The tracking issue for this feature is: [#18598] [#18598]: https://github.com/rust-lang/rust/issues/18598 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "command_resolved_envs", + description: r##"# `command_resolved_envs` + + + +The tracking issue for this feature is: [#149070] + +[#149070]: https://github.com/rust-lang/rust/issues/149070 + ------------------------ "##, default_severity: Severity::Allow, @@ -4240,40 +5002,13 @@ pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { label: "concat_bytes", description: r##"# `concat_bytes` + + The tracking issue for this feature is: [#87555] [#87555]: https://github.com/rust-lang/rust/issues/87555 ------------------------ -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "concat_idents", - description: r##"# `concat_idents` - -The tracking issue for this feature is: [#29599] - -[#29599]: https://github.com/rust-lang/rust/issues/29599 - ------------------------- - -The `concat_idents` feature adds a macro for concatenating multiple identifiers -into one identifier. - -## Examples - -```rust -#![feature(concat_idents)] - -fn main() { - fn foobar() -> u32 { 23 } - let f = concat_idents!(foo, bar); - assert_eq!(f(), 23); -} -``` "##, default_severity: Severity::Allow, warn_since: None, @@ -4283,6 +5018,8 @@ fn foobar() -> u32 { 23 } label: "const_alloc_error", description: r##"# `const_alloc_error` + + The tracking issue for this feature is: [#92523] [#92523]: https://github.com/rust-lang/rust/issues/92523 @@ -4294,40 +5031,14 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_alloc_layout", - description: r##"# `const_alloc_layout` + label: "const_array", + description: r##"# `const_array` -The tracking issue for this feature is: [#67521] -[#67521]: https://github.com/rust-lang/rust/issues/67521 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "const_array_as_mut_slice", - description: r##"# `const_array_as_mut_slice` +The tracking issue for this feature is: [#147606] -The tracking issue for this feature is: [#133333] - -[#133333]: https://github.com/rust-lang/rust/issues/133333 - ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "const_array_each_ref", - description: r##"# `const_array_each_ref` - -The tracking issue for this feature is: [#133289] - -[#133289]: https://github.com/rust-lang/rust/issues/133289 +[#147606]: https://github.com/rust-lang/rust/issues/147606 ------------------------ "##, @@ -4339,6 +5050,8 @@ fn foobar() -> u32 { 23 } label: "const_async_blocks", description: r##"# `const_async_blocks` +Allows `async {}` expressions in const contexts. + The tracking issue for this feature is: [#85368] [#85368]: https://github.com/rust-lang/rust/issues/85368 @@ -4350,10 +5063,14 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_black_box", - description: r##"# `const_black_box` + label: "const_block_items", + description: r##"# `const_block_items` -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +Allows `const { ... }` as a shorthand for `const _: () = const { ... };` for module items. + +The tracking issue for this feature is: [#149226] + +[#149226]: https://github.com/rust-lang/rust/issues/149226 ------------------------ "##, @@ -4362,12 +5079,14 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_box", - description: r##"# `const_box` + label: "const_bool", + description: r##"# `const_bool` -The tracking issue for this feature is: [#92521] -[#92521]: https://github.com/rust-lang/rust/issues/92521 + +The tracking issue for this feature is: [#151531] + +[#151531]: https://github.com/rust-lang/rust/issues/151531 ------------------------ "##, @@ -4379,6 +5098,8 @@ fn foobar() -> u32 { 23 } label: "const_btree_len", description: r##"# `const_btree_len` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -4388,12 +5109,14 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_cell", - description: r##"# `const_cell` + label: "const_c_variadic", + description: r##"# `const_c_variadic` -The tracking issue for this feature is: [#131283] +Allows defining and calling c-variadic functions in const contexts. -[#131283]: https://github.com/rust-lang/rust/issues/131283 +The tracking issue for this feature is: [#151787] + +[#151787]: https://github.com/rust-lang/rust/issues/151787 ------------------------ "##, @@ -4402,12 +5125,46 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_char_classify", - description: r##"# `const_char_classify` + label: "const_carrying_mul_add", + description: r##"# `const_carrying_mul_add` -The tracking issue for this feature is: [#132241] -[#132241]: https://github.com/rust-lang/rust/issues/132241 + +The tracking issue for this feature is: [#85532] + +[#85532]: https://github.com/rust-lang/rust/issues/85532 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_cell_traits", + description: r##"# `const_cell_traits` + + + +The tracking issue for this feature is: [#147787] + +[#147787]: https://github.com/rust-lang/rust/issues/147787 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_clone", + description: r##"# `const_clone` + + + +The tracking issue for this feature is: [#142757] + +[#142757]: https://github.com/rust-lang/rust/issues/142757 ------------------------ "##, @@ -4419,6 +5176,8 @@ fn foobar() -> u32 { 23 } label: "const_closures", description: r##"# `const_closures` +Allows `const || {}` closures in const contexts. + The tracking issue for this feature is: [#106003] [#106003]: https://github.com/rust-lang/rust/issues/106003 @@ -4430,12 +5189,62 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_copy_from_slice", - description: r##"# `const_copy_from_slice` + label: "const_cmp", + description: r##"# `const_cmp` -The tracking issue for this feature is: [#131415] -[#131415]: https://github.com/rust-lang/rust/issues/131415 + +The tracking issue for this feature is: [#143800] + +[#143800]: https://github.com/rust-lang/rust/issues/143800 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_control_flow", + description: r##"# `const_control_flow` + + + +The tracking issue for this feature is: [#148739] + +[#148739]: https://github.com/rust-lang/rust/issues/148739 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_convert", + description: r##"# `const_convert` + + + +The tracking issue for this feature is: [#143773] + +[#143773]: https://github.com/rust-lang/rust/issues/143773 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_default", + description: r##"# `const_default` + + + +The tracking issue for this feature is: [#143894] + +[#143894]: https://github.com/rust-lang/rust/issues/143894 ------------------------ "##, @@ -4447,10 +5256,42 @@ fn foobar() -> u32 { 23 } label: "const_destruct", description: r##"# `const_destruct` +Allows using `[const] Destruct` bounds and calling drop impls in const contexts. + The tracking issue for this feature is: [#133214] [#133214]: https://github.com/rust-lang/rust/issues/133214 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_drop_guard", + description: r##"# `const_drop_guard` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_drop_in_place", + description: r##"# `const_drop_in_place` + + + +The tracking issue for this feature is: [#109342] + +[#109342]: https://github.com/rust-lang/rust/issues/109342 + ------------------------ "##, default_severity: Severity::Allow, @@ -4461,6 +5302,8 @@ fn foobar() -> u32 { 23 } label: "const_eval_select", description: r##"# `const_eval_select` + + The tracking issue for this feature is: [#124625] [#124625]: https://github.com/rust-lang/rust/issues/124625 @@ -4475,6 +5318,8 @@ fn foobar() -> u32 { 23 } label: "const_for", description: r##"# `const_for` +Allows `for _ in _` loops in const contexts. + The tracking issue for this feature is: [#87575] [#87575]: https://github.com/rust-lang/rust/issues/87575 @@ -4489,6 +5334,8 @@ fn foobar() -> u32 { 23 } label: "const_format_args", description: r##"# `const_format_args` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -4501,6 +5348,8 @@ fn foobar() -> u32 { 23 } label: "const_heap", description: r##"# `const_heap` + + The tracking issue for this feature is: [#79597] [#79597]: https://github.com/rust-lang/rust/issues/79597 @@ -4512,12 +5361,14 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_is_char_boundary", - description: r##"# `const_is_char_boundary` + label: "const_index", + description: r##"# `const_index` -The tracking issue for this feature is: [#131516] -[#131516]: https://github.com/rust-lang/rust/issues/131516 + +The tracking issue for this feature is: [#143775] + +[#143775]: https://github.com/rust-lang/rust/issues/143775 ------------------------ "##, @@ -4526,12 +5377,124 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_mut_cursor", - description: r##"# `const_mut_cursor` + label: "const_iter", + description: r##"# `const_iter` -The tracking issue for this feature is: [#130801] -[#130801]: https://github.com/rust-lang/rust/issues/130801 + +The tracking issue for this feature is: [#92476] + +[#92476]: https://github.com/rust-lang/rust/issues/92476 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_manually_drop_take", + description: r##"# `const_manually_drop_take` + + + +The tracking issue for this feature is: [#148773] + +[#148773]: https://github.com/rust-lang/rust/issues/148773 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_never_short_circuit", + description: r##"# `const_never_short_circuit` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_nonnull_with_exposed_provenance", + description: r##"# `const_nonnull_with_exposed_provenance` + + + +The tracking issue for this feature is: [#154215] + +[#154215]: https://github.com/rust-lang/rust/issues/154215 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_ops", + description: r##"# `const_ops` + + + +The tracking issue for this feature is: [#143802] + +[#143802]: https://github.com/rust-lang/rust/issues/143802 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_option_ops", + description: r##"# `const_option_ops` + + + +The tracking issue for this feature is: [#143956] + +[#143956]: https://github.com/rust-lang/rust/issues/143956 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_param_ty_trait", + description: r##"# `const_param_ty_trait` + + + +The tracking issue for this feature is: [#95174] + +[#95174]: https://github.com/rust-lang/rust/issues/95174 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_path_separators", + description: r##"# `const_path_separators` + + + +The tracking issue for this feature is: [#153106] + +[#153106]: https://github.com/rust-lang/rust/issues/153106 ------------------------ "##, @@ -4543,6 +5506,8 @@ fn foobar() -> u32 { 23 } label: "const_precise_live_drops", description: r##"# `const_precise_live_drops` +Be more precise when looking for live drops in a const context. + The tracking issue for this feature is: [#73255] [#73255]: https://github.com/rust-lang/rust/issues/73255 @@ -4554,12 +5519,12 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_ptr_sub_ptr", - description: r##"# `const_ptr_sub_ptr` + label: "const_range", + description: r##"# `const_range` -The tracking issue for this feature is: [#95892] -[#95892]: https://github.com/rust-lang/rust/issues/95892 + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, @@ -4571,6 +5536,8 @@ fn foobar() -> u32 { 23 } label: "const_range_bounds", description: r##"# `const_range_bounds` + + The tracking issue for this feature is: [#108082] [#108082]: https://github.com/rust-lang/rust/issues/108082 @@ -4585,6 +5552,8 @@ fn foobar() -> u32 { 23 } label: "const_raw_ptr_comparison", description: r##"# `const_raw_ptr_comparison` + + The tracking issue for this feature is: [#53020] [#53020]: https://github.com/rust-lang/rust/issues/53020 @@ -4596,12 +5565,62 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_slice_flatten", - description: r##"# `const_slice_flatten` + label: "const_ref_cell", + description: r##"# `const_ref_cell` -The tracking issue for this feature is: [#95629] -[#95629]: https://github.com/rust-lang/rust/issues/95629 + +The tracking issue for this feature is: [#137844] + +[#137844]: https://github.com/rust-lang/rust/issues/137844 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_result_trait_fn", + description: r##"# `const_result_trait_fn` + + + +The tracking issue for this feature is: [#144211] + +[#144211]: https://github.com/rust-lang/rust/issues/144211 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_result_unwrap_unchecked", + description: r##"# `const_result_unwrap_unchecked` + + + +The tracking issue for this feature is: [#148714] + +[#148714]: https://github.com/rust-lang/rust/issues/148714 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "const_select_unpredictable", + description: r##"# `const_select_unpredictable` + + + +The tracking issue for this feature is: [#145938] + +[#145938]: https://github.com/rust-lang/rust/issues/145938 ------------------------ "##, @@ -4613,6 +5632,8 @@ fn foobar() -> u32 { 23 } label: "const_slice_from_mut_ptr_range", description: r##"# `const_slice_from_mut_ptr_range` + + The tracking issue for this feature is: [#89792] [#89792]: https://github.com/rust-lang/rust/issues/89792 @@ -4627,6 +5648,8 @@ fn foobar() -> u32 { 23 } label: "const_slice_from_ptr_range", description: r##"# `const_slice_from_ptr_range` + + The tracking issue for this feature is: [#89792] [#89792]: https://github.com/rust-lang/rust/issues/89792 @@ -4638,12 +5661,14 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_sockaddr_setters", - description: r##"# `const_sockaddr_setters` + label: "const_slice_make_iter", + description: r##"# `const_slice_make_iter` -The tracking issue for this feature is: [#131714] -[#131714]: https://github.com/rust-lang/rust/issues/131714 + +The tracking issue for this feature is: [#137737] + +[#137737]: https://github.com/rust-lang/rust/issues/137737 ------------------------ "##, @@ -4652,12 +5677,14 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_str_from_utf8", - description: r##"# `const_str_from_utf8` + label: "const_split_off_first_last", + description: r##"# `const_split_off_first_last` -The tracking issue for this feature is: [#91006] -[#91006]: https://github.com/rust-lang/rust/issues/91006 + +The tracking issue for this feature is: [#138539] + +[#138539]: https://github.com/rust-lang/rust/issues/138539 ------------------------ "##, @@ -4666,40 +5693,14 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_str_split_at", - description: r##"# `const_str_split_at` + label: "const_swap_with_slice", + description: r##"# `const_swap_with_slice` -The tracking issue for this feature is: [#131518] -[#131518]: https://github.com/rust-lang/rust/issues/131518 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "const_swap", - description: r##"# `const_swap` +The tracking issue for this feature is: [#142204] -The tracking issue for this feature is: [#83163] - -[#83163]: https://github.com/rust-lang/rust/issues/83163 - ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "const_swap_nonoverlapping", - description: r##"# `const_swap_nonoverlapping` - -The tracking issue for this feature is: [#133668] - -[#133668]: https://github.com/rust-lang/rust/issues/133668 +[#142204]: https://github.com/rust-lang/rust/issues/142204 ------------------------ "##, @@ -4711,6 +5712,8 @@ fn foobar() -> u32 { 23 } label: "const_trait_impl", description: r##"# `const_trait_impl` +Allows `impl const Trait for T` syntax. + The tracking issue for this feature is: [#143874] [#143874]: https://github.com/rust-lang/rust/issues/143874 @@ -4725,6 +5728,8 @@ fn foobar() -> u32 { 23 } label: "const_try", description: r##"# `const_try` +Allows the `?` operator in const contexts. + The tracking issue for this feature is: [#74935] [#74935]: https://github.com/rust-lang/rust/issues/74935 @@ -4736,12 +5741,14 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_type_id", - description: r##"# `const_type_id` + label: "const_try_residual", + description: r##"# `const_try_residual` -The tracking issue for this feature is: [#77125] -[#77125]: https://github.com/rust-lang/rust/issues/77125 + +The tracking issue for this feature is: [#91285] + +[#91285]: https://github.com/rust-lang/rust/issues/91285 ------------------------ "##, @@ -4753,6 +5760,8 @@ fn foobar() -> u32 { 23 } label: "const_type_name", description: r##"# `const_type_name` + + The tracking issue for this feature is: [#63084] [#63084]: https://github.com/rust-lang/rust/issues/63084 @@ -4764,24 +5773,14 @@ fn foobar() -> u32 { 23 } deny_since: None, }, Lint { - label: "const_typed_swap", - description: r##"# `const_typed_swap` + label: "const_unsigned_bigint_helpers", + description: r##"# `const_unsigned_bigint_helpers` -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "const_vec_string_slice", - description: r##"# `const_vec_string_slice` -The tracking issue for this feature is: [#129041] +The tracking issue for this feature is: [#152015] -[#129041]: https://github.com/rust-lang/rust/issues/129041 +[#152015]: https://github.com/rust-lang/rust/issues/152015 ------------------------ "##, @@ -4793,6 +5792,8 @@ fn foobar() -> u32 { 23 } label: "container_error_extra", description: r##"# `container_error_extra` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -4805,10 +5806,60 @@ fn foobar() -> u32 { 23 } label: "context_ext", description: r##"# `context_ext` + + The tracking issue for this feature is: [#123392] [#123392]: https://github.com/rust-lang/rust/issues/123392 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "contracts", + description: r##"# `contracts` + +Allows use of contracts attributes. + +The tracking issue for this feature is: [#128044] + +[#128044]: https://github.com/rust-lang/rust/issues/128044 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "contracts_internals", + description: r##"# `contracts_internals` + +Allows access to internal machinery used to implement contracts. + +The tracking issue for this feature is: [#128044] + +[#128044]: https://github.com/rust-lang/rust/issues/128044 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "control_flow_into_value", + description: r##"# `control_flow_into_value` + + + +The tracking issue for this feature is: [#137461] + +[#137461]: https://github.com/rust-lang/rust/issues/137461 + ------------------------ "##, default_severity: Severity::Allow, @@ -4819,10 +5870,42 @@ fn foobar() -> u32 { 23 } label: "convert_float_to_int", description: r##"# `convert_float_to_int` + + The tracking issue for this feature is: [#67057] [#67057]: https://github.com/rust-lang/rust/issues/67057 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "copied_into_inner", + description: r##"# `copied_into_inner` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "core_float_math", + description: r##"# `core_float_math` + + + +The tracking issue for this feature is: [#137578] + +[#137578]: https://github.com/rust-lang/rust/issues/137578 + ------------------------ "##, default_severity: Severity::Allow, @@ -4835,6 +5918,20 @@ fn foobar() -> u32 { 23 } This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "core_intrinsics_fallbacks", + description: r##"# `core_intrinsics_fallbacks` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, default_severity: Severity::Allow, @@ -4845,6 +5942,8 @@ fn foobar() -> u32 { 23 } label: "core_io_borrowed_buf", description: r##"# `core_io_borrowed_buf` + + The tracking issue for this feature is: [#117693] [#117693]: https://github.com/rust-lang/rust/issues/117693 @@ -4883,6 +5982,8 @@ fn foobar() -> u32 { 23 } label: "coroutine_clone", description: r##"# `coroutine_clone` +Allows coroutines to be cloned. + The tracking issue for this feature is: [#95360] [#95360]: https://github.com/rust-lang/rust/issues/95360 @@ -4897,6 +5998,8 @@ fn foobar() -> u32 { 23 } label: "coroutine_trait", description: r##"# `coroutine_trait` + + The tracking issue for this feature is: [#43122] [#43122]: https://github.com/rust-lang/rust/issues/43122 @@ -5202,6 +6305,8 @@ fn bar() { label: "cow_is_borrowed", description: r##"# `cow_is_borrowed` + + The tracking issue for this feature is: [#65143] [#65143]: https://github.com/rust-lang/rust/issues/65143 @@ -5216,9 +6321,11 @@ fn bar() { label: "csky_target_feature", description: r##"# `csky_target_feature` -The tracking issue for this feature is: [#44839] +Target features on csky. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150248] + +[#150248]: https://github.com/rust-lang/rust/issues/150248 ------------------------ "##, @@ -5230,10 +6337,28 @@ fn bar() { label: "cstr_bytes", description: r##"# `cstr_bytes` + + The tracking issue for this feature is: [#112115] [#112115]: https://github.com/rust-lang/rust/issues/112115 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "cstr_display", + description: r##"# `cstr_display` + + + +The tracking issue for this feature is: [#139984] + +[#139984]: https://github.com/rust-lang/rust/issues/139984 + ------------------------ "##, default_severity: Severity::Allow, @@ -5244,8 +6369,26 @@ fn bar() { label: "cstr_internals", description: r##"# `cstr_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "current_thread_id", + description: r##"# `current_thread_id` + + + +The tracking issue for this feature is: [#147194] + +[#147194]: https://github.com/rust-lang/rust/issues/147194 + ------------------------ "##, default_severity: Severity::Allow, @@ -5256,6 +6399,8 @@ fn bar() { label: "cursor_split", description: r##"# `cursor_split` + + The tracking issue for this feature is: [#86369] [#86369]: https://github.com/rust-lang/rust/issues/86369 @@ -5270,6 +6415,8 @@ fn bar() { label: "custom_inner_attributes", description: r##"# `custom_inner_attributes` +Allows non-builtin attributes in inner attribute position. + The tracking issue for this feature is: [#54726] [#54726]: https://github.com/rust-lang/rust/issues/54726 @@ -5284,6 +6431,8 @@ fn bar() { label: "custom_mir", description: r##"# `custom_mir` +Allows writing custom MIR + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -5326,6 +6475,22 @@ fn my_runner(tests: &[&i32]) { #[test_case] const WILL_FAIL: i32 = 4; ``` +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "darwin_objc", + description: r##"# `darwin_objc` + + + +The tracking issue for this feature is: [#145496] + +[#145496]: https://github.com/rust-lang/rust/issues/145496 + +------------------------ "##, default_severity: Severity::Allow, warn_since: None, @@ -5335,6 +6500,8 @@ fn my_runner(tests: &[&i32]) { label: "deadline_api", description: r##"# `deadline_api` + + The tracking issue for this feature is: [#46316] [#46316]: https://github.com/rust-lang/rust/issues/46316 @@ -5349,6 +6516,8 @@ fn my_runner(tests: &[&i32]) { label: "debug_closure_helpers", description: r##"# `debug_closure_helpers` + + The tracking issue for this feature is: [#117729] [#117729]: https://github.com/rust-lang/rust/issues/117729 @@ -5375,6 +6544,8 @@ fn my_runner(tests: &[&i32]) { label: "decl_macro", description: r##"# `decl_macro` +Allows declarative macros 2.0 (`macro`). + The tracking issue for this feature is: [#39412] [#39412]: https://github.com/rust-lang/rust/issues/39412 @@ -5393,21 +6564,93 @@ fn my_runner(tests: &[&i32]) { [#132162]: https://github.com/rust-lang/rust/issues/132162 +The RFC for this feature is: [#3681] + +[#3681]: https://github.com/rust-lang/rfcs/blob/master/text/3681-default-field-values.md + ------------------------ -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, + +The `default_field_values` feature allows users to specify a const value for +individual fields in struct definitions, allowing those to be omitted from +initializers. + +## Examples + +```rust +#![feature(default_field_values)] + +#[derive(Default)] +struct Pet { + name: Option, // impl Default for Pet will use Default::default() for name + age: i128 = 42, // impl Default for Pet will use the literal 42 for age +} + +fn main() { + let a = Pet { name: Some(String::new()), .. }; // Pet { name: Some(""), age: 42 } + let b = Pet::default(); // Pet { name: None, age: 42 } + assert_eq!(a.age, b.age); + // The following would be a compilation error: `name` needs to be specified + // let _ = Pet { .. }; +} +``` + +## `#[derive(Default)]` + +When deriving Default, the provided values are then used. On enum variants, +the variant must still be marked with `#[default]` and have all its fields +with default values. + +```rust +#![feature(default_field_values)] + +#[derive(Default)] +enum A { + #[default] + B { + x: i32 = 0, + y: i32 = 0, }, - Lint { - label: "deprecated_safe", - description: r##"# `deprecated_safe` + C, +} +``` -The tracking issue for this feature is: [#94978] +## Enum variants -[#94978]: https://github.com/rust-lang/rust/issues/94978 +This feature also supports enum variants for both specifying default values +and `#[derive(Default)]`. ------------------------- +## Interaction with `#[non_exhaustive]` + +A struct or enum variant marked with `#[non_exhaustive]` is not allowed to +have default field values. + +## Lints + +When manually implementing the `Default` trait for a type that has default +field values, if any of these are overridden in the impl the +`default_overrides_default_fields` lint will trigger. This lint is in place +to avoid surprising diverging behavior between `S { .. }` and +`S::default()`, where using the same type in both ways could result in +different values. The appropriate way to write a manual `Default` +implementation is to use the functional update syntax: + +```rust +#![feature(default_field_values)] + +struct Pet { + name: String, + age: i128 = 42, // impl Default for Pet will use the literal 42 for age +} + +impl Default for Pet { + fn default() -> Pet { + Pet { + name: "no-name".to_string(), + .. + } + } +} +``` "##, default_severity: Severity::Allow, warn_since: None, @@ -5417,10 +6660,28 @@ fn my_runner(tests: &[&i32]) { label: "deprecated_suggestion", description: r##"# `deprecated_suggestion` +Allows having using `suggestion` in the `#[deprecated]` attribute. + The tracking issue for this feature is: [#94785] [#94785]: https://github.com/rust-lang/rust/issues/94785 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "deque_extend_front", + description: r##"# `deque_extend_front` + + + +The tracking issue for this feature is: [#146975] + +[#146975]: https://github.com/rust-lang/rust/issues/146975 + ------------------------ "##, default_severity: Severity::Allow, @@ -5436,6 +6697,101 @@ fn my_runner(tests: &[&i32]) { [#87121]: https://github.com/rust-lang/rust/issues/87121 ------------------------ + +> **Note**: This feature supersedes [`box_patterns`]. + +This feature permits pattern matching on [smart pointers in the standard library] through their +`Deref` target types, either implicitly or with explicit `deref!(_)` patterns (the syntax of which +is currently a placeholder). + +```rust +#![feature(deref_patterns)] + +let mut v = vec![Box::new(Some(0))]; + +// Implicit dereferences are inserted when a pattern can match against the +// result of repeatedly dereferencing but can't match against a smart +// pointer itself. This works alongside match ergonomics for references. +if let [Some(x)] = &mut v { + *x += 1; +} + +// Explicit `deref!(_)` patterns may instead be used when finer control is +// needed, e.g. to dereference only a single smart pointer, or to bind the +// the result of dereferencing to a variable. +if let deref!([deref!(opt_x @ Some(1))]) = &mut v { + opt_x.as_mut().map(|x| *x += 1); +} + +assert_eq!(v, [Box::new(Some(2))]); +``` + +Without this feature, it may be necessary to introduce temporaries to represent dereferenced places +when matching on nested structures: + +```rust +let mut v = vec![Box::new(Some(0))]; +if let [b] = &mut *v { + if let Some(x) = &mut **b { + *x += 1; + } +} +if let [b] = &mut *v { + if let opt_x @ Some(1) = &mut **b { + opt_x.as_mut().map(|x| *x += 1); + } +} +assert_eq!(v, [Box::new(Some(2))]); +``` + +Like [`box_patterns`], deref patterns may move out of boxes: + +```rust +# #![feature(deref_patterns)] +struct NoCopy; +let deref!(x) = Box::new(NoCopy); +drop::(x); +``` + +Additionally, `deref_patterns` implements changes to string and byte string literal patterns, +allowing then to be used in deref patterns: + +```rust +# #![feature(deref_patterns)] +match ("test".to_string(), Box::from("test"), b"test".to_vec()) { + ("test", "test", b"test") => {} + _ => panic!(), +} + +// This works through multiple layers of reference and smart pointer: +match (&Box::new(&"test".to_string()), &&&"test") { + ("test", "test") => {} + _ => panic!(), +} + +// `deref!("...")` syntax may also be used: +match "test".to_string() { + deref!("test") => {} + _ => panic!(), +} + +// Matching on slices and arrays using literals is possible elsewhere as well: +match *"test" { + "test" => {} + _ => panic!(), +} +match *b"test" { + b"test" => {} + _ => panic!(), +} +match *(b"test" as &[u8]) { + b"test" => {} + _ => panic!(), +} +``` + +[`box_patterns`]: ./box-patterns.md +[smart pointers in the standard library]: https://doc.rust-lang.org/std/ops/trait.DerefPure.html#implementors "##, default_severity: Severity::Allow, warn_since: None, @@ -5445,6 +6801,8 @@ fn my_runner(tests: &[&i32]) { label: "deref_pure_trait", description: r##"# `deref_pure_trait` + + The tracking issue for this feature is: [#87121] [#87121]: https://github.com/rust-lang/rust/issues/87121 @@ -5456,8 +6814,8 @@ fn my_runner(tests: &[&i32]) { deny_since: None, }, Lint { - label: "derive_clone_copy", - description: r##"# `derive_clone_copy` + label: "derive_clone_copy_internals", + description: r##"# `derive_clone_copy_internals` This feature is internal to the Rust compiler and is not intended for general use. @@ -5471,6 +6829,8 @@ fn my_runner(tests: &[&i32]) { label: "derive_coerce_pointee", description: r##"# `derive_coerce_pointee` + + The tracking issue for this feature is: [#123430] [#123430]: https://github.com/rust-lang/rust/issues/123430 @@ -5485,7 +6845,11 @@ fn my_runner(tests: &[&i32]) { label: "derive_const", description: r##"# `derive_const` -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + + +The tracking issue for this feature is: [#118304] + +[#118304]: https://github.com/rust-lang/rust/issues/118304 ------------------------ "##, @@ -5494,11 +6858,75 @@ fn my_runner(tests: &[&i32]) { deny_since: None, }, Lint { - label: "derive_eq", - description: r##"# `derive_eq` + label: "derive_eq_internals", + description: r##"# `derive_eq_internals` This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "derive_from", + description: r##"# `derive_from` + +Allows deriving the From trait on single-field structs. + +The tracking issue for this feature is: [#144889] + +[#144889]: https://github.com/rust-lang/rust/issues/144889 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "derive_macro_global_path", + description: r##"# `derive_macro_global_path` + + + +The tracking issue for this feature is: [#154645] + +[#154645]: https://github.com/rust-lang/rust/issues/154645 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "diagnostic_on_const", + description: r##"# `diagnostic_on_const` + +Allows giving non-const impls custom diagnostic messages if attempted to be used as const + +The tracking issue for this feature is: [#143874] + +[#143874]: https://github.com/rust-lang/rust/issues/143874 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "diagnostic_on_move", + description: r##"# `diagnostic_on_move` + +Allows giving on-move borrowck custom diagnostic messages for a type + +The tracking issue for this feature is: [#154181] + +[#154181]: https://github.com/rust-lang/rust/issues/154181 + ------------------------ "##, default_severity: Severity::Allow, @@ -5509,10 +6937,44 @@ fn my_runner(tests: &[&i32]) { label: "dir_entry_ext2", description: r##"# `dir_entry_ext2` + + The tracking issue for this feature is: [#85573] [#85573]: https://github.com/rust-lang/rust/issues/85573 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "dirfd", + description: r##"# `dirfd` + + + +The tracking issue for this feature is: [#120426] + +[#120426]: https://github.com/rust-lang/rust/issues/120426 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "dirhandle", + description: r##"# `dirhandle` + + + +The tracking issue for this feature is: [#120426] + +[#120426]: https://github.com/rust-lang/rust/issues/120426 + ------------------------ "##, default_severity: Severity::Allow, @@ -5523,8 +6985,26 @@ fn my_runner(tests: &[&i32]) { label: "discriminant_kind", description: r##"# `discriminant_kind` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "disjoint_bitor", + description: r##"# `disjoint_bitor` + + + +The tracking issue for this feature is: [#135758] + +[#135758]: https://github.com/rust-lang/rust/issues/135758 + ------------------------ "##, default_severity: Severity::Allow, @@ -5535,36 +7015,10 @@ fn my_runner(tests: &[&i32]) { label: "dispatch_from_dyn", description: r##"# `dispatch_from_dyn` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "do_not_recommend", - description: r##"# `do_not_recommend` - -The tracking issue for this feature is: [#51992] - -[#51992]: https://github.com/rust-lang/rust/issues/51992 - ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "doc_auto_cfg", - description: r##"# `doc_auto_cfg` - -The tracking issue for this feature is: [#43781] - -[#43781]: https://github.com/rust-lang/rust/issues/43781 - ------------------------ "##, default_severity: Severity::Allow, @@ -5619,20 +7073,6 @@ pub struct Icon { [#43781]: https://github.com/rust-lang/rust/issues/43781 [#43348]: https://github.com/rust-lang/rust/issues/43348 -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "doc_cfg_hide", - description: r##"# `doc_cfg_hide` - -The tracking issue for this feature is: [#43781] - -[#43781]: https://github.com/rust-lang/rust/issues/43781 - ------------------------- "##, default_severity: Severity::Allow, warn_since: None, @@ -5713,6 +7153,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "downcast_unchecked", description: r##"# `downcast_unchecked` + + The tracking issue for this feature is: [#90850] [#90850]: https://github.com/rust-lang/rust/issues/90850 @@ -5727,10 +7169,28 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "drain_keep_rest", description: r##"# `drain_keep_rest` + + The tracking issue for this feature is: [#101122] [#101122]: https://github.com/rust-lang/rust/issues/101122 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "drop_guard", + description: r##"# `drop_guard` + + + +The tracking issue for this feature is: [#144426] + +[#144426]: https://github.com/rust-lang/rust/issues/144426 + ------------------------ "##, default_severity: Severity::Allow, @@ -5741,6 +7201,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "dropck_eyepatch", description: r##"# `dropck_eyepatch` +Allows using the `may_dangle` attribute (RFC 1327). + The tracking issue for this feature is: [#34761] [#34761]: https://github.com/rust-lang/rust/issues/34761 @@ -5755,6 +7217,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "duration_constants", description: r##"# `duration_constants` + + The tracking issue for this feature is: [#57391] [#57391]: https://github.com/rust-lang/rust/issues/57391 @@ -5776,6 +7240,22 @@ pub fn my_fn() -> MyStruct { MyStruct } ------------------------ Add the methods `from_days` and `from_weeks` to `Duration`. +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "duration_integer_division", + description: r##"# `duration_integer_division` + + + +The tracking issue for this feature is: [#149573] + +[#149573]: https://github.com/rust-lang/rust/issues/149573 + +------------------------ "##, default_severity: Severity::Allow, warn_since: None, @@ -5785,6 +7265,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "duration_millis_float", description: r##"# `duration_millis_float` + + The tracking issue for this feature is: [#122451] [#122451]: https://github.com/rust-lang/rust/issues/122451 @@ -5799,38 +7281,12 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "duration_units", description: r##"# `duration_units` + + The tracking issue for this feature is: [#120301] [#120301]: https://github.com/rust-lang/rust/issues/120301 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "dyn_compatible_for_dispatch", - description: r##"# `dyn_compatible_for_dispatch` - -The tracking issue for this feature is: [#43561] - -[#43561]: https://github.com/rust-lang/rust/issues/43561 - ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "dyn_star", - description: r##"# `dyn_star` - -The tracking issue for this feature is: [#102425] - -[#102425]: https://github.com/rust-lang/rust/issues/102425 - ------------------------ "##, default_severity: Severity::Allow, @@ -5841,8 +7297,56 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "edition_panic", description: r##"# `edition_panic` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "effective_target_features", + description: r##"# `effective_target_features` + +Allows features to allow target_feature to better interact with traits. + +The tracking issue for this feature is: [#143352] + +[#143352]: https://github.com/rust-lang/rust/issues/143352 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "eii_internals", + description: r##"# `eii_internals` + +Implementation details of externally implementable items + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "ergonomic_clones", + description: r##"# `ergonomic_clones` + +Allows the .use postfix syntax `x.use` and use closures `use |x| { ... }` + +The tracking issue for this feature is: [#132290] + +[#132290]: https://github.com/rust-lang/rust/issues/132290 + ------------------------ "##, default_severity: Severity::Allow, @@ -5853,9 +7357,11 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "ermsb_target_feature", description: r##"# `ermsb_target_feature` -The tracking issue for this feature is: [#44839] +ermsb target feature on x86. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150249] + +[#150249]: https://github.com/rust-lang/rust/issues/150249 ------------------------ "##, @@ -5867,6 +7373,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "error_generic_member_access", description: r##"# `error_generic_member_access` + + The tracking issue for this feature is: [#99301] [#99301]: https://github.com/rust-lang/rust/issues/99301 @@ -5881,6 +7389,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "error_iter", description: r##"# `error_iter` + + The tracking issue for this feature is: [#58520] [#58520]: https://github.com/rust-lang/rust/issues/58520 @@ -5895,6 +7405,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "error_reporter", description: r##"# `error_reporter` + + The tracking issue for this feature is: [#90172] [#90172]: https://github.com/rust-lang/rust/issues/90172 @@ -5909,10 +7421,44 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "error_type_id", description: r##"# `error_type_id` + + The tracking issue for this feature is: [#60784] [#60784]: https://github.com/rust-lang/rust/issues/60784 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "exact_bitshifts", + description: r##"# `exact_bitshifts` + + + +The tracking issue for this feature is: [#144336] + +[#144336]: https://github.com/rust-lang/rust/issues/144336 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "exact_div", + description: r##"# `exact_div` + + + +The tracking issue for this feature is: [#139911] + +[#139911]: https://github.com/rust-lang/rust/issues/139911 + ------------------------ "##, default_severity: Severity::Allow, @@ -5923,6 +7469,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "exact_size_is_empty", description: r##"# `exact_size_is_empty` + + The tracking issue for this feature is: [#35428] [#35428]: https://github.com/rust-lang/rust/issues/35428 @@ -5937,6 +7485,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "exclusive_wrapper", description: r##"# `exclusive_wrapper` + + The tracking issue for this feature is: [#98407] [#98407]: https://github.com/rust-lang/rust/issues/98407 @@ -5951,6 +7501,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "exhaustive_patterns", description: r##"# `exhaustive_patterns` +Allows exhaustive pattern matching on types that contain uninhabited types. + The tracking issue for this feature is: [#51085] [#51085]: https://github.com/rust-lang/rust/issues/51085 @@ -5965,6 +7517,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "exit_status_error", description: r##"# `exit_status_error` + + The tracking issue for this feature is: [#84908] [#84908]: https://github.com/rust-lang/rust/issues/84908 @@ -5979,11 +7533,45 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "exitcode_exit_method", description: r##"# `exitcode_exit_method` + + The tracking issue for this feature is: [#97100] [#97100]: https://github.com/rust-lang/rust/issues/97100 ------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "explicit_extern_abis", + description: r##"# `explicit_extern_abis` + +The tracking issue for this feature is: [#134986] + +------ + +Disallow `extern` without an explicit ABI. We should write `extern "C"` +(or another ABI) instead of just `extern`. + +By making the ABI explicit, it becomes much clearer that "C" is just one of the +possible choices, rather than the "standard" way for external functions. +Removing the default makes it easier to add a new ABI on equal footing as "C". + +```rust,editionfuture,compile_fail +#![feature(explicit_extern_abis)] + +extern fn function1() {} // ERROR `extern` declarations without an explicit ABI + // are disallowed + +extern "C" fn function2() {} // compiles + +extern "aapcs" fn function3() {} // compiles +``` + +[#134986]: https://github.com/rust-lang/rust/issues/134986 "##, default_severity: Severity::Allow, warn_since: None, @@ -5993,10 +7581,28 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "explicit_tail_calls", description: r##"# `explicit_tail_calls` +Allows explicit tail calls via `become` expression. + The tracking issue for this feature is: [#112788] [#112788]: https://github.com/rust-lang/rust/issues/112788 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "export_stable", + description: r##"# `export_stable` + +Allows using `#[export_stable]` which indicates that an item is exportable. + +The tracking issue for this feature is: [#139939] + +[#139939]: https://github.com/rust-lang/rust/issues/139939 + ------------------------ "##, default_severity: Severity::Allow, @@ -6007,6 +7613,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "extend_one", description: r##"# `extend_one` + + The tracking issue for this feature is: [#72631] [#72631]: https://github.com/rust-lang/rust/issues/72631 @@ -6021,8 +7629,26 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "extend_one_unchecked", description: r##"# `extend_one_unchecked` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "extern_item_impls", + description: r##"# `extern_item_impls` + +Externally implementable items + +The tracking issue for this feature is: [#125418] + +[#125418]: https://github.com/rust-lang/rust/issues/125418 + ------------------------ "##, default_severity: Severity::Allow, @@ -6033,24 +7659,12 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "extern_types", description: r##"# `extern_types` +Allows defining `extern type`s. + The tracking issue for this feature is: [#43467] [#43467]: https://github.com/rust-lang/rust/issues/43467 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "extract_if", - description: r##"# `extract_if` - -The tracking issue for this feature is: [#43244] - -[#43244]: https://github.com/rust-lang/rust/issues/43244 - ------------------------ "##, default_severity: Severity::Allow, @@ -6067,7 +7681,7 @@ pub fn my_fn() -> MyStruct { MyStruct } --- -Enable the `f128` type for IEEE 128-bit floating numbers (quad precision). +Enable the `f128` type for IEEE 128-bit floating numbers (quad precision). "##, default_severity: Severity::Allow, warn_since: None, @@ -6083,7 +7697,7 @@ pub fn my_fn() -> MyStruct { MyStruct } --- -Enable the `f16` type for IEEE 16-bit floating numbers (half precision). +Enable the `f16` type for IEEE 16-bit floating numbers (half precision). "##, default_severity: Severity::Allow, warn_since: None, @@ -6095,18 +7709,6 @@ pub fn my_fn() -> MyStruct { MyStruct } This feature is internal to the Rust compiler and is not intended for general use. ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "fd_read", - description: r##"# `fd_read` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------ "##, default_severity: Severity::Allow, @@ -6230,6 +7832,36 @@ pub fn my_fn() -> MyStruct { MyStruct } [ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacigdac.html [GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute [IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_pure.htm +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "field_projections", + description: r##"# `field_projections` + +Experimental field projections. + +The tracking issue for this feature is: [#145383] + +[#145383]: https://github.com/rust-lang/rust/issues/145383 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "field_representing_type_raw", + description: r##"# `field_representing_type_raw` + +Implementation details of field representing types. + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ "##, default_severity: Severity::Allow, warn_since: None, @@ -6239,6 +7871,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "file_buffered", description: r##"# `file_buffered` + + The tracking issue for this feature is: [#130804] [#130804]: https://github.com/rust-lang/rust/issues/130804 @@ -6250,12 +7884,78 @@ pub fn my_fn() -> MyStruct { MyStruct } deny_since: None, }, Lint { - label: "file_lock", - description: r##"# `file_lock` + label: "final_associated_functions", + description: r##"# `final_associated_functions` -The tracking issue for this feature is: [#130994] +Allows marking trait functions as `final` to prevent overriding impls -[#130994]: https://github.com/rust-lang/rust/issues/130994 +The tracking issue for this feature is: [#131179] + +[#131179]: https://github.com/rust-lang/rust/issues/131179 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "float_algebraic", + description: r##"# `float_algebraic` + + + +The tracking issue for this feature is: [#136469] + +[#136469]: https://github.com/rust-lang/rust/issues/136469 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "float_bits_const", + description: r##"# `float_bits_const` + + + +The tracking issue for this feature is: [#151073] + +[#151073]: https://github.com/rust-lang/rust/issues/151073 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "float_erf", + description: r##"# `float_erf` + + + +The tracking issue for this feature is: [#136321] + +[#136321]: https://github.com/rust-lang/rust/issues/136321 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "float_exact_integer_constants", + description: r##"# `float_exact_integer_constants` + + + +The tracking issue for this feature is: [#152466] + +[#152466]: https://github.com/rust-lang/rust/issues/152466 ------------------------ "##, @@ -6267,6 +7967,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "float_gamma", description: r##"# `float_gamma` + + The tracking issue for this feature is: [#99842] [#99842]: https://github.com/rust-lang/rust/issues/99842 @@ -6281,24 +7983,12 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "float_minimum_maximum", description: r##"# `float_minimum_maximum` + + The tracking issue for this feature is: [#91079] [#91079]: https://github.com/rust-lang/rust/issues/91079 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "float_next_up_down", - description: r##"# `float_next_up_down` - -The tracking issue for this feature is: [#91399] - -[#91399]: https://github.com/rust-lang/rust/issues/91399 - ------------------------ "##, default_severity: Severity::Allow, @@ -6311,6 +8001,22 @@ pub fn my_fn() -> MyStruct { MyStruct } This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "fmt_arguments_from_str", + description: r##"# `fmt_arguments_from_str` + + + +The tracking issue for this feature is: [#148905] + +[#148905]: https://github.com/rust-lang/rust/issues/148905 + ------------------------ "##, default_severity: Severity::Allow, @@ -6321,6 +8027,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "fmt_debug", description: r##"# `fmt_debug` +Controlling the behavior of fmt::Debug + The tracking issue for this feature is: [#129709] [#129709]: https://github.com/rust-lang/rust/issues/129709 @@ -6335,6 +8043,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "fmt_helpers_for_derive", description: r##"# `fmt_helpers_for_derive` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -6359,6 +8069,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "fn_align", description: r##"# `fn_align` +Allows using `#[align(...)]` on function items + The tracking issue for this feature is: [#82232] [#82232]: https://github.com/rust-lang/rust/issues/82232 @@ -6373,6 +8085,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "fn_delegation", description: r##"# `fn_delegation` +Support delegating implementation of functions to other already implemented functions. + The tracking issue for this feature is: [#118212] [#118212]: https://github.com/rust-lang/rust/issues/118212 @@ -6387,6 +8101,8 @@ pub fn my_fn() -> MyStruct { MyStruct } label: "fn_ptr_trait", description: r##"# `fn_ptr_trait` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -6441,6 +8157,8 @@ fn main() { label: "forget_unsized", description: r##"# `forget_unsized` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -6453,6 +8171,8 @@ fn main() { label: "format_args_nl", description: r##"# `format_args_nl` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -6465,6 +8185,8 @@ fn main() { label: "formatting_options", description: r##"# `formatting_options` + + The tracking issue for this feature is: [#118117] [#118117]: https://github.com/rust-lang/rust/issues/118117 @@ -6479,6 +8201,8 @@ fn main() { label: "freeze", description: r##"# `freeze` + + The tracking issue for this feature is: [#121675] [#121675]: https://github.com/rust-lang/rust/issues/121675 @@ -6493,10 +8217,60 @@ fn main() { label: "freeze_impls", description: r##"# `freeze_impls` +Allows impls for the Freeze trait. + The tracking issue for this feature is: [#121675] [#121675]: https://github.com/rust-lang/rust/issues/121675 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "frontmatter", + description: r##"# `frontmatter` + +The tracking issue for this feature is: [#136889] + +------ + +The `frontmatter` feature allows an extra metadata block at the top of files for consumption by +external tools. For example, it can be used by [`cargo-script`] files to specify dependencies. + +```rust +#!/usr/bin/env -S cargo -Zscript +--- +[dependencies] +libc = "0.2.172" +--- +#![feature(frontmatter)] +# mod libc { pub type c_int = i32; } + +fn main() { + let x: libc::c_int = 1i32; +} +``` + +[#136889]: https://github.com/rust-lang/rust/issues/136889 +[`cargo-script`]: https://rust-lang.github.io/rfcs/3502-cargo-script.html +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "fs_set_times", + description: r##"# `fs_set_times` + + + +The tracking issue for this feature is: [#147455] + +[#147455]: https://github.com/rust-lang/rust/issues/147455 + ------------------------ "##, default_severity: Severity::Allow, @@ -6507,10 +8281,28 @@ fn main() { label: "fundamental", description: r##"# `fundamental` +Allows using the `#[fundamental]` attribute. + The tracking issue for this feature is: [#29635] [#29635]: https://github.com/rust-lang/rust/issues/29635 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "funnel_shifts", + description: r##"# `funnel_shifts` + + + +The tracking issue for this feature is: [#145686] + +[#145686]: https://github.com/rust-lang/rust/issues/145686 + ------------------------ "##, default_severity: Severity::Allow, @@ -6521,6 +8313,8 @@ fn main() { label: "future_join", description: r##"# `future_join` + + The tracking issue for this feature is: [#91642] [#91642]: https://github.com/rust-lang/rust/issues/91642 @@ -6535,6 +8329,8 @@ fn main() { label: "gen_blocks", description: r##"# `gen_blocks` +Allows defining gen blocks and `gen fn`. + The tracking issue for this feature is: [#117078] [#117078]: https://github.com/rust-lang/rust/issues/117078 @@ -6549,23 +8345,9 @@ fn main() { label: "gen_future", description: r##"# `gen_future` -The tracking issue for this feature is: [#50547] -[#50547]: https://github.com/rust-lang/rust/issues/50547 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "generic_arg_infer", - description: r##"# `generic_arg_infer` - -The tracking issue for this feature is: [#85077] - -[#85077]: https://github.com/rust-lang/rust/issues/85077 +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, @@ -6577,6 +8359,8 @@ fn main() { label: "generic_assert", description: r##"# `generic_assert` +Outputs useful `assert!` messages + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -6589,10 +8373,44 @@ fn main() { label: "generic_assert_internals", description: r##"# `generic_assert_internals` + + The tracking issue for this feature is: [#44838] [#44838]: https://github.com/rust-lang/rust/issues/44838 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "generic_atomic", + description: r##"# `generic_atomic` + + + +The tracking issue for this feature is: [#130539] + +[#130539]: https://github.com/rust-lang/rust/issues/130539 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "generic_const_args", + description: r##"# `generic_const_args` + +Allows using generics in more complex const expressions, based on definitional equality. + +The tracking issue for this feature is: [#151972] + +[#151972]: https://github.com/rust-lang/rust/issues/151972 + ------------------------ "##, default_severity: Severity::Allow, @@ -6603,6 +8421,8 @@ fn main() { label: "generic_const_exprs", description: r##"# `generic_const_exprs` +Allows non-trivial generic constants which have to have wfness manually propagated to callers + The tracking issue for this feature is: [#76560] [#76560]: https://github.com/rust-lang/rust/issues/76560 @@ -6617,6 +8437,8 @@ fn main() { label: "generic_const_items", description: r##"# `generic_const_items` +Allows generic parameters and where-clauses on free & associated const items. + The tracking issue for this feature is: [#113521] [#113521]: https://github.com/rust-lang/rust/issues/113521 @@ -6628,12 +8450,14 @@ fn main() { deny_since: None, }, Lint { - label: "get_many_mut", - description: r##"# `get_many_mut` + label: "generic_const_parameter_types", + description: r##"# `generic_const_parameter_types` -The tracking issue for this feature is: [#104642] +Allows the type of const generics to depend on generic parameters -[#104642]: https://github.com/rust-lang/rust/issues/104642 +The tracking issue for this feature is: [#137626] + +[#137626]: https://github.com/rust-lang/rust/issues/137626 ------------------------ "##, @@ -6642,8 +8466,26 @@ fn main() { deny_since: None, }, Lint { - label: "get_many_mut_helpers", - description: r##"# `get_many_mut_helpers` + label: "generic_pattern_types", + description: r##"# `generic_pattern_types` + +Allows any generic constants being used as pattern type range ends + +The tracking issue for this feature is: [#136574] + +[#136574]: https://github.com/rust-lang/rust/issues/136574 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "get_disjoint_mut_helpers", + description: r##"# `get_disjoint_mut_helpers` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. @@ -6657,10 +8499,28 @@ fn main() { label: "get_mut_unchecked", description: r##"# `get_mut_unchecked` + + The tracking issue for this feature is: [#63292] [#63292]: https://github.com/rust-lang/rust/issues/63292 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "gethostname", + description: r##"# `gethostname` + + + +The tracking issue for this feature is: [#135142] + +[#135142]: https://github.com/rust-lang/rust/issues/135142 + ------------------------ "##, default_severity: Severity::Allow, @@ -6671,10 +8531,26 @@ fn main() { label: "global_registration", description: r##"# `global_registration` +Allows registering static items globally, possibly across crates, to iterate over at runtime. + The tracking issue for this feature is: [#125119] [#125119]: https://github.com/rust-lang/rust/issues/125119 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "gpu_intrinsics", + description: r##"# `gpu_intrinsics` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, default_severity: Severity::Allow, @@ -6685,6 +8561,8 @@ fn main() { label: "guard_patterns", description: r##"# `guard_patterns` +Allows using guards in patterns. + The tracking issue for this feature is: [#129967] [#129967]: https://github.com/rust-lang/rust/issues/129967 @@ -6732,12 +8610,12 @@ fn main() { deny_since: None, }, Lint { - label: "hash_extract_if", - description: r##"# `hash_extract_if` + label: "hash_map_internals", + description: r##"# `hash_map_internals` -The tracking issue for this feature is: [#59618] -[#59618]: https://github.com/rust-lang/rust/issues/59618 + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, @@ -6746,12 +8624,14 @@ fn main() { deny_since: None, }, Lint { - label: "hash_raw_entry", - description: r##"# `hash_raw_entry` + label: "hash_map_macro", + description: r##"# `hash_map_macro` -The tracking issue for this feature is: [#56167] -[#56167]: https://github.com/rust-lang/rust/issues/56167 + +The tracking issue for this feature is: [#144032] + +[#144032]: https://github.com/rust-lang/rust/issues/144032 ------------------------ "##, @@ -6763,6 +8643,8 @@ fn main() { label: "hash_set_entry", description: r##"# `hash_set_entry` + + The tracking issue for this feature is: [#60896] [#60896]: https://github.com/rust-lang/rust/issues/60896 @@ -6777,6 +8659,8 @@ fn main() { label: "hasher_prefixfree_extras", description: r##"# `hasher_prefixfree_extras` + + The tracking issue for this feature is: [#96762] [#96762]: https://github.com/rust-lang/rust/issues/96762 @@ -6791,6 +8675,8 @@ fn main() { label: "hashmap_internals", description: r##"# `hashmap_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -6803,9 +8689,11 @@ fn main() { label: "hexagon_target_feature", description: r##"# `hexagon_target_feature` -The tracking issue for this feature is: [#44839] +Target features on hexagon. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150250] + +[#150250]: https://github.com/rust-lang/rust/issues/150250 ------------------------ "##, @@ -6817,6 +8705,8 @@ fn main() { label: "hint_must_use", description: r##"# `hint_must_use` + + The tracking issue for this feature is: [#94745] [#94745]: https://github.com/rust-lang/rust/issues/94745 @@ -6828,12 +8718,30 @@ fn main() { deny_since: None, }, Lint { - label: "if_let_guard", - description: r##"# `if_let_guard` + label: "hint_prefetch", + description: r##"# `hint_prefetch` -The tracking issue for this feature is: [#51114] -[#51114]: https://github.com/rust-lang/rust/issues/51114 + +The tracking issue for this feature is: [#146941] + +[#146941]: https://github.com/rust-lang/rust/issues/146941 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "impl_restriction", + description: r##"# `impl_restriction` + +Allows `impl(crate) trait Foo` restrictions. + +The tracking issue for this feature is: [#105077] + +[#105077]: https://github.com/rust-lang/rust/issues/105077 ------------------------ "##, @@ -6845,10 +8753,28 @@ fn main() { label: "impl_trait_in_assoc_type", description: r##"# `impl_trait_in_assoc_type` +Allows `impl Trait` to be used inside associated types (RFC 2515). + The tracking issue for this feature is: [#63063] [#63063]: https://github.com/rust-lang/rust/issues/63063 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "impl_trait_in_bindings", + description: r##"# `impl_trait_in_bindings` + +Allows `impl Trait` in bindings (`let`). + +The tracking issue for this feature is: [#63065] + +[#63065]: https://github.com/rust-lang/rust/issues/63065 + ------------------------ "##, default_severity: Severity::Allow, @@ -6859,11 +8785,42 @@ fn main() { label: "impl_trait_in_fn_trait_return", description: r##"# `impl_trait_in_fn_trait_return` +Allows `impl Trait` as output type in `Fn` traits in return position of functions. + The tracking issue for this feature is: [#99697] [#99697]: https://github.com/rust-lang/rust/issues/99697 ------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "import_trait_associated_functions", + description: r##"# import_trait_associated_functions + +The tracking issue for this feature is: [#134691] + +[#134691]: https://github.com/rust-lang/rust/issues/134691 + +------------------------ + +This feature allows importing associated functions and constants from traits and then using them like regular items. + +```rust +#![feature(import_trait_associated_functions)] + +use std::ops::Add::add; + +fn main() { + let numbers = vec![1, 2, 3, 4, 5, 6]; + let sum = numbers.into_iter().reduce(add); // instead of `.reduce(Add:add)` + + assert_eq!(sum, Some(21)); +} +``` "##, default_severity: Severity::Allow, warn_since: None, @@ -6873,40 +8830,13 @@ fn main() { label: "inherent_associated_types", description: r##"# `inherent_associated_types` +Allows associated types in inherent impls. + The tracking issue for this feature is: [#8995] [#8995]: https://github.com/rust-lang/rust/issues/8995 ------------------------ -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "inline_const_pat", - description: r##"# `inline_const_pat` - -The tracking issue for this feature is: [#76001] - ------- - -This feature allows you to use inline constant expressions in pattern position: - -```rust -#![feature(inline_const_pat)] - -const fn one() -> i32 { 1 } - -let some_int = 3; -match some_int { - const { 1 + 2 } => println!("Matched 1 + 2"), - const { one() } => println!("Matched const fn returning 1"), - _ => println!("Didn't match anything :("), -} -``` - -[#76001]: https://github.com/rust-lang/rust/issues/76001 "##, default_severity: Severity::Allow, warn_since: None, @@ -6916,8 +8846,58 @@ const fn one() -> i32 { 1 } label: "inplace_iteration", description: r##"# `inplace_iteration` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "int_format_into", + description: r##"# `int_format_into` + + + +The tracking issue for this feature is: [#138215] + +[#138215]: https://github.com/rust-lang/rust/issues/138215 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "int_from_ascii", + description: r##"# `int_from_ascii` + + + +The tracking issue for this feature is: [#134821] + +[#134821]: https://github.com/rust-lang/rust/issues/134821 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "int_lowest_highest_one", + description: r##"# `int_lowest_highest_one` + + + +The tracking issue for this feature is: [#145203] + +[#145203]: https://github.com/rust-lang/rust/issues/145203 + ------------------------ "##, default_severity: Severity::Allow, @@ -6928,6 +8908,8 @@ const fn one() -> i32 { 1 } label: "int_roundings", description: r##"# `int_roundings` + + The tracking issue for this feature is: [#88581] [#88581]: https://github.com/rust-lang/rust/issues/88581 @@ -6942,6 +8924,8 @@ const fn one() -> i32 { 1 } label: "integer_atomics", description: r##"# `integer_atomics` + + The tracking issue for this feature is: [#99069] [#99069]: https://github.com/rust-lang/rust/issues/99069 @@ -6953,24 +8937,14 @@ const fn one() -> i32 { 1 } deny_since: None, }, Lint { - label: "integer_sign_cast", - description: r##"# `integer_sign_cast` + label: "integer_extend_truncate", + description: r##"# `integer_extend_truncate` -The tracking issue for this feature is: [#125882] -[#125882]: https://github.com/rust-lang/rust/issues/125882 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "internal_impls_macro", - description: r##"# `internal_impls_macro` +The tracking issue for this feature is: [#154330] -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +[#154330]: https://github.com/rust-lang/rust/issues/154330 ------------------------ "##, @@ -7068,9 +9042,9 @@ mod foo { Various intrinsics have native MIR operations that they correspond to. Instead of requiring backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass will convert the calls to the MIR operation. Backends do not need to know about these intrinsics -at all. These intrinsics only make sense without a body, and can either be declared as a "rust-intrinsic" -or as a `#[rustc_intrinsic]`. The body is never used, as calls to the intrinsic do not exist -anymore after MIR analyses. +at all. These intrinsics only make sense without a body, and can be declared as a `#[rustc_intrinsic]`. +The body is never used as the lowering pass implements support for all backends, so we never have to +use the fallback logic. ## Intrinsics without fallback logic @@ -7078,33 +9052,14 @@ mod foo { ### `#[rustc_intrinsic]` declarations -These are written like intrinsics with fallback bodies, but the body is irrelevant. -Use `loop {}` for the body or call the intrinsic recursively and add -`#[rustc_intrinsic_must_be_overridden]` to the function to ensure that backends don't -invoke the body. - -### Legacy extern ABI based intrinsics - -These are imported as if they were FFI functions, with the special -`rust-intrinsic` ABI. For example, if one was in a freestanding -context, but wished to be able to `transmute` between types, and -perform efficient pointer arithmetic, one would import those functions -via a declaration like - +These are written without a body: ```rust #![feature(intrinsics)] #![allow(internal_features)] -# fn main() {} -extern "rust-intrinsic" { - fn transmute(x: T) -> U; - - fn arith_offset(dst: *const T, offset: isize) -> *const T; -} +#[rustc_intrinsic] +pub fn abort() -> !; ``` - -As with any other FFI functions, these are by default always `unsafe` to call. -You can add `#[rustc_safe_intrinsic]` to the intrinsic to make it safe to call. "##, default_severity: Severity::Allow, warn_since: None, @@ -7114,6 +9069,8 @@ mod foo { label: "io_const_error", description: r##"# `io_const_error` + + The tracking issue for this feature is: [#133448] [#133448]: https://github.com/rust-lang/rust/issues/133448 @@ -7128,6 +9085,8 @@ mod foo { label: "io_const_error_internals", description: r##"# `io_const_error_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -7140,6 +9099,8 @@ mod foo { label: "io_error_inprogress", description: r##"# `io_error_inprogress` + + The tracking issue for this feature is: [#130840] [#130840]: https://github.com/rust-lang/rust/issues/130840 @@ -7154,6 +9115,8 @@ mod foo { label: "io_error_more", description: r##"# `io_error_more` + + The tracking issue for this feature is: [#86442] [#86442]: https://github.com/rust-lang/rust/issues/86442 @@ -7168,6 +9131,8 @@ mod foo { label: "io_error_uncategorized", description: r##"# `io_error_uncategorized` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -7180,6 +9145,8 @@ mod foo { label: "io_slice_as_bytes", description: r##"# `io_slice_as_bytes` + + The tracking issue for this feature is: [#132818] [#132818]: https://github.com/rust-lang/rust/issues/132818 @@ -7194,6 +9161,8 @@ mod foo { label: "ip", description: r##"# `ip` + + The tracking issue for this feature is: [#27709] [#27709]: https://github.com/rust-lang/rust/issues/27709 @@ -7205,12 +9174,28 @@ mod foo { deny_since: None, }, Lint { - label: "ip_from", - description: r##"# `ip_from` + label: "ip_as_octets", + description: r##"# `ip_as_octets` -The tracking issue for this feature is: [#131360] -[#131360]: https://github.com/rust-lang/rust/issues/131360 + +The tracking issue for this feature is: [#137259] + +[#137259]: https://github.com/rust-lang/rust/issues/137259 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "ip_multicast_reserved", + description: r##"# `ip_multicast_reserved` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, @@ -7222,6 +9207,8 @@ mod foo { label: "is_ascii_octdigit", description: r##"# `is_ascii_octdigit` + + The tracking issue for this feature is: [#101288] [#101288]: https://github.com/rust-lang/rust/issues/101288 @@ -7236,6 +9223,8 @@ mod foo { label: "is_loongarch_feature_detected", description: r##"# `is_loongarch_feature_detected` + + The tracking issue for this feature is: [#117425] [#117425]: https://github.com/rust-lang/rust/issues/117425 @@ -7250,10 +9239,28 @@ mod foo { label: "is_riscv_feature_detected", description: r##"# `is_riscv_feature_detected` + + The tracking issue for this feature is: [#111192] [#111192]: https://github.com/rust-lang/rust/issues/111192 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "isolate_most_least_significant_one", + description: r##"# `isolate_most_least_significant_one` + + + +The tracking issue for this feature is: [#136909] + +[#136909]: https://github.com/rust-lang/rust/issues/136909 + ------------------------ "##, default_severity: Severity::Allow, @@ -7264,6 +9271,8 @@ mod foo { label: "iter_advance_by", description: r##"# `iter_advance_by` + + The tracking issue for this feature is: [#77404] [#77404]: https://github.com/rust-lang/rust/issues/77404 @@ -7278,24 +9287,12 @@ mod foo { label: "iter_array_chunks", description: r##"# `iter_array_chunks` + + The tracking issue for this feature is: [#100450] [#100450]: https://github.com/rust-lang/rust/issues/100450 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "iter_chain", - description: r##"# `iter_chain` - -The tracking issue for this feature is: [#125964] - -[#125964]: https://github.com/rust-lang/rust/issues/125964 - ------------------------ "##, default_severity: Severity::Allow, @@ -7306,6 +9303,8 @@ mod foo { label: "iter_collect_into", description: r##"# `iter_collect_into` + + The tracking issue for this feature is: [#94780] [#94780]: https://github.com/rust-lang/rust/issues/94780 @@ -7320,6 +9319,8 @@ mod foo { label: "iter_from_coroutine", description: r##"# `iter_from_coroutine` + + The tracking issue for this feature is: [#43122] [#43122]: https://github.com/rust-lang/rust/issues/43122 @@ -7334,6 +9335,8 @@ mod foo { label: "iter_intersperse", description: r##"# `iter_intersperse` + + The tracking issue for this feature is: [#79524] [#79524]: https://github.com/rust-lang/rust/issues/79524 @@ -7348,10 +9351,28 @@ mod foo { label: "iter_is_partitioned", description: r##"# `iter_is_partitioned` + + The tracking issue for this feature is: [#62544] [#62544]: https://github.com/rust-lang/rust/issues/62544 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "iter_macro", + description: r##"# `iter_macro` + + + +The tracking issue for this feature is: [#142269] + +[#142269]: https://github.com/rust-lang/rust/issues/142269 + ------------------------ "##, default_severity: Severity::Allow, @@ -7362,6 +9383,8 @@ mod foo { label: "iter_map_windows", description: r##"# `iter_map_windows` + + The tracking issue for this feature is: [#87155] [#87155]: https://github.com/rust-lang/rust/issues/87155 @@ -7376,6 +9399,8 @@ mod foo { label: "iter_next_chunk", description: r##"# `iter_next_chunk` + + The tracking issue for this feature is: [#98326] [#98326]: https://github.com/rust-lang/rust/issues/98326 @@ -7390,6 +9415,8 @@ mod foo { label: "iter_order_by", description: r##"# `iter_order_by` + + The tracking issue for this feature is: [#64295] [#64295]: https://github.com/rust-lang/rust/issues/64295 @@ -7404,6 +9431,8 @@ mod foo { label: "iter_partition_in_place", description: r##"# `iter_partition_in_place` + + The tracking issue for this feature is: [#62543] [#62543]: https://github.com/rust-lang/rust/issues/62543 @@ -7418,6 +9447,8 @@ mod foo { label: "iterator_try_collect", description: r##"# `iterator_try_collect` + + The tracking issue for this feature is: [#94047] [#94047]: https://github.com/rust-lang/rust/issues/94047 @@ -7432,6 +9463,8 @@ mod foo { label: "iterator_try_reduce", description: r##"# `iterator_try_reduce` + + The tracking issue for this feature is: [#87053] [#87053]: https://github.com/rust-lang/rust/issues/87053 @@ -7446,6 +9479,8 @@ mod foo { label: "junction_point", description: r##"# `junction_point` + + The tracking issue for this feature is: [#121709] [#121709]: https://github.com/rust-lang/rust/issues/121709 @@ -7460,9 +9495,11 @@ mod foo { label: "lahfsahf_target_feature", description: r##"# `lahfsahf_target_feature` -The tracking issue for this feature is: [#44839] +lahfsahf target feature on x86. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150251] + +[#150251]: https://github.com/rust-lang/rust/issues/150251 ------------------------ "##, @@ -7520,14 +9557,15 @@ mod foo { allocations via `malloc` and `free`: ```rust,ignore (libc-is-finicky) -#![feature(lang_items, start, core_intrinsics, rustc_private, panic_unwind, rustc_attrs)] +#![feature(lang_items, core_intrinsics, rustc_private, panic_unwind, rustc_attrs)] #![allow(internal_features)] #![no_std] +#![no_main] extern crate libc; extern crate unwind; -use core::ffi::c_void; +use core::ffi::{c_int, c_void}; use core::intrinsics; use core::panic::PanicInfo; use core::ptr::NonNull; @@ -7565,8 +9603,8 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { p } -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(_argc: c_int, _argv: *const *const u8) -> c_int { let _x = Box::new(1); 0 @@ -7596,6 +9634,8 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "large_assignments", description: r##"# `large_assignments` +Allows setting the threshold for the `large_assignments` lint. + The tracking issue for this feature is: [#83518] [#83518]: https://github.com/rust-lang/rust/issues/83518 @@ -7610,6 +9650,8 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "layout_for_ptr", description: r##"# `layout_for_ptr` + + The tracking issue for this feature is: [#69835] [#69835]: https://github.com/rust-lang/rust/issues/69835 @@ -7624,24 +9666,12 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "lazy_cell_into_inner", description: r##"# `lazy_cell_into_inner` + + The tracking issue for this feature is: [#125623] [#125623]: https://github.com/rust-lang/rust/issues/125623 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "lazy_get", - description: r##"# `lazy_get` - -The tracking issue for this feature is: [#129333] - -[#129333]: https://github.com/rust-lang/rust/issues/129333 - ------------------------ "##, default_severity: Severity::Allow, @@ -7652,6 +9682,8 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "lazy_type_alias", description: r##"# `lazy_type_alias` +Allow to have type alias types for inter-crate use. + The tracking issue for this feature is: [#112792] [#112792]: https://github.com/rust-lang/rust/issues/112792 @@ -7666,22 +9698,10 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "legacy_receiver_trait", description: r##"# `legacy_receiver_trait` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "let_chains", - description: r##"# `let_chains` - -The tracking issue for this feature is: [#53667] - -[#53667]: https://github.com/rust-lang/rust/issues/53667 - ------------------------ "##, default_severity: Severity::Allow, @@ -7692,6 +9712,8 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "liballoc_internals", description: r##"# `liballoc_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -7713,10 +9735,14 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } deny_since: None, }, Lint { - label: "lifetime_capture_rules_2024", - description: r##"# `lifetime_capture_rules_2024` + label: "likely_unlikely", + description: r##"# `likely_unlikely` -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + + +The tracking issue for this feature is: [#151619] + +[#151619]: https://github.com/rust-lang/rust/issues/151619 ------------------------ "##, @@ -7768,6 +9794,8 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "link_llvm_intrinsics", description: r##"# `link_llvm_intrinsics` +Allows using `#[link_name="llvm.*"]`. + The tracking issue for this feature is: [#29602] [#29602]: https://github.com/rust-lang/rust/issues/29602 @@ -7782,6 +9810,8 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "linkage", description: r##"# `linkage` +Allows using the `#[linkage = ".."]` attribute. + The tracking issue for this feature is: [#29603] [#29603]: https://github.com/rust-lang/rust/issues/29603 @@ -7796,6 +9826,8 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "linked_list_cursors", description: r##"# `linked_list_cursors` + + The tracking issue for this feature is: [#58533] [#58533]: https://github.com/rust-lang/rust/issues/58533 @@ -7810,6 +9842,8 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "linked_list_remove", description: r##"# `linked_list_remove` + + The tracking issue for this feature is: [#69210] [#69210]: https://github.com/rust-lang/rust/issues/69210 @@ -7824,6 +9858,8 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "linked_list_retain", description: r##"# `linked_list_retain` + + The tracking issue for this feature is: [#114135] [#114135]: https://github.com/rust-lang/rust/issues/114135 @@ -7838,10 +9874,28 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "linux_pidfd", description: r##"# `linux_pidfd` + + The tracking issue for this feature is: [#82971] [#82971]: https://github.com/rust-lang/rust/issues/82971 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "local_key_cell_update", + description: r##"# `local_key_cell_update` + + + +The tracking issue for this feature is: [#143989] + +[#143989]: https://github.com/rust-lang/rust/issues/143989 + ------------------------ "##, default_severity: Severity::Allow, @@ -7852,10 +9906,28 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "local_waker", description: r##"# `local_waker` + + The tracking issue for this feature is: [#118959] [#118959]: https://github.com/rust-lang/rust/issues/118959 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "lock_value_accessors", + description: r##"# `lock_value_accessors` + + + +The tracking issue for this feature is: [#133407] + +[#133407]: https://github.com/rust-lang/rust/issues/133407 + ------------------------ "##, default_severity: Severity::Allow, @@ -7866,6 +9938,8 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "log_syntax", description: r##"# `log_syntax` + + The tracking issue for this feature is: [#29598] [#29598]: https://github.com/rust-lang/rust/issues/29598 @@ -7880,9 +9954,134 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "loongarch_target_feature", description: r##"# `loongarch_target_feature` -The tracking issue for this feature is: [#44839] +Target features on loongarch. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150252] + +[#150252]: https://github.com/rust-lang/rust/issues/150252 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "loop_match", + description: r##"# `loop_match` + +The tracking issue for this feature is: [#132306] + +[#132306]: https://github.com/rust-lang/rust/issues/132306 + +------ + +The `#[loop_match]` and `#[const_continue]` attributes can be used to improve the code +generation of logic that fits this shape: + +```ignore (pseudo-rust) +loop { + state = 'blk: { + match state { + State::A => { + break 'blk State::B + } + State::B => { /* ... */ } + /* ... */ + } + } +} +``` + +Here the loop itself can be annotated with `#[loop_match]`, and any `break 'blk` with +`#[const_continue]` if the value is know at compile time: + +```ignore (pseudo-rust) +#[loop_match] +loop { + state = 'blk: { + match state { + State::A => { + #[const_continue] + break 'blk State::B + } + State::B => { /* ... */ } + /* ... */ + } + } +} +``` + +The observable behavior of this loop is exactly the same as without the extra attributes. +The difference is in the generated output: normally, when the state is `A`, control flow +moves from the `A` branch, back to the top of the loop, then to the `B` branch. With the +attributes, The `A` branch will immediately jump to the `B` branch. + +Removing the indirection can be beneficial for stack usage and branch prediction, and +enables other optimizations by clearly splitting out the control flow paths that your +program will actually use. +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "m68k_target_feature", + description: r##"# `m68k_target_feature` + +Target features on m68k. + +The tracking issue for this feature is: [#134328] + +[#134328]: https://github.com/rust-lang/rust/issues/134328 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "macro_attr", + description: r##"# `macro_attr` + +Allow `macro_rules!` attribute rules + +The tracking issue for this feature is: [#143547] + +[#143547]: https://github.com/rust-lang/rust/issues/143547 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "macro_derive", + description: r##"# `macro_derive` + +Allow `macro_rules!` derive rules + +The tracking issue for this feature is: [#143549] + +[#143549]: https://github.com/rust-lang/rust/issues/143549 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "macro_guard_matcher", + description: r##"# `macro_guard_matcher` + +Allow `$x:guard` matcher in macros + +The tracking issue for this feature is: [#153104] + +[#153104]: https://github.com/rust-lang/rust/issues/153104 ------------------------ "##, @@ -7896,9 +10095,12 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } The tracking issue for this feature is: [#83527] -[#83527]: https://github.com/rust-lang/rust/issues/83527 - ------------------------ + +> This feature is not to be confused with [`macro_metavar_expr_concat`]. + +[`macro_metavar_expr_concat`]: ./macro-metavar-expr-concat.md +[#83527]: https://github.com/rust-lang/rust/issues/83527 "##, default_severity: Severity::Allow, warn_since: None, @@ -7910,23 +10112,135 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } The tracking issue for this feature is: [#124225] +------------------------ + +In stable Rust, there is no way to create new identifiers by joining identifiers to literals or other identifiers without using procedural macros such as [`paste`]. + `#![feature(macro_metavar_expr_concat)]` introduces a way to do this, using the concat metavariable expression. + +> This feature uses the syntax from [`macro_metavar_expr`] but is otherwise +> independent. It replaces the since-removed unstable feature +> [`concat_idents`]. + +> This is an experimental feature; it and its syntax will require a RFC before stabilization. + + +### Overview + +`#![feature(macro_metavar_expr_concat)]` provides the `concat` metavariable expression for creating new identifiers: + +```rust +#![feature(macro_metavar_expr_concat)] + +macro_rules! create_some_structs { + ($name:ident) => { + pub struct ${ concat(First, $name) }; + pub struct ${ concat(Second, $name) }; + pub struct ${ concat(Third, $name) }; + } +} + +create_some_structs!(Thing); +``` + +This macro invocation expands to: + +```rust +pub struct FirstThing; +pub struct SecondThing; +pub struct ThirdThing; +``` + +### Syntax + +This feature builds upon the metavariable expression syntax `${ .. }` as specified in [RFC 3086] ([`macro_metavar_expr`]). + `concat` is available like `${ concat(items) }`, where `items` is a comma separated sequence of idents and/or literals. + +### Examples + +#### Create a function or method with a concatenated name + +```rust +#![feature(macro_metavar_expr_concat)] + +macro_rules! make_getter { + ($name:ident, $field: ident, $ret:ty) => { + impl $name { + pub fn ${ concat(get_, $field) }(&self) -> &$ret { + &self.$field + } + } + } +} + +pub struct Thing { + description: String, +} + +make_getter!(Thing, description, String); +``` + +This expands to: + +```rust +pub struct Thing { + description: String, +} + +impl Thing { + pub fn get_description(&self) -> &String { + &self.description + } +} +``` + +#### Create names for macro generated tests + +```rust +#![feature(macro_metavar_expr_concat)] + +macro_rules! test_math { + ($integer:ident) => { + #[test] + fn ${ concat(test_, $integer, _, addition) } () { + let a: $integer = 73; + let b: $integer = 42; + assert_eq!(a + b, 115) + } + + #[test] + fn ${ concat(test_, $integer, _, subtraction) } () { + let a: $integer = 73; + let b: $integer = 42; + assert_eq!(a - b, 31) + } + } +} + +test_math!(i32); +test_math!(u64); +test_math!(u128); +``` + +Running this returns the following output: + +```text +running 6 tests +test test_i32_subtraction ... ok +test test_i32_addition ... ok +test test_u128_addition ... ok +test test_u128_subtraction ... ok +test test_u64_addition ... ok +test test_u64_subtraction ... ok + +test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +[`paste`]: https://crates.io/crates/paste +[RFC 3086]: https://rust-lang.github.io/rfcs/3086-macro-metavar-expr.html +[`macro_metavar_expr`]: ../language-features/macro-metavar-expr.md +[`concat_idents`]: https://github.com/rust-lang/rust/issues/29599 [#124225]: https://github.com/rust-lang/rust/issues/124225 - ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "map_many_mut", - description: r##"# `map_many_mut` - -The tracking issue for this feature is: [#97601] - -[#97601]: https://github.com/rust-lang/rust/issues/97601 - ------------------------- +[declarative macros]: https://doc.rust-lang.org/stable/reference/macros-by-example.html "##, default_severity: Severity::Allow, warn_since: None, @@ -7936,6 +10250,8 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "map_try_insert", description: r##"# `map_try_insert` + + The tracking issue for this feature is: [#82766] [#82766]: https://github.com/rust-lang/rust/issues/82766 @@ -7950,6 +10266,8 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } label: "mapped_lock_guards", description: r##"# `mapped_lock_guards` + + The tracking issue for this feature is: [#117108] [#117108]: https://github.com/rust-lang/rust/issues/117108 @@ -7997,6 +10315,22 @@ fn cheap_clone(t: T) -> T { This is expected to replace the unstable `overlapping_marker_traits` feature, which applied to all empty traits (without needing an opt-in). +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "maybe_dangling", + description: r##"# `maybe_dangling` + + + +The tracking issue for this feature is: [#118166] + +[#118166]: https://github.com/rust-lang/rust/issues/118166 + +------------------------ "##, default_severity: Severity::Allow, warn_since: None, @@ -8006,6 +10340,8 @@ fn cheap_clone(t: T) -> T { label: "maybe_uninit_array_assume_init", description: r##"# `maybe_uninit_array_assume_init` + + The tracking issue for this feature is: [#96097] [#96097]: https://github.com/rust-lang/rust/issues/96097 @@ -8020,6 +10356,8 @@ fn cheap_clone(t: T) -> T { label: "maybe_uninit_as_bytes", description: r##"# `maybe_uninit_as_bytes` + + The tracking issue for this feature is: [#93092] [#93092]: https://github.com/rust-lang/rust/issues/93092 @@ -8034,38 +10372,12 @@ fn cheap_clone(t: T) -> T { label: "maybe_uninit_fill", description: r##"# `maybe_uninit_fill` + + The tracking issue for this feature is: [#117428] [#117428]: https://github.com/rust-lang/rust/issues/117428 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "maybe_uninit_slice", - description: r##"# `maybe_uninit_slice` - -The tracking issue for this feature is: [#63569] - -[#63569]: https://github.com/rust-lang/rust/issues/63569 - ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "maybe_uninit_uninit_array", - description: r##"# `maybe_uninit_uninit_array` - -The tracking issue for this feature is: [#96097] - -[#96097]: https://github.com/rust-lang/rust/issues/96097 - ------------------------ "##, default_severity: Severity::Allow, @@ -8076,6 +10388,8 @@ fn cheap_clone(t: T) -> T { label: "maybe_uninit_uninit_array_transpose", description: r##"# `maybe_uninit_uninit_array_transpose` + + The tracking issue for this feature is: [#96097] [#96097]: https://github.com/rust-lang/rust/issues/96097 @@ -8087,12 +10401,14 @@ fn cheap_clone(t: T) -> T { deny_since: None, }, Lint { - label: "maybe_uninit_write_slice", - description: r##"# `maybe_uninit_write_slice` + label: "mem_conjure_zst", + description: r##"# `mem_conjure_zst` -The tracking issue for this feature is: [#79995] -[#79995]: https://github.com/rust-lang/rust/issues/79995 + +The tracking issue for this feature is: [#95383] + +[#95383]: https://github.com/rust-lang/rust/issues/95383 ------------------------ "##, @@ -8104,10 +10420,44 @@ fn cheap_clone(t: T) -> T { label: "mem_copy_fn", description: r##"# `mem_copy_fn` + + The tracking issue for this feature is: [#98262] [#98262]: https://github.com/rust-lang/rust/issues/98262 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "mgca_type_const_syntax", + description: r##"# `mgca_type_const_syntax` + +Enable mgca `type const` syntax before expansion. + +The tracking issue for this feature is: [#132980] + +[#132980]: https://github.com/rust-lang/rust/issues/132980 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "min_adt_const_params", + description: r##"# `min_adt_const_params` + +Allows additional const parameter types, such as [u8; 10] or user defined types. User defined types must not have fields more private than the type itself. + +The tracking issue for this feature is: [#154042] + +[#154042]: https://github.com/rust-lang/rust/issues/154042 + ------------------------ "##, default_severity: Severity::Allow, @@ -8118,6 +10468,8 @@ fn cheap_clone(t: T) -> T { label: "min_generic_const_args", description: r##"# `min_generic_const_args` +Enables the generic const args MVP (only bare paths, not arbitrary computation). + The tracking issue for this feature is: [#132980] [#132980]: https://github.com/rust-lang/rust/issues/132980 @@ -8132,6 +10484,8 @@ fn cheap_clone(t: T) -> T { label: "min_specialization", description: r##"# `min_specialization` +A minimal, sound subset of specialization intended to be used by the standard library until the soundness issues with specialization are fixed. + The tracking issue for this feature is: [#31844] [#31844]: https://github.com/rust-lang/rust/issues/31844 @@ -8146,23 +10500,11 @@ fn cheap_clone(t: T) -> T { label: "mips_target_feature", description: r##"# `mips_target_feature` -The tracking issue for this feature is: [#44839] +Target features on mips. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150253] ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "mixed_integer_ops_unsigned_sub", - description: r##"# `mixed_integer_ops_unsigned_sub` - -The tracking issue for this feature is: [#126043] - -[#126043]: https://github.com/rust-lang/rust/issues/126043 +[#150253]: https://github.com/rust-lang/rust/issues/150253 ------------------------ "##, @@ -8174,9 +10516,11 @@ fn cheap_clone(t: T) -> T { label: "more_float_constants", description: r##"# `more_float_constants` -The tracking issue for this feature is: [#103883] -[#103883]: https://github.com/rust-lang/rust/issues/103883 + +The tracking issue for this feature is: [#146939] + +[#146939]: https://github.com/rust-lang/rust/issues/146939 ------------------------ "##, @@ -8188,6 +10532,8 @@ fn cheap_clone(t: T) -> T { label: "more_maybe_bounds", description: r##"# `more_maybe_bounds` +Allows using `?Trait` trait bounds in more contexts. + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -8231,6 +10577,38 @@ impl A for Foo { type Assoc = StructStruct; } ``` +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "motor_ext", + description: r##"# `motor_ext` + + + +The tracking issue for this feature is: [#147456] + +[#147456]: https://github.com/rust-lang/rust/issues/147456 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "movrs_target_feature", + description: r##"# `movrs_target_feature` + +The `movrs` target feature on x86. + +The tracking issue for this feature is: [#137976] + +[#137976]: https://github.com/rust-lang/rust/issues/137976 + +------------------------ "##, default_severity: Severity::Allow, warn_since: None, @@ -8240,10 +10618,28 @@ impl A for Foo { label: "mpmc_channel", description: r##"# `mpmc_channel` + + The tracking issue for this feature is: [#126840] [#126840]: https://github.com/rust-lang/rust/issues/126840 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "mpsc_is_disconnected", + description: r##"# `mpsc_is_disconnected` + + + +The tracking issue for this feature is: [#153668] + +[#153668]: https://github.com/rust-lang/rust/issues/153668 + ------------------------ "##, default_severity: Severity::Allow, @@ -8254,7 +10650,11 @@ impl A for Foo { label: "multiple_supertrait_upcastable", description: r##"# `multiple_supertrait_upcastable` -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +Allows the `multiple_supertrait_upcastable` lint. + +The tracking issue for this feature is: [#150833] + +[#150833]: https://github.com/rust-lang/rust/issues/150833 ------------------------ "##, @@ -8266,6 +10666,8 @@ impl A for Foo { label: "must_not_suspend", description: r##"# `must_not_suspend` +Allows the `#[must_not_suspend]` attribute. + The tracking issue for this feature is: [#83310] [#83310]: https://github.com/rust-lang/rust/issues/83310 @@ -8280,6 +10682,8 @@ impl A for Foo { label: "mut_ref", description: r##"# `mut_ref` +Allows `mut ref` and `mut ref mut` identifier patterns. + The tracking issue for this feature is: [#123076] [#123076]: https://github.com/rust-lang/rust/issues/123076 @@ -8291,12 +10695,46 @@ impl A for Foo { deny_since: None, }, Lint { - label: "naked_functions", - description: r##"# `naked_functions` + label: "mutex_data_ptr", + description: r##"# `mutex_data_ptr` -The tracking issue for this feature is: [#90957] -[#90957]: https://github.com/rust-lang/rust/issues/90957 + +The tracking issue for this feature is: [#140368] + +[#140368]: https://github.com/rust-lang/rust/issues/140368 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "naked_functions_rustic_abi", + description: r##"# `naked_functions_rustic_abi` + +Allows using `#[naked]` on `extern "Rust"` functions. + +The tracking issue for this feature is: [#138997] + +[#138997]: https://github.com/rust-lang/rust/issues/138997 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "naked_functions_target_feature", + description: r##"# `naked_functions_target_feature` + +Allows using `#[target_feature(enable = "...")]` on `#[naked]` on functions. + +The tracking issue for this feature is: [#138568] + +[#138568]: https://github.com/rust-lang/rust/issues/138568 ------------------------ "##, @@ -8333,6 +10771,8 @@ impl A for Foo { label: "needs_panic_runtime", description: r##"# `needs_panic_runtime` +Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. + The tracking issue for this feature is: [#32837] [#32837]: https://github.com/rust-lang/rust/issues/32837 @@ -8347,6 +10787,8 @@ impl A for Foo { label: "negative_bounds", description: r##"# `negative_bounds` +Allow negative trait bounds. This is an internal-only feature for testing the trait solver! + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -8423,6 +10865,8 @@ impl at all, but that is not an option for auto traits. A workaround label: "never_patterns", description: r##"# `never_patterns` +Allows the `!` pattern. + The tracking issue for this feature is: [#118155] [#118155]: https://github.com/rust-lang/rust/issues/118155 @@ -8437,6 +10881,8 @@ impl at all, but that is not an option for auto traits. A workaround label: "never_type", description: r##"# `never_type` +Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. + The tracking issue for this feature is: [#35121] [#35121]: https://github.com/rust-lang/rust/issues/35121 @@ -8448,22 +10894,26 @@ impl at all, but that is not an option for auto traits. A workaround deny_since: None, }, Lint { - label: "never_type_fallback", - description: r##"# `never_type_fallback` + label: "new_range", + description: r##"# `new_range` -The tracking issue for this feature is: [#65992] +The tracking issue for this feature is: [#123741] -[#65992]: https://github.com/rust-lang/rust/issues/65992 +[#123741]: https://github.com/rust-lang/rust/issues/123741 ------------------------- +--- + +Switch the syntaxes `a..`, `a..b`, and `a..=b` to resolve the new range types. "##, default_severity: Severity::Allow, warn_since: None, deny_since: None, }, Lint { - label: "new_range_api", - description: r##"# `new_range_api` + label: "new_range_api_legacy", + description: r##"# `new_range_api_legacy` + + The tracking issue for this feature is: [#125687] @@ -8476,12 +10926,30 @@ impl at all, but that is not an option for auto traits. A workaround deny_since: None, }, Lint { - label: "new_zeroed_alloc", - description: r##"# `new_zeroed_alloc` + label: "new_range_remainder", + description: r##"# `new_range_remainder` -The tracking issue for this feature is: [#129396] -[#129396]: https://github.com/rust-lang/rust/issues/129396 + +The tracking issue for this feature is: [#154458] + +[#154458]: https://github.com/rust-lang/rust/issues/154458 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "next_index", + description: r##"# `next_index` + + + +The tracking issue for this feature is: [#130711] + +[#130711]: https://github.com/rust-lang/rust/issues/130711 ------------------------ "##, @@ -8493,47 +10961,13 @@ impl at all, but that is not an option for auto traits. A workaround label: "no_core", description: r##"# `no_core` +Allows `#![no_core]`. + The tracking issue for this feature is: [#29639] [#29639]: https://github.com/rust-lang/rust/issues/29639 ------------------------ -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "no_sanitize", - description: r##"# `no_sanitize` - -The tracking issue for this feature is: [#39699] - -[#39699]: https://github.com/rust-lang/rust/issues/39699 - ------------------------- - -The `no_sanitize` attribute can be used to selectively disable sanitizer -instrumentation in an annotated function. This might be useful to: avoid -instrumentation overhead in a performance critical function, or avoid -instrumenting code that contains constructs unsupported by given sanitizer. - -The precise effect of this annotation depends on particular sanitizer in use. -For example, with `no_sanitize(thread)`, the thread sanitizer will no longer -instrument non-atomic store / load operations, but it will instrument atomic -operations to avoid reporting false positives and provide meaning full stack -traces. - -## Examples - -``` rust -#![feature(no_sanitize)] - -#[no_sanitize(address)] -fn foo() { - // ... -} -``` "##, default_severity: Severity::Allow, warn_since: None, @@ -8543,6 +10977,8 @@ fn foo() { label: "non_exhaustive_omitted_patterns_lint", description: r##"# `non_exhaustive_omitted_patterns_lint` +Allows using the `non_exhaustive_omitted_patterns` lint. + The tracking issue for this feature is: [#89554] [#89554]: https://github.com/rust-lang/rust/issues/89554 @@ -8557,6 +10993,8 @@ fn foo() { label: "non_lifetime_binders", description: r##"# `non_lifetime_binders` +Allows `for` binders in where-clauses + The tracking issue for this feature is: [#108185] [#108185]: https://github.com/rust-lang/rust/issues/108185 @@ -8568,12 +11006,14 @@ fn foo() { deny_since: None, }, Lint { - label: "non_null_from_ref", - description: r##"# `non_null_from_ref` + label: "nonpoison_condvar", + description: r##"# `nonpoison_condvar` -The tracking issue for this feature is: [#130823] -[#130823]: https://github.com/rust-lang/rust/issues/130823 + +The tracking issue for this feature is: [#134645] + +[#134645]: https://github.com/rust-lang/rust/issues/134645 ------------------------ "##, @@ -8582,12 +11022,30 @@ fn foo() { deny_since: None, }, Lint { - label: "non_zero_count_ones", - description: r##"# `non_zero_count_ones` + label: "nonpoison_mutex", + description: r##"# `nonpoison_mutex` -The tracking issue for this feature is: [#120287] -[#120287]: https://github.com/rust-lang/rust/issues/120287 + +The tracking issue for this feature is: [#134645] + +[#134645]: https://github.com/rust-lang/rust/issues/134645 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "nonpoison_rwlock", + description: r##"# `nonpoison_rwlock` + + + +The tracking issue for this feature is: [#134645] + +[#134645]: https://github.com/rust-lang/rust/issues/134645 ------------------------ "##, @@ -8599,6 +11057,8 @@ fn foo() { label: "nonzero_bitwise", description: r##"# `nonzero_bitwise` + + The tracking issue for this feature is: [#128281] [#128281]: https://github.com/rust-lang/rust/issues/128281 @@ -8613,10 +11073,28 @@ fn foo() { label: "nonzero_from_mut", description: r##"# `nonzero_from_mut` + + The tracking issue for this feature is: [#106290] [#106290]: https://github.com/rust-lang/rust/issues/106290 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "nonzero_from_str_radix", + description: r##"# `nonzero_from_str_radix` + + + +The tracking issue for this feature is: [#152193] + +[#152193]: https://github.com/rust-lang/rust/issues/152193 + ------------------------ "##, default_severity: Severity::Allow, @@ -8627,6 +11105,8 @@ fn foo() { label: "nonzero_internals", description: r##"# `nonzero_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -8639,6 +11119,8 @@ fn foo() { label: "nonzero_ops", description: r##"# `nonzero_ops` + + The tracking issue for this feature is: [#84186] [#84186]: https://github.com/rust-lang/rust/issues/84186 @@ -8650,12 +11132,28 @@ fn foo() { deny_since: None, }, Lint { - label: "num_midpoint_signed", - description: r##"# `num_midpoint_signed` + label: "normalize_lexically", + description: r##"# `normalize_lexically` -The tracking issue for this feature is: [#110840] -[#110840]: https://github.com/rust-lang/rust/issues/110840 + +The tracking issue for this feature is: [#134694] + +[#134694]: https://github.com/rust-lang/rust/issues/134694 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "num_internals", + description: r##"# `num_internals` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, @@ -8667,6 +11165,52 @@ fn foo() { label: "numfmt", description: r##"# `numfmt` + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "nvptx_target_feature", + description: r##"# `nvptx_target_feature` + +Target feaures on nvptx. + +The tracking issue for this feature is: [#150254] + +[#150254]: https://github.com/rust-lang/rust/issues/150254 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "objc_class_variant", + description: r##"# `objc_class_variant` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "objc_selector_variant", + description: r##"# `objc_selector_variant` + + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -8684,6 +11228,28 @@ fn foo() { [#120141]: https://github.com/rust-lang/rust/issues/120141 ------------------------ + +When the `offset_of_enum` feature is enabled, the [`offset_of!`] macro may be used to obtain the +offsets of fields of `enum`s; to express this, `enum` variants may be traversed as if they were +fields. Variants themselves do not have an offset, so they cannot appear as the last path component. + +```rust +#![feature(offset_of_enum)] +use std::mem; + +#[repr(u8)] +enum Enum { + A(u8, u16), + B { one: u8, two: u16 }, +} + +assert_eq!(mem::offset_of!(Enum, A.0), 1); +assert_eq!(mem::offset_of!(Enum, B.two), 2); + +assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); +``` + +[`offset_of!`]: ../../std/mem/macro.offset_of.html "##, default_severity: Severity::Allow, warn_since: None, @@ -8698,18 +11264,29 @@ fn foo() { [#126151]: https://github.com/rust-lang/rust/issues/126151 ------------------------ -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "omit_gdb_pretty_printer_section", - description: r##"# `omit_gdb_pretty_printer_section` -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +When the `offset_of_slice` feature is enabled, the [`offset_of!`] macro may be used to determine +the offset of fields whose type is `[T]`, that is, a slice of dynamic size. ------------------------- +In general, fields whose type is dynamically sized do not have statically known offsets because +they do not have statically known alignments. However, `[T]` has the same alignment as `T`, so +it specifically may be allowed. + +```rust +#![feature(offset_of_slice)] + +#[repr(C)] +pub struct Struct { + head: u32, + tail: [u8], +} + +fn main() { + assert_eq!(std::mem::offset_of!(Struct, tail), 4); +} +``` + +[`offset_of!`]: ../../std/mem/macro.offset_of.html "##, default_severity: Severity::Allow, warn_since: None, @@ -8719,6 +11296,8 @@ fn foo() { label: "once_cell_get_mut", description: r##"# `once_cell_get_mut` + + The tracking issue for this feature is: [#121641] [#121641]: https://github.com/rust-lang/rust/issues/121641 @@ -8733,6 +11312,8 @@ fn foo() { label: "once_cell_try", description: r##"# `once_cell_try` + + The tracking issue for this feature is: [#109737] [#109737]: https://github.com/rust-lang/rust/issues/109737 @@ -8747,24 +11328,12 @@ fn foo() { label: "once_cell_try_insert", description: r##"# `once_cell_try_insert` + + The tracking issue for this feature is: [#116693] [#116693]: https://github.com/rust-lang/rust/issues/116693 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "once_wait", - description: r##"# `once_wait` - -The tracking issue for this feature is: [#127527] - -[#127527]: https://github.com/rust-lang/rust/issues/127527 - ------------------------ "##, default_severity: Severity::Allow, @@ -8775,10 +11344,28 @@ fn foo() { label: "one_sided_range", description: r##"# `one_sided_range` + + The tracking issue for this feature is: [#69780] [#69780]: https://github.com/rust-lang/rust/issues/69780 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "oneshot_channel", + description: r##"# `oneshot_channel` + + + +The tracking issue for this feature is: [#143674] + +[#143674]: https://github.com/rust-lang/rust/issues/143674 + ------------------------ "##, default_severity: Severity::Allow, @@ -8789,6 +11376,8 @@ fn foo() { label: "optimize_attribute", description: r##"# `optimize_attribute` +Allows using `#[optimize(X)]`. + The tracking issue for this feature is: [#54882] [#54882]: https://github.com/rust-lang/rust/issues/54882 @@ -8803,10 +11392,76 @@ fn foo() { label: "option_array_transpose", description: r##"# `option_array_transpose` + + The tracking issue for this feature is: [#130828] [#130828]: https://github.com/rust-lang/rust/issues/130828 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "option_get_or_try_insert_with", + description: r##"# `option_get_or_try_insert_with` + + + +The tracking issue for this feature is: [#143648] + +[#143648]: https://github.com/rust-lang/rust/issues/143648 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "option_into_flat_iter", + description: r##"# `option_into_flat_iter` + + + +The tracking issue for this feature is: [#148441] + +[#148441]: https://github.com/rust-lang/rust/issues/148441 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "option_reduce", + description: r##"# `option_reduce` + + + +The tracking issue for this feature is: [#144273] + +[#144273]: https://github.com/rust-lang/rust/issues/144273 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "option_reference_flattening", + description: r##"# `option_reference_flattening` + + + +The tracking issue for this feature is: [#149221] + +[#149221]: https://github.com/rust-lang/rust/issues/149221 + ------------------------ "##, default_severity: Severity::Allow, @@ -8817,24 +11472,12 @@ fn foo() { label: "option_zip", description: r##"# `option_zip` + + The tracking issue for this feature is: [#70086] [#70086]: https://github.com/rust-lang/rust/issues/70086 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "os_str_display", - description: r##"# `os_str_display` - -The tracking issue for this feature is: [#120048] - -[#120048]: https://github.com/rust-lang/rust/issues/120048 - ------------------------ "##, default_severity: Severity::Allow, @@ -8845,24 +11488,12 @@ fn foo() { label: "os_str_slice", description: r##"# `os_str_slice` + + The tracking issue for this feature is: [#118485] [#118485]: https://github.com/rust-lang/rust/issues/118485 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "os_string_pathbuf_leak", - description: r##"# `os_string_pathbuf_leak` - -The tracking issue for this feature is: [#125965] - -[#125965]: https://github.com/rust-lang/rust/issues/125965 - ------------------------ "##, default_severity: Severity::Allow, @@ -8873,6 +11504,8 @@ fn foo() { label: "os_string_truncate", description: r##"# `os_string_truncate` + + The tracking issue for this feature is: [#133262] [#133262]: https://github.com/rust-lang/rust/issues/133262 @@ -8887,6 +11520,8 @@ fn foo() { label: "panic_abort", description: r##"# `panic_abort` + + The tracking issue for this feature is: [#32837] [#32837]: https://github.com/rust-lang/rust/issues/32837 @@ -8901,6 +11536,8 @@ fn foo() { label: "panic_always_abort", description: r##"# `panic_always_abort` + + The tracking issue for this feature is: [#84438] [#84438]: https://github.com/rust-lang/rust/issues/84438 @@ -8915,6 +11552,8 @@ fn foo() { label: "panic_backtrace_config", description: r##"# `panic_backtrace_config` + + The tracking issue for this feature is: [#93346] [#93346]: https://github.com/rust-lang/rust/issues/93346 @@ -8929,6 +11568,8 @@ fn foo() { label: "panic_can_unwind", description: r##"# `panic_can_unwind` + + The tracking issue for this feature is: [#92988] [#92988]: https://github.com/rust-lang/rust/issues/92988 @@ -8943,22 +11584,10 @@ fn foo() { label: "panic_internals", description: r##"# `panic_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "panic_payload_as_str", - description: r##"# `panic_payload_as_str` - -The tracking issue for this feature is: [#125175] - -[#125175]: https://github.com/rust-lang/rust/issues/125175 - ------------------------ "##, default_severity: Severity::Allow, @@ -8969,6 +11598,8 @@ fn foo() { label: "panic_runtime", description: r##"# `panic_runtime` +Allows using the `#![panic_runtime]` attribute. + The tracking issue for this feature is: [#32837] [#32837]: https://github.com/rust-lang/rust/issues/32837 @@ -8983,6 +11614,8 @@ fn foo() { label: "panic_unwind", description: r##"# `panic_unwind` + + The tracking issue for this feature is: [#32837] [#32837]: https://github.com/rust-lang/rust/issues/32837 @@ -8997,10 +11630,26 @@ fn foo() { label: "panic_update_hook", description: r##"# `panic_update_hook` + + The tracking issue for this feature is: [#92649] [#92649]: https://github.com/rust-lang/rust/issues/92649 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "partial_ord_chaining_methods", + description: r##"# `partial_ord_chaining_methods` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, default_severity: Severity::Allow, @@ -9011,6 +11660,8 @@ fn foo() { label: "patchable_function_entry", description: r##"# `patchable_function_entry` +Allows specifying nop padding on functions for dynamic patching. + The tracking issue for this feature is: [#123115] [#123115]: https://github.com/rust-lang/rust/issues/123115 @@ -9022,12 +11673,14 @@ fn foo() { deny_since: None, }, Lint { - label: "path_add_extension", - description: r##"# `path_add_extension` + label: "path_absolute_method", + description: r##"# `path_absolute_method` -The tracking issue for this feature is: [#127292] -[#127292]: https://github.com/rust-lang/rust/issues/127292 + +The tracking issue for this feature is: [#153328] + +[#153328]: https://github.com/rust-lang/rust/issues/153328 ------------------------ "##, @@ -9036,12 +11689,30 @@ fn foo() { deny_since: None, }, Lint { - label: "path_file_prefix", - description: r##"# `path_file_prefix` + label: "path_is_empty", + description: r##"# `path_is_empty` -The tracking issue for this feature is: [#86319] -[#86319]: https://github.com/rust-lang/rust/issues/86319 + +The tracking issue for this feature is: [#148494] + +[#148494]: https://github.com/rust-lang/rust/issues/148494 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "path_trailing_sep", + description: r##"# `path_trailing_sep` + + + +The tracking issue for this feature is: [#142503] + +[#142503]: https://github.com/rust-lang/rust/issues/142503 ------------------------ "##, @@ -9053,6 +11724,8 @@ fn foo() { label: "pattern", description: r##"# `pattern` + + The tracking issue for this feature is: [#27721] [#27721]: https://github.com/rust-lang/rust/issues/27721 @@ -9067,6 +11740,8 @@ fn foo() { label: "pattern_complexity_limit", description: r##"# `pattern_complexity_limit` +Set the maximum pattern complexity allowed (not limited by default). + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -9079,6 +11754,24 @@ fn foo() { label: "pattern_type_macro", description: r##"# `pattern_type_macro` + + +The tracking issue for this feature is: [#123646] + +[#123646]: https://github.com/rust-lang/rust/issues/123646 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "pattern_type_range_trait", + description: r##"# `pattern_type_range_trait` + + + The tracking issue for this feature is: [#123646] [#123646]: https://github.com/rust-lang/rust/issues/123646 @@ -9093,6 +11786,8 @@ fn foo() { label: "pattern_types", description: r##"# `pattern_types` +Allows using pattern types. + The tracking issue for this feature is: [#123646] [#123646]: https://github.com/rust-lang/rust/issues/123646 @@ -9107,10 +11802,28 @@ fn foo() { label: "peer_credentials_unix_socket", description: r##"# `peer_credentials_unix_socket` + + The tracking issue for this feature is: [#42839] [#42839]: https://github.com/rust-lang/rust/issues/42839 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "phantom_variance_markers", + description: r##"# `phantom_variance_markers` + + + +The tracking issue for this feature is: [#135806] + +[#135806]: https://github.com/rust-lang/rust/issues/135806 + ------------------------ "##, default_severity: Severity::Allow, @@ -9121,9 +11834,25 @@ fn foo() { label: "pin_coerce_unsized_trait", description: r##"# `pin_coerce_unsized_trait` -The tracking issue for this feature is: [#123430] -[#123430]: https://github.com/rust-lang/rust/issues/123430 + +The tracking issue for this feature is: [#150112] + +[#150112]: https://github.com/rust-lang/rust/issues/150112 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "pin_derefmut_internals", + description: r##"# `pin_derefmut_internals` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, @@ -9135,6 +11864,8 @@ fn foo() { label: "pin_ergonomics", description: r##"# `pin_ergonomics` +Experimental features that make `Pin` more ergonomic. + The tracking issue for this feature is: [#130494] [#130494]: https://github.com/rust-lang/rust/issues/130494 @@ -9149,6 +11880,8 @@ fn foo() { label: "pointer_is_aligned_to", description: r##"# `pointer_is_aligned_to` + + The tracking issue for this feature is: [#96284] [#96284]: https://github.com/rust-lang/rust/issues/96284 @@ -9160,10 +11893,14 @@ fn foo() { deny_since: None, }, Lint { - label: "pointer_like_trait", - description: r##"# `pointer_like_trait` + label: "pointer_try_cast_aligned", + description: r##"# `pointer_try_cast_aligned` -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + + +The tracking issue for this feature is: [#141221] + +[#141221]: https://github.com/rust-lang/rust/issues/141221 ------------------------ "##, @@ -9175,6 +11912,8 @@ fn foo() { label: "portable_simd", description: r##"# `portable_simd` + + The tracking issue for this feature is: [#86656] [#86656]: https://github.com/rust-lang/rust/issues/86656 @@ -9222,9 +11961,11 @@ fn get_foo() -> Foo { label: "powerpc_target_feature", description: r##"# `powerpc_target_feature` -The tracking issue for this feature is: [#44839] +Target features on powerpc. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150255] + +[#150255]: https://github.com/rust-lang/rust/issues/150255 ------------------------ "##, @@ -9233,26 +11974,12 @@ fn get_foo() -> Foo { deny_since: None, }, Lint { - label: "precise_capturing_in_traits", - description: r##"# `precise_capturing_in_traits` + label: "prelude_future", + description: r##"# `prelude_future` -The tracking issue for this feature is: [#130044] -[#130044]: https://github.com/rust-lang/rust/issues/130044 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "prelude_2024", - description: r##"# `prelude_2024` - -The tracking issue for this feature is: [#121042] - -[#121042]: https://github.com/rust-lang/rust/issues/121042 +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, @@ -9264,6 +11991,22 @@ fn get_foo() -> Foo { label: "prelude_import", description: r##"# `prelude_import` +Allows using `#[prelude_import]` on glob `use` items. + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "prelude_next", + description: r##"# `prelude_next` + + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -9276,9 +12019,11 @@ fn get_foo() -> Foo { label: "prfchw_target_feature", description: r##"# `prfchw_target_feature` -The tracking issue for this feature is: [#44839] +The prfchw target feature on x86. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150256] + +[#150256]: https://github.com/rust-lang/rust/issues/150256 ------------------------ "##, @@ -9302,6 +12047,8 @@ fn get_foo() -> Foo { label: "proc_macro_def_site", description: r##"# `proc_macro_def_site` + + The tracking issue for this feature is: [#54724] [#54724]: https://github.com/rust-lang/rust/issues/54724 @@ -9316,6 +12063,8 @@ fn get_foo() -> Foo { label: "proc_macro_diagnostic", description: r##"# `proc_macro_diagnostic` + + The tracking issue for this feature is: [#54140] [#54140]: https://github.com/rust-lang/rust/issues/54140 @@ -9330,6 +12079,8 @@ fn get_foo() -> Foo { label: "proc_macro_expand", description: r##"# `proc_macro_expand` + + The tracking issue for this feature is: [#90765] [#90765]: https://github.com/rust-lang/rust/issues/90765 @@ -9344,6 +12095,8 @@ fn get_foo() -> Foo { label: "proc_macro_hygiene", description: r##"# `proc_macro_hygiene` +Allows macro attributes on expressions, statements and non-inline modules. + The tracking issue for this feature is: [#54727] [#54727]: https://github.com/rust-lang/rust/issues/54727 @@ -9358,6 +12111,8 @@ fn get_foo() -> Foo { label: "proc_macro_internals", description: r##"# `proc_macro_internals` + + The tracking issue for this feature is: [#27812] [#27812]: https://github.com/rust-lang/rust/issues/27812 @@ -9372,6 +12127,8 @@ fn get_foo() -> Foo { label: "proc_macro_quote", description: r##"# `proc_macro_quote` + + The tracking issue for this feature is: [#54722] [#54722]: https://github.com/rust-lang/rust/issues/54722 @@ -9386,6 +12143,8 @@ fn get_foo() -> Foo { label: "proc_macro_span", description: r##"# `proc_macro_span` + + The tracking issue for this feature is: [#54725] [#54725]: https://github.com/rust-lang/rust/issues/54725 @@ -9400,6 +12159,8 @@ fn get_foo() -> Foo { label: "proc_macro_totokens", description: r##"# `proc_macro_totokens` + + The tracking issue for this feature is: [#130977] [#130977]: https://github.com/rust-lang/rust/issues/130977 @@ -9414,10 +12175,60 @@ fn get_foo() -> Foo { label: "proc_macro_tracked_env", description: r##"# `proc_macro_tracked_env` + + The tracking issue for this feature is: [#99515] [#99515]: https://github.com/rust-lang/rust/issues/99515 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "proc_macro_tracked_path", + description: r##"# `proc_macro_tracked_path` + + + +The tracking issue for this feature is: [#99515] + +[#99515]: https://github.com/rust-lang/rust/issues/99515 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "proc_macro_value", + description: r##"# `proc_macro_value` + + + +The tracking issue for this feature is: [#136652] + +[#136652]: https://github.com/rust-lang/rust/issues/136652 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "process_chroot", + description: r##"# `process_chroot` + + + +The tracking issue for this feature is: [#141298] + +[#141298]: https://github.com/rust-lang/rust/issues/141298 + ------------------------ "##, default_severity: Severity::Allow, @@ -9428,6 +12239,8 @@ fn get_foo() -> Foo { label: "process_exitcode_internals", description: r##"# `process_exitcode_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -9440,8 +12253,26 @@ fn get_foo() -> Foo { label: "process_internals", description: r##"# `process_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "process_setsid", + description: r##"# `process_setsid` + + + +The tracking issue for this feature is: [#105376] + +[#105376]: https://github.com/rust-lang/rust/issues/105376 + ------------------------ "##, default_severity: Severity::Allow, @@ -9466,6 +12297,22 @@ fn get_foo() -> Foo { This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "profiling_marker_api", + description: r##"# `profiling_marker_api` + + + +The tracking issue for this feature is: [#148197] + +[#148197]: https://github.com/rust-lang/rust/issues/148197 + ------------------------ "##, default_severity: Severity::Allow, @@ -9476,24 +12323,12 @@ fn get_foo() -> Foo { label: "ptr_alignment_type", description: r##"# `ptr_alignment_type` + + The tracking issue for this feature is: [#102070] [#102070]: https://github.com/rust-lang/rust/issues/102070 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "ptr_as_ref_unchecked", - description: r##"# `ptr_as_ref_unchecked` - -The tracking issue for this feature is: [#122034] - -[#122034]: https://github.com/rust-lang/rust/issues/122034 - ------------------------ "##, default_severity: Severity::Allow, @@ -9504,10 +12339,44 @@ fn get_foo() -> Foo { label: "ptr_as_uninit", description: r##"# `ptr_as_uninit` + + The tracking issue for this feature is: [#75402] [#75402]: https://github.com/rust-lang/rust/issues/75402 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "ptr_cast_array", + description: r##"# `ptr_cast_array` + + + +The tracking issue for this feature is: [#144514] + +[#144514]: https://github.com/rust-lang/rust/issues/144514 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "ptr_cast_slice", + description: r##"# `ptr_cast_slice` + + + +The tracking issue for this feature is: [#149103] + +[#149103]: https://github.com/rust-lang/rust/issues/149103 + ------------------------ "##, default_severity: Severity::Allow, @@ -9518,6 +12387,8 @@ fn get_foo() -> Foo { label: "ptr_internals", description: r##"# `ptr_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -9530,6 +12401,8 @@ fn get_foo() -> Foo { label: "ptr_mask", description: r##"# `ptr_mask` + + The tracking issue for this feature is: [#98290] [#98290]: https://github.com/rust-lang/rust/issues/98290 @@ -9544,24 +12417,12 @@ fn get_foo() -> Foo { label: "ptr_metadata", description: r##"# `ptr_metadata` + + The tracking issue for this feature is: [#81513] [#81513]: https://github.com/rust-lang/rust/issues/81513 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "ptr_sub_ptr", - description: r##"# `ptr_sub_ptr` - -The tracking issue for this feature is: [#95892] - -[#95892]: https://github.com/rust-lang/rust/issues/95892 - ------------------------ "##, default_severity: Severity::Allow, @@ -9572,6 +12433,8 @@ fn get_foo() -> Foo { label: "pub_crate_should_not_need_unstable_attr", description: r##"# `pub_crate_should_not_need_unstable_attr` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -9584,10 +12447,60 @@ fn get_foo() -> Foo { label: "random", description: r##"# `random` + + The tracking issue for this feature is: [#130703] [#130703]: https://github.com/rust-lang/rust/issues/130703 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "range_bounds_is_empty", + description: r##"# `range_bounds_is_empty` + + + +The tracking issue for this feature is: [#137300] + +[#137300]: https://github.com/rust-lang/rust/issues/137300 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "range_into_bounds", + description: r##"# `range_into_bounds` + + + +The tracking issue for this feature is: [#136903] + +[#136903]: https://github.com/rust-lang/rust/issues/136903 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "raw_dylib_elf", + description: r##"# `raw_dylib_elf` + +Allows the use of raw-dylibs on ELF platforms + +The tracking issue for this feature is: [#135694] + +[#135694]: https://github.com/rust-lang/rust/issues/135694 + ------------------------ "##, default_severity: Severity::Allow, @@ -9598,6 +12511,8 @@ fn get_foo() -> Foo { label: "raw_os_error_ty", description: r##"# `raw_os_error_ty` + + The tracking issue for this feature is: [#107792] [#107792]: https://github.com/rust-lang/rust/issues/107792 @@ -9612,6 +12527,8 @@ fn get_foo() -> Foo { label: "raw_slice_split", description: r##"# `raw_slice_split` + + The tracking issue for this feature is: [#95595] [#95595]: https://github.com/rust-lang/rust/issues/95595 @@ -9626,8 +12543,26 @@ fn get_foo() -> Foo { label: "raw_vec_internals", description: r##"# `raw_vec_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "read_array", + description: r##"# `read_array` + + + +The tracking issue for this feature is: [#148848] + +[#148848]: https://github.com/rust-lang/rust/issues/148848 + ------------------------ "##, default_severity: Severity::Allow, @@ -9638,10 +12573,44 @@ fn get_foo() -> Foo { label: "read_buf", description: r##"# `read_buf` + + The tracking issue for this feature is: [#78485] [#78485]: https://github.com/rust-lang/rust/issues/78485 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "read_buf_at", + description: r##"# `read_buf_at` + + + +The tracking issue for this feature is: [#140771] + +[#140771]: https://github.com/rust-lang/rust/issues/140771 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "reborrow", + description: r##"# `reborrow` + + + +The tracking issue for this feature is: [#145612] + +[#145612]: https://github.com/rust-lang/rust/issues/145612 + ------------------------ "##, default_severity: Severity::Allow, @@ -9652,10 +12621,28 @@ fn get_foo() -> Foo { label: "reentrant_lock", description: r##"# `reentrant_lock` + + The tracking issue for this feature is: [#121440] [#121440]: https://github.com/rust-lang/rust/issues/121440 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "reentrant_lock_data_ptr", + description: r##"# `reentrant_lock_data_ptr` + + + +The tracking issue for this feature is: [#140368] + +[#140368]: https://github.com/rust-lang/rust/issues/140368 + ------------------------ "##, default_severity: Severity::Allow, @@ -9670,7 +12657,41 @@ fn get_foo() -> Foo { [#123076]: https://github.com/rust-lang/rust/issues/123076 ------------------------- +--- + +This feature is incomplete and not yet intended for general use. + +This implements experimental, Edition-dependent match ergonomics under consideration for inclusion +in Rust, allowing `&` patterns in more places. For example: + +```rust,edition2024 +#![feature(ref_pat_eat_one_layer_2024)] +#![allow(incomplete_features)] +# +# // Tests type equality in a way that avoids coercing `&&T` or `&mut T` to `&T`. +# trait Eq {} +# impl Eq for T {} +# fn has_type(_: impl Eq) {} + +// `&` can match against a `ref` binding mode instead of a reference type: +let (x, &y) = &(0, 1); +has_type::<&u8>(x); +has_type::(y); + +// `&` can match against `&mut` references: +let &z = &mut 2; +has_type::(z); +``` + +For specifics, see the corresponding typing rules for [Editions 2021 and earlier] and for +[Editions 2024 and later]. For more information on binding modes, see [The Rust Reference]. + +For alternative experimental match ergonomics, see the feature +[`ref_pat_eat_one_layer_2024_structural`](./ref-pat-eat-one-layer-2024-structural.md). + +[Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQIBAQABAAAAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false +[Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAAABAQABAgIAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false +[The Rust Reference]: https://doc.rust-lang.org/reference/patterns.html#binding-modes "##, default_severity: Severity::Allow, warn_since: None, @@ -9684,6 +12705,55 @@ fn get_foo() -> Foo { [#123076]: https://github.com/rust-lang/rust/issues/123076 +--- + +This feature is incomplete and not yet intended for general use. + +This implements experimental, Edition-dependent match ergonomics under consideration for inclusion +in Rust, allowing `&` patterns in more places. For example: +```rust,edition2024 +#![feature(ref_pat_eat_one_layer_2024_structural)] +#![allow(incomplete_features)] +# +# // Tests type equality in a way that avoids coercing `&&T` or `&mut T` to `&T`. +# trait Eq {} +# impl Eq for T {} +# fn has_type(_: impl Eq) {} + +// `&` can match against a `ref` binding mode instead of a reference type: +let (x, &y) = &(0, 1); +has_type::<&u8>(x); +has_type::(y); + +// `&` can match against `&mut` references: +let &z = &mut 2; +has_type::(z); +``` + +For specifics, see the corresponding typing rules for [Editions 2021 and earlier] and for +[Editions 2024 and later]. For more information on binding modes, see [The Rust Reference]. + +For alternative experimental match ergonomics, see the feature +[`ref_pat_eat_one_layer_2024`](./ref-pat-eat-one-layer-2024.md). + +[Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQIBAQEBAAAAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false +[Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAgEBAQEBAgIAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false +[The Rust Reference]: https://doc.rust-lang.org/reference/patterns.html#binding-modes +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "refcell_try_map", + description: r##"# `refcell_try_map` + + + +The tracking issue for this feature is: [#143801] + +[#143801]: https://github.com/rust-lang/rust/issues/143801 + ------------------------ "##, default_severity: Severity::Allow, @@ -9699,31 +12769,54 @@ fn get_foo() -> Foo { [#66079]: https://github.com/rust-lang/rust/issues/66079 ------------------------ -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "repr128", - description: r##"# `repr128` -The tracking issue for this feature is: [#56071] +The `register_tool` language feature informs the compiler that attributes in your code are meant to be used with tools other than the compiler itself. This can be useful if your code has semantic meaning without the external tool, but enables additional features when the tool is present. -[#56071]: https://github.com/rust-lang/rust/issues/56071 +`register_tool` also allows configuring lint levels for external tools. + +Tool attributes are only meant for ignorable attributes. If your code *changes* meaning when the attribute is present, it should not use a tool attribute (because it cannot be compiled with anything other than the external tool, and in a sense is a fork of the language). ------------------------ -The `repr128` feature adds support for `#[repr(u128)]` on `enum`s. +`#![register_tool(tool)]` is an attribute, and is only valid at the crate root. +Attributes using the registered tool are checked for valid syntax, and lint attributes are checked to be in a valid format. However, the compiler cannot validate the semantics of the attribute, nor can it tell whether the configured lint is present in the external tool. + +Semantically, `clippy::*`, `rustdoc::*`, and `rustfmt::*` lints and attributes all behave as if `#![register_tool(clippy, rustdoc, rustfmt)]` were injected into the crate root, except that the `rustdoc` namespace can only be used for lints, not for attributes. +When compiling with `-Z unstable-features`, `rustc::*` lints can also be used. Like `rustdoc`, the `rustc` namespace can only be used with lints, not attributes. + +The compiler will emit an error if it encounters a lint/attribute whose namespace isn't a registered tool. + +Tool namespaces cannot be nested; `register_tool(main_tool::subtool)` is an error. + +## Examples + +Tool attributes: ```rust -#![feature(repr128)] +#![feature(register_tool)] +#![register_tool(c2rust)] -#[repr(u128)] -enum Foo { - Bar(u64), +// Mark which C header file this module was generated from. +#[c2rust::header_src = "operations.h"] +pub mod operations_h { + use std::ffi::c_int; + + // Mark which source line this struct was generated from. + #[c2rust::src_loc = "11:0"] + pub struct Point { + pub x: c_int, + pub y: c_int, + } } ``` + +Tool lints: + +``` +#![feature(register_tool)] +#![register_tool(bevy)] +#![deny(bevy::duplicate_bevy_dependencies)] +``` "##, default_severity: Severity::Allow, warn_since: None, @@ -9733,6 +12826,8 @@ enum Foo { label: "repr_simd", description: r##"# `repr_simd` +Allows `repr(simd)` and importing the various simd intrinsics. + The tracking issue for this feature is: [#27731] [#27731]: https://github.com/rust-lang/rust/issues/27731 @@ -9747,6 +12842,8 @@ enum Foo { label: "restricted_std", description: r##"# `restricted_std` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -9756,12 +12853,14 @@ enum Foo { deny_since: None, }, Lint { - label: "result_flattening", - description: r##"# `result_flattening` + label: "result_option_map_or_default", + description: r##"# `result_option_map_or_default` -The tracking issue for this feature is: [#70142] -[#70142]: https://github.com/rust-lang/rust/issues/70142 + +The tracking issue for this feature is: [#138099] + +[#138099]: https://github.com/rust-lang/rust/issues/138099 ------------------------ "##, @@ -9773,6 +12872,8 @@ enum Foo { label: "return_type_notation", description: r##"# `return_type_notation` +Allows bounding the return type of AFIT/RPITIT. + The tracking issue for this feature is: [#109417] [#109417]: https://github.com/rust-lang/rust/issues/109417 @@ -9784,12 +12885,14 @@ enum Foo { deny_since: None, }, Lint { - label: "riscv_target_feature", - description: r##"# `riscv_target_feature` + label: "rev_into_inner", + description: r##"# `rev_into_inner` -The tracking issue for this feature is: [#44839] -[#44839]: https://github.com/rust-lang/rust/issues/44839 + +The tracking issue for this feature is: [#144277] + +[#144277]: https://github.com/rust-lang/rust/issues/144277 ------------------------ "##, @@ -9798,12 +12901,14 @@ enum Foo { deny_since: None, }, Lint { - label: "round_char_boundary", - description: r##"# `round_char_boundary` + label: "riscv_target_feature", + description: r##"# `riscv_target_feature` -The tracking issue for this feature is: [#93743] +Target features on riscv. -[#93743]: https://github.com/rust-lang/rust/issues/93743 +The tracking issue for this feature is: [#150257] + +[#150257]: https://github.com/rust-lang/rust/issues/150257 ------------------------ "##, @@ -9827,9 +12932,11 @@ enum Foo { label: "rtm_target_feature", description: r##"# `rtm_target_feature` -The tracking issue for this feature is: [#44839] +The rtm target feature on x86. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150258] + +[#150258]: https://github.com/rust-lang/rust/issues/150258 ------------------------ "##, @@ -9841,6 +12948,8 @@ enum Foo { label: "rust_cold_cc", description: r##"# `rust_cold_cc` +Allows `extern "rust-cold"`. + The tracking issue for this feature is: [#97544] [#97544]: https://github.com/rust-lang/rust/issues/97544 @@ -9852,12 +12961,14 @@ enum Foo { deny_since: None, }, Lint { - label: "rustc_allow_const_fn_unstable", - description: r##"# `rustc_allow_const_fn_unstable` + label: "rust_preserve_none_cc", + description: r##"# `rust_preserve_none_cc` -The tracking issue for this feature is: [#69399] +Allows `extern "rust-preserve-none"`. -[#69399]: https://github.com/rust-lang/rust/issues/69399 +The tracking issue for this feature is: [#151401] + +[#151401]: https://github.com/rust-lang/rust/issues/151401 ------------------------ "##, @@ -9920,18 +13031,6 @@ pub enum X { error: aborting due to 2 previous errors ``` -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "rustc_encodable_decodable", - description: r##"# `rustc_encodable_decodable` - -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. - ------------------------- "##, default_severity: Severity::Allow, warn_since: None, @@ -9947,9 +13046,42 @@ pub enum X { ------------------------ -This feature allows access to unstable internal compiler crates. +This feature allows access to unstable internal compiler crates such as `rustc_driver`. -Additionally it changes the linking behavior of crates which have this feature enabled. It will prevent linking to a dylib if there's a static variant of it already statically linked into another dylib dependency. This is required to successfully link to `rustc_driver`. +The presence of this feature changes the way the linkage format for dylibs is calculated in a way +that is necessary for linking against dylibs that statically link `std` (such as `rustc_driver`). +This makes this feature "viral" in linkage; its use in a given crate makes its use required in +dependent crates which link to it (including integration tests, which are built as separate crates). + +## Common linker failures related to missing LLVM libraries + +### When using `rustc-private` with Official Toolchains + +When using the `rustc_private` feature with official toolchains distributed via rustup, you'll need to install: + +1. The `rustc-dev` component (provides compiler libraries) +2. The `llvm-tools` component (provides LLVM libraries needed for linking) + +You can install these components using `rustup`: + +```text +rustup component add rustc-dev llvm-tools +``` + +Without the `llvm-tools` component, you may encounter linking errors like: + +```text +error: linking with `cc` failed: exit status: 1 + | + = note: rust-lld: error: unable to find library -lLLVM-{version} +``` + +### When using `rustc-private` with Custom Toolchains + +For custom-built toolchains or environments not using rustup, different configuration may be required: + +- Ensure LLVM libraries are available in your library search paths +- You might need to configure library paths explicitly depending on your LLVM installation "##, default_severity: Severity::Allow, warn_since: None, @@ -9959,6 +13091,8 @@ pub enum X { label: "rustdoc_internals", description: r##"# `rustdoc_internals` +Allows using internal rustdoc features like `doc(keyword)`. + The tracking issue for this feature is: [#90418] [#90418]: https://github.com/rust-lang/rust/issues/90418 @@ -9973,6 +13107,8 @@ pub enum X { label: "rustdoc_missing_doc_code_examples", description: r##"# `rustdoc_missing_doc_code_examples` +Allows using the `rustdoc::missing_doc_code_examples` lint + The tracking issue for this feature is: [#101730] [#101730]: https://github.com/rust-lang/rust/issues/101730 @@ -9984,12 +13120,14 @@ pub enum X { deny_since: None, }, Lint { - label: "rwlock_downgrade", - description: r##"# `rwlock_downgrade` + label: "rwlock_data_ptr", + description: r##"# `rwlock_data_ptr` -The tracking issue for this feature is: [#128203] -[#128203]: https://github.com/rust-lang/rust/issues/128203 + +The tracking issue for this feature is: [#140368] + +[#140368]: https://github.com/rust-lang/rust/issues/140368 ------------------------ "##, @@ -10001,11 +13139,93 @@ pub enum X { label: "s390x_target_feature", description: r##"# `s390x_target_feature` -The tracking issue for this feature is: [#44839] +Target features on s390x. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150259] + +[#150259]: https://github.com/rust-lang/rust/issues/150259 ------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "sanitize", + description: r##"# `sanitize` + +The tracking issue for this feature is: [#39699] + +[#39699]: https://github.com/rust-lang/rust/issues/39699 + +------------------------ + +The `sanitize` attribute can be used to selectively disable or enable sanitizer +instrumentation in an annotated function. This might be useful to: avoid +instrumentation overhead in a performance critical function, or avoid +instrumenting code that contains constructs unsupported by given sanitizer. + +The precise effect of this annotation depends on particular sanitizer in use. +For example, with `sanitize(thread = "off")`, the thread sanitizer will no +longer instrument non-atomic store / load operations, but it will instrument +atomic operations to avoid reporting false positives and provide meaning full +stack traces. + +This attribute was previously named `no_sanitize`. + +## Examples + +``` rust +#![feature(sanitize)] + +#[sanitize(address = "off")] +fn foo() { + // ... +} +``` + +It is also possible to disable sanitizers for entire modules and enable them +for single items or functions. + +```rust +#![feature(sanitize)] + +#[sanitize(address = "off")] +mod foo { + fn unsanitized() { + // ... + } + + #[sanitize(address = "on")] + fn sanitized() { + // ... + } +} +``` + +It's also applicable to impl blocks. + +```rust +#![feature(sanitize)] + +trait MyTrait { + fn foo(&self); + fn bar(&self); +} + +#[sanitize(address = "off")] +impl MyTrait for () { + fn foo(&self) { + // ... + } + + #[sanitize(address = "on")] + fn bar(&self) { + // ... + } +} +``` "##, default_severity: Severity::Allow, warn_since: None, @@ -10015,8 +13235,26 @@ pub enum X { label: "sealed", description: r##"# `sealed` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "seek_io_take_position", + description: r##"# `seek_io_take_position` + + + +The tracking issue for this feature is: [#97227] + +[#97227]: https://github.com/rust-lang/rust/issues/97227 + ------------------------ "##, default_severity: Severity::Allow, @@ -10027,10 +13265,28 @@ pub enum X { label: "seek_stream_len", description: r##"# `seek_stream_len` + + The tracking issue for this feature is: [#59359] [#59359]: https://github.com/rust-lang/rust/issues/59359 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "set_permissions_nofollow", + description: r##"# `set_permissions_nofollow` + + + +The tracking issue for this feature is: [#141607] + +[#141607]: https://github.com/rust-lang/rust/issues/141607 + ------------------------ "##, default_severity: Severity::Allow, @@ -10041,6 +13297,8 @@ pub enum X { label: "set_ptr_value", description: r##"# `set_ptr_value` + + The tracking issue for this feature is: [#75091] [#75091]: https://github.com/rust-lang/rust/issues/75091 @@ -10055,6 +13313,8 @@ pub enum X { label: "setgroups", description: r##"# `setgroups` + + The tracking issue for this feature is: [#90747] [#90747]: https://github.com/rust-lang/rust/issues/90747 @@ -10069,6 +13329,8 @@ pub enum X { label: "sgx_platform", description: r##"# `sgx_platform` + + The tracking issue for this feature is: [#56975] [#56975]: https://github.com/rust-lang/rust/issues/56975 @@ -10080,12 +13342,14 @@ pub enum X { deny_since: None, }, Lint { - label: "sha512_sm_x86", - description: r##"# `sha512_sm_x86` + label: "signed_bigint_helpers", + description: r##"# `signed_bigint_helpers` -The tracking issue for this feature is: [#126624] -[#126624]: https://github.com/rust-lang/rust/issues/126624 + +The tracking issue for this feature is: [#151989] + +[#151989]: https://github.com/rust-lang/rust/issues/151989 ------------------------ "##, @@ -10097,10 +13361,28 @@ pub enum X { label: "simd_ffi", description: r##"# `simd_ffi` +Allows the use of SIMD types in functions declared in `extern` blocks. + The tracking issue for this feature is: [#27731] [#27731]: https://github.com/rust-lang/rust/issues/27731 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "sized_hierarchy", + description: r##"# `sized_hierarchy` + +Introduces a hierarchy of `Sized` traits (RFC 3729). + +The tracking issue for this feature is: [#144404] + +[#144404]: https://github.com/rust-lang/rust/issues/144404 + ------------------------ "##, default_severity: Severity::Allow, @@ -10111,36 +13393,10 @@ pub enum X { label: "sized_type_properties", description: r##"# `sized_type_properties` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "slice_as_array", - description: r##"# `slice_as_array` - -The tracking issue for this feature is: [#133508] - -[#133508]: https://github.com/rust-lang/rust/issues/133508 - ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "slice_as_chunks", - description: r##"# `slice_as_chunks` - -The tracking issue for this feature is: [#74985] - -[#74985]: https://github.com/rust-lang/rust/issues/74985 - ------------------------ "##, default_severity: Severity::Allow, @@ -10151,6 +13407,8 @@ pub enum X { label: "slice_concat_ext", description: r##"# `slice_concat_ext` + + The tracking issue for this feature is: [#27747] [#27747]: https://github.com/rust-lang/rust/issues/27747 @@ -10165,6 +13423,8 @@ pub enum X { label: "slice_concat_trait", description: r##"# `slice_concat_trait` + + The tracking issue for this feature is: [#27747] [#27747]: https://github.com/rust-lang/rust/issues/27747 @@ -10179,6 +13439,8 @@ pub enum X { label: "slice_from_ptr_range", description: r##"# `slice_from_ptr_range` + + The tracking issue for this feature is: [#89792] [#89792]: https://github.com/rust-lang/rust/issues/89792 @@ -10193,6 +13455,8 @@ pub enum X { label: "slice_index_methods", description: r##"# `slice_index_methods` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -10205,6 +13469,8 @@ pub enum X { label: "slice_internals", description: r##"# `slice_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -10217,10 +13483,28 @@ pub enum X { label: "slice_iter_mut_as_mut_slice", description: r##"# `slice_iter_mut_as_mut_slice` + + The tracking issue for this feature is: [#93079] [#93079]: https://github.com/rust-lang/rust/issues/93079 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "slice_partial_sort_unstable", + description: r##"# `slice_partial_sort_unstable` + + + +The tracking issue for this feature is: [#149046] + +[#149046]: https://github.com/rust-lang/rust/issues/149046 + ------------------------ "##, default_severity: Severity::Allow, @@ -10231,6 +13515,8 @@ pub enum X { label: "slice_partition_dedup", description: r##"# `slice_partition_dedup` + + The tracking issue for this feature is: [#54279] [#54279]: https://github.com/rust-lang/rust/issues/54279 @@ -10245,6 +13531,8 @@ pub enum X { label: "slice_pattern", description: r##"# `slice_pattern` + + The tracking issue for this feature is: [#56345] [#56345]: https://github.com/rust-lang/rust/issues/56345 @@ -10259,6 +13547,8 @@ pub enum X { label: "slice_ptr_get", description: r##"# `slice_ptr_get` + + The tracking issue for this feature is: [#74265] [#74265]: https://github.com/rust-lang/rust/issues/74265 @@ -10273,10 +13563,28 @@ pub enum X { label: "slice_range", description: r##"# `slice_range` + + The tracking issue for this feature is: [#76393] [#76393]: https://github.com/rust-lang/rust/issues/76393 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "slice_shift", + description: r##"# `slice_shift` + + + +The tracking issue for this feature is: [#151772] + +[#151772]: https://github.com/rust-lang/rust/issues/151772 + ------------------------ "##, default_severity: Severity::Allow, @@ -10287,6 +13595,8 @@ pub enum X { label: "slice_split_once", description: r##"# `slice_split_once` + + The tracking issue for this feature is: [#112811] [#112811]: https://github.com/rust-lang/rust/issues/112811 @@ -10301,6 +13611,8 @@ pub enum X { label: "slice_swap_unchecked", description: r##"# `slice_swap_unchecked` + + The tracking issue for this feature is: [#88539] [#88539]: https://github.com/rust-lang/rust/issues/88539 @@ -10312,12 +13624,30 @@ pub enum X { deny_since: None, }, Lint { - label: "slice_take", - description: r##"# `slice_take` + label: "sliceindex_wrappers", + description: r##"# `sliceindex_wrappers` -The tracking issue for this feature is: [#62280] -[#62280]: https://github.com/rust-lang/rust/issues/62280 + +The tracking issue for this feature is: [#146179] + +[#146179]: https://github.com/rust-lang/rust/issues/146179 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "smart_pointer_try_map", + description: r##"# `smart_pointer_try_map` + + + +The tracking issue for this feature is: [#144419] + +[#144419]: https://github.com/rust-lang/rust/issues/144419 ------------------------ "##, @@ -10329,6 +13659,8 @@ pub enum X { label: "solid_ext", description: r##"# `solid_ext` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -10341,6 +13673,8 @@ pub enum X { label: "sort_floats", description: r##"# `sort_floats` + + The tracking issue for this feature is: [#93396] [#93396]: https://github.com/rust-lang/rust/issues/93396 @@ -10355,6 +13689,8 @@ pub enum X { label: "sparc_target_feature", description: r##"# `sparc_target_feature` +Target features on sparc. + The tracking issue for this feature is: [#132783] [#132783]: https://github.com/rust-lang/rust/issues/132783 @@ -10369,6 +13705,8 @@ pub enum X { label: "specialization", description: r##"# `specialization` +Allows specialization of implementations (RFC 1210). + The tracking issue for this feature is: [#31844] [#31844]: https://github.com/rust-lang/rust/issues/31844 @@ -10383,6 +13721,8 @@ pub enum X { label: "split_array", description: r##"# `split_array` + + The tracking issue for this feature is: [#90091] [#90091]: https://github.com/rust-lang/rust/issues/90091 @@ -10397,24 +13737,12 @@ pub enum X { label: "split_as_slice", description: r##"# `split_as_slice` + + The tracking issue for this feature is: [#96137] [#96137]: https://github.com/rust-lang/rust/issues/96137 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "sse4a_target_feature", - description: r##"# `sse4a_target_feature` - -The tracking issue for this feature is: [#44839] - -[#44839]: https://github.com/rust-lang/rust/issues/44839 - ------------------------ "##, default_severity: Severity::Allow, @@ -10425,6 +13753,8 @@ pub enum X { label: "staged_api", description: r##"# `staged_api` +Allows using the `#[stable]` and `#[unstable]` attributes. + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -10434,66 +13764,16 @@ pub enum X { deny_since: None, }, Lint { - label: "start", - description: r##"# `start` + label: "static_align", + description: r##"# `static_align` -The tracking issue for this feature is: [#29633] +Allows using `#[rustc_align_static(...)]` on static items. -[#29633]: https://github.com/rust-lang/rust/issues/29633 +The tracking issue for this feature is: [#146177] + +[#146177]: https://github.com/rust-lang/rust/issues/146177 ------------------------ - -Allows you to mark a function as the entry point of the executable, which is -necessary in `#![no_std]` environments. - -The function marked `#[start]` is passed the command line parameters in the same -format as the C main function (aside from the integer types being used). -It has to be non-generic and have the following signature: - -```rust,ignore (only-for-syntax-highlight) -# let _: -fn(isize, *const *const u8) -> isize -# ; -``` - -This feature should not be confused with the `start` *lang item* which is -defined by the `std` crate and is written `#[lang = "start"]`. - -## Usage together with the `std` crate - -`#[start]` can be used in combination with the `std` crate, in which case the -normal `main` function (which would get called from the `std` crate) won't be -used as an entry point. -The initialization code in `std` will be skipped this way. - -Example: - -```rust -#![feature(start)] - -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - 0 -} -``` - -Unwinding the stack past the `#[start]` function is currently considered -Undefined Behavior (for any unwinding implementation): - -```rust,ignore (UB) -#![feature(start)] - -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - std::panic::catch_unwind(|| { - panic!(); // panic safely gets caught or safely aborts execution - }); - - panic!(); // UB! - - 0 -} -``` "##, default_severity: Severity::Allow, warn_since: None, @@ -10503,8 +13783,26 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "std_internals", description: r##"# `std_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "stdarch_aarch64_feature_detection", + description: r##"# `stdarch_aarch64_feature_detection` + + + +The tracking issue for this feature is: [#127764] + +[#127764]: https://github.com/rust-lang/rust/issues/127764 + ------------------------ "##, default_severity: Severity::Allow, @@ -10515,10 +13813,42 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "stdarch_arm_feature_detection", description: r##"# `stdarch_arm_feature_detection` + + The tracking issue for this feature is: [#111190] [#111190]: https://github.com/rust-lang/rust/issues/111190 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "stdarch_internal", + description: r##"# `stdarch_internal` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "stdarch_loongarch_feature_detection", + description: r##"# `stdarch_loongarch_feature_detection` + + + +The tracking issue for this feature is: [#117425] + +[#117425]: https://github.com/rust-lang/rust/issues/117425 + ------------------------ "##, default_severity: Severity::Allow, @@ -10529,6 +13859,8 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "stdarch_mips_feature_detection", description: r##"# `stdarch_mips_feature_detection` + + The tracking issue for this feature is: [#111188] [#111188]: https://github.com/rust-lang/rust/issues/111188 @@ -10543,10 +13875,44 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "stdarch_powerpc_feature_detection", description: r##"# `stdarch_powerpc_feature_detection` + + The tracking issue for this feature is: [#111191] [#111191]: https://github.com/rust-lang/rust/issues/111191 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "stdarch_riscv_feature_detection", + description: r##"# `stdarch_riscv_feature_detection` + + + +The tracking issue for this feature is: [#111192] + +[#111192]: https://github.com/rust-lang/rust/issues/111192 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "stdio_fd_consts", + description: r##"# `stdio_fd_consts` + + + +The tracking issue for this feature is: [#150836] + +[#150836]: https://github.com/rust-lang/rust/issues/150836 + ------------------------ "##, default_severity: Severity::Allow, @@ -10557,10 +13923,28 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "stdio_makes_pipe", description: r##"# `stdio_makes_pipe` + + The tracking issue for this feature is: [#98288] [#98288]: https://github.com/rust-lang/rust/issues/98288 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "stdio_swap", + description: r##"# `stdio_swap` + + + +The tracking issue for this feature is: [#150667] + +[#150667]: https://github.com/rust-lang/rust/issues/150667 + ------------------------ "##, default_severity: Severity::Allow, @@ -10571,6 +13955,8 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "step_trait", description: r##"# `step_trait` + + The tracking issue for this feature is: [#42168] [#42168]: https://github.com/rust-lang/rust/issues/42168 @@ -10585,6 +13971,8 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "stmt_expr_attributes", description: r##"# `stmt_expr_attributes` +Allows attributes on expressions and non-item statements. + The tracking issue for this feature is: [#15701] [#15701]: https://github.com/rust-lang/rust/issues/15701 @@ -10599,6 +13987,8 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "str_as_str", description: r##"# `str_as_str` + + The tracking issue for this feature is: [#130366] [#130366]: https://github.com/rust-lang/rust/issues/130366 @@ -10613,6 +14003,8 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "str_from_raw_parts", description: r##"# `str_from_raw_parts` + + The tracking issue for this feature is: [#119206] [#119206]: https://github.com/rust-lang/rust/issues/119206 @@ -10627,6 +14019,8 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "str_from_utf16_endian", description: r##"# `str_from_utf16_endian` + + The tracking issue for this feature is: [#116258] [#116258]: https://github.com/rust-lang/rust/issues/116258 @@ -10653,6 +14047,8 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "str_lines_remainder", description: r##"# `str_lines_remainder` + + The tracking issue for this feature is: [#77998] [#77998]: https://github.com/rust-lang/rust/issues/77998 @@ -10667,6 +14063,8 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "str_split_inclusive_remainder", description: r##"# `str_split_inclusive_remainder` + + The tracking issue for this feature is: [#77998] [#77998]: https://github.com/rust-lang/rust/issues/77998 @@ -10681,6 +14079,8 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "str_split_remainder", description: r##"# `str_split_remainder` + + The tracking issue for this feature is: [#77998] [#77998]: https://github.com/rust-lang/rust/issues/77998 @@ -10695,24 +14095,12 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { label: "str_split_whitespace_remainder", description: r##"# `str_split_whitespace_remainder` + + The tracking issue for this feature is: [#77998] [#77998]: https://github.com/rust-lang/rust/issues/77998 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "strict_provenance_atomic_ptr", - description: r##"# `strict_provenance_atomic_ptr` - -The tracking issue for this feature is: [#99108] - -[#99108]: https://github.com/rust-lang/rust/issues/99108 - ------------------------ "##, default_severity: Severity::Allow, @@ -10742,72 +14130,6 @@ fn main() { //~^ WARNING: strict provenance disallows casting integer `usize` to pointer `*const u8` } ``` -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "string_deref_patterns", - description: r##"# `string_deref_patterns` - -The tracking issue for this feature is: [#87121] - -[#87121]: https://github.com/rust-lang/rust/issues/87121 - ------------------------- - -This feature permits pattern matching `String` to `&str` through [its `Deref` implementation]. - -```rust -#![feature(string_deref_patterns)] - -pub enum Value { - String(String), - Number(u32), -} - -pub fn is_it_the_answer(value: Value) -> bool { - match value { - Value::String("42") => true, - Value::Number(42) => true, - _ => false, - } -} -``` - -Without this feature other constructs such as match guards have to be used. - -```rust -# pub enum Value { -# String(String), -# Number(u32), -# } -# -pub fn is_it_the_answer(value: Value) -> bool { - match value { - Value::String(s) if s == "42" => true, - Value::Number(42) => true, - _ => false, - } -} -``` - -[its `Deref` implementation]: https://doc.rust-lang.org/std/string/struct.String.html#impl-Deref-for-String -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "string_extend_from_within", - description: r##"# `string_extend_from_within` - -The tracking issue for this feature is: [#103806] - -[#103806]: https://github.com/rust-lang/rust/issues/103806 - ------------------------- "##, default_severity: Severity::Allow, warn_since: None, @@ -10817,10 +14139,28 @@ pub fn is_it_the_answer(value: Value) -> bool { label: "string_from_utf8_lossy_owned", description: r##"# `string_from_utf8_lossy_owned` + + The tracking issue for this feature is: [#129436] [#129436]: https://github.com/rust-lang/rust/issues/129436 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "string_into_chars", + description: r##"# `string_into_chars` + + + +The tracking issue for this feature is: [#133125] + +[#133125]: https://github.com/rust-lang/rust/issues/133125 + ------------------------ "##, default_severity: Severity::Allow, @@ -10831,10 +14171,44 @@ pub fn is_it_the_answer(value: Value) -> bool { label: "string_remove_matches", description: r##"# `string_remove_matches` + + The tracking issue for this feature is: [#72826] [#72826]: https://github.com/rust-lang/rust/issues/72826 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "string_replace_in_place", + description: r##"# `string_replace_in_place` + + + +The tracking issue for this feature is: [#147949] + +[#147949]: https://github.com/rust-lang/rust/issues/147949 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "strip_circumfix", + description: r##"# `strip_circumfix` + + + +The tracking issue for this feature is: [#147946] + +[#147946]: https://github.com/rust-lang/rust/issues/147946 + ------------------------ "##, default_severity: Severity::Allow, @@ -10845,6 +14219,8 @@ pub fn is_it_the_answer(value: Value) -> bool { label: "structural_match", description: r##"# `structural_match` +Allows using `#[structural_match]` which indicates that a type is structurally matchable. FIXME: Subsumed by trait `StructuralPartialEq`, cannot move to removed until a library feature with the same name exists. + The tracking issue for this feature is: [#31434] [#31434]: https://github.com/rust-lang/rust/issues/31434 @@ -10859,10 +14235,76 @@ pub fn is_it_the_answer(value: Value) -> bool { label: "substr_range", description: r##"# `substr_range` + + The tracking issue for this feature is: [#126769] [#126769]: https://github.com/rust-lang/rust/issues/126769 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "super_let", + description: r##"# `super_let` + +Allows `super let` statements. + +The tracking issue for this feature is: [#139076] + +[#139076]: https://github.com/rust-lang/rust/issues/139076 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "supertrait_item_shadowing", + description: r##"# `supertrait_item_shadowing` + +Allows subtrait items to shadow supertrait items. + +The tracking issue for this feature is: [#89151] + +[#89151]: https://github.com/rust-lang/rust/issues/89151 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "sync_nonpoison", + description: r##"# `sync_nonpoison` + + + +The tracking issue for this feature is: [#134645] + +[#134645]: https://github.com/rust-lang/rust/issues/134645 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "sync_poison_mod", + description: r##"# `sync_poison_mod` + + + +The tracking issue for this feature is: [#134646] + +[#134646]: https://github.com/rust-lang/rust/issues/134646 + ------------------------ "##, default_severity: Severity::Allow, @@ -10873,6 +14315,8 @@ pub fn is_it_the_answer(value: Value) -> bool { label: "sync_unsafe_cell", description: r##"# `sync_unsafe_cell` + + The tracking issue for this feature is: [#95439] [#95439]: https://github.com/rust-lang/rust/issues/95439 @@ -10884,26 +14328,14 @@ pub fn is_it_the_answer(value: Value) -> bool { deny_since: None, }, Lint { - label: "target_feature_11", - description: r##"# `target_feature_11` + label: "target_feature_inline_always", + description: r##"# `target_feature_inline_always` -The tracking issue for this feature is: [#69098] +Allows the use of target_feature when a function is marked inline(always). -[#69098]: https://github.com/rust-lang/rust/issues/69098 +The tracking issue for this feature is: [#145574] ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "tbm_target_feature", - description: r##"# `tbm_target_feature` - -The tracking issue for this feature is: [#44839] - -[#44839]: https://github.com/rust-lang/rust/issues/44839 +[#145574]: https://github.com/rust-lang/rust/issues/145574 ------------------------ "##, @@ -10915,6 +14347,8 @@ pub fn is_it_the_answer(value: Value) -> bool { label: "tcp_deferaccept", description: r##"# `tcp_deferaccept` + + The tracking issue for this feature is: [#119639] [#119639]: https://github.com/rust-lang/rust/issues/119639 @@ -10929,6 +14363,8 @@ pub fn is_it_the_answer(value: Value) -> bool { label: "tcp_linger", description: r##"# `tcp_linger` + + The tracking issue for this feature is: [#88494] [#88494]: https://github.com/rust-lang/rust/issues/88494 @@ -10940,12 +14376,14 @@ pub fn is_it_the_answer(value: Value) -> bool { deny_since: None, }, Lint { - label: "tcp_quickack", - description: r##"# `tcp_quickack` + label: "tcplistener_into_incoming", + description: r##"# `tcplistener_into_incoming` -The tracking issue for this feature is: [#96256] -[#96256]: https://github.com/rust-lang/rust/issues/96256 + +The tracking issue for this feature is: [#88373] + +[#88373]: https://github.com/rust-lang/rust/issues/88373 ------------------------ "##, @@ -10954,12 +14392,12 @@ pub fn is_it_the_answer(value: Value) -> bool { deny_since: None, }, Lint { - label: "tcplistener_into_incoming", - description: r##"# `tcplistener_into_incoming` + label: "temporary_niche_types", + description: r##"# `temporary_niche_types` -The tracking issue for this feature is: [#88373] -[#88373]: https://github.com/rust-lang/rust/issues/88373 + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, @@ -11127,6 +14565,20 @@ fn bench_xor_1000_ints(b: &mut Bencher) { However, the optimizer can still modify a testcase in an undesirable manner even when using either of the above. +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "test_incomplete_feature", + description: r##"# `test_incomplete_feature` + +Perma-unstable, only used to test the `incomplete_features` lint. + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ "##, default_severity: Severity::Allow, warn_since: None, @@ -11136,6 +14588,8 @@ fn bench_xor_1000_ints(b: &mut Bencher) { label: "test_unstable_lint", description: r##"# `test_unstable_lint` +Added for testing unstable lints; perma-unstable. + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -11148,6 +14602,8 @@ fn bench_xor_1000_ints(b: &mut Bencher) { label: "thin_box", description: r##"# `thin_box` + + The tracking issue for this feature is: [#92791] [#92791]: https://github.com/rust-lang/rust/issues/92791 @@ -11162,6 +14618,8 @@ fn bench_xor_1000_ints(b: &mut Bencher) { label: "thread_id_value", description: r##"# `thread_id_value` + + The tracking issue for this feature is: [#67939] [#67939]: https://github.com/rust-lang/rust/issues/67939 @@ -11176,6 +14634,8 @@ fn bench_xor_1000_ints(b: &mut Bencher) { label: "thread_local", description: r##"# `thread_local` +Allows using `#[thread_local]` on `static` items. + The tracking issue for this feature is: [#29594] [#29594]: https://github.com/rust-lang/rust/issues/29594 @@ -11202,6 +14662,8 @@ fn bench_xor_1000_ints(b: &mut Bencher) { label: "thread_raw", description: r##"# `thread_raw` + + The tracking issue for this feature is: [#97523] [#97523]: https://github.com/rust-lang/rust/issues/97523 @@ -11216,6 +14678,8 @@ fn bench_xor_1000_ints(b: &mut Bencher) { label: "thread_sleep_until", description: r##"# `thread_sleep_until` + + The tracking issue for this feature is: [#113752] [#113752]: https://github.com/rust-lang/rust/issues/113752 @@ -11230,10 +14694,60 @@ fn bench_xor_1000_ints(b: &mut Bencher) { label: "thread_spawn_hook", description: r##"# `thread_spawn_hook` + + The tracking issue for this feature is: [#132951] [#132951]: https://github.com/rust-lang/rust/issues/132951 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "time_saturating_systemtime", + description: r##"# `time_saturating_systemtime` + + + +The tracking issue for this feature is: [#151199] + +[#151199]: https://github.com/rust-lang/rust/issues/151199 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "time_systemtime_limits", + description: r##"# `time_systemtime_limits` + + + +The tracking issue for this feature is: [#149067] + +[#149067]: https://github.com/rust-lang/rust/issues/149067 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "titlecase", + description: r##"# `titlecase` + + + +The tracking issue for this feature is: [#153892] + +[#153892]: https://github.com/rust-lang/rust/issues/153892 + ------------------------ "##, default_severity: Severity::Allow, @@ -11281,20 +14795,6 @@ fn main() { Finished dev [unoptimized + debuginfo] target(s) in 0.60 secs ``` -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "track_path", - description: r##"# `track_path` - -The tracking issue for this feature is: [#99515] - -[#99515]: https://github.com/rust-lang/rust/issues/99515 - ------------------------- "##, default_severity: Severity::Allow, warn_since: None, @@ -11336,39 +14836,6 @@ pub fn main() { println!("{:?}", b); } ``` -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "trait_upcasting", - description: r##"# `trait_upcasting` - -The tracking issue for this feature is: [#65991] - -[#65991]: https://github.com/rust-lang/rust/issues/65991 - ------------------------- - -The `trait_upcasting` feature adds support for trait upcasting coercion. This allows a -trait object of type `dyn Bar` to be cast to a trait object of type `dyn Foo` -so long as `Bar: Foo`. - -```rust,edition2018 -#![feature(trait_upcasting)] - -trait Foo {} - -trait Bar: Foo {} - -impl Foo for i32 {} - -impl Bar for T {} - -let bar: &dyn Bar = &123; -let foo: &dyn Foo = bar; -``` "##, default_severity: Severity::Allow, warn_since: None, @@ -11378,6 +14845,8 @@ impl Bar for T {} label: "transmutability", description: r##"# `transmutability` + + The tracking issue for this feature is: [#99571] [#99571]: https://github.com/rust-lang/rust/issues/99571 @@ -11392,6 +14861,8 @@ impl Bar for T {} label: "transmute_generic_consts", description: r##"# `transmute_generic_consts` +Allows for transmuting between arrays with sizes that contain generic consts. + The tracking issue for this feature is: [#109929] [#109929]: https://github.com/rust-lang/rust/issues/109929 @@ -11487,6 +14958,22 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. it is transparent). The Rust compiler is free to perform this optimization if possible, but is not required to, and different compiler versions may differ in their application of these optimizations. +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "trim_prefix_suffix", + description: r##"# `trim_prefix_suffix` + + + +The tracking issue for this feature is: [#142312] + +[#142312]: https://github.com/rust-lang/rust/issues/142312 + +------------------------ "##, default_severity: Severity::Allow, warn_since: None, @@ -11496,10 +14983,26 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "trivial_bounds", description: r##"# `trivial_bounds` +Allows inconsistent bounds in where clauses. + The tracking issue for this feature is: [#48214] [#48214]: https://github.com/rust-lang/rust/issues/48214 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "trivial_clone", + description: r##"# `trivial_clone` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, default_severity: Severity::Allow, @@ -11510,6 +15013,8 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "trusted_fused", description: r##"# `trusted_fused` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -11522,6 +15027,8 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "trusted_len", description: r##"# `trusted_len` + + The tracking issue for this feature is: [#37572] [#37572]: https://github.com/rust-lang/rust/issues/37572 @@ -11536,6 +15043,8 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "trusted_len_next_unchecked", description: r##"# `trusted_len_next_unchecked` + + The tracking issue for this feature is: [#37572] [#37572]: https://github.com/rust-lang/rust/issues/37572 @@ -11550,6 +15059,8 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "trusted_random_access", description: r##"# `trusted_random_access` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -11562,10 +15073,28 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "trusted_step", description: r##"# `trusted_step` + + The tracking issue for this feature is: [#85731] [#85731]: https://github.com/rust-lang/rust/issues/85731 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "try_as_dyn", + description: r##"# `try_as_dyn` + + + +The tracking issue for this feature is: [#144361] + +[#144361]: https://github.com/rust-lang/rust/issues/144361 + ------------------------ "##, default_severity: Severity::Allow, @@ -11604,6 +15133,22 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. }; assert!(result.is_err()); ``` +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "try_blocks_heterogeneous", + description: r##"# `try_blocks_heterogeneous` + +Allows using `try bikeshed TargetType {...}` expressions. + +The tracking issue for this feature is: [#149488] + +[#149488]: https://github.com/rust-lang/rust/issues/149488 + +------------------------ "##, default_severity: Severity::Allow, warn_since: None, @@ -11613,6 +15158,8 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "try_find", description: r##"# `try_find` + + The tracking issue for this feature is: [#63178] [#63178]: https://github.com/rust-lang/rust/issues/63178 @@ -11627,6 +15174,8 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "try_reserve_kind", description: r##"# `try_reserve_kind` + + The tracking issue for this feature is: [#48043] [#48043]: https://github.com/rust-lang/rust/issues/48043 @@ -11641,6 +15190,8 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "try_trait_v2", description: r##"# `try_trait_v2` + + The tracking issue for this feature is: [#84277] [#84277]: https://github.com/rust-lang/rust/issues/84277 @@ -11655,6 +15206,8 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "try_trait_v2_residual", description: r##"# `try_trait_v2_residual` + + The tracking issue for this feature is: [#91285] [#91285]: https://github.com/rust-lang/rust/issues/91285 @@ -11669,6 +15222,8 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "try_trait_v2_yeet", description: r##"# `try_trait_v2_yeet` + + The tracking issue for this feature is: [#96374] [#96374]: https://github.com/rust-lang/rust/issues/96374 @@ -11683,6 +15238,8 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "try_with_capacity", description: r##"# `try_with_capacity` + + The tracking issue for this feature is: [#91913] [#91913]: https://github.com/rust-lang/rust/issues/91913 @@ -11697,6 +15254,8 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "tuple_trait", description: r##"# `tuple_trait` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -11711,9 +15270,161 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. The tracking issue for this feature is: [#63063] -[#63063]: https://github.com/rust-lang/rust/issues/63063 - ------------------------ + +> This feature is not to be confused with [`trait_alias`] or [`impl_trait_in_assoc_type`]. + +### What is `impl Trait`? + +`impl Trait` in return position is useful for declaring types that are constrained by traits, but whose concrete type should be hidden: + +```rust +use std::fmt::Debug; + +fn new() -> impl Debug { + 42 +} + +fn main() { + let thing = new(); + // What actually is a `thing`? + // No idea but we know it implements `Debug`, so we can debug print it + println!("{thing:?}"); +} +``` + +See the [reference] for more information about `impl Trait` in return position. + +### `type_alias_impl_trait` + +However, we might want to use an `impl Trait` in multiple locations but actually use the same concrete type everywhere while keeping it hidden. +This can be useful in libraries where you want to hide implementation details. + +The `#[define_opaque]` attribute must be used to explicitly list opaque items constrained by the item it's on. + +```rust +#![feature(type_alias_impl_trait)] +# #![allow(unused_variables, dead_code)] +trait Trait {} + +struct MyType; + +impl Trait for MyType {} + +type Alias = impl Trait; + +#[define_opaque(Alias)] // To constrain the type alias to `MyType` +fn new() -> Alias { + MyType +} + +#[define_opaque(Alias)] // So we can name the concrete type inside this item +fn main() { + let thing: MyType = new(); +} + +// It can be a part of a struct too +struct HaveAlias { + stuff: String, + thing: Alias, +} +``` + +In this example, the concrete type referred to by `Alias` is guaranteed to be the same wherever `Alias` occurs. + +> Originally this feature included type aliases as an associated type of a trait. In [#110237] this was split off to [`impl_trait_in_assoc_type`]. + +### `type_alias_impl_trait` in argument position. + +Note that using `Alias` as an argument type is *not* the same as argument-position `impl Trait`, as `Alias` refers to a unique type, whereas the concrete type for argument-position `impl Trait` is chosen by the caller. + +```rust +# #![feature(type_alias_impl_trait)] +# #![allow(unused_variables)] +# pub mod x { +# pub trait Trait {} +# +# struct MyType; +# +# impl Trait for MyType {} +# +# pub type Alias = impl Trait; +# +# #[define_opaque(Alias)] +# pub fn new() -> Alias { +# MyType +# } +# } +# use x::*; +// this... +pub fn take_alias(x: Alias) { + // ... +} + +// ...is *not* the same as +pub fn take_impl(x: impl Trait) { + // ... +} +# fn main(){} +``` + +```rust,compile_fail,E0308 +# #![feature(type_alias_impl_trait)] +# #![allow(unused_variables)] +# pub mod x { +# pub trait Trait {} +# +# struct MyType; +# +# impl Trait for MyType {} +# +# pub type Alias = impl Trait; +# +# #[define_opaque(Alias)] +# pub fn new() -> Alias { +# MyType +# } +# } +# use x::*; +# pub fn take_alias(x: Alias) { +# // ... +# } +# +# pub fn take_impl(x: impl Trait) { +# // ... +# } +# +// a user's crate using the trait and type alias +struct UserType; +impl Trait for UserType {} + +# fn main(){ +let x = UserType; +take_alias(x); +// ERROR expected opaque type, found `UserType` +// this function *actually* takes a `MyType` as is constrained in `new` + +let x = UserType; +take_impl(x); +// OK + +let x = new(); +take_alias(x); +// OK + +let x = new(); +take_impl(x); +// OK +# } +``` + +Note that the user cannot use `#[define_opaque(Alias)]` to reify the opaque type because only the crate where the type alias is declared may do so. But if this happened in the same crate and the opaque type was reified, they'd get a familiar error: "expected `MyType`, got `UserType`". + +[#63063]: https://github.com/rust-lang/rust/issues/63063 +[#110237]: https://github.com/rust-lang/rust/pull/110237 +[reference]: https://doc.rust-lang.org/stable/reference/types/impl-trait.html#abstract-return-types +[`trait_alias`]: ./trait-alias.md +[`impl_trait_in_assoc_type`]: ./impl-trait-in-assoc-type.md "##, default_severity: Severity::Allow, warn_since: None, @@ -11723,6 +15434,8 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. label: "type_ascription", description: r##"# `type_ascription` + + The tracking issue for this feature is: [#23416] [#23416]: https://github.com/rust-lang/rust/issues/23416 @@ -11768,6 +15481,22 @@ struct Foo { }; } ``` +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "type_info", + description: r##"# `type_info` + + + +The tracking issue for this feature is: [#146922] + +[#146922]: https://github.com/rust-lang/rust/issues/146922 + +------------------------ "##, default_severity: Severity::Allow, warn_since: None, @@ -11777,6 +15506,8 @@ struct Foo { label: "ub_checks", description: r##"# `ub_checks` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -11789,6 +15520,8 @@ struct Foo { label: "uefi_std", description: r##"# `uefi_std` + + The tracking issue for this feature is: [#100499] [#100499]: https://github.com/rust-lang/rust/issues/100499 @@ -11800,12 +15533,46 @@ struct Foo { deny_since: None, }, Lint { - label: "unbounded_shifts", - description: r##"# `unbounded_shifts` + label: "uint_bit_width", + description: r##"# `uint_bit_width` -The tracking issue for this feature is: [#129375] -[#129375]: https://github.com/rust-lang/rust/issues/129375 + +The tracking issue for this feature is: [#142326] + +[#142326]: https://github.com/rust-lang/rust/issues/142326 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "uint_carryless_mul", + description: r##"# `uint_carryless_mul` + + + +The tracking issue for this feature is: [#152080] + +[#152080]: https://github.com/rust-lang/rust/issues/152080 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "uint_gather_scatter_bits", + description: r##"# `uint_gather_scatter_bits` + + + +The tracking issue for this feature is: [#149069] + +[#149069]: https://github.com/rust-lang/rust/issues/149069 ------------------------ "##, @@ -11849,6 +15616,8 @@ fn main() {} label: "unicode_internals", description: r##"# `unicode_internals` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -11861,6 +15630,8 @@ fn main() {} label: "unique_rc_arc", description: r##"# `unique_rc_arc` + + The tracking issue for this feature is: [#112566] [#112566]: https://github.com/rust-lang/rust/issues/112566 @@ -11875,10 +15646,44 @@ fn main() {} label: "unix_file_vectored_at", description: r##"# `unix_file_vectored_at` + + The tracking issue for this feature is: [#89517] [#89517]: https://github.com/rust-lang/rust/issues/89517 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "unix_mkfifo", + description: r##"# `unix_mkfifo` + + + +The tracking issue for this feature is: [#139324] + +[#139324]: https://github.com/rust-lang/rust/issues/139324 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "unix_send_signal", + description: r##"# `unix_send_signal` + + + +The tracking issue for this feature is: [#141975] + +[#141975]: https://github.com/rust-lang/rust/issues/141975 + ------------------------ "##, default_severity: Severity::Allow, @@ -11889,6 +15694,8 @@ fn main() {} label: "unix_set_mark", description: r##"# `unix_set_mark` + + The tracking issue for this feature is: [#96467] [#96467]: https://github.com/rust-lang/rust/issues/96467 @@ -11903,10 +15710,28 @@ fn main() {} label: "unix_socket_ancillary_data", description: r##"# `unix_socket_ancillary_data` + + The tracking issue for this feature is: [#76915] [#76915]: https://github.com/rust-lang/rust/issues/76915 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "unix_socket_exclbind", + description: r##"# `unix_socket_exclbind` + + + +The tracking issue for this feature is: [#123481] + +[#123481]: https://github.com/rust-lang/rust/issues/123481 + ------------------------ "##, default_severity: Severity::Allow, @@ -11917,6 +15742,8 @@ fn main() {} label: "unix_socket_peek", description: r##"# `unix_socket_peek` + + The tracking issue for this feature is: [#76923] [#76923]: https://github.com/rust-lang/rust/issues/76923 @@ -11931,7 +15758,43 @@ fn main() {} label: "unqualified_local_imports", description: r##"# `unqualified_local_imports` -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +Helps with formatting for `group_imports = "StdExternalCrate"`. + +The tracking issue for this feature is: [#138299] + +[#138299]: https://github.com/rust-lang/rust/issues/138299 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "unsafe_binders", + description: r##"# `unsafe_binders` + +Allows using `unsafe<'a> &'a T` unsafe binder types. + +The tracking issue for this feature is: [#130516] + +[#130516]: https://github.com/rust-lang/rust/issues/130516 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "unsafe_cell_access", + description: r##"# `unsafe_cell_access` + + + +The tracking issue for this feature is: [#136327] + +[#136327]: https://github.com/rust-lang/rust/issues/136327 ------------------------ "##, @@ -11943,6 +15806,8 @@ fn main() {} label: "unsafe_fields", description: r##"# `unsafe_fields` +Allows declaring fields `unsafe`. + The tracking issue for this feature is: [#132922] [#132922]: https://github.com/rust-lang/rust/issues/132922 @@ -11954,10 +15819,14 @@ fn main() {} deny_since: None, }, Lint { - label: "unsafe_pin_internals", - description: r##"# `unsafe_pin_internals` + label: "unsafe_pinned", + description: r##"# `unsafe_pinned` -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + + +The tracking issue for this feature is: [#125735] + +[#125735]: https://github.com/rust-lang/rust/issues/125735 ------------------------ "##, @@ -11966,40 +15835,14 @@ fn main() {} deny_since: None, }, Lint { - label: "unsigned_is_multiple_of", - description: r##"# `unsigned_is_multiple_of` + label: "unsafe_unpin", + description: r##"# `unsafe_unpin` -The tracking issue for this feature is: [#128101] -[#128101]: https://github.com/rust-lang/rust/issues/128101 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "unsigned_nonzero_div_ceil", - description: r##"# `unsigned_nonzero_div_ceil` +The tracking issue for this feature is: [#125735] -The tracking issue for this feature is: [#132968] - -[#132968]: https://github.com/rust-lang/rust/issues/132968 - ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "unsigned_signed_diff", - description: r##"# `unsigned_signed_diff` - -The tracking issue for this feature is: [#126041] - -[#126041]: https://github.com/rust-lang/rust/issues/126041 +[#125735]: https://github.com/rust-lang/rust/issues/125735 ------------------------ "##, @@ -12011,6 +15854,8 @@ fn main() {} label: "unsize", description: r##"# `unsize` + + The tracking issue for this feature is: [#18598] [#18598]: https://github.com/rust-lang/rust/issues/18598 @@ -12025,6 +15870,8 @@ fn main() {} label: "unsized_const_params", description: r##"# `unsized_const_params` +Allows const generic parameters to be defined with types that are not `Sized`, e.g. `fn foo() {`. + The tracking issue for this feature is: [#95174] [#95174]: https://github.com/rust-lang/rust/issues/95174 @@ -12039,193 +15886,13 @@ fn main() {} label: "unsized_fn_params", description: r##"# `unsized_fn_params` -The tracking issue for this feature is: [#48055] - -[#48055]: https://github.com/rust-lang/rust/issues/48055 - ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "unsized_locals", - description: r##"# `unsized_locals` +Allows unsized fn parameters. The tracking issue for this feature is: [#48055] [#48055]: https://github.com/rust-lang/rust/issues/48055 ------------------------ - -This implements [RFC1909]. When turned on, you can have unsized arguments and locals: - -[RFC1909]: https://github.com/rust-lang/rfcs/blob/master/text/1909-unsized-rvalues.md - -```rust -#![allow(incomplete_features)] -#![feature(unsized_locals, unsized_fn_params)] - -use std::any::Any; - -fn main() { - let x: Box = Box::new(42); - let x: dyn Any = *x; - // ^ unsized local variable - // ^^ unsized temporary - foo(x); -} - -fn foo(_: dyn Any) {} -// ^^^^^^ unsized argument -``` - -The RFC still forbids the following unsized expressions: - -```rust,compile_fail -#![feature(unsized_locals)] - -use std::any::Any; - -struct MyStruct { - content: T, -} - -struct MyTupleStruct(T); - -fn answer() -> Box { - Box::new(42) -} - -fn main() { - // You CANNOT have unsized statics. - static X: dyn Any = *answer(); // ERROR - const Y: dyn Any = *answer(); // ERROR - - // You CANNOT have struct initialized unsized. - MyStruct { content: *answer() }; // ERROR - MyTupleStruct(*answer()); // ERROR - (42, *answer()); // ERROR - - // You CANNOT have unsized return types. - fn my_function() -> dyn Any { *answer() } // ERROR - - // You CAN have unsized local variables... - let mut x: dyn Any = *answer(); // OK - // ...but you CANNOT reassign to them. - x = *answer(); // ERROR - - // You CANNOT even initialize them separately. - let y: dyn Any; // OK - y = *answer(); // ERROR - - // Not mentioned in the RFC, but by-move captured variables are also Sized. - let x: dyn Any = *answer(); - (move || { // ERROR - let y = x; - })(); - - // You CAN create a closure with unsized arguments, - // but you CANNOT call it. - // This is an implementation detail and may be changed in the future. - let f = |x: dyn Any| {}; - f(*answer()); // ERROR -} -``` - -## By-value trait objects - -With this feature, you can have by-value `self` arguments without `Self: Sized` bounds. - -```rust -#![feature(unsized_fn_params)] - -trait Foo { - fn foo(self) {} -} - -impl Foo for T {} - -fn main() { - let slice: Box<[i32]> = Box::new([1, 2, 3]); - <[i32] as Foo>::foo(*slice); -} -``` - -And `Foo` will also be object-safe. - -```rust -#![feature(unsized_fn_params)] - -trait Foo { - fn foo(self) {} -} - -impl Foo for T {} - -fn main () { - let slice: Box = Box::new([1, 2, 3]); - // doesn't compile yet - ::foo(*slice); -} -``` - -One of the objectives of this feature is to allow `Box`. - -## Variable length arrays - -The RFC also describes an extension to the array literal syntax: `[e; dyn n]`. In the syntax, `n` isn't necessarily a constant expression. The array is dynamically allocated on the stack and has the type of `[T]`, instead of `[T; n]`. - -```rust,ignore (not-yet-implemented) -#![feature(unsized_locals)] - -fn mergesort(a: &mut [T]) { - let mut tmp = [T; dyn a.len()]; - // ... -} - -fn main() { - let mut a = [3, 1, 5, 6]; - mergesort(&mut a); - assert_eq!(a, [1, 3, 5, 6]); -} -``` - -VLAs are not implemented yet. The syntax isn't final, either. We may need an alternative syntax for Rust 2015 because, in Rust 2015, expressions like `[e; dyn(1)]` would be ambiguous. One possible alternative proposed in the RFC is `[e; n]`: if `n` captures one or more local variables, then it is considered as `[e; dyn n]`. - -## Advisory on stack usage - -It's advised not to casually use the `#![feature(unsized_locals)]` feature. Typical use-cases are: - -- When you need a by-value trait objects. -- When you really need a fast allocation of small temporary arrays. - -Another pitfall is repetitive allocation and temporaries. Currently the compiler simply extends the stack frame every time it encounters an unsized assignment. So for example, the code - -```rust -#![feature(unsized_locals)] - -fn main() { - let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]); - let _x = {{{{{{{{{{*x}}}}}}}}}}; -} -``` - -and the code - -```rust -#![feature(unsized_locals)] - -fn main() { - for _ in 0..10 { - let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]); - let _x = *x; - } -} -``` - -will unnecessarily extend the stack frame. "##, default_severity: Severity::Allow, warn_since: None, @@ -12235,6 +15902,8 @@ fn main() { label: "unwrap_infallible", description: r##"# `unwrap_infallible` + + The tracking issue for this feature is: [#61695] [#61695]: https://github.com/rust-lang/rust/issues/61695 @@ -12261,6 +15930,8 @@ fn main() { label: "used_with_arg", description: r##"# `used_with_arg` +Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute. + The tracking issue for this feature is: [#93798] [#93798]: https://github.com/rust-lang/rust/issues/93798 @@ -12275,6 +15946,8 @@ fn main() { label: "utf16_extra", description: r##"# `utf16_extra` + + The tracking issue for this feature is: [#94919] [#94919]: https://github.com/rust-lang/rust/issues/94919 @@ -12289,10 +15962,28 @@ fn main() { label: "variant_count", description: r##"# `variant_count` + + The tracking issue for this feature is: [#73662] [#73662]: https://github.com/rust-lang/rust/issues/73662 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "vec_deque_extract_if", + description: r##"# `vec_deque_extract_if` + + + +The tracking issue for this feature is: [#147750] + +[#147750]: https://github.com/rust-lang/rust/issues/147750 + ------------------------ "##, default_severity: Severity::Allow, @@ -12303,6 +15994,8 @@ fn main() { label: "vec_deque_iter_as_slices", description: r##"# `vec_deque_iter_as_slices` + + The tracking issue for this feature is: [#123947] [#123947]: https://github.com/rust-lang/rust/issues/123947 @@ -12314,12 +16007,14 @@ fn main() { deny_since: None, }, Lint { - label: "vec_into_raw_parts", - description: r##"# `vec_into_raw_parts` + label: "vec_deque_truncate_front", + description: r##"# `vec_deque_truncate_front` -The tracking issue for this feature is: [#65816] -[#65816]: https://github.com/rust-lang/rust/issues/65816 + +The tracking issue for this feature is: [#140667] + +[#140667]: https://github.com/rust-lang/rust/issues/140667 ------------------------ "##, @@ -12328,12 +16023,62 @@ fn main() { deny_since: None, }, Lint { - label: "vec_pop_if", - description: r##"# `vec_pop_if` + label: "vec_fallible_shrink", + description: r##"# `vec_fallible_shrink` -The tracking issue for this feature is: [#122741] -[#122741]: https://github.com/rust-lang/rust/issues/122741 + +The tracking issue for this feature is: [#152350] + +[#152350]: https://github.com/rust-lang/rust/issues/152350 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "vec_from_fn", + description: r##"# `vec_from_fn` + + + +The tracking issue for this feature is: [#149698] + +[#149698]: https://github.com/rust-lang/rust/issues/149698 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "vec_into_chunks", + description: r##"# `vec_into_chunks` + + + +The tracking issue for this feature is: [#142137] + +[#142137]: https://github.com/rust-lang/rust/issues/142137 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "vec_peek_mut", + description: r##"# `vec_peek_mut` + + + +The tracking issue for this feature is: [#122742] + +[#122742]: https://github.com/rust-lang/rust/issues/122742 ------------------------ "##, @@ -12345,10 +16090,28 @@ fn main() { label: "vec_push_within_capacity", description: r##"# `vec_push_within_capacity` + + The tracking issue for this feature is: [#100486] [#100486]: https://github.com/rust-lang/rust/issues/100486 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "vec_recycle", + description: r##"# `vec_recycle` + + + +The tracking issue for this feature is: [#148227] + +[#148227]: https://github.com/rust-lang/rust/issues/148227 + ------------------------ "##, default_severity: Severity::Allow, @@ -12359,10 +16122,60 @@ fn main() { label: "vec_split_at_spare", description: r##"# `vec_split_at_spare` + + The tracking issue for this feature is: [#81944] [#81944]: https://github.com/rust-lang/rust/issues/81944 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "vec_try_remove", + description: r##"# `vec_try_remove` + + + +The tracking issue for this feature is: [#146954] + +[#146954]: https://github.com/rust-lang/rust/issues/146954 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "waker_fn", + description: r##"# `waker_fn` + + + +The tracking issue for this feature is: [#149580] + +[#149580]: https://github.com/rust-lang/rust/issues/149580 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "waker_from_fn_ptr", + description: r##"# `waker_from_fn_ptr` + + + +The tracking issue for this feature is: [#148457] + +[#148457]: https://github.com/rust-lang/rust/issues/148457 + ------------------------ "##, default_severity: Severity::Allow, @@ -12373,6 +16186,8 @@ fn main() { label: "wasi_ext", description: r##"# `wasi_ext` + + The tracking issue for this feature is: [#71213] [#71213]: https://github.com/rust-lang/rust/issues/71213 @@ -12387,9 +16202,43 @@ fn main() { label: "wasm_target_feature", description: r##"# `wasm_target_feature` -The tracking issue for this feature is: [#44839] +Target features on wasm. -[#44839]: https://github.com/rust-lang/rust/issues/44839 +The tracking issue for this feature is: [#150260] + +[#150260]: https://github.com/rust-lang/rust/issues/150260 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "where_clause_attrs", + description: r##"# `where_clause_attrs` + +Allows use of attributes in `where` clauses. + +The tracking issue for this feature is: [#115590] + +[#115590]: https://github.com/rust-lang/rust/issues/115590 + +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "widening_mul", + description: r##"# `widening_mul` + + + +The tracking issue for this feature is: [#152016] + +[#152016]: https://github.com/rust-lang/rust/issues/152016 ------------------------ "##, @@ -12401,6 +16250,8 @@ fn main() { label: "windows_by_handle", description: r##"# `windows_by_handle` + + The tracking issue for this feature is: [#63010] [#63010]: https://github.com/rust-lang/rust/issues/63010 @@ -12427,10 +16278,28 @@ fn main() { label: "windows_change_time", description: r##"# `windows_change_time` + + The tracking issue for this feature is: [#121478] [#121478]: https://github.com/rust-lang/rust/issues/121478 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "windows_freeze_file_times", + description: r##"# `windows_freeze_file_times` + + + +The tracking issue for this feature is: [#149715] + +[#149715]: https://github.com/rust-lang/rust/issues/149715 + ------------------------ "##, default_severity: Severity::Allow, @@ -12465,6 +16334,8 @@ fn main() { label: "windows_process_exit_code_from", description: r##"# `windows_process_exit_code_from` + + The tracking issue for this feature is: [#111688] [#111688]: https://github.com/rust-lang/rust/issues/111688 @@ -12479,6 +16350,8 @@ fn main() { label: "windows_process_extensions_async_pipes", description: r##"# `windows_process_extensions_async_pipes` + + The tracking issue for this feature is: [#98289] [#98289]: https://github.com/rust-lang/rust/issues/98289 @@ -12493,10 +16366,28 @@ fn main() { label: "windows_process_extensions_force_quotes", description: r##"# `windows_process_extensions_force_quotes` + + The tracking issue for this feature is: [#82227] [#82227]: https://github.com/rust-lang/rust/issues/82227 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "windows_process_extensions_inherit_handles", + description: r##"# `windows_process_extensions_inherit_handles` + + + +The tracking issue for this feature is: [#146407] + +[#146407]: https://github.com/rust-lang/rust/issues/146407 + ------------------------ "##, default_severity: Severity::Allow, @@ -12507,6 +16398,8 @@ fn main() { label: "windows_process_extensions_main_thread_handle", description: r##"# `windows_process_extensions_main_thread_handle` + + The tracking issue for this feature is: [#96723] [#96723]: https://github.com/rust-lang/rust/issues/96723 @@ -12521,6 +16414,8 @@ fn main() { label: "windows_process_extensions_raw_attribute", description: r##"# `windows_process_extensions_raw_attribute` + + The tracking issue for this feature is: [#114854] [#114854]: https://github.com/rust-lang/rust/issues/114854 @@ -12535,10 +16430,28 @@ fn main() { label: "windows_process_extensions_show_window", description: r##"# `windows_process_extensions_show_window` + + The tracking issue for this feature is: [#127544] [#127544]: https://github.com/rust-lang/rust/issues/127544 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "windows_process_extensions_startupinfo", + description: r##"# `windows_process_extensions_startupinfo` + + + +The tracking issue for this feature is: [#141010] + +[#141010]: https://github.com/rust-lang/rust/issues/141010 + ------------------------ "##, default_severity: Severity::Allow, @@ -12551,6 +16464,22 @@ fn main() { This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "windows_unix_domain_sockets", + description: r##"# `windows_unix_domain_sockets` + + + +The tracking issue for this feature is: [#150487] + +[#150487]: https://github.com/rust-lang/rust/issues/150487 + ------------------------ "##, default_severity: Severity::Allow, @@ -12561,6 +16490,8 @@ fn main() { label: "with_negative_coherence", description: r##"# `with_negative_coherence` +Use for stable + negative coherence and strict coherence depending on trait's rustc_strict_coherence value. + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -12573,6 +16504,8 @@ fn main() { label: "wrapping_int_impl", description: r##"# `wrapping_int_impl` + + The tracking issue for this feature is: [#32463] [#32463]: https://github.com/rust-lang/rust/issues/32463 @@ -12587,6 +16520,8 @@ fn main() { label: "wrapping_next_power_of_two", description: r##"# `wrapping_next_power_of_two` + + The tracking issue for this feature is: [#32463] [#32463]: https://github.com/rust-lang/rust/issues/32463 @@ -12601,10 +16536,26 @@ fn main() { label: "write_all_vectored", description: r##"# `write_all_vectored` + + The tracking issue for this feature is: [#70436] [#70436]: https://github.com/rust-lang/rust/issues/70436 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "wtf8_internals", + description: r##"# `wtf8_internals` + + + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, default_severity: Severity::Allow, @@ -12615,10 +16566,28 @@ fn main() { label: "x86_amx_intrinsics", description: r##"# `x86_amx_intrinsics` +Allows use of x86 `AMX` target-feature attributes and intrinsics + The tracking issue for this feature is: [#126622] [#126622]: https://github.com/rust-lang/rust/issues/126622 +------------------------ +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "x87_target_feature", + description: r##"# `x87_target_feature` + +The x87 target feature on x86. + +The tracking issue for this feature is: [#150261] + +[#150261]: https://github.com/rust-lang/rust/issues/150261 + ------------------------ "##, default_severity: Severity::Allow, @@ -12629,6 +16598,8 @@ fn main() { label: "xop_target_feature", description: r##"# `xop_target_feature` +Allows use of the `xop` target-feature + The tracking issue for this feature is: [#127208] [#127208]: https://github.com/rust-lang/rust/issues/127208 @@ -12643,6 +16614,8 @@ fn main() { label: "yeet_desugar_details", description: r##"# `yeet_desugar_details` + + This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ @@ -12679,6 +16652,22 @@ fn bar() -> Option { } assert_eq!(bar(), None); ``` +"##, + default_severity: Severity::Allow, + warn_since: None, + deny_since: None, + }, + Lint { + label: "yield_expr", + description: r##"# `yield_expr` + + + +The tracking issue for this feature is: [#43122] + +[#43122]: https://github.com/rust-lang/rust/issues/43122 + +------------------------ "##, default_severity: Severity::Allow, warn_since: None, @@ -14967,7 +18956,7 @@ fn bar() -> Option { }, Lint { label: "clippy::manual_bits", - description: r##"Checks for usage of `size_of::() * 8` when + description: r##"Checks for usage of `std::mem::size_of::() * 8` when `T::BITS` is available."##, default_severity: Severity::Allow, warn_since: None, @@ -17309,7 +21298,7 @@ fn bar() -> Option { }, Lint { label: "clippy::size_of_ref", - description: r##"Checks for calls to `size_of_val()` where the argument is + description: r##"Checks for calls to `std::mem::size_of_val()` where the argument is a reference to a reference."##, default_severity: Severity::Allow, warn_since: None, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs index 2f696d07e21b..9018552afb4d 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs @@ -117,7 +117,9 @@ fn deduce_from_path(path: &ast::Path, exact: bool) -> Self { // validate that the following segment resolve. SyntaxKind::PATH => Self { modules: true, type_namespace: true, ..Self::ALL_DISABLED }, SyntaxKind::MACRO_CALL => Self { bang_macros: true, ..Self::ALL_DISABLED }, - SyntaxKind::META => Self { attr_macros: true, ..Self::ALL_DISABLED }, + SyntaxKind::PATH_META | SyntaxKind::KEY_VALUE_META | SyntaxKind::TOKEN_TREE_META => { + Self { attr_macros: true, ..Self::ALL_DISABLED } + } SyntaxKind::USE_TREE => { if ast::UseTree::cast(parent).unwrap().use_tree_list().is_some() { Self { modules: true, ..Self::ALL_DISABLED } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs index 41ce1e59603d..9318c3e13272 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs @@ -101,14 +101,12 @@ pub fn find_insert_use_container( { block = b.stmt_list(); } - if has_attrs - .attrs() - .any(|attr| attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg")) + if has_attrs.attrs().any(|attr| matches!(attr.meta(), Some(ast::Meta::CfgMeta(_)))) { if let Some(b) = block.clone() { - let current_cfgs = has_attrs.attrs().filter(|attr| { - attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg") - }); + let current_cfgs = has_attrs + .attrs() + .filter(|attr| matches!(attr.meta(), Some(ast::Meta::CfgMeta(_)))); let total_cfgs: Vec<_> = required_cfgs.iter().cloned().chain(current_cfgs).collect(); @@ -118,7 +116,7 @@ pub fn find_insert_use_container( if let Some(parent) = parent { can_merge = parent.children().filter_map(ast::Use::cast).any(|u| { let u_attrs = u.attrs().filter(|attr| { - attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg") + matches!(attr.meta(), Some(ast::Meta::CfgMeta(_))) }); crate::imports::merge_imports::eq_attrs( u_attrs, @@ -134,9 +132,11 @@ pub fn find_insert_use_container( }); } } - required_cfgs.extend(has_attrs.attrs().filter(|attr| { - attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg") - })); + required_cfgs.extend( + has_attrs + .attrs() + .filter(|attr| matches!(attr.meta(), Some(ast::Meta::CfgMeta(_)))), + ); } } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs index 3301719f5ce2..76645464ddf5 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs @@ -256,16 +256,6 @@ pub fn try_normalize_import(use_item: &ast::Use, style: NormalizationStyle) -> O Some(use_item) } -/// Normalizes a use tree (see [`try_normalize_import`] doc). -pub fn try_normalize_use_tree( - use_tree: &ast::UseTree, - style: NormalizationStyle, -) -> Option { - let use_tree = use_tree.clone_subtree().clone_for_update(); - try_normalize_use_tree_mut(&use_tree, style)?; - Some(use_tree) -} - pub fn try_normalize_use_tree_mut( use_tree: &ast::UseTree, style: NormalizationStyle, diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs index 9bfbeeebf780..be4fe763a054 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs @@ -209,8 +209,8 @@ fn cfg_true_false() { #[cfg(true)] fn active() {} - #[cfg(any(not(true)), false)] fn inactive2() {} -//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: true is enabled + #[cfg(any(not(true), false))] fn inactive2() {} +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: true is enabled and false is disabled "#, ); diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs index 6f4ea70e0adc..fb885c2ad11f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs +++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs @@ -54,8 +54,9 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< let InFile { file_id, value: tokens } = hir::InMacroFile::new(macro_file, descended).upmap_once(db); let token = sema.parse_or_expand(file_id).covering_element(tokens[0]).into_token()?; - let attr = token.parent_ancestors().find_map(ast::Attr::cast)?; + let attr = token.parent_ancestors().find_map(ast::Meta::cast)?; let expansions = sema.expand_derive_macro(&attr)?; + let ast::Meta::TokenTreeMeta(attr) = attr else { return None }; let idx = attr .token_tree()? .token_trees_and_tokens() diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index ce9ec7431a97..dcfe4dd41e76 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html @@ -166,12 +166,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd /// /// ``` /// loop {} -#[cfg_attr(not(feature = "false"), doc = "loop {}")] +#[cfg_attr(not(feature = "false"), doc = "loop {}")] #[doc = "loop {}"] /// ``` /// -#[cfg_attr(feature = "alloc", doc = "```rust")] -#[cfg_attr(not(feature = "alloc"), doc = "```ignore")] +#[cfg_attr(feature = "alloc", doc = "```rust")] +#[cfg_attr(not(feature = "alloc"), doc = "```ignore")] /// let _ = example(&alloc::vec![1, 2, 3]); /// ``` pub fn mix_and_match() {} diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs index c0cf43a87bf7..2eeaa25257db 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs @@ -40,6 +40,86 @@ fn attr(p: &mut Parser<'_>, inner: bool) { // #![unsafe] // #![unsafe =] +fn cfg_attr_meta(p: &mut Parser<'_>, m: Marker) { + // test cfg_attr + // #![cfg_attr(not(foo), unsafe(bar()), cfg_attr(all(true, foo = "bar"), baz = "baz"))] + p.eat_contextual_kw(T![cfg_attr]); + p.bump(T!['(']); + cfg_predicate(p); + p.expect(T![,]); + while !p.at(T![')']) && !p.at(EOF) { + meta(p); + if !p.eat(T![,]) { + break; + } + } + p.expect(T![')']); + m.complete(p, CFG_ATTR_META); +} + +const CFG_PREDICATE_FIRST_SET: TokenSet = TokenSet::new(&[T![true], T![false], T![ident]]); + +fn cfg_predicate(p: &mut Parser<'_>) { + let m = p.start(); + if p.eat(T![true]) || p.eat(T![false]) { + // test cfg_true_false_pred + // #![cfg(true)] + // #![cfg(false)] + m.complete(p, CFG_ATOM); + return; + } + p.expect(T![ident]); + if p.eat(T![=]) { + if p.at(T![ident]) { + // This is required for completion, that inserts an identifier, to work in cases like + // `#[cfg(key = $0)]`, and also makes sense on itself. + + // test_err key_ident_cfg_predicate + // #![cfg(key = value)] + p.err_and_bump("expected a string literal"); + } else { + // test cfg_key_value_pred + // #![cfg(key = "value")] + p.expect(T![string]); + } + m.complete(p, CFG_ATOM); + } else if p.at(T!['(']) { + // test cfg_composite_pred + // #![cfg(any(a, all(b = "c", d)))] + delimited( + p, + T!['('], + T![')'], + T![,], + || "expected a cfg predicate".to_owned(), + CFG_PREDICATE_FIRST_SET, + |p| { + if p.at_ts(CFG_PREDICATE_FIRST_SET) { + cfg_predicate(p); + true + } else { + false + } + }, + ); + m.complete(p, CFG_COMPOSITE); + } else { + m.complete(p, CFG_ATOM); + } +} + +fn cfg_meta(p: &mut Parser<'_>, m: Marker) { + // test cfg_meta + // #![cfg(foo)] + // #![cfg(foo = "bar",)] + p.eat_contextual_kw(T![cfg]); + p.bump(T!['(']); + cfg_predicate(p); + p.eat(T![,]); + p.expect(T![')']); + m.complete(p, CFG_META); +} + // test metas // #![simple_ident] // #![simple::path] @@ -62,11 +142,23 @@ fn attr(p: &mut Parser<'_>, inner: bool) { // #![unsafe(simple::path::tt[a b c])] // #![unsafe(simple::path::tt{a b c})] pub(super) fn meta(p: &mut Parser<'_>) { - let meta = p.start(); - let is_unsafe = p.eat(T![unsafe]); - if is_unsafe { + let m = p.start(); + if p.eat(T![unsafe]) { p.expect(T!['(']); + meta(p); + p.expect(T![')']); + m.complete(p, UNSAFE_META); + return; } + + if p.nth_at(1, T!['(']) { + if p.at_contextual_kw(T![cfg_attr]) { + return cfg_attr_meta(p, m); + } else if p.at_contextual_kw(T![cfg]) { + return cfg_meta(p, m); + } + } + paths::attr_path(p); match p.current() { @@ -75,13 +167,14 @@ pub(super) fn meta(p: &mut Parser<'_>) { if expressions::expr(p).is_none() { p.error("expected expression"); } + m.complete(p, KEY_VALUE_META); + } + T!['('] | T!['['] | T!['{'] => { + items::token_tree(p); + m.complete(p, TOKEN_TREE_META); + } + _ => { + m.complete(p, PATH_META); } - T!['('] | T!['['] | T!['{'] => items::token_tree(p), - _ => {} } - if is_unsafe { - p.expect(T![')']); - } - - meta.complete(p, META); } diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs index a2295e449550..9cd48f2aa4f3 100644 --- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs +++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs @@ -116,6 +116,8 @@ pub enum SyntaxKind { AWAIT_KW, BIKESHED_KW, BUILTIN_KW, + CFG_ATTR_KW, + CFG_KW, CLOBBER_ABI_KW, DEFAULT_KW, DYN_KW, @@ -186,6 +188,10 @@ pub enum SyntaxKind { BREAK_EXPR, CALL_EXPR, CAST_EXPR, + CFG_ATOM, + CFG_ATTR_META, + CFG_COMPOSITE, + CFG_META, CLOSURE_EXPR, CONST, CONST_ARG, @@ -216,6 +222,7 @@ pub enum SyntaxKind { INDEX_EXPR, INFER_TYPE, ITEM_LIST, + KEY_VALUE_META, LABEL, LET_ELSE, LET_EXPR, @@ -238,7 +245,6 @@ pub enum SyntaxKind { MATCH_ARM_LIST, MATCH_EXPR, MATCH_GUARD, - META, METHOD_CALL_EXPR, MODULE, NAME, @@ -254,6 +260,7 @@ pub enum SyntaxKind { PAREN_TYPE, PATH, PATH_EXPR, + PATH_META, PATH_PAT, PATH_SEGMENT, PATH_TYPE, @@ -285,6 +292,7 @@ pub enum SyntaxKind { STMT_LIST, STRUCT, TOKEN_TREE, + TOKEN_TREE_META, TRAIT, TRY_BLOCK_MODIFIER, TRY_EXPR, @@ -302,6 +310,7 @@ pub enum SyntaxKind { TYPE_PARAM, UNDERSCORE_EXPR, UNION, + UNSAFE_META, USE, USE_BOUND_GENERIC_ARGS, USE_TREE, @@ -360,6 +369,10 @@ pub const fn text(self) -> &'static str { | BREAK_EXPR | CALL_EXPR | CAST_EXPR + | CFG_ATOM + | CFG_ATTR_META + | CFG_COMPOSITE + | CFG_META | CLOSURE_EXPR | CONST | CONST_ARG @@ -390,6 +403,7 @@ pub const fn text(self) -> &'static str { | INDEX_EXPR | INFER_TYPE | ITEM_LIST + | KEY_VALUE_META | LABEL | LET_ELSE | LET_EXPR @@ -412,7 +426,6 @@ pub const fn text(self) -> &'static str { | MATCH_ARM_LIST | MATCH_EXPR | MATCH_GUARD - | META | METHOD_CALL_EXPR | MODULE | NAME @@ -428,6 +441,7 @@ pub const fn text(self) -> &'static str { | PAREN_TYPE | PATH | PATH_EXPR + | PATH_META | PATH_PAT | PATH_SEGMENT | PATH_TYPE @@ -459,6 +473,7 @@ pub const fn text(self) -> &'static str { | STMT_LIST | STRUCT | TOKEN_TREE + | TOKEN_TREE_META | TRAIT | TRY_BLOCK_MODIFIER | TRY_EXPR @@ -476,6 +491,7 @@ pub const fn text(self) -> &'static str { | TYPE_PARAM | UNDERSCORE_EXPR | UNION + | UNSAFE_META | USE | USE_BOUND_GENERIC_ARGS | USE_TREE @@ -601,6 +617,8 @@ pub const fn text(self) -> &'static str { AUTO_KW => "auto", BIKESHED_KW => "bikeshed", BUILTIN_KW => "builtin", + CFG_KW => "cfg", + CFG_ATTR_KW => "cfg_attr", CLOBBER_ABI_KW => "clobber_abi", DEFAULT_KW => "default", DYN_KW => "dyn", @@ -704,6 +722,8 @@ pub fn is_contextual_keyword(self, edition: Edition) -> bool { AUTO_KW => true, BIKESHED_KW => true, BUILTIN_KW => true, + CFG_KW => true, + CFG_ATTR_KW => true, CLOBBER_ABI_KW => true, DEFAULT_KW => true, DYN_KW if edition < Edition::Edition2018 => true, @@ -795,6 +815,8 @@ pub fn is_keyword(self, edition: Edition) -> bool { AUTO_KW => true, BIKESHED_KW => true, BUILTIN_KW => true, + CFG_KW => true, + CFG_ATTR_KW => true, CLOBBER_ABI_KW => true, DEFAULT_KW => true, DYN_KW if edition < Edition::Edition2018 => true, @@ -949,6 +971,8 @@ pub fn from_contextual_keyword(ident: &str, edition: Edition) -> Option AUTO_KW, "bikeshed" => BIKESHED_KW, "builtin" => BUILTIN_KW, + "cfg" => CFG_KW, + "cfg_attr" => CFG_ATTR_KW, "clobber_abi" => CLOBBER_ABI_KW, "default" => DEFAULT_KW, "dyn" if edition < Edition::Edition2018 => DYN_KW, @@ -1121,6 +1145,8 @@ pub fn from_char(c: char) -> Option { [auto] => { $ crate :: SyntaxKind :: AUTO_KW }; [bikeshed] => { $ crate :: SyntaxKind :: BIKESHED_KW }; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW }; + [cfg] => { $ crate :: SyntaxKind :: CFG_KW }; + [cfg_attr] => { $ crate :: SyntaxKind :: CFG_ATTR_KW }; [clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW }; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW }; [dyn] => { $ crate :: SyntaxKind :: DYN_KW }; diff --git a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs index 01fc172ed953..71978390df6a 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs +++ b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs @@ -87,6 +87,22 @@ fn break_ambiguity() { #[test] fn cast_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/cast_expr.rs"); } #[test] + fn cfg_attr() { run_and_expect_no_errors("test_data/parser/inline/ok/cfg_attr.rs"); } + #[test] + fn cfg_composite_pred() { + run_and_expect_no_errors("test_data/parser/inline/ok/cfg_composite_pred.rs"); + } + #[test] + fn cfg_key_value_pred() { + run_and_expect_no_errors("test_data/parser/inline/ok/cfg_key_value_pred.rs"); + } + #[test] + fn cfg_meta() { run_and_expect_no_errors("test_data/parser/inline/ok/cfg_meta.rs"); } + #[test] + fn cfg_true_false_pred() { + run_and_expect_no_errors("test_data/parser/inline/ok/cfg_true_false_pred.rs"); + } + #[test] fn closure_binder() { run_and_expect_no_errors("test_data/parser/inline/ok/closure_binder.rs"); } @@ -826,6 +842,10 @@ fn invalid_question_for_type_trait_bound() { ); } #[test] + fn key_ident_cfg_predicate() { + run_and_expect_errors("test_data/parser/inline/err/key_ident_cfg_predicate.rs"); + } + #[test] fn let_else_right_curly_brace() { run_and_expect_errors("test_data/parser/inline/err/let_else_right_curly_brace.rs"); } diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0005_attribute_recover.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0005_attribute_recover.rast index 77b4d06321d5..cf45dcf522ad 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0005_attribute_recover.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0005_attribute_recover.rast @@ -3,7 +3,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -37,7 +37,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0032_match_arms_inner_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0032_match_arms_inner_attrs.rast index b657e9834156..2334b730e4cc 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0032_match_arms_inner_attrs.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0032_match_arms_inner_attrs.rast @@ -136,15 +136,12 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM IDENT "test" - R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE "\n " ATTR diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0033_match_arms_outer_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0033_match_arms_outer_attrs.rast index b5bc3d84df09..acacee234826 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0033_match_arms_outer_attrs.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0033_match_arms_outer_attrs.rast @@ -48,15 +48,12 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM IDENT "test" - R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE "\n " R_CURLY "}" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/key_ident_cfg_predicate.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/key_ident_cfg_predicate.rast new file mode 100644 index 000000000000..de5fc7d5bdc0 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/key_ident_cfg_predicate.rast @@ -0,0 +1,19 @@ +SOURCE_FILE + ATTR + POUND "#" + BANG "!" + L_BRACK "[" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM + IDENT "key" + WHITESPACE " " + EQ "=" + WHITESPACE " " + ERROR + IDENT "value" + R_PAREN ")" + R_BRACK "]" + WHITESPACE "\n" +error 13: expected a string literal diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/key_ident_cfg_predicate.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/key_ident_cfg_predicate.rs new file mode 100644 index 000000000000..9a981bf939cc --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/key_ident_cfg_predicate.rs @@ -0,0 +1 @@ +#![cfg(key = value)] diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/meta_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/meta_recovery.rast index b5c16e0798cc..9e456c98554d 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/meta_recovery.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/meta_recovery.rast @@ -3,14 +3,14 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + PATH_META R_BRACK "]" WHITESPACE "\n" ATTR POUND "#" BANG "!" L_BRACK "[" - META + KEY_VALUE_META PATH PATH_SEGMENT NAME_REF @@ -24,7 +24,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + PATH_META PATH PATH PATH_SEGMENT @@ -37,7 +37,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + KEY_VALUE_META PATH PATH PATH_SEGMENT @@ -52,18 +52,20 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + UNSAFE_META UNSAFE_KW "unsafe" + PATH_META R_BRACK "]" WHITESPACE "\n" ATTR POUND "#" BANG "!" L_BRACK "[" - META + UNSAFE_META UNSAFE_KW "unsafe" WHITESPACE " " - EQ "=" + KEY_VALUE_META + EQ "=" R_BRACK "]" WHITESPACE "\n" error 3: expected identifier, `self`, `super`, `crate`, or `Self` @@ -77,7 +79,7 @@ error 41: expected L_PAREN error 41: expected identifier, `self`, `super`, `crate`, or `Self` error 41: expected R_PAREN error 52: expected L_PAREN -error 52: expected identifier, `self`, `super`, `crate`, or `Self` +error 53: expected identifier, `self`, `super`, `crate`, or `Self` error 54: expected expression error 54: expected expression error 54: expected R_PAREN diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/arg_with_attr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/arg_with_attr.rast index ae1074c3680c..672f2c2f7f99 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/arg_with_attr.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/arg_with_attr.rast @@ -24,7 +24,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_attrs.rast index 6eb8af331195..2812bbf71bcc 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_attrs.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_attrs.rast @@ -31,15 +31,12 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM IDENT "test" - R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE " " INT_NUMBER "2" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_item_list_inner_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_item_list_inner_attrs.rast index 9cb3c8a5c3b4..7c6dbf65cfdc 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_item_list_inner_attrs.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_item_list_inner_attrs.rast @@ -15,7 +15,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/attr_on_expr_stmt.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/attr_on_expr_stmt.rast index 81b7f2b3cbbe..248e6d1360db 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/attr_on_expr_stmt.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/attr_on_expr_stmt.rast @@ -17,7 +17,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -39,7 +39,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -61,7 +61,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -71,7 +71,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -87,7 +87,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_attr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_attr.rast new file mode 100644 index 000000000000..9af94f447db8 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_attr.rast @@ -0,0 +1,63 @@ +SOURCE_FILE + ATTR + POUND "#" + BANG "!" + L_BRACK "[" + CFG_ATTR_META + CFG_ATTR_KW "cfg_attr" + L_PAREN "(" + CFG_COMPOSITE + IDENT "not" + L_PAREN "(" + CFG_ATOM + IDENT "foo" + R_PAREN ")" + COMMA "," + WHITESPACE " " + UNSAFE_META + UNSAFE_KW "unsafe" + L_PAREN "(" + TOKEN_TREE_META + PATH + PATH_SEGMENT + NAME_REF + IDENT "bar" + TOKEN_TREE + L_PAREN "(" + R_PAREN ")" + R_PAREN ")" + COMMA "," + WHITESPACE " " + CFG_ATTR_META + CFG_ATTR_KW "cfg_attr" + L_PAREN "(" + CFG_COMPOSITE + IDENT "all" + L_PAREN "(" + CFG_ATOM + TRUE_KW "true" + COMMA "," + WHITESPACE " " + CFG_ATOM + IDENT "foo" + WHITESPACE " " + EQ "=" + WHITESPACE " " + STRING "\"bar\"" + R_PAREN ")" + COMMA "," + WHITESPACE " " + KEY_VALUE_META + PATH + PATH_SEGMENT + NAME_REF + IDENT "baz" + WHITESPACE " " + EQ "=" + WHITESPACE " " + LITERAL + STRING "\"baz\"" + R_PAREN ")" + R_PAREN ")" + R_BRACK "]" + WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_attr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_attr.rs new file mode 100644 index 000000000000..5fe2776144e3 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_attr.rs @@ -0,0 +1 @@ +#![cfg_attr(not(foo), unsafe(bar()), cfg_attr(all(true, foo = "bar"), baz = "baz"))] diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_composite_pred.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_composite_pred.rast new file mode 100644 index 000000000000..89d06d134fe2 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_composite_pred.rast @@ -0,0 +1,33 @@ +SOURCE_FILE + ATTR + POUND "#" + BANG "!" + L_BRACK "[" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_COMPOSITE + IDENT "any" + L_PAREN "(" + CFG_ATOM + IDENT "a" + COMMA "," + WHITESPACE " " + CFG_COMPOSITE + IDENT "all" + L_PAREN "(" + CFG_ATOM + IDENT "b" + WHITESPACE " " + EQ "=" + WHITESPACE " " + STRING "\"c\"" + COMMA "," + WHITESPACE " " + CFG_ATOM + IDENT "d" + R_PAREN ")" + R_PAREN ")" + R_PAREN ")" + R_BRACK "]" + WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_composite_pred.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_composite_pred.rs new file mode 100644 index 000000000000..7d830c128815 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_composite_pred.rs @@ -0,0 +1 @@ +#![cfg(any(a, all(b = "c", d)))] diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_key_value_pred.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_key_value_pred.rast new file mode 100644 index 000000000000..e48d39bf55db --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_key_value_pred.rast @@ -0,0 +1,17 @@ +SOURCE_FILE + ATTR + POUND "#" + BANG "!" + L_BRACK "[" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM + IDENT "key" + WHITESPACE " " + EQ "=" + WHITESPACE " " + STRING "\"value\"" + R_PAREN ")" + R_BRACK "]" + WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_key_value_pred.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_key_value_pred.rs new file mode 100644 index 000000000000..dc194ed86be2 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_key_value_pred.rs @@ -0,0 +1 @@ +#![cfg(key = "value")] diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_meta.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_meta.rast new file mode 100644 index 000000000000..f024cfd1aae4 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_meta.rast @@ -0,0 +1,30 @@ +SOURCE_FILE + ATTR + POUND "#" + BANG "!" + L_BRACK "[" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM + IDENT "foo" + R_PAREN ")" + R_BRACK "]" + WHITESPACE "\n" + ATTR + POUND "#" + BANG "!" + L_BRACK "[" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM + IDENT "foo" + WHITESPACE " " + EQ "=" + WHITESPACE " " + STRING "\"bar\"" + COMMA "," + R_PAREN ")" + R_BRACK "]" + WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_meta.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_meta.rs new file mode 100644 index 000000000000..ef0030e75fde --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_meta.rs @@ -0,0 +1,2 @@ +#![cfg(foo)] +#![cfg(foo = "bar",)] diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_true_false_pred.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_true_false_pred.rast new file mode 100644 index 000000000000..e33595a93dcd --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_true_false_pred.rast @@ -0,0 +1,25 @@ +SOURCE_FILE + ATTR + POUND "#" + BANG "!" + L_BRACK "[" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM + TRUE_KW "true" + R_PAREN ")" + R_BRACK "]" + WHITESPACE "\n" + ATTR + POUND "#" + BANG "!" + L_BRACK "[" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM + FALSE_KW "false" + R_PAREN ")" + R_BRACK "]" + WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_true_false_pred.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_true_false_pred.rs new file mode 100644 index 000000000000..473582164a22 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cfg_true_false_pred.rs @@ -0,0 +1,2 @@ +#![cfg(true)] +#![cfg(false)] diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_param_attribute.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_param_attribute.rast index 28a216e87309..5567a53c56a2 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_param_attribute.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_param_attribute.rast @@ -10,7 +10,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -25,7 +25,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_inner_attribute.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_inner_attribute.rast index 6fd9f424676b..edb04387336a 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_inner_attribute.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_inner_attribute.rast @@ -26,7 +26,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -41,7 +41,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -56,7 +56,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_outer_attributes.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_outer_attributes.rast index 0f7580c1a339..321db782d133 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_outer_attributes.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_outer_attributes.rast @@ -26,19 +26,16 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM IDENT "feature" WHITESPACE " " EQ "=" WHITESPACE " " STRING "\"some\"" - R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE "\n " WILDCARD_PAT @@ -55,19 +52,16 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM IDENT "feature" WHITESPACE " " EQ "=" WHITESPACE " " STRING "\"other\"" - R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE "\n " WILDCARD_PAT @@ -84,55 +78,46 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM IDENT "feature" WHITESPACE " " EQ "=" WHITESPACE " " STRING "\"many\"" - R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE "\n " ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM IDENT "feature" WHITESPACE " " EQ "=" WHITESPACE " " STRING "\"attributes\"" - R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE "\n " ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM IDENT "feature" WHITESPACE " " EQ "=" WHITESPACE " " STRING "\"before\"" - R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE "\n " WILDCARD_PAT diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/metas.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/metas.rast index b1ac60b530ef..6360552a6f06 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/metas.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/metas.rast @@ -3,7 +3,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -14,7 +14,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + PATH_META PATH PATH PATH_SEGMENT @@ -30,7 +30,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + KEY_VALUE_META PATH PATH_SEGMENT NAME_REF @@ -46,7 +46,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + KEY_VALUE_META PATH PATH PATH @@ -72,7 +72,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -91,7 +91,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -110,7 +110,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -129,7 +129,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH PATH @@ -158,7 +158,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH PATH @@ -187,7 +187,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH PATH @@ -216,32 +216,14 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + UNSAFE_META UNSAFE_KW "unsafe" L_PAREN "(" - PATH - PATH_SEGMENT - NAME_REF - IDENT "simple_ident" - R_PAREN ")" - R_BRACK "]" - WHITESPACE "\n" - ATTR - POUND "#" - BANG "!" - L_BRACK "[" - META - UNSAFE_KW "unsafe" - L_PAREN "(" - PATH + PATH_META PATH PATH_SEGMENT NAME_REF - IDENT "simple" - COLON2 "::" - PATH_SEGMENT - NAME_REF - IDENT "path" + IDENT "simple_ident" R_PAREN ")" R_BRACK "]" WHITESPACE "\n" @@ -249,29 +231,10 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + UNSAFE_META UNSAFE_KW "unsafe" L_PAREN "(" - PATH - PATH_SEGMENT - NAME_REF - IDENT "simple_ident_expr" - WHITESPACE " " - EQ "=" - WHITESPACE " " - LITERAL - STRING "\"\"" - R_PAREN ")" - R_BRACK "]" - WHITESPACE "\n" - ATTR - POUND "#" - BANG "!" - L_BRACK "[" - META - UNSAFE_KW "unsafe" - L_PAREN "(" - PATH + PATH_META PATH PATH PATH_SEGMENT @@ -281,15 +244,6 @@ SOURCE_FILE PATH_SEGMENT NAME_REF IDENT "path" - COLON2 "::" - PATH_SEGMENT - NAME_REF - IDENT "Expr" - WHITESPACE " " - EQ "=" - WHITESPACE " " - LITERAL - STRING "\"\"" R_PAREN ")" R_BRACK "]" WHITESPACE "\n" @@ -297,21 +251,19 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + UNSAFE_META UNSAFE_KW "unsafe" L_PAREN "(" - PATH - PATH_SEGMENT - NAME_REF - IDENT "simple_ident_tt" - TOKEN_TREE - L_PAREN "(" - IDENT "a" + KEY_VALUE_META + PATH + PATH_SEGMENT + NAME_REF + IDENT "simple_ident_expr" WHITESPACE " " - IDENT "b" + EQ "=" WHITESPACE " " - IDENT "c" - R_PAREN ")" + LITERAL + STRING "\"\"" R_PAREN ")" R_BRACK "]" WHITESPACE "\n" @@ -319,75 +271,29 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + UNSAFE_META UNSAFE_KW "unsafe" L_PAREN "(" - PATH - PATH_SEGMENT - NAME_REF - IDENT "simple_ident_tt" - TOKEN_TREE - L_BRACK "[" - IDENT "a" - WHITESPACE " " - IDENT "b" - WHITESPACE " " - IDENT "c" - R_BRACK "]" - R_PAREN ")" - R_BRACK "]" - WHITESPACE "\n" - ATTR - POUND "#" - BANG "!" - L_BRACK "[" - META - UNSAFE_KW "unsafe" - L_PAREN "(" - PATH - PATH_SEGMENT - NAME_REF - IDENT "simple_ident_tt" - TOKEN_TREE - L_CURLY "{" - IDENT "a" - WHITESPACE " " - IDENT "b" - WHITESPACE " " - IDENT "c" - R_CURLY "}" - R_PAREN ")" - R_BRACK "]" - WHITESPACE "\n" - ATTR - POUND "#" - BANG "!" - L_BRACK "[" - META - UNSAFE_KW "unsafe" - L_PAREN "(" - PATH + KEY_VALUE_META PATH PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "simple" + COLON2 "::" PATH_SEGMENT NAME_REF - IDENT "simple" + IDENT "path" COLON2 "::" PATH_SEGMENT NAME_REF - IDENT "path" - COLON2 "::" - PATH_SEGMENT - NAME_REF - IDENT "tt" - TOKEN_TREE - L_PAREN "(" - IDENT "a" + IDENT "Expr" WHITESPACE " " - IDENT "b" + EQ "=" WHITESPACE " " - IDENT "c" - R_PAREN ")" + LITERAL + STRING "\"\"" R_PAREN ")" R_BRACK "]" WHITESPACE "\n" @@ -395,31 +301,22 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + UNSAFE_META UNSAFE_KW "unsafe" L_PAREN "(" - PATH + TOKEN_TREE_META PATH - PATH - PATH_SEGMENT - NAME_REF - IDENT "simple" - COLON2 "::" PATH_SEGMENT NAME_REF - IDENT "path" - COLON2 "::" - PATH_SEGMENT - NAME_REF - IDENT "tt" - TOKEN_TREE - L_BRACK "[" - IDENT "a" - WHITESPACE " " - IDENT "b" - WHITESPACE " " - IDENT "c" - R_BRACK "]" + IDENT "simple_ident_tt" + TOKEN_TREE + L_PAREN "(" + IDENT "a" + WHITESPACE " " + IDENT "b" + WHITESPACE " " + IDENT "c" + R_PAREN ")" R_PAREN ")" R_BRACK "]" WHITESPACE "\n" @@ -427,31 +324,144 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + UNSAFE_META UNSAFE_KW "unsafe" L_PAREN "(" - PATH + TOKEN_TREE_META PATH - PATH - PATH_SEGMENT - NAME_REF - IDENT "simple" - COLON2 "::" PATH_SEGMENT NAME_REF - IDENT "path" - COLON2 "::" - PATH_SEGMENT - NAME_REF - IDENT "tt" - TOKEN_TREE - L_CURLY "{" - IDENT "a" - WHITESPACE " " - IDENT "b" - WHITESPACE " " - IDENT "c" - R_CURLY "}" + IDENT "simple_ident_tt" + TOKEN_TREE + L_BRACK "[" + IDENT "a" + WHITESPACE " " + IDENT "b" + WHITESPACE " " + IDENT "c" + R_BRACK "]" + R_PAREN ")" + R_BRACK "]" + WHITESPACE "\n" + ATTR + POUND "#" + BANG "!" + L_BRACK "[" + UNSAFE_META + UNSAFE_KW "unsafe" + L_PAREN "(" + TOKEN_TREE_META + PATH + PATH_SEGMENT + NAME_REF + IDENT "simple_ident_tt" + TOKEN_TREE + L_CURLY "{" + IDENT "a" + WHITESPACE " " + IDENT "b" + WHITESPACE " " + IDENT "c" + R_CURLY "}" + R_PAREN ")" + R_BRACK "]" + WHITESPACE "\n" + ATTR + POUND "#" + BANG "!" + L_BRACK "[" + UNSAFE_META + UNSAFE_KW "unsafe" + L_PAREN "(" + TOKEN_TREE_META + PATH + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "simple" + COLON2 "::" + PATH_SEGMENT + NAME_REF + IDENT "path" + COLON2 "::" + PATH_SEGMENT + NAME_REF + IDENT "tt" + TOKEN_TREE + L_PAREN "(" + IDENT "a" + WHITESPACE " " + IDENT "b" + WHITESPACE " " + IDENT "c" + R_PAREN ")" + R_PAREN ")" + R_BRACK "]" + WHITESPACE "\n" + ATTR + POUND "#" + BANG "!" + L_BRACK "[" + UNSAFE_META + UNSAFE_KW "unsafe" + L_PAREN "(" + TOKEN_TREE_META + PATH + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "simple" + COLON2 "::" + PATH_SEGMENT + NAME_REF + IDENT "path" + COLON2 "::" + PATH_SEGMENT + NAME_REF + IDENT "tt" + TOKEN_TREE + L_BRACK "[" + IDENT "a" + WHITESPACE " " + IDENT "b" + WHITESPACE " " + IDENT "c" + R_BRACK "]" + R_PAREN ")" + R_BRACK "]" + WHITESPACE "\n" + ATTR + POUND "#" + BANG "!" + L_BRACK "[" + UNSAFE_META + UNSAFE_KW "unsafe" + L_PAREN "(" + TOKEN_TREE_META + PATH + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "simple" + COLON2 "::" + PATH_SEGMENT + NAME_REF + IDENT "path" + COLON2 "::" + PATH_SEGMENT + NAME_REF + IDENT "tt" + TOKEN_TREE + L_CURLY "{" + IDENT "a" + WHITESPACE " " + IDENT "b" + WHITESPACE " " + IDENT "c" + R_CURLY "}" R_PAREN ")" R_BRACK "]" WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_outer_arg.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_outer_arg.rast index c63ea020a3f7..7495ba7b31a2 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_outer_arg.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_outer_arg.rast @@ -10,7 +10,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_attrs.rast index 639ee0eb7770..cfa2694fd1de 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_attrs.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_attrs.rast @@ -12,7 +12,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_literal_field_with_attr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_literal_field_with_attr.rast index a1df70841e85..717dee8c9f39 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_literal_field_with_attr.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_literal_field_with_attr.rast @@ -25,15 +25,12 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM IDENT "test" - R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE " " NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field.rast index f3d2fde46698..7fba529be9e9 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field.rast @@ -88,18 +88,14 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_COMPOSITE IDENT "any" - TOKEN_TREE - L_PAREN "(" - R_PAREN ")" + L_PAREN "(" R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE " " NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field_list.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field_list.rast index f69ae1d6445f..af5b82b889d3 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field_list.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field_list.rast @@ -146,18 +146,14 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_COMPOSITE IDENT "any" - TOKEN_TREE - L_PAREN "(" - R_PAREN ")" + L_PAREN "(" R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE " " DOT2 ".." diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/self_param_outer_attr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/self_param_outer_attr.rast index db583f7d5266..3a163e5b8ee7 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/self_param_outer_attr.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/self_param_outer_attr.rast @@ -10,7 +10,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_attrs.rast index 39857b23c6e3..76954927d566 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_attrs.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_attrs.rast @@ -34,15 +34,12 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM IDENT "test" - R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE " " INT_NUMBER "2" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_field_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_field_attrs.rast index 1699602f4fba..1f7100c46d4e 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_field_attrs.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_field_attrs.rast @@ -11,7 +11,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0006_inner_attributes.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0006_inner_attributes.rast index cb63ba80e77d..ddab028c0686 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0006_inner_attributes.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0006_inner_attributes.rast @@ -3,7 +3,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -14,7 +14,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -29,7 +29,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -44,7 +44,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -89,7 +89,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -104,7 +104,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -123,7 +123,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -138,7 +138,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -153,7 +153,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -175,7 +175,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0008_mod_item.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0008_mod_item.rast index adee67181b1a..cb6da8717ddd 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0008_mod_item.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0008_mod_item.rast @@ -48,7 +48,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0011_outer_attribute.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0011_outer_attribute.rast index dbb9bc54da8d..47a5cfce081a 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0011_outer_attribute.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0011_outer_attribute.rast @@ -3,21 +3,18 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM IDENT "test" - R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE "\n" ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -41,7 +38,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + KEY_VALUE_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0017_attr_trailing_comma.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0017_attr_trailing_comma.rast index 7c914e2542eb..c5d054702fa4 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0017_attr_trailing_comma.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0017_attr_trailing_comma.rast @@ -3,7 +3,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0035_weird_exprs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0035_weird_exprs.rast index 318d492ab4a5..15ce6c70bea7 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0035_weird_exprs.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0035_weird_exprs.rast @@ -11,7 +11,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -26,7 +26,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -41,7 +41,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -56,7 +56,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -71,7 +71,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + KEY_VALUE_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0044_let_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0044_let_attrs.rast index f3c20337e43f..fcdc1a9895d8 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0044_let_attrs.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0044_let_attrs.rast @@ -18,19 +18,16 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM IDENT "feature" WHITESPACE " " EQ "=" WHITESPACE " " STRING "\"backtrace\"" - R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE "\n " LET_KW "let" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast index c22d99f1ae10..f26bb85df292 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast @@ -16,7 +16,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -38,7 +38,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -53,7 +53,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -77,7 +77,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -119,7 +119,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF @@ -211,7 +211,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0046_extern_inner_attributes.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0046_extern_inner_attributes.rast index 4eb51cfdf09e..3d33eb4ff73c 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0046_extern_inner_attributes.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0046_extern_inner_attributes.rast @@ -14,7 +14,7 @@ SOURCE_FILE POUND "#" BANG "!" L_BRACK "[" - META + TOKEN_TREE_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast index eafee90db427..24d4392282a0 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast @@ -10,7 +10,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -20,7 +20,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -55,7 +55,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -116,7 +116,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -158,7 +158,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -181,7 +181,7 @@ SOURCE_FILE POUND "#" WHITESPACE " " L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -228,7 +228,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -255,7 +255,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -282,7 +282,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -316,7 +316,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -352,7 +352,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -389,7 +389,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -422,7 +422,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -456,7 +456,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast index b94d43beb3c2..c300b7af5058 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast @@ -5,7 +5,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0062_macro_2.0.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0062_macro_2.0.rast index 1415a866b695..b92d78e5bd60 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0062_macro_2.0.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0062_macro_2.0.rast @@ -54,7 +54,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0063_variadic_fun.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0063_variadic_fun.rast index e36399123bcc..f1c6d2efeb9c 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0063_variadic_fun.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0063_variadic_fun.rast @@ -96,15 +96,12 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META - PATH - PATH_SEGMENT - NAME_REF - IDENT "cfg" - TOKEN_TREE - L_PAREN "(" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM IDENT "never" - R_PAREN ")" + R_PAREN ")" R_BRACK "]" WHITESPACE " " SLICE_PAT diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0070_expr_attr_placement.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0070_expr_attr_placement.rast index 3d00b27ab8d3..5229b97eb2af 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0070_expr_attr_placement.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0070_expr_attr_placement.rast @@ -19,7 +19,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -39,7 +39,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0071_stmt_attr_placement.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0071_stmt_attr_placement.rast index 1cafc775cdf7..c0685448f256 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0071_stmt_attr_placement.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0071_stmt_attr_placement.rast @@ -17,7 +17,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -31,7 +31,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF @@ -56,7 +56,7 @@ SOURCE_FILE ATTR POUND "#" L_BRACK "[" - META + PATH_META PATH PATH_SEGMENT NAME_REF diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 86516b6079c7..c1806c82c724 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -2442,8 +2442,7 @@ fn run_rustfmt( } RustfmtConfig::CustomCommand { command, args } => { let cmd = Utf8PathBuf::from(&command); - let target_spec = - crates.first().and_then(|&crate_id| snap.target_spec_for_file(file_id, crate_id)); + let target_spec = TargetSpec::for_file(snap, file_id).ok().flatten(); let extra_env = snap.config.extra_env(source_root_id); let mut cmd = match target_spec { Some(TargetSpec::Cargo(_)) => { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs index 01196b80cdb2..5bdc9d8ca315 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs @@ -381,23 +381,13 @@ mod tests { SmolStr, ast::{self, AstNode}, }; - use syntax_bridge::{ - DocCommentDesugarMode, - dummy_test_span_utils::{DUMMY, DummyTestSpanMap}, - syntax_node_to_token_tree, - }; fn check(cfg: &str, expected_features: &[&str]) { let cfg_expr = { let source_file = ast::SourceFile::parse(cfg, Edition::CURRENT).ok().unwrap(); - let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); - let tt = syntax_node_to_token_tree( - tt.syntax(), - &DummyTestSpanMap, - DUMMY, - DocCommentDesugarMode::Mbe, - ); - CfgExpr::parse(&tt) + let cfg_predicate = + source_file.syntax().descendants().find_map(ast::CfgPredicate::cast).unwrap(); + CfgExpr::parse_from_ast(cfg_predicate) }; let mut features = vec![]; diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml index 8909fb423c4d..e65836ed8dcb 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -21,6 +21,7 @@ rustc-literal-escaper.workspace = true smol_str.workspace = true triomphe.workspace = true tracing.workspace = true +smallvec.workspace = true parser.workspace = true stdx.workspace = true diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram index 3113fc74308b..324b2bbd58e1 100644 --- a/src/tools/rust-analyzer/crates/syntax/rust.ungram +++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram @@ -126,9 +126,41 @@ MacroStmts = Attr = '#' '!'? '[' Meta ']' +CfgAttrMeta = + 'cfg_attr' '(' CfgPredicate ',' (Meta (',' Meta)* ','?) ')' + +CfgMeta = + 'cfg' '(' CfgPredicate ','? ')' + +CfgPredicate = + CfgAtom +| CfgComposite + +CfgAtom = + ('#ident' | 'true' | 'false') ('=' '@string')? + +CfgComposite = + keyword:'#ident' '(' (CfgPredicate (',' CfgPredicate)* ','?) ')' + Meta = - 'unsafe' '(' Path ('=' Expr | TokenTree)? ')' -| Path ('=' Expr | TokenTree)? + CfgAttrMeta +| CfgMeta +| UnsafeMeta +| PathMeta +| KeyValueMeta +| TokenTreeMeta + +UnsafeMeta = + 'unsafe' '(' Meta ')' + +PathMeta = + Path + +KeyValueMeta = + Path '=' Expr + +TokenTreeMeta = + Path TokenTree //*************************// // Items // diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast.rs b/src/tools/rust-analyzer/crates/syntax/src/ast.rs index 5d67fd449175..dc592a43727b 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast.rs @@ -25,9 +25,9 @@ expr_ext::{ArrayExprKind, BlockModifier, CallableExpr, ElseBranch, LiteralKind}, generated::{nodes::*, tokens::*}, node_ext::{ - AttrKind, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, SelfParamKind, - SlicePatComponents, StructKind, TokenTreeChildren, TypeBoundKind, TypeOrConstParam, - VisibilityKind, + AttrKind, CfgAtomKey, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, + SelfParamKind, SlicePatComponents, StructKind, TokenTreeChildren, TypeBoundKind, + TypeOrConstParam, VisibilityKind, }, operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp}, token_ext::{ diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs index 7334de0fd96f..cd7f6a018ab2 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs @@ -377,6 +377,68 @@ pub fn ty(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn as_token(&self) -> Option { support::token(&self.syntax, T![as]) } } +pub struct CfgAtom { + pub(crate) syntax: SyntaxNode, +} +impl CfgAtom { + #[inline] + pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } + #[inline] + pub fn false_token(&self) -> Option { support::token(&self.syntax, T![false]) } + #[inline] + pub fn ident_token(&self) -> Option { support::token(&self.syntax, T![ident]) } + #[inline] + pub fn string_token(&self) -> Option { support::token(&self.syntax, T![string]) } + #[inline] + pub fn true_token(&self) -> Option { support::token(&self.syntax, T![true]) } +} +pub struct CfgAttrMeta { + pub(crate) syntax: SyntaxNode, +} +impl CfgAttrMeta { + #[inline] + pub fn cfg_predicate(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn metas(&self) -> AstChildren { support::children(&self.syntax) } + #[inline] + pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } + #[inline] + pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } + #[inline] + pub fn comma_token(&self) -> Option { support::token(&self.syntax, T![,]) } + #[inline] + pub fn cfg_attr_token(&self) -> Option { + support::token(&self.syntax, T![cfg_attr]) + } +} +pub struct CfgComposite { + pub(crate) syntax: SyntaxNode, +} +impl CfgComposite { + #[inline] + pub fn cfg_predicates(&self) -> AstChildren { support::children(&self.syntax) } + #[inline] + pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } + #[inline] + pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } + #[inline] + pub fn keyword(&self) -> Option { support::token(&self.syntax, T![ident]) } +} +pub struct CfgMeta { + pub(crate) syntax: SyntaxNode, +} +impl CfgMeta { + #[inline] + pub fn cfg_predicate(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } + #[inline] + pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } + #[inline] + pub fn comma_token(&self) -> Option { support::token(&self.syntax, T![,]) } + #[inline] + pub fn cfg_token(&self) -> Option { support::token(&self.syntax, T![cfg]) } +} pub struct ClosureExpr { pub(crate) syntax: SyntaxNode, } @@ -783,6 +845,17 @@ pub fn l_curly_token(&self) -> Option { support::token(&self.syntax #[inline] pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } +pub struct KeyValueMeta { + pub(crate) syntax: SyntaxNode, +} +impl KeyValueMeta { + #[inline] + pub fn expr(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn path(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } +} pub struct Label { pub(crate) syntax: SyntaxNode, } @@ -1012,25 +1085,6 @@ impl MatchGuard { #[inline] pub fn if_token(&self) -> Option { support::token(&self.syntax, T![if]) } } -pub struct Meta { - pub(crate) syntax: SyntaxNode, -} -impl Meta { - #[inline] - pub fn expr(&self) -> Option { support::child(&self.syntax) } - #[inline] - pub fn path(&self) -> Option { support::child(&self.syntax) } - #[inline] - pub fn token_tree(&self) -> Option { support::child(&self.syntax) } - #[inline] - pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } - #[inline] - pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } - #[inline] - pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } - #[inline] - pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } -} pub struct MethodCallExpr { pub(crate) syntax: SyntaxNode, } @@ -1225,6 +1279,13 @@ impl PathExpr { #[inline] pub fn path(&self) -> Option { support::child(&self.syntax) } } +pub struct PathMeta { + pub(crate) syntax: SyntaxNode, +} +impl PathMeta { + #[inline] + pub fn path(&self) -> Option { support::child(&self.syntax) } +} pub struct PathPat { pub(crate) syntax: SyntaxNode, } @@ -1607,6 +1668,15 @@ pub fn l_curly_token(&self) -> Option { support::token(&self.syntax #[inline] pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } +pub struct TokenTreeMeta { + pub(crate) syntax: SyntaxNode, +} +impl TokenTreeMeta { + #[inline] + pub fn path(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn token_tree(&self) -> Option { support::child(&self.syntax) } +} pub struct Trait { pub(crate) syntax: SyntaxNode, } @@ -1834,6 +1904,19 @@ pub fn record_field_list(&self) -> Option { support::child(&sel #[inline] pub fn union_token(&self) -> Option { support::token(&self.syntax, T![union]) } } +pub struct UnsafeMeta { + pub(crate) syntax: SyntaxNode, +} +impl UnsafeMeta { + #[inline] + pub fn meta(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } + #[inline] + pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } + #[inline] + pub fn unsafe_token(&self) -> Option { support::token(&self.syntax, T![unsafe]) } +} pub struct Use { pub(crate) syntax: SyntaxNode, } @@ -2024,6 +2107,12 @@ pub enum AssocItem { impl ast::HasAttrs for AssocItem {} impl ast::HasDocComments for AssocItem {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum CfgPredicate { + CfgAtom(CfgAtom), + CfgComposite(CfgComposite), +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Expr { ArrayExpr(ArrayExpr), @@ -2118,6 +2207,16 @@ pub enum Item { } impl ast::HasAttrs for Item {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum Meta { + CfgAttrMeta(CfgAttrMeta), + CfgMeta(CfgMeta), + KeyValueMeta(KeyValueMeta), + PathMeta(PathMeta), + TokenTreeMeta(TokenTreeMeta), + UnsafeMeta(UnsafeMeta), +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Pat { BoxPat(BoxPat), @@ -3133,6 +3232,134 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("CastExpr").field("syntax", &self.syntax).finish() } } +impl AstNode for CfgAtom { + #[inline] + fn kind() -> SyntaxKind + where + Self: Sized, + { + CFG_ATOM + } + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == CFG_ATOM } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl hash::Hash for CfgAtom { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for CfgAtom {} +impl PartialEq for CfgAtom { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for CfgAtom { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for CfgAtom { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("CfgAtom").field("syntax", &self.syntax).finish() + } +} +impl AstNode for CfgAttrMeta { + #[inline] + fn kind() -> SyntaxKind + where + Self: Sized, + { + CFG_ATTR_META + } + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == CFG_ATTR_META } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl hash::Hash for CfgAttrMeta { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for CfgAttrMeta {} +impl PartialEq for CfgAttrMeta { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for CfgAttrMeta { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for CfgAttrMeta { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("CfgAttrMeta").field("syntax", &self.syntax).finish() + } +} +impl AstNode for CfgComposite { + #[inline] + fn kind() -> SyntaxKind + where + Self: Sized, + { + CFG_COMPOSITE + } + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == CFG_COMPOSITE } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl hash::Hash for CfgComposite { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for CfgComposite {} +impl PartialEq for CfgComposite { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for CfgComposite { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for CfgComposite { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("CfgComposite").field("syntax", &self.syntax).finish() + } +} +impl AstNode for CfgMeta { + #[inline] + fn kind() -> SyntaxKind + where + Self: Sized, + { + CFG_META + } + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == CFG_META } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl hash::Hash for CfgMeta { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for CfgMeta {} +impl PartialEq for CfgMeta { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for CfgMeta { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for CfgMeta { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("CfgMeta").field("syntax", &self.syntax).finish() + } +} impl AstNode for ClosureExpr { #[inline] fn kind() -> SyntaxKind @@ -4093,6 +4320,38 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ItemList").field("syntax", &self.syntax).finish() } } +impl AstNode for KeyValueMeta { + #[inline] + fn kind() -> SyntaxKind + where + Self: Sized, + { + KEY_VALUE_META + } + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == KEY_VALUE_META } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl hash::Hash for KeyValueMeta { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for KeyValueMeta {} +impl PartialEq for KeyValueMeta { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for KeyValueMeta { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for KeyValueMeta { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("KeyValueMeta").field("syntax", &self.syntax).finish() + } +} impl AstNode for Label { #[inline] fn kind() -> SyntaxKind @@ -4797,38 +5056,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("MatchGuard").field("syntax", &self.syntax).finish() } } -impl AstNode for Meta { - #[inline] - fn kind() -> SyntaxKind - where - Self: Sized, - { - META - } - #[inline] - fn can_cast(kind: SyntaxKind) -> bool { kind == META } - #[inline] - fn cast(syntax: SyntaxNode) -> Option { - if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } - } - #[inline] - fn syntax(&self) -> &SyntaxNode { &self.syntax } -} -impl hash::Hash for Meta { - fn hash(&self, state: &mut H) { self.syntax.hash(state); } -} -impl Eq for Meta {} -impl PartialEq for Meta { - fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } -} -impl Clone for Meta { - fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } -} -impl fmt::Debug for Meta { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Meta").field("syntax", &self.syntax).finish() - } -} impl AstNode for MethodCallExpr { #[inline] fn kind() -> SyntaxKind @@ -5309,6 +5536,38 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("PathExpr").field("syntax", &self.syntax).finish() } } +impl AstNode for PathMeta { + #[inline] + fn kind() -> SyntaxKind + where + Self: Sized, + { + PATH_META + } + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_META } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl hash::Hash for PathMeta { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for PathMeta {} +impl PartialEq for PathMeta { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for PathMeta { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for PathMeta { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PathMeta").field("syntax", &self.syntax).finish() + } +} impl AstNode for PathPat { #[inline] fn kind() -> SyntaxKind @@ -6301,6 +6560,38 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("TokenTree").field("syntax", &self.syntax).finish() } } +impl AstNode for TokenTreeMeta { + #[inline] + fn kind() -> SyntaxKind + where + Self: Sized, + { + TOKEN_TREE_META + } + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == TOKEN_TREE_META } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl hash::Hash for TokenTreeMeta { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for TokenTreeMeta {} +impl PartialEq for TokenTreeMeta { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for TokenTreeMeta { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for TokenTreeMeta { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TokenTreeMeta").field("syntax", &self.syntax).finish() + } +} impl AstNode for Trait { #[inline] fn kind() -> SyntaxKind @@ -6845,6 +7136,38 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Union").field("syntax", &self.syntax).finish() } } +impl AstNode for UnsafeMeta { + #[inline] + fn kind() -> SyntaxKind + where + Self: Sized, + { + UNSAFE_META + } + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == UNSAFE_META } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl hash::Hash for UnsafeMeta { + fn hash(&self, state: &mut H) { self.syntax.hash(state); } +} +impl Eq for UnsafeMeta {} +impl PartialEq for UnsafeMeta { + fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax } +} +impl Clone for UnsafeMeta { + fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } } +} +impl fmt::Debug for UnsafeMeta { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("UnsafeMeta").field("syntax", &self.syntax).finish() + } +} impl AstNode for Use { #[inline] fn kind() -> SyntaxKind @@ -7413,6 +7736,34 @@ fn syntax(&self) -> &SyntaxNode { } } } +impl From for CfgPredicate { + #[inline] + fn from(node: CfgAtom) -> CfgPredicate { CfgPredicate::CfgAtom(node) } +} +impl From for CfgPredicate { + #[inline] + fn from(node: CfgComposite) -> CfgPredicate { CfgPredicate::CfgComposite(node) } +} +impl AstNode for CfgPredicate { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, CFG_ATOM | CFG_COMPOSITE) } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + CFG_ATOM => CfgPredicate::CfgAtom(CfgAtom { syntax }), + CFG_COMPOSITE => CfgPredicate::CfgComposite(CfgComposite { syntax }), + _ => return None, + }; + Some(res) + } + #[inline] + fn syntax(&self) -> &SyntaxNode { + match self { + CfgPredicate::CfgAtom(it) => &it.syntax, + CfgPredicate::CfgComposite(it) => &it.syntax, + } + } +} impl From for Expr { #[inline] fn from(node: ArrayExpr) -> Expr { Expr::ArrayExpr(node) } @@ -7970,6 +8321,63 @@ fn syntax(&self) -> &SyntaxNode { } } } +impl From for Meta { + #[inline] + fn from(node: CfgAttrMeta) -> Meta { Meta::CfgAttrMeta(node) } +} +impl From for Meta { + #[inline] + fn from(node: CfgMeta) -> Meta { Meta::CfgMeta(node) } +} +impl From for Meta { + #[inline] + fn from(node: KeyValueMeta) -> Meta { Meta::KeyValueMeta(node) } +} +impl From for Meta { + #[inline] + fn from(node: PathMeta) -> Meta { Meta::PathMeta(node) } +} +impl From for Meta { + #[inline] + fn from(node: TokenTreeMeta) -> Meta { Meta::TokenTreeMeta(node) } +} +impl From for Meta { + #[inline] + fn from(node: UnsafeMeta) -> Meta { Meta::UnsafeMeta(node) } +} +impl AstNode for Meta { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { + matches!( + kind, + CFG_ATTR_META | CFG_META | KEY_VALUE_META | PATH_META | TOKEN_TREE_META | UNSAFE_META + ) + } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + CFG_ATTR_META => Meta::CfgAttrMeta(CfgAttrMeta { syntax }), + CFG_META => Meta::CfgMeta(CfgMeta { syntax }), + KEY_VALUE_META => Meta::KeyValueMeta(KeyValueMeta { syntax }), + PATH_META => Meta::PathMeta(PathMeta { syntax }), + TOKEN_TREE_META => Meta::TokenTreeMeta(TokenTreeMeta { syntax }), + UNSAFE_META => Meta::UnsafeMeta(UnsafeMeta { syntax }), + _ => return None, + }; + Some(res) + } + #[inline] + fn syntax(&self) -> &SyntaxNode { + match self { + Meta::CfgAttrMeta(it) => &it.syntax, + Meta::CfgMeta(it) => &it.syntax, + Meta::KeyValueMeta(it) => &it.syntax, + Meta::PathMeta(it) => &it.syntax, + Meta::TokenTreeMeta(it) => &it.syntax, + Meta::UnsafeMeta(it) => &it.syntax, + } + } +} impl From for Pat { #[inline] fn from(node: BoxPat) -> Pat { Pat::BoxPat(node) } @@ -9334,6 +9742,11 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for CfgPredicate { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for Expr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -9364,6 +9777,11 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for Meta { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for Pat { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -9524,6 +9942,26 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for CfgAtom { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for CfgAttrMeta { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for CfgComposite { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for CfgMeta { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for ClosureExpr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -9674,6 +10112,11 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for KeyValueMeta { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for Label { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -9784,11 +10227,6 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } } -impl std::fmt::Display for Meta { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(self.syntax(), f) - } -} impl std::fmt::Display for MethodCallExpr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -9864,6 +10302,11 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for PathMeta { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for PathPat { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -10019,6 +10462,11 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for TokenTreeMeta { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for Trait { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -10104,6 +10552,11 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for UnsafeMeta { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for Use { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs index 00971569a2ef..ac02cc9e43fd 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -1322,6 +1322,18 @@ pub fn meta_path(path: ast::Path) -> ast::Meta { ast_from_text(&format!("#[{path}]")) } +pub fn cfg_attr_meta( + predicate: ast::CfgPredicate, + inner: impl IntoIterator, +) -> ast::CfgAttrMeta { + let inner = inner.into_iter().join(", "); + ast_from_text(&format!("#![cfg_attr({predicate}, {inner})]")) +} + +pub fn cfg_flag(flag: &str) -> ast::CfgPredicate { + ast_from_text(&format!("#![cfg({flag})]")) +} + pub fn token_tree( delimiter: SyntaxKind, tt: impl IntoIterator>, diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs index 3fc3b39feef0..03118d01dc90 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs @@ -8,6 +8,7 @@ use itertools::Itertools; use parser::SyntaxKind; use rowan::{GreenNodeData, GreenTokenData}; +use smallvec::{SmallVec, smallvec}; use crate::{ NodeOrToken, SmolStr, SyntaxElement, SyntaxElementChildren, SyntaxToken, T, TokenText, @@ -201,36 +202,82 @@ pub fn is_outer(&self) -> bool { } } -impl ast::Attr { +impl ast::Meta { pub fn as_simple_atom(&self) -> Option { - let meta = self.meta()?; - if meta.eq_token().is_some() || meta.token_tree().is_some() { - return None; - } - self.simple_name() + Some(self.as_simple_path()?.as_single_name_ref()?.text().into()) } pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> { - let tt = self.meta()?.token_tree()?; - Some((self.simple_name()?, tt)) + let ast::Meta::TokenTreeMeta(meta) = self else { return None }; + Some((meta.path()?.as_single_name_ref()?.text().into(), meta.token_tree()?)) } pub fn as_simple_path(&self) -> Option { - let meta = self.meta()?; - if meta.eq_token().is_some() || meta.token_tree().is_some() { - return None; - } - self.path() + let ast::Meta::PathMeta(meta) = self else { return None }; + meta.path() } pub fn simple_name(&self) -> Option { - let path = self.meta()?.path()?; - match (path.segment(), path.qualifier()) { - (Some(segment), None) => Some(segment.syntax().first_token()?.text().into()), - _ => None, + match self { + ast::Meta::CfgAttrMeta(_) => Some(SmolStr::new_static("cfg_attr")), + ast::Meta::CfgMeta(_) => Some(SmolStr::new_static("cfg")), + _ => { + let path = self.path()?; + match (path.segment(), path.qualifier()) { + (Some(segment), None) => Some(segment.syntax().first_token()?.text().into()), + _ => None, + } + } } } + pub fn path(&self) -> Option { + match self { + ast::Meta::CfgAttrMeta(_) | ast::Meta::CfgMeta(_) => None, + ast::Meta::KeyValueMeta(it) => it.path(), + ast::Meta::PathMeta(it) => it.path(), + ast::Meta::TokenTreeMeta(it) => it.path(), + ast::Meta::UnsafeMeta(it) => it.meta()?.path(), + } + } + + /// Includes `cfg_attr()` inner metas (without considering the predicate). + pub fn skip_cfg_attrs(self) -> SmallVec<[ast::Meta; 1]> { + match self { + ast::Meta::CfgAttrMeta(meta) => { + meta.metas().flat_map(|meta| meta.skip_cfg_attrs()).collect() + } + _ => smallvec![self], + } + } + + /// FIXME: Calling this is almost always incorrect, as `cfg_attr` can contains multiple `Meta`s. + pub fn parent_attr(&self) -> Option { + self.syntax().ancestors().find_map(ast::Attr::cast) + } +} + +impl ast::Attr { + pub fn as_simple_atom(&self) -> Option { + self.meta().and_then(|meta| meta.as_simple_atom()) + } + + pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> { + self.meta().and_then(|meta| meta.as_simple_call()) + } + + pub fn as_simple_path(&self) -> Option { + self.meta().and_then(|meta| meta.as_simple_path()) + } + + pub fn simple_name(&self) -> Option { + self.meta().and_then(|meta| meta.simple_name()) + } + + pub fn path(&self) -> Option { + self.meta().and_then(|meta| meta.path()) + } + pub fn kind(&self) -> AttrKind { match self.excl_token() { Some(_) => AttrKind::Inner, @@ -238,16 +285,12 @@ pub fn kind(&self) -> AttrKind { } } - pub fn path(&self) -> Option { - self.meta()?.path() - } - - pub fn expr(&self) -> Option { - self.meta()?.expr() - } - - pub fn token_tree(&self) -> Option { - self.meta()?.token_tree() + /// Includes `cfg_attr()` inner metas (without considering the predicate). + pub fn skip_cfg_attrs(&self) -> SmallVec<[ast::Meta; 1]> { + match self.meta() { + Some(meta) => meta.skip_cfg_attrs(), + None => SmallVec::new(), + } } } @@ -1015,12 +1058,6 @@ pub fn parent_meta(&self) -> Option { } } -impl ast::Meta { - pub fn parent_attr(&self) -> Option { - self.syntax().parent().and_then(ast::Attr::cast) - } -} - impl ast::GenericArgList { pub fn lifetime_args(&self) -> impl Iterator { self.generic_args().filter_map(|arg| match arg { @@ -1164,6 +1201,25 @@ pub fn leading_pipe(&self) -> Option { } } +#[derive(Debug, Clone)] +pub enum CfgAtomKey { + True, + False, + Ident(SyntaxToken), +} + +impl ast::CfgAtom { + pub fn key(&self) -> Option { + if self.true_token().is_some() { + Some(CfgAtomKey::True) + } else if self.false_token().is_some() { + Some(CfgAtomKey::False) + } else { + self.ident_token().map(CfgAtomKey::Ident) + } + } +} + /// An iterator over the elements in an [`ast::TokenTree`]. /// /// Does not yield trivia or the delimiters. diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs index e91e444a3233..c66f096e8342 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs @@ -1848,7 +1848,36 @@ pub fn meta_token_tree(&self, path: ast::Path, tt: ast::TokenTree) -> ast::Meta if let Some(mut mapping) = self.mappings() { let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); builder.map_node(path.syntax().clone(), ast.path().unwrap().syntax().clone()); - builder.map_node(tt.syntax().clone(), ast.token_tree().unwrap().syntax().clone()); + let ast::Meta::TokenTreeMeta(meta) = &ast else { unreachable!() }; + builder.map_node(tt.syntax().clone(), meta.token_tree().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn cfg_flag(&self, flag: &str) -> ast::CfgPredicate { + make::cfg_flag(flag).clone_for_update() + } + + pub fn cfg_attr_meta( + &self, + predicate: ast::CfgPredicate, + inner: impl IntoIterator, + ) -> ast::CfgAttrMeta { + let inner = Vec::from_iter(inner); + let ast = make::cfg_attr_meta(predicate.clone(), inner.iter().cloned()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node( + predicate.syntax().clone(), + ast.cfg_predicate().unwrap().syntax().clone(), + ); + builder.map_children( + inner.iter().map(|it| it.syntax().clone()), + ast.metas().map(|it| it.syntax().clone()), + ); builder.finish(&mut mapping); } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/traits.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/traits.rs index 2f4109a2c976..6fe5abb84e22 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/traits.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/traits.rs @@ -73,9 +73,6 @@ pub trait HasAttrs: AstNode { fn attrs(&self) -> AstChildren { support::children(self.syntax()) } - fn has_atom_attr(&self, atom: &str) -> bool { - self.attrs().filter_map(|x| x.as_simple_atom()).any(|x| x == atom) - } /// This may return the same node as called with (with `SourceFile`). The caller has the responsibility /// to avoid duplicate attributes. diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0031_block_inner_attrs.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0031_block_inner_attrs.rast index 50057a02d809..5fdde93c603d 100644 --- a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0031_block_inner_attrs.rast +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0031_block_inner_attrs.rast @@ -29,7 +29,7 @@ SOURCE_FILE@0..350 POUND@39..40 "#" BANG@40..41 "!" L_BRACK@41..42 "[" - META@42..82 + TOKEN_TREE_META@42..82 PATH@42..45 PATH_SEGMENT@42..45 NAME_REF@42..45 @@ -60,7 +60,7 @@ SOURCE_FILE@0..350 POUND@152..153 "#" BANG@153..154 "!" L_BRACK@154..155 "[" - META@155..170 + TOKEN_TREE_META@155..170 PATH@155..158 PATH_SEGMENT@155..158 NAME_REF@155..158 @@ -75,7 +75,7 @@ SOURCE_FILE@0..350 POUND@180..181 "#" BANG@181..182 "!" L_BRACK@182..183 "[" - META@183..211 + TOKEN_TREE_META@183..211 PATH@183..186 PATH_SEGMENT@183..186 NAME_REF@183..186 @@ -104,7 +104,7 @@ SOURCE_FILE@0..350 POUND@283..284 "#" BANG@284..285 "!" L_BRACK@285..286 "[" - META@286..301 + TOKEN_TREE_META@286..301 PATH@286..289 PATH_SEGMENT@286..289 NAME_REF@286..289 diff --git a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs index 4e980bb3d986..257429c42661 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs @@ -780,7 +780,7 @@ fn is_many(&self) -> bool { } fn token_kind(&self) -> Option { match self { - Field::Token(token) => { + Field::Token { token, .. } => { let token: proc_macro2::TokenStream = token.parse().unwrap(); Some(quote! { T![#token] }) } @@ -789,8 +789,11 @@ fn token_kind(&self) -> Option { } fn method_name(&self) -> String { match self { - Field::Token(name) => { - let name = match name.as_str() { + Field::Token { name, token, .. } => { + if let Some(name) = name { + return name.clone(); + } + let name = match token.as_str() { ";" => "semicolon", "->" => "thin_arrow", "'{'" => "l_curly", @@ -820,7 +823,7 @@ fn method_name(&self) -> String { "," => "comma", "|" => "pipe", "~" => "tilde", - _ => name, + _ => token, }; format!("{name}_token",) } @@ -835,7 +838,7 @@ fn method_name(&self) -> String { } fn ty(&self) -> proc_macro2::Ident { match self { - Field::Token(_) => format_ident!("SyntaxToken"), + Field::Token { .. } => format_ident!("SyntaxToken"), Field::Node { ty, .. } => format_ident!("{}", ty), } } @@ -885,7 +888,7 @@ fn lower(grammar: &Grammar) -> AstSrc { res.nodes.iter_mut().for_each(|it| { it.traits.sort(); it.fields.sort_by_key(|it| match it { - Field::Token(name) => (true, name.clone()), + Field::Token { token, .. } => (true, token.clone()), Field::Node { name, .. } => (false, name.clone()), }); }); @@ -925,12 +928,11 @@ fn lower_rule(acc: &mut Vec, grammar: &Grammar, label: Option<&String>, r acc.push(field); } Rule::Token(token) => { - assert!(label.is_none()); - let mut name = clean_token_name(&grammar[*token].name); - if "[]{}()".contains(&name) { - name = format!("'{name}'"); + let mut token = clean_token_name(&grammar[*token].name); + if "[]{}()".contains(&token) { + token = format!("'{token}'"); } - let field = Field::Token(name); + let field = Field::Token { name: label.cloned(), token }; acc.push(field); } Rule::Rep(inner) => { @@ -1018,8 +1020,8 @@ fn lower_separated_list( } match nt { Either::Right(token) => { - let name = clean_token_name(&grammar[*token].name); - let field = Field::Token(name); + let token = clean_token_name(&grammar[*token].name); + let field = Field::Token { token, name: None }; acc.push(field); } Either::Left(node) => { diff --git a/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs index 564d9cc24efe..a0abdf09d3a5 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs @@ -111,8 +111,19 @@ fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { ]; // keywords that are keywords only in specific parse contexts #[doc(alias = "WEAK_KEYWORDS")] -const CONTEXTUAL_KEYWORDS: &[&str] = - &["macro_rules", "union", "default", "raw", "dyn", "auto", "yeet", "safe", "bikeshed"]; +const CONTEXTUAL_KEYWORDS: &[&str] = &[ + "macro_rules", + "union", + "default", + "raw", + "dyn", + "auto", + "yeet", + "safe", + "bikeshed", + "cfg_attr", + "cfg", +]; // keywords we use for special macro expansions const CONTEXTUAL_BUILTIN_KEYWORDS: &[&str] = &[ "asm", @@ -261,7 +272,7 @@ pub(crate) struct AstNodeSrc { #[derive(Debug, Eq, PartialEq)] pub(crate) enum Field { - Token(String), + Token { name: Option, token: String }, Node { name: String, ty: String, cardinality: Cardinality }, } diff --git a/src/tools/rust-analyzer/xtask/src/codegen/lints.rs b/src/tools/rust-analyzer/xtask/src/codegen/lints.rs index 3b4c2e8da3c3..788ae8d6c1dd 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen/lints.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen/lints.rs @@ -83,7 +83,7 @@ pub struct LintGroup { let lints_json = project_root().join("./target/clippy_lints.json"); cmd!( sh, - "curl https://rust-lang.github.io/rust-clippy/stable/lints.json --output {lints_json}" + "curl -f https://raw.githubusercontent.com/rust-lang/rust-clippy/21fd71e3fe6eb063cfb619ecc37b1023f5283894/beta/lints.json --output {lints_json}" ) .run() .unwrap();