Skip to content

Rollup of 5 pull requests #113855

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 15 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 3 additions & 11 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
@@ -551,17 +551,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
for &(ref use_tree, id) in trees {
let new_hir_id = self.local_def_id(id);

let mut prefix = prefix.clone();

// Give the segments new node-ids since they are being cloned.
for seg in &mut prefix.segments {
// Give the cloned segment the same resolution information
// as the old one (this is needed for stability checking).
let new_id = self.next_node_id();
self.resolver.clone_res(seg.id, new_id);
seg.id = new_id;
}

// Each `use` import is an item and thus are owners of the
// names in the path. Up to this point the nested import is
// the current owner, since we want each desugared import to
@@ -570,6 +559,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.with_hir_id_owner(id, |this| {
let mut ident = *ident;

// `prefix` is lowered multiple times, but in different HIR owners.
// So each segment gets renewed `HirId` with the same
// `ItemLocalId` and the new owner. (See `lower_node_id`)
let kind =
this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs);
if let Some(attrs) = attrs {
10 changes: 0 additions & 10 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
@@ -148,10 +148,6 @@ trait ResolverAstLoweringExt {
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>>;
// Clones the resolution (if any) on 'source' and applies it
// to 'target'. Used when desugaring a `UseTreeKind::Nested` to
// multiple `UseTreeKind::Simple`s
fn clone_res(&mut self, source: NodeId, target: NodeId);
fn get_label_res(&self, id: NodeId) -> Option<NodeId>;
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
@@ -184,12 +180,6 @@ impl ResolverAstLoweringExt for ResolverAstLowering {
None
}

fn clone_res(&mut self, source: NodeId, target: NodeId) {
if let Some(res) = self.partial_res_map.get(&source) {
self.partial_res_map.insert(target, *res);
}
}

/// Obtains resolution for a `NodeId` with a single resolution.
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes> {
self.partial_res_map.get(&id).copied()
17 changes: 13 additions & 4 deletions compiler/rustc_metadata/src/foreign_modules.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_middle::query::LocalCrate;
use rustc_middle::ty::TyCtxt;
use rustc_session::cstore::ForeignModule;

pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
let mut modules = Vec::new();
pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> FxIndexMap<DefId, ForeignModule> {
let mut modules = FxIndexMap::default();

// We need to collect all the `ForeignMod`, even if they are empty.
for id in tcx.hir().items() {
if !matches!(tcx.def_kind(id.owner_id), DefKind::ForeignMod) {
continue;
}

let def_id = id.owner_id.to_def_id();
let item = tcx.hir().item(id);
if let hir::ItemKind::ForeignMod { items, .. } = item.kind {

if let hir::ItemKind::ForeignMod { abi, items } = item.kind {
let foreign_items = items.iter().map(|it| it.id.owner_id.to_def_id()).collect();
modules.push(ForeignModule { foreign_items, def_id: id.owner_id.to_def_id() });
modules.insert(def_id, ForeignModule { def_id, abi, foreign_items });
}
}

modules
}
80 changes: 34 additions & 46 deletions compiler/rustc_metadata/src/native_libs.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use rustc_ast::{NestedMetaItem, CRATE_NODE_ID};
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_middle::query::LocalCrate;
use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_session::config::CrateType;
use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib, PeImportNameType};
use rustc_session::cstore::{
DllCallingConvention, DllImport, ForeignModule, NativeLib, PeImportNameType,
};
use rustc_session::parse::feature_err;
use rustc_session::search_paths::PathKind;
use rustc_session::utils::NativeLibKind;
use rustc_session::Session;
use rustc_span::def_id::{DefId, LOCAL_CRATE};
use rustc_span::symbol::{sym, Symbol};
use rustc_target::spec::abi::Abi;

@@ -66,10 +68,12 @@ fn find_bundled_library(
None
}

pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> Vec<NativeLib> {
let mut collector = Collector { tcx, libs: Vec::new() };
for id in tcx.hir().items() {
collector.process_item(id);
if tcx.sess.opts.unstable_opts.link_directives {
for module in tcx.foreign_modules(LOCAL_CRATE).values() {
collector.process_module(module);
}
}
collector.process_command_line();
collector.libs
@@ -88,29 +92,20 @@ struct Collector<'tcx> {
}

impl<'tcx> Collector<'tcx> {
fn process_item(&mut self, id: rustc_hir::ItemId) {
if !matches!(self.tcx.def_kind(id.owner_id), DefKind::ForeignMod) {
return;
}
fn process_module(&mut self, module: &ForeignModule) {
let ForeignModule { def_id, abi, ref foreign_items } = *module;
let def_id = def_id.expect_local();

let it = self.tcx.hir().item(id);
let hir::ItemKind::ForeignMod { abi, items: foreign_mod_items } = it.kind else {
return;
};
let sess = self.tcx.sess;

if matches!(abi, Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic) {
return;
}

// Process all of the #[link(..)]-style arguments
let sess = self.tcx.sess;
let features = self.tcx.features();

if !sess.opts.unstable_opts.link_directives {
return;
}

for m in self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| a.has_name(sym::link)) {
for m in self.tcx.get_attrs(def_id, sym::link) {
let Some(items) = m.meta_item_list() else {
continue;
};
@@ -340,9 +335,9 @@ impl<'tcx> Collector<'tcx> {
if name.as_str().contains('\0') {
sess.emit_err(errors::RawDylibNoNul { span: name_span });
}
foreign_mod_items
foreign_items
.iter()
.map(|child_item| {
.map(|&child_item| {
self.build_dll_import(
abi,
import_name_type.map(|(import_name_type, _)| import_name_type),
@@ -352,21 +347,12 @@ impl<'tcx> Collector<'tcx> {
.collect()
}
_ => {
for child_item in foreign_mod_items {
if self.tcx.def_kind(child_item.id.owner_id).has_codegen_attrs()
&& self
.tcx
.codegen_fn_attrs(child_item.id.owner_id)
.link_ordinal
.is_some()
for &child_item in foreign_items {
if self.tcx.def_kind(child_item).has_codegen_attrs()
&& self.tcx.codegen_fn_attrs(child_item).link_ordinal.is_some()
{
let link_ordinal_attr = self
.tcx
.hir()
.attrs(child_item.id.owner_id.into())
.iter()
.find(|a| a.has_name(sym::link_ordinal))
.unwrap();
let link_ordinal_attr =
self.tcx.get_attr(child_item, sym::link_ordinal).unwrap();
sess.emit_err(errors::LinkOrdinalRawDylib {
span: link_ordinal_attr.span,
});
@@ -384,7 +370,7 @@ impl<'tcx> Collector<'tcx> {
filename,
kind,
cfg,
foreign_module: Some(it.owner_id.to_def_id()),
foreign_module: Some(def_id.to_def_id()),
verbatim,
dll_imports,
});
@@ -476,10 +462,10 @@ impl<'tcx> Collector<'tcx> {
}
}

fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize {
fn i686_arg_list_size(&self, item: DefId) -> usize {
let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions(
self.tcx
.type_of(item.id.owner_id)
.type_of(item)
.instantiate_identity()
.fn_sig(self.tcx)
.inputs()
@@ -505,8 +491,10 @@ impl<'tcx> Collector<'tcx> {
&self,
abi: Abi,
import_name_type: Option<PeImportNameType>,
item: &hir::ForeignItemRef,
item: DefId,
) -> DllImport {
let span = self.tcx.def_span(item);

let calling_convention = if self.tcx.sess.target.arch == "x86" {
match abi {
Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C,
@@ -520,29 +508,29 @@ impl<'tcx> Collector<'tcx> {
DllCallingConvention::Vectorcall(self.i686_arg_list_size(item))
}
_ => {
self.tcx.sess.emit_fatal(errors::UnsupportedAbiI686 { span: item.span });
self.tcx.sess.emit_fatal(errors::UnsupportedAbiI686 { span });
}
}
} else {
match abi {
Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C,
_ => {
self.tcx.sess.emit_fatal(errors::UnsupportedAbi { span: item.span });
self.tcx.sess.emit_fatal(errors::UnsupportedAbi { span });
}
}
};

let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item.id.owner_id);
let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item);
let import_name_type = codegen_fn_attrs
.link_ordinal
.map_or(import_name_type, |ord| Some(PeImportNameType::Ordinal(ord)));

DllImport {
name: codegen_fn_attrs.link_name.unwrap_or(item.ident.name),
name: codegen_fn_attrs.link_name.unwrap_or(self.tcx.item_name(item)),
import_name_type,
calling_convention,
span: item.span,
is_fn: self.tcx.def_kind(item.id.owner_id).is_fn_like(),
span,
is_fn: self.tcx.def_kind(item).is_fn_like(),
}
}
}
6 changes: 2 additions & 4 deletions compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
@@ -403,10 +403,8 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
.contains(&id)
})
},
native_libraries: |tcx, LocalCrate| native_libs::collect(tcx),
foreign_modules: |tcx, LocalCrate| {
foreign_modules::collect(tcx).into_iter().map(|m| (m.def_id, m)).collect()
},
native_libraries: native_libs::collect,
foreign_modules: foreign_modules::collect,

// Returns a map from a sufficiently visible external item (i.e., an
// external item that is visible from at least one local module) to a
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
@@ -1579,7 +1579,7 @@ rustc_queries! {
}

/// Returns a list of all `extern` blocks of a crate.
query foreign_modules(_: CrateNum) -> &'tcx FxHashMap<DefId, ForeignModule> {
query foreign_modules(_: CrateNum) -> &'tcx FxIndexMap<DefId, ForeignModule> {
arena_cache
desc { "looking up the foreign modules of a linked crate" }
separate_provide_extern
2 changes: 2 additions & 0 deletions compiler/rustc_session/src/cstore.rs
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
use rustc_span::hygiene::{ExpnHash, ExpnId};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
use rustc_target::spec::Target;

use std::any::Any;
@@ -147,6 +148,7 @@ pub enum DllCallingConvention {
pub struct ForeignModule {
pub foreign_items: Vec<DefId>,
pub def_id: DefId,
pub abi: Abi,
}

#[derive(Copy, Clone, Debug, HashStable_Generic)]
2 changes: 1 addition & 1 deletion compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
@@ -1420,7 +1420,7 @@ pub fn build_session(
let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
let hash_kind = sopts.unstable_opts.src_hash_algorithm.unwrap_or_else(|| {
if target_cfg.is_like_msvc {
SourceFileHashAlgorithm::Sha1
SourceFileHashAlgorithm::Sha256
} else {
SourceFileHashAlgorithm::Md5
}
19 changes: 16 additions & 3 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
@@ -90,6 +90,19 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
}
v
}));
items.extend(doc.inlined_foreigns.iter().flat_map(|((_, renamed), (res, local_import_id))| {
let Some(def_id) = res.opt_def_id() else { return Vec::new() };
let name = renamed.unwrap_or_else(|| cx.tcx.item_name(def_id));
let import = cx.tcx.hir().expect_item(*local_import_id);
match import.kind {
hir::ItemKind::Use(path, kind) => {
let hir::UsePath { segments, span, .. } = *path;
let path = hir::Path { segments, res: *res, span };
clean_use_statement_inner(import, name, &path, kind, cx, &mut Default::default())
}
_ => unreachable!(),
}
}));
items.extend(doc.items.values().flat_map(|(item, renamed, _)| {
// Now we actually lower the imports, skipping everything else.
if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
@@ -2652,9 +2665,6 @@ fn clean_use_statement<'tcx>(
let mut items = Vec::new();
let hir::UsePath { segments, ref res, span } = *path;
for &res in res {
if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res {
continue;
}
let path = hir::Path { segments, res, span };
items.append(&mut clean_use_statement_inner(import, name, &path, kind, cx, inlined_names));
}
@@ -2669,6 +2679,9 @@ fn clean_use_statement_inner<'tcx>(
cx: &mut DocContext<'tcx>,
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
) -> Vec<Item> {
if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = path.res {
return Vec::new();
}
// We need this comparison because some imports (for std types for example)
// are "inserted" as well but directly by the compiler and they should not be
// taken into account.
39 changes: 25 additions & 14 deletions src/librustdoc/visit_ast.rs
Original file line number Diff line number Diff line change
@@ -35,6 +35,8 @@ pub(crate) struct Module<'hir> {
(LocalDefId, Option<Symbol>),
(&'hir hir::Item<'hir>, Option<Symbol>, Option<LocalDefId>),
>,
/// Same as for `items`.
pub(crate) inlined_foreigns: FxIndexMap<(DefId, Option<Symbol>), (Res, LocalDefId)>,
pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>,
}

@@ -54,6 +56,7 @@ impl Module<'_> {
import_id,
mods: Vec::new(),
items: FxIndexMap::default(),
inlined_foreigns: FxIndexMap::default(),
foreigns: Vec::new(),
}
}
@@ -272,21 +275,30 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
return false;
}

// For cross-crate impl inlining we need to know whether items are
// reachable in documentation -- a previously unreachable item can be
// made reachable by cross-crate inlining which we're checking here.
// (this is done here because we need to know this upfront).
if !ori_res_did.is_local() && !is_no_inline {
crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did);
return false;
}

let is_hidden = !document_hidden && tcx.is_doc_hidden(ori_res_did);
let Some(res_did) = ori_res_did.as_local() else {
return false;
// For cross-crate impl inlining we need to know whether items are
// reachable in documentation -- a previously unreachable item can be
// made reachable by cross-crate inlining which we're checking here.
// (this is done here because we need to know this upfront).
crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did);
if is_hidden {
return false;
}
// We store inlined foreign items otherwise, it'd mean that the `use` item would be kept
// around. It's not a problem unless this `use` imports both a local AND a foreign item.
// If a local item is inlined, its `use` is not supposed to still be around in `clean`,
// which would make appear the `use` in the generated documentation like the local item
// was not inlined even though it actually was.
self.modules
.last_mut()
.unwrap()
.inlined_foreigns
.insert((ori_res_did, renamed), (res, def_id));
return true;
};

let is_private = !self.cx.cache.effective_visibilities.is_directly_public(tcx, ori_res_did);
let is_hidden = !document_hidden && tcx.is_doc_hidden(ori_res_did);
let item = tcx.hir().get_by_def_id(res_did);

if !please_inline {
@@ -314,7 +326,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
return false;
}

let inlined = match tcx.hir().get_by_def_id(res_did) {
let inlined = match item {
// Bang macros are handled a bit on their because of how they are handled by the
// compiler. If they have `#[doc(hidden)]` and the re-export doesn't have
// `#[doc(inline)]`, then we don't inline it.
@@ -346,7 +358,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
};
self.view_item_stack.remove(&res_did);
if inlined {
self.cx.cache.inlined_items.insert(res_did.to_def_id());
self.cx.cache.inlined_items.insert(ori_res_did);
}
inlined
}
@@ -483,7 +495,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
continue;
}
}

self.add_to_current_mod(item, renamed, import_id);
}
}
25 changes: 25 additions & 0 deletions tests/rustdoc/issue-105735-overlapping-reexport-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Regression test to ensure that both `AtomicU8` items are displayed but not the re-export.

#![crate_name = "foo"]
#![no_std]

// @has 'foo/index.html'
// @has - '//*[@class="item-name"]/a[@class="type"]' 'AtomicU8'
// @has - '//*[@class="item-name"]/a[@class="constant"]' 'AtomicU8'
// We also ensure we don't have another item displayed.
// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 2
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Type Definitions'
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Constants'

mod other {
pub type AtomicU8 = ();
}

mod thing {
pub use crate::other::AtomicU8;

#[allow(non_upper_case_globals)]
pub const AtomicU8: () = ();
}

pub use crate::thing::AtomicU8;
21 changes: 21 additions & 0 deletions tests/rustdoc/issue-105735-overlapping-reexport.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Regression test to ensure that both `AtomicU8` items are displayed but not the re-export.

#![crate_name = "foo"]
#![no_std]

// @has 'foo/index.html'
// @has - '//*[@class="item-name"]/a[@class="struct"]' 'AtomicU8'
// @has - '//*[@class="item-name"]/a[@class="constant"]' 'AtomicU8'
// We also ensure we don't have another item displayed.
// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 2
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs'
// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Constants'

mod thing {
pub use core::sync::atomic::AtomicU8;

#[allow(non_upper_case_globals)]
pub const AtomicU8: () = ();
}

pub use crate::thing::AtomicU8;
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error: multiple declarations of external function `f` from library `foo.dll` hav
--> $DIR/multiple-declarations.rs:13:9
|
LL | fn f(x: i32);
| ^^^^^^^^^^^^^
| ^^^^^^^^^^^^

error: aborting due to previous error

2 changes: 1 addition & 1 deletion tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error: ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
--> $DIR/unsupported-abi.rs:6:5
|
LL | fn f(x: i32);
| ^^^^^^^^^^^^^
| ^^^^^^^^^^^^

error: aborting due to previous error

39 changes: 39 additions & 0 deletions tests/ui/traits/new-solver/alias-bound-preference.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// revisions: old next
//[next] compile-flags: -Ztrait-solver=next
// run-pass

// A test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/45.

trait Trait {
type Assoc: Into<u32>;
}
impl<T: Into<u32>> Trait for T {
type Assoc = T;
}
fn prefer_alias_bound_projection<T: Trait>(x: T::Assoc) {
// There are two possible types for `x`:
// - `u32` by using the "alias bound" of `<T as Trait>::Assoc`
// - `<T as Trait>::Assoc`, i.e. `u16`, by using `impl<T> From<T> for T`
//
// We infer the type of `x` to be `u32` here as it is highly likely
// that this is expected by the user.
let x = x.into();
assert_eq!(std::mem::size_of_val(&x), 4);
}

fn impl_trait() -> impl Into<u32> {
0u16
}

fn main() {
// There are two possible types for `x`:
// - `u32` by using the "alias bound" of `impl Into<u32>`
// - `impl Into<u32>`, i.e. `u16`, by using `impl<T> From<T> for T`
//
// We infer the type of `x` to be `u32` here as it is highly likely
// that this is expected by the user.
let x = impl_trait().into();
assert_eq!(std::mem::size_of_val(&x), 4);

prefer_alias_bound_projection::<u16>(1);
}