mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-07 01:05:39 +03:00
Merge pull request #22044 from ChayimFriedman2/internal-features
feat: Do not complete unstable items that use an internal feature
This commit is contained in:
@@ -1076,6 +1076,41 @@ fn derive_info(db: &dyn DefDatabase, owner: MacroId) -> Option<DeriveInfo> {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unstable_feature(self, db: &dyn DefDatabase, owner: AttrDefId) -> Option<Symbol> {
|
||||
if !self.contains(AttrFlags::IS_UNSTABLE) {
|
||||
return None;
|
||||
}
|
||||
|
||||
return unstable_feature(db, owner);
|
||||
|
||||
#[salsa::tracked]
|
||||
fn unstable_feature(db: &dyn DefDatabase, owner: AttrDefId) -> Option<Symbol> {
|
||||
collect_attrs(db, owner, |attr| {
|
||||
if let ast::Meta::TokenTreeMeta(attr) = attr
|
||||
&& let path = attr.path()
|
||||
&& path.is1("unstable")
|
||||
&& let Some(tt) = attr.token_tree()
|
||||
{
|
||||
let mut tt = TokenTreeChildren::new(&tt);
|
||||
// Technically the `feature = "..."` always comes first, but it's not a requirement.
|
||||
while let Some(token) = tt.next() {
|
||||
if let NodeOrToken::Token(token) = token
|
||||
&& token.text() == "feature"
|
||||
&& let Some(NodeOrToken::Token(eq)) = tt.next()
|
||||
&& eq.kind() == T![=]
|
||||
&& let Some(NodeOrToken::Token(feature)) = tt.next()
|
||||
&& let Some(feature) = ast::String::cast(feature)
|
||||
&& let Ok(feature) = feature.value()
|
||||
{
|
||||
return ControlFlow::Break(Symbol::intern(&feature));
|
||||
}
|
||||
}
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_repr(this: &mut ReprOptions, other: ReprOptions) {
|
||||
|
||||
@@ -85,6 +85,19 @@ pub fn is_unstable(&self) -> bool {
|
||||
self.attrs.contains(AttrFlags::IS_UNSTABLE)
|
||||
}
|
||||
|
||||
/// Currently, it could be that `is_unstable() == true` but `unstable_feature == None`
|
||||
/// (due to unstable features not being retrieved for fields etc.).
|
||||
#[inline]
|
||||
pub fn unstable_feature(&self, db: &dyn HirDatabase) -> Option<Symbol> {
|
||||
match self.owner {
|
||||
AttrsOwner::AttrDef(owner) => self.attrs.unstable_feature(db, owner),
|
||||
AttrsOwner::Field(_)
|
||||
| AttrsOwner::LifetimeParam(_)
|
||||
| AttrsOwner::TypeOrConstParam(_)
|
||||
| AttrsOwner::Dummy => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_macro_export(&self) -> bool {
|
||||
self.attrs.contains(AttrFlags::IS_MACRO_EXPORT)
|
||||
|
||||
@@ -342,6 +342,10 @@ fn core(db: &dyn HirDatabase) -> Option<Crate> {
|
||||
})
|
||||
.map(Crate::from)
|
||||
}
|
||||
|
||||
pub fn is_unstable_feature_enabled(self, db: &dyn HirDatabase, feature: &Symbol) -> bool {
|
||||
crate_def_map(db, self.id).is_unstable_feature_enabled(feature)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use std::iter;
|
||||
use std::{iter, sync::LazyLock};
|
||||
|
||||
use base_db::toolchain_channel;
|
||||
use hir::{
|
||||
DisplayTarget, HasAttrs, InFile, Local, ModuleDef, ModuleSource, Name, PathResolution,
|
||||
ScopeDef, Semantics, SemanticsScope, Symbol, Type, TypeInfo,
|
||||
ScopeDef, Semantics, SemanticsScope, Symbol, Type, TypeInfo, sym,
|
||||
};
|
||||
use ide_db::{
|
||||
FilePosition, FxHashMap, FxHashSet, RootDatabase, famous_defs::FamousDefs,
|
||||
@@ -601,7 +601,18 @@ pub(crate) fn check_stability(&self, attrs: Option<&hir::AttrsWithOwner>) -> boo
|
||||
let Some(attrs) = attrs else {
|
||||
return true;
|
||||
};
|
||||
!attrs.is_unstable() || self.is_nightly
|
||||
if !attrs.is_unstable() {
|
||||
return true;
|
||||
}
|
||||
if !self.is_nightly {
|
||||
return false;
|
||||
}
|
||||
// Unstable on nightly, but we still don't want to suggest internal features, unless the feature flag is enabled.
|
||||
let Some(unstable_feature) = attrs.unstable_feature(self.db) else {
|
||||
return true;
|
||||
};
|
||||
!INTERNAL_FEATURES.contains(&unstable_feature)
|
||||
|| self.krate.is_unstable_feature_enabled(self.db, &unstable_feature)
|
||||
}
|
||||
|
||||
pub(crate) fn check_stability_and_hidden<I>(&self, item: I) -> bool
|
||||
@@ -924,3 +935,40 @@ pub(crate) fn new(
|
||||
hir::LangItem::Shr,
|
||||
hir::LangItem::Sub,
|
||||
];
|
||||
|
||||
// FIXME: Find a way to keep this up to date somehow?
|
||||
const INTERNAL_FEATURES_LIST: &[Symbol] = &[
|
||||
sym::abi_unadjusted,
|
||||
sym::allocator_internals,
|
||||
sym::allow_internal_unsafe,
|
||||
sym::allow_internal_unstable,
|
||||
sym::cfg_emscripten_wasm_eh,
|
||||
sym::cfg_target_has_reliable_f16_f128,
|
||||
sym::compiler_builtins,
|
||||
sym::custom_mir,
|
||||
sym::eii_internals,
|
||||
sym::field_representing_type_raw,
|
||||
sym::intrinsics,
|
||||
sym::lang_items,
|
||||
sym::link_cfg,
|
||||
sym::more_maybe_bounds,
|
||||
sym::negative_bounds,
|
||||
sym::pattern_complexity_limit,
|
||||
sym::prelude_import,
|
||||
sym::profiler_runtime,
|
||||
sym::rustc_attrs,
|
||||
sym::staged_api,
|
||||
sym::test_unstable_lint,
|
||||
sym::builtin_syntax,
|
||||
sym::link_llvm_intrinsics,
|
||||
sym::needs_panic_runtime,
|
||||
sym::panic_runtime,
|
||||
sym::pattern_types,
|
||||
sym::rustdoc_internals,
|
||||
sym::contracts_internals,
|
||||
sym::freeze_impls,
|
||||
sym::unsized_fn_params,
|
||||
];
|
||||
|
||||
static INTERNAL_FEATURES: LazyLock<FxHashSet<Symbol>> =
|
||||
LazyLock::new(|| INTERNAL_FEATURES_LIST.iter().cloned().collect());
|
||||
|
||||
@@ -2273,7 +2273,7 @@ fn main() {
|
||||
$0
|
||||
}
|
||||
//- /std.rs crate:std
|
||||
#[unstable]
|
||||
#[unstable(feature = "some_non_internal_feature")]
|
||||
pub struct UnstableButWeAreOnNightlyAnyway;
|
||||
"#,
|
||||
expect![[r#"
|
||||
@@ -2317,6 +2317,112 @@ fn main() fn()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expr_unstable_item_internal_feature() {
|
||||
check(
|
||||
r#"
|
||||
//- toolchain:nightly
|
||||
//- /main.rs crate:main deps:std
|
||||
use std::*;
|
||||
fn main() {
|
||||
$0
|
||||
}
|
||||
//- /std.rs crate:std
|
||||
#[unstable(feature = "intrinsics")]
|
||||
pub mod intrinsics {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn main() fn()
|
||||
md std
|
||||
bt u32 u32
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw enum
|
||||
kw extern
|
||||
kw false
|
||||
kw fn
|
||||
kw for
|
||||
kw if
|
||||
kw if let
|
||||
kw impl
|
||||
kw impl for
|
||||
kw let
|
||||
kw letm
|
||||
kw loop
|
||||
kw match
|
||||
kw mod
|
||||
kw return
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw trait
|
||||
kw true
|
||||
kw type
|
||||
kw union
|
||||
kw unsafe
|
||||
kw use
|
||||
kw while
|
||||
kw while let
|
||||
sn macro_rules
|
||||
sn pd
|
||||
sn ppd
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
//- toolchain:nightly
|
||||
//- /main.rs crate:main deps:std
|
||||
#![feature(intrinsics)]
|
||||
use std::*;
|
||||
fn main() {
|
||||
$0
|
||||
}
|
||||
//- /std.rs crate:std
|
||||
#[unstable(feature = "intrinsics")]
|
||||
pub mod intrinsics {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn main() fn()
|
||||
md intrinsics
|
||||
md std
|
||||
bt u32 u32
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw enum
|
||||
kw extern
|
||||
kw false
|
||||
kw fn
|
||||
kw for
|
||||
kw if
|
||||
kw if let
|
||||
kw impl
|
||||
kw impl for
|
||||
kw let
|
||||
kw letm
|
||||
kw loop
|
||||
kw match
|
||||
kw mod
|
||||
kw return
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw trait
|
||||
kw true
|
||||
kw type
|
||||
kw union
|
||||
kw unsafe
|
||||
kw use
|
||||
kw while
|
||||
kw while let
|
||||
sn macro_rules
|
||||
sn pd
|
||||
sn ppd
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inside_format_args_completions_work() {
|
||||
check(
|
||||
|
||||
@@ -123,7 +123,6 @@ pub(super) fn prefill() -> DashMap<Symbol, (), BuildHasherDefault<FxHasher>> {
|
||||
all,
|
||||
alloc_layout,
|
||||
alloc,
|
||||
allow_internal_unsafe,
|
||||
allow,
|
||||
any,
|
||||
as_str,
|
||||
@@ -541,4 +540,32 @@ pub(super) fn prefill() -> DashMap<Symbol, (), BuildHasherDefault<FxHasher>> {
|
||||
DispatchFromDyn,
|
||||
define_opaque,
|
||||
marker,
|
||||
abi_unadjusted,
|
||||
allocator_internals,
|
||||
allow_internal_unsafe,
|
||||
allow_internal_unstable,
|
||||
cfg_emscripten_wasm_eh,
|
||||
cfg_target_has_reliable_f16_f128,
|
||||
compiler_builtins,
|
||||
custom_mir,
|
||||
eii_internals,
|
||||
field_representing_type_raw,
|
||||
intrinsics,
|
||||
link_cfg,
|
||||
more_maybe_bounds,
|
||||
negative_bounds,
|
||||
pattern_complexity_limit,
|
||||
profiler_runtime,
|
||||
rustc_attrs,
|
||||
staged_api,
|
||||
test_unstable_lint,
|
||||
builtin_syntax,
|
||||
link_llvm_intrinsics,
|
||||
needs_panic_runtime,
|
||||
panic_runtime,
|
||||
pattern_types,
|
||||
rustdoc_internals,
|
||||
contracts_internals,
|
||||
freeze_impls,
|
||||
unsized_fn_params,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user