Skip to content

Commit 42ce9ae

Browse files
authored
Merge pull request rust-lang#22747 from Veykril/lukaswirth/push-zwpsumlyprzo
fix: Reimplement `crate_supports_no_std` syntactic heuristic
2 parents b669719 + ff3a288 commit 42ce9ae

2 files changed

Lines changed: 60 additions & 3 deletions

File tree

crates/hir-def/src/attrs.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,29 @@ pub fn parse_extra_crate_attrs(db: &dyn SourceDatabase, krate: Crate) -> Option<
380380
Some(p.tree())
381381
}
382382

383+
/// Whether the crate root declares `#![no_std]`, looking through `cfg_attr` gating.
384+
#[salsa::tracked(returns(copy))]
385+
pub(crate) fn crate_supports_no_std(db: &dyn SourceDatabase, krate: Crate) -> bool {
386+
fn contains_no_std(meta: ast::Meta) -> bool {
387+
match meta {
388+
ast::Meta::PathMeta(meta) => meta.path().is1("no_std"),
389+
ast::Meta::CfgAttrMeta(meta) => meta.metas().any(contains_no_std),
390+
ast::Meta::UnsafeMeta(meta) => meta.meta().is_some_and(contains_no_std),
391+
ast::Meta::CfgMeta(_) | ast::Meta::KeyValueMeta(_) | ast::Meta::TokenTreeMeta(_) => {
392+
false
393+
}
394+
}
395+
}
396+
397+
let root_file = krate.root_file_id(db).parse(db).tree();
398+
parse_extra_crate_attrs(db, krate)
399+
.into_iter()
400+
.flat_map(|extra| extra.attrs())
401+
.chain(root_file.attrs())
402+
.filter_map(|attr| attr.meta())
403+
.any(contains_no_std)
404+
}
405+
383406
fn attrs_source(
384407
db: &dyn SourceDatabase,
385408
owner: AttrDefId,

crates/hir-def/src/find_path.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_hash::FxHashSet;
1313

1414
use crate::{
1515
ModuleDefId, ModuleIdLt,
16+
attrs::crate_supports_no_std,
1617
import_map::ImportMap,
1718
item_scope::ItemInNs,
1819
nameres::DefMap,
@@ -59,7 +60,9 @@ pub fn find_path(
5960

6061
let from_def_map = from.def_map(db);
6162

62-
cfg.prefer_no_std = cfg.prefer_no_std || from_def_map.is_no_std();
63+
let from_crate = from.krate(db);
64+
cfg.prefer_no_std =
65+
cfg.prefer_no_std || from_def_map.is_no_std() || crate_supports_no_std(db, from_crate);
6366

6467
find_path_inner(
6568
&FindPathCtx {
@@ -69,7 +72,7 @@ pub fn find_path(
6972
ignore_local_imports,
7073
is_std_item: item_module.krate(db).data(db).origin.is_lang(),
7174
from,
72-
from_crate: from.krate(db),
75+
from_crate,
7376
crate_root: from_def_map.crate_root(db),
7477
from_def_map,
7578
fuel: Cell::new(FIND_PATH_FUEL),
@@ -1485,7 +1488,7 @@ pub mod fmt {
14851488
"#]],
14861489
);
14871490

1488-
// Should also work (on a best-effort basis) if `no_std` is conditional.
1491+
// Should also work (on a best-effort basis) if `no_std` is conditionally enabled.
14891492
check_found_path(
14901493
r#"
14911494
//- /main.rs crate:main deps:core,std
@@ -1501,6 +1504,37 @@ pub mod fmt {
15011504
15021505
//- /zzz.rs crate:core
15031506
1507+
pub mod fmt {
1508+
pub struct Error;
1509+
}
1510+
"#,
1511+
"core::fmt::Error",
1512+
expect![[r#"
1513+
Plain (imports ✔): core::fmt::Error
1514+
Plain (imports ✖): core::fmt::Error
1515+
ByCrate(imports ✔): core::fmt::Error
1516+
ByCrate(imports ✖): core::fmt::Error
1517+
BySelf (imports ✔): core::fmt::Error
1518+
BySelf (imports ✖): core::fmt::Error
1519+
"#]],
1520+
);
1521+
1522+
// Should also work (on a best-effort basis) if `no_std` is conditionally disabled.
1523+
check_found_path(
1524+
r#"
1525+
//- /main.rs crate:main deps:core,std cfg:test
1526+
#![cfg_attr(not(test), no_std)]
1527+
1528+
$0
1529+
1530+
//- /std.rs crate:std deps:core
1531+
1532+
pub mod fmt {
1533+
pub use core::fmt::Error;
1534+
}
1535+
1536+
//- /zzz.rs crate:core
1537+
15041538
pub mod fmt {
15051539
pub struct Error;
15061540
}

0 commit comments

Comments
 (0)