Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2afe5b1
Fix ICE in inline always warning emission.
JamieCunliffe Jan 8, 2026
45e0fbf
Implement partial_sort_unstable for slice
tisonkun Jan 9, 2026
97fc739
std: sys: fs: uefi: Implement File::tell
Ayush1325 Jan 9, 2026
3c8265a
add test for 149981
jdonszelmann Dec 19, 2025
5e5c724
turn panics into `span_delayed_bug` to make sure this pattern doesn't…
jdonszelmann Dec 19, 2025
e3cff18
dont resolve defaults anymore, store foreign item defid instead of macro
jdonszelmann Jan 8, 2026
5ddda0c
fix up diagnostics referring to the right items
jdonszelmann Jan 8, 2026
52b3ac4
trick with super imports that fixes nameres in anonymous modules
jdonszelmann Jan 8, 2026
7791bc2
mark ICE regression test as fixed
jdonszelmann Jan 8, 2026
2cde8d9
Fix std::fs::copy on WASI by setting proper OpenOptions flags
cdmurph32 Jan 9, 2026
43c1db7
Run clippy
cdmurph32 Jan 9, 2026
fd59b32
std: sys: fs: uefi: Implement File::read
Ayush1325 Jan 9, 2026
0401e79
Fix a trivial typo
Daniel-B-Smith Jan 9, 2026
9d2ce87
Don't check `[mentions]` paths in submodules from tidy
Urgau Jan 9, 2026
8e61f0d
cg_llvm: add a pause to make comment less confusing
tshepang Jan 9, 2026
229673a
make sentence more simple
tshepang Jan 9, 2026
65c0847
Rollup merge of #149318 - slice_partial_sort_unstable, r=tgross35
Urgau Jan 9, 2026
3bb7de6
Rollup merge of #150805 - fix-def-path-ice, r=davidtwco
Urgau Jan 9, 2026
a8028ab
Rollup merge of #150822 - fix-149981, r=@Kivooeo
Urgau Jan 9, 2026
93f6171
Rollup merge of #150853 - uefi-fs-read, r=joboet
Urgau Jan 9, 2026
92b9e84
Rollup merge of #150855 - uefi-fs-tell, r=joboet
Urgau Jan 9, 2026
c2f0209
Rollup merge of #150881 - fix-wasi-fs-copy, r=alexcrichton
Urgau Jan 9, 2026
f44b516
Rollup merge of #150891 - def-id-typo, r=Kivooeo
Urgau Jan 9, 2026
90de6e5
Rollup merge of #150892 - tidy-triagebot-mentions-submodules, r=tgross35
Urgau Jan 9, 2026
2b8d078
Rollup merge of #150894 - patch-1, r=mati865
Urgau Jan 9, 2026
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
16 changes: 14 additions & 2 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2117,10 +2117,9 @@ pub struct MacroDef {

#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic, Walkable)]
pub struct EiiExternTarget {
/// path to the extern item we're targetting
/// path to the extern item we're targeting
pub extern_item_path: Path,
pub impl_unsafe: bool,
pub span: Span,
}

#[derive(Clone, Encodable, Decodable, Debug, Copy, Hash, Eq, PartialEq)]
Expand Down Expand Up @@ -3813,6 +3812,19 @@ pub struct Fn {
pub struct EiiImpl {
pub node_id: NodeId,
pub eii_macro_path: Path,
/// This field is an implementation detail that prevents a lot of bugs.
/// See <https://github.com/rust-lang/rust/issues/149981> for an example.
///
/// The problem is, that if we generate a declaration *together* with its default,
/// we generate both a declaration and an implementation. The generated implementation
/// uses the same mechanism to register itself as a user-defined implementation would,
/// despite being invisible to users. What does happen is a name resolution step.
/// The invisible default implementation has to find the declaration.
/// Both are generated at the same time, so we can skip that name resolution step.
///
/// This field is that shortcut: we prefill the extern target to skip a name resolution step,
/// making sure it never fails. It'd be awful UX if we fail name resolution in code invisible to the user.
pub known_eii_macro_resolution: Option<EiiExternTarget>,
pub impl_safety: Safety,
pub span: Span,
pub inner_span: Span,
Expand Down
97 changes: 56 additions & 41 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use rustc_abi::ExternAbi;
use rustc_ast::visit::AssocCtxt;
use rustc_ast::*;
use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
use rustc_hir::attrs::{AttributeKind, EiiDecl};
use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImplResolution};
use rustc_hir::def::{DefKind, PerNS, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_hir::{
Expand Down Expand Up @@ -134,6 +134,56 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

fn lower_eii_extern_target(
&mut self,
id: NodeId,
eii_name: Ident,
EiiExternTarget { extern_item_path, impl_unsafe }: &EiiExternTarget,
) -> Option<EiiDecl> {
self.lower_path_simple_eii(id, extern_item_path).map(|did| EiiDecl {
eii_extern_target: did,
impl_unsafe: *impl_unsafe,
name: eii_name,
})
}

fn lower_eii_impl(
&mut self,
EiiImpl {
node_id,
eii_macro_path,
impl_safety,
span,
inner_span,
is_default,
known_eii_macro_resolution,
}: &EiiImpl,
) -> hir::attrs::EiiImpl {
let resolution = if let Some(target) = known_eii_macro_resolution
&& let Some(decl) = self.lower_eii_extern_target(
*node_id,
// the expect is ok here since we always generate this path in the eii macro.
eii_macro_path.segments.last().expect("at least one segment").ident,
target,
) {
EiiImplResolution::Known(decl)
} else if let Some(macro_did) = self.lower_path_simple_eii(*node_id, eii_macro_path) {
EiiImplResolution::Macro(macro_did)
} else {
EiiImplResolution::Error(
self.dcx().span_delayed_bug(*span, "eii never resolved without errors given"),
)
};

hir::attrs::EiiImpl {
span: self.lower_span(*span),
inner_span: self.lower_span(*inner_span),
impl_marked_unsafe: self.lower_safety(*impl_safety, hir::Safety::Safe).is_unsafe(),
is_default: *is_default,
resolution,
}
}

fn generate_extra_attrs_for_item_kind(
&mut self,
id: NodeId,
Expand All @@ -143,49 +193,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::Fn(box Fn { eii_impls, .. }) if eii_impls.is_empty() => Vec::new(),
ItemKind::Fn(box Fn { eii_impls, .. }) => {
vec![hir::Attribute::Parsed(AttributeKind::EiiImpls(
eii_impls
.iter()
.flat_map(
|EiiImpl {
node_id,
eii_macro_path,
impl_safety,
span,
inner_span,
is_default,
}| {
self.lower_path_simple_eii(*node_id, eii_macro_path).map(|did| {
hir::attrs::EiiImpl {
eii_macro: did,
span: self.lower_span(*span),
inner_span: self.lower_span(*inner_span),
impl_marked_unsafe: self
.lower_safety(*impl_safety, hir::Safety::Safe)
.is_unsafe(),
is_default: *is_default,
}
})
},
)
.collect(),
eii_impls.iter().map(|i| self.lower_eii_impl(i)).collect(),
))]
}
ItemKind::MacroDef(
_,
MacroDef {
eii_extern_target: Some(EiiExternTarget { extern_item_path, impl_unsafe, span }),
..
},
) => self
.lower_path_simple_eii(id, extern_item_path)
.map(|did| {
vec![hir::Attribute::Parsed(AttributeKind::EiiExternTarget(EiiDecl {
eii_extern_target: did,
impl_unsafe: *impl_unsafe,
span: self.lower_span(*span),
}))]
})
ItemKind::MacroDef(name, MacroDef { eii_extern_target: Some(target), .. }) => self
.lower_eii_extern_target(id, *name, target)
.map(|decl| vec![hir::Attribute::Parsed(AttributeKind::EiiExternTarget(decl))])
.unwrap_or_default(),

ItemKind::ExternCrate(..)
| ItemKind::Use(..)
| ItemKind::Static(..)
Expand Down
83 changes: 73 additions & 10 deletions compiler/rustc_builtin_macros/src/eii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,19 @@ fn eii_(

// span of the declaring item without attributes
let item_span = func.sig.span;
// span of the eii attribute and the item below it, i.e. the full declaration
let decl_span = eii_attr_span.to(item_span);
let foreign_item_name = func.ident;

let mut return_items = Vec::new();

if func.body.is_some() {
return_items.push(Box::new(generate_default_impl(
ecx,
&func,
impl_unsafe,
macro_name,
eii_attr_span,
item_span,
foreign_item_name,
)))
}

Expand All @@ -133,7 +133,6 @@ fn eii_(
macro_name,
foreign_item_name,
impl_unsafe,
decl_span,
)));

return_items.into_iter().map(wrap_item).collect()
Expand Down Expand Up @@ -187,11 +186,13 @@ fn filter_attrs_for_multiple_eii_attr(
}

fn generate_default_impl(
ecx: &mut ExtCtxt<'_>,
func: &ast::Fn,
impl_unsafe: bool,
macro_name: Ident,
eii_attr_span: Span,
item_span: Span,
foreign_item_name: Ident,
) -> ast::Item {
// FIXME: re-add some original attrs
let attrs = ThinVec::new();
Expand All @@ -208,6 +209,21 @@ fn generate_default_impl(
},
span: eii_attr_span,
is_default: true,
known_eii_macro_resolution: Some(ast::EiiExternTarget {
extern_item_path: ast::Path {
span: foreign_item_name.span,
segments: thin_vec![
ast::PathSegment {
ident: Ident::from_str_and_span("super", foreign_item_name.span,),
id: DUMMY_NODE_ID,
args: None
},
ast::PathSegment { ident: foreign_item_name, id: DUMMY_NODE_ID, args: None },
],
tokens: None,
},
impl_unsafe,
}),
});

ast::Item {
Expand Down Expand Up @@ -236,18 +252,66 @@ fn generate_default_impl(
stmts: thin_vec![ast::Stmt {
id: DUMMY_NODE_ID,
kind: ast::StmtKind::Item(Box::new(ast::Item {
attrs,
attrs: ThinVec::new(),
id: DUMMY_NODE_ID,
span: item_span,
vis: ast::Visibility {
span: eii_attr_span,
span: item_span,
kind: ast::VisibilityKind::Inherited,
tokens: None
},
kind: ItemKind::Fn(Box::new(default_func)),
kind: ItemKind::Mod(
ast::Safety::Default,
Ident::from_str_and_span("dflt", item_span),
ast::ModKind::Loaded(
thin_vec![
Box::new(ast::Item {
attrs: thin_vec![ecx.attr_nested_word(
sym::allow,
sym::unused_imports,
item_span
),],
id: DUMMY_NODE_ID,
span: item_span,
vis: ast::Visibility {
span: eii_attr_span,
kind: ast::VisibilityKind::Inherited,
tokens: None
},
kind: ItemKind::Use(ast::UseTree {
prefix: ast::Path::from_ident(
Ident::from_str_and_span(
"super", item_span,
)
),
kind: ast::UseTreeKind::Glob,
span: item_span,
}),
tokens: None,
}),
Box::new(ast::Item {
attrs,
id: DUMMY_NODE_ID,
span: item_span,
vis: ast::Visibility {
span: eii_attr_span,
kind: ast::VisibilityKind::Inherited,
tokens: None
},
kind: ItemKind::Fn(Box::new(default_func)),
tokens: None,
}),
],
ast::Inline::Yes,
ast::ModSpans {
inner_span: item_span,
inject_use_span: item_span,
}
)
),
tokens: None,
})),
span: eii_attr_span
span: eii_attr_span,
}],
id: DUMMY_NODE_ID,
rules: ast::BlockCheckMode::Default,
Expand Down Expand Up @@ -352,7 +416,6 @@ fn generate_attribute_macro_to_implement(
macro_name: Ident,
foreign_item_name: Ident,
impl_unsafe: bool,
decl_span: Span,
) -> ast::Item {
let mut macro_attrs = ThinVec::new();

Expand Down Expand Up @@ -394,7 +457,6 @@ fn generate_attribute_macro_to_implement(
eii_extern_target: Some(ast::EiiExternTarget {
extern_item_path: ast::Path::from_ident(foreign_item_name),
impl_unsafe,
span: decl_span,
}),
},
),
Expand Down Expand Up @@ -451,7 +513,7 @@ pub(crate) fn eii_extern_target(
false
};

d.eii_extern_target = Some(EiiExternTarget { extern_item_path, impl_unsafe, span });
d.eii_extern_target = Some(EiiExternTarget { extern_item_path, impl_unsafe });

// Return the original item and the new methods.
vec![item]
Expand Down Expand Up @@ -508,6 +570,7 @@ pub(crate) fn eii_shared_macro(
impl_safety: meta_item.unsafety,
span,
is_default,
known_eii_macro_resolution: None,
});

vec![item]
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_llvm/src/mono_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ impl CodegenCx<'_, '_> {
}
}

/// Whether a definition or declaration can be assumed to be local to a group of
/// A definition or declaration can be assumed to be local to a group of
/// libraries that form a single DSO or executable.
/// Marks the local as DSO if so.
pub(crate) fn assume_dso_local(&self, llval: &llvm::Value, is_declaration: bool) -> bool {
Expand Down Expand Up @@ -153,7 +153,7 @@ impl CodegenCx<'_, '_> {
return false;
}

// With pie relocation model calls of functions defined in the translation
// With pie relocation model, calls of functions defined in the translation
// unit can use copy relocations.
if self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration {
return true;
Expand Down
28 changes: 21 additions & 7 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use std::str::FromStr;
use rustc_abi::{Align, ExternAbi};
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
use rustc_hir::attrs::{AttributeKind, InlineAttr, Linkage, RtsanSetting, UsedBy};
use rustc_hir::attrs::{
AttributeKind, EiiImplResolution, InlineAttr, Linkage, RtsanSetting, UsedBy,
};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items};
Expand Down Expand Up @@ -285,11 +287,23 @@ fn process_builtin_attrs(
}
AttributeKind::EiiImpls(impls) => {
for i in impls {
let extern_item = find_attr!(
tcx.get_all_attrs(i.eii_macro),
AttributeKind::EiiExternTarget(target) => target.eii_extern_target
)
.expect("eii should have declaration macro with extern target attribute");
let extern_item = match i.resolution {
EiiImplResolution::Macro(def_id) => {
let Some(extern_item) = find_attr!(
tcx.get_all_attrs(def_id),
AttributeKind::EiiExternTarget(target) => target.eii_extern_target
) else {
tcx.dcx().span_delayed_bug(
i.span,
"resolved to something that's not an EII",
);
continue;
};
extern_item
}
EiiImplResolution::Known(decl) => decl.eii_extern_target,
EiiImplResolution::Error(_eg) => continue,
};

// this is to prevent a bug where a single crate defines both the default and explicit implementation
// for an EII. In that case, both of them may be part of the same final object file. I'm not 100% sure
Expand All @@ -302,7 +316,7 @@ fn process_builtin_attrs(
// iterate over all implementations *in the current crate*
// (this is ok since we generate codegen fn attrs in the local crate)
// if any of them is *not default* then don't emit the alias.
&& tcx.externally_implementable_items(LOCAL_CRATE).get(&i.eii_macro).expect("at least one").1.iter().any(|(_, imp)| !imp.is_default)
&& tcx.externally_implementable_items(LOCAL_CRATE).get(&extern_item).expect("at least one").1.iter().any(|(_, imp)| !imp.is_default)
{
continue;
}
Expand Down
Loading
Loading