Skip to content

Commit 7b39afd

Browse files
committed
fix various bugs in EII (todo: absorb)
1 parent 77d29b0 commit 7b39afd

File tree

25 files changed

+281
-100
lines changed

25 files changed

+281
-100
lines changed

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
5959
let special_runtime_crate =
6060
tcx.is_panic_runtime(LOCAL_CRATE) || tcx.is_compiler_builtins(LOCAL_CRATE);
6161

62+
let eii_map = tcx.get_externally_implementable_item_impls(());
63+
6264
let mut reachable_non_generics: DefIdMap<_> = tcx
6365
.reachable_set(())
6466
.items()
@@ -99,6 +101,17 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
99101
return None;
100102
}
101103

104+
// We don't want to export EII shims. These are always created in final crates of a
105+
// compile graph. The are exported in the linker sense - other compilation units can access them.
106+
// But once we made a shim, we're the last one so we don't have to export downwards.
107+
// The reason we explicitly need to exclude these is that for dylibs (.so) we already
108+
// generate EII shims. However, these aren't always the final crate. However, in that
109+
// case the final crate will generate its own shim so we shouldn't export the existing
110+
// one from the dylib.
111+
if eii_map.contains_key(&def_id) {
112+
return None;
113+
}
114+
102115
if tcx.cross_crate_inlinable(def_id) { None } else { Some(def_id) }
103116
})
104117
.map(|def_id| {

compiler/rustc_const_eval/src/const_eval/fn_queries.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
3939
// If the function itself is not annotated with `const`, it may still be a `const fn`
4040
// if it resides in a const trait impl.
4141
parent_impl_or_trait_constness(tcx, def_id)
42+
} else if tcx.get_externally_implementable_item_impls(()).contains_key(&def_id) {
43+
hir::Constness::NotConst
4244
} else {
4345
tcx.dcx().span_bug(
4446
tcx.def_span(def_id),

compiler/rustc_hir_analysis/messages.ftl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
159159
hir_analysis_duplicate_precise_capture = cannot capture parameter `{$name}` twice
160160
.label = parameter captured again here
161161
162+
hir_analysis_eii_with_generics =
163+
#[{$eii_name}] cannot have generic parameters other than lifetimes
164+
.label = required by this attribute
165+
162166
hir_analysis_empty_specialization = specialization impl does not specialize any associated items
163167
.note = impl is a specialization of this impl
164168
@@ -295,10 +299,10 @@ hir_analysis_lifetime_not_captured = `impl Trait` captures lifetime parameter, b
295299
.param_label = this lifetime parameter is captured
296300
297301
hir_analysis_lifetimes_or_bounds_mismatch_on_eii =
298-
lifetime parameters or bounds `{$ident}` do not match the declaration
302+
lifetime parameters or bounds of `{$ident}` do not match the declaration
299303
.label = lifetimes do not match
300304
.generics_label = lifetimes in impl do not match this signature
301-
.where_label = this `where` clause might not match the one in the trait
305+
.where_label = this `where` clause might not match the one in the declaration
302306
.bounds_label = this bound might be missing in the implementation
303307
304308
hir_analysis_lifetimes_or_bounds_mismatch_on_trait =

compiler/rustc_hir_analysis/src/check/compare_eii.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_trait_selection::traits::ObligationCtxt;
1616
use tracing::{debug, instrument};
1717

1818
use super::potentially_plural_count;
19-
use crate::errors::LifetimesOrBoundsMismatchOnEII;
19+
use crate::errors::{EiiWithGenerics, LifetimesOrBoundsMismatchOnEII};
2020

2121
/// Checks a bunch of different properties of the impl/trait methods for
2222
/// compatibility, such as asyncness, number of argument, self receiver kind,
@@ -28,12 +28,31 @@ fn check_is_structurally_compatible<'tcx>(
2828
eii_name: Symbol,
2929
eii_attr_span: Span,
3030
) -> Result<(), ErrorGuaranteed> {
31-
// FIXME(jdonszelmann): check no generics
31+
check_no_generics(tcx, external_impl, declaration, eii_name, eii_attr_span)?;
3232
compare_number_of_method_arguments(tcx, external_impl, declaration, eii_name, eii_attr_span)?;
3333
check_region_bounds_on_impl_item(tcx, external_impl, declaration, eii_attr_span)?;
3434
Ok(())
3535
}
3636

37+
fn check_no_generics<'tcx>(
38+
tcx: TyCtxt<'tcx>,
39+
external_impl: LocalDefId,
40+
_declaration: DefId,
41+
eii_name: Symbol,
42+
eii_attr_span: Span,
43+
) -> Result<(), ErrorGuaranteed> {
44+
let generics = tcx.generics_of(external_impl);
45+
if generics.own_requires_monomorphization() {
46+
tcx.dcx().emit_err(EiiWithGenerics {
47+
span: tcx.def_span(external_impl),
48+
attr: eii_attr_span,
49+
eii_name,
50+
});
51+
}
52+
53+
Ok(())
54+
}
55+
3756
fn check_region_bounds_on_impl_item<'tcx>(
3857
tcx: TyCtxt<'tcx>,
3958
external_impl: LocalDefId,
@@ -268,6 +287,8 @@ pub(crate) fn compare_eii_function_types<'tcx>(
268287
terr,
269288
(declaration, declaration_sig),
270289
(external_impl, external_impl_sig),
290+
eii_attr_span,
291+
eii_name,
271292
);
272293
return Err(emitted);
273294
}
@@ -299,6 +320,8 @@ fn report_eii_mismatch<'tcx>(
299320
terr: TypeError<'tcx>,
300321
(declaration_did, declaration_sig): (DefId, ty::FnSig<'tcx>),
301322
(external_impl_did, external_impl_sig): (LocalDefId, ty::FnSig<'tcx>),
323+
eii_attr_span: Span,
324+
eii_name: Symbol,
302325
) -> ErrorGuaranteed {
303326
let tcx = infcx.tcx;
304327
let (impl_err_span, trait_err_span, external_impl_name) =
@@ -308,9 +331,12 @@ fn report_eii_mismatch<'tcx>(
308331
tcx.dcx(),
309332
impl_err_span,
310333
E0053, // TODO: new error code
311-
"function `{}` has a type that is incompatible with the declaration",
334+
"function `{}` has a type that is incompatible with the declaration of `#[{eii_name}]`",
312335
external_impl_name
313336
);
337+
338+
diag.span_note(eii_attr_span, "expected this because of this attribute");
339+
314340
match &terr {
315341
TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
316342
if declaration_sig.inputs().len() == *i {

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgK
3333
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
3434
use rustc_infer::traits::ObligationCause;
3535
use rustc_middle::hir::nested_filter;
36+
use rustc_middle::middle::eii::EiiMapping;
3637
use rustc_middle::query::Providers;
3738
use rustc_middle::ty::util::{Discr, IntTypeExt};
3839
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode, fold_regions};
@@ -1372,6 +1373,16 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
13721373
bug!("to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",);
13731374
}
13741375

1376+
x @ Synthetic => {
1377+
if let Some(EiiMapping { extern_item, .. }) =
1378+
tcx.get_externally_implementable_item_impls(()).get(&def_id)
1379+
{
1380+
return tcx.fn_sig(extern_item);
1381+
} else {
1382+
bug!("unexpected sort of node in fn_sig(): {:?}", x);
1383+
}
1384+
}
1385+
13751386
x => {
13761387
bug!("unexpected sort of node in fn_sig(): {:?}", x);
13771388
}

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,16 @@ pub(crate) struct LifetimesOrBoundsMismatchOnEII {
222222
pub ident: Symbol,
223223
}
224224

225+
#[derive(Diagnostic)]
226+
#[diag(hir_analysis_eii_with_generics)]
227+
pub(crate) struct EiiWithGenerics {
228+
#[primary_span]
229+
pub span: Span,
230+
#[label]
231+
pub attr: Span,
232+
pub eii_name: Symbol,
233+
}
234+
225235
#[derive(Diagnostic)]
226236
#[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)]
227237
pub(crate) struct DropImplOnWrongItem {

compiler/rustc_middle/src/arena.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ macro_rules! arena_types {
115115
[decode] specialization_graph: rustc_middle::traits::specialization_graph::Graph,
116116
[] crate_inherent_impls: rustc_middle::ty::CrateInherentImpls,
117117
[] hir_owner_nodes: rustc_hir::OwnerNodes<'tcx>,
118-
[] get_externally_implementable_item_impls: rustc_data_structures::fx::FxIndexMap<rustc_hir::def_id::DefId, (rustc_hir::def_id::DefId, rustc_hir::def_id::LocalDefId)>,
118+
[] get_externally_implementable_item_impls: rustc_middle::middle::eii::EiiMap,
119119
]);
120120
)
121121
}

compiler/rustc_middle/src/hir/map.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym, with_metavar_spa
1919

2020
use crate::hir::{ModuleItems, nested_filter};
2121
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
22+
use crate::middle::eii::EiiMapping;
2223
use crate::query::LocalCrate;
2324
use crate::ty::TyCtxt;
2425

@@ -1027,7 +1028,15 @@ impl<'tcx> TyCtxt<'tcx> {
10271028
Node::Crate(item) => item.spans.inner_span,
10281029
Node::WherePredicate(pred) => pred.span,
10291030
Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span,
1030-
Node::Synthetic => unreachable!(),
1031+
Node::Synthetic => {
1032+
if let Some(EiiMapping { chosen_impl, .. }) =
1033+
self.tcx.get_externally_implementable_item_impls(()).get(&hir_id.owner.def_id)
1034+
{
1035+
self.tcx.def_span(chosen_impl)
1036+
} else {
1037+
unreachable!()
1038+
}
1039+
}
10311040
Node::Err(span) => span,
10321041
}
10331042
}

compiler/rustc_middle/src/hir/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_hir::*;
1616
use rustc_macros::{Decodable, Encodable, HashStable};
1717
use rustc_span::{ErrorGuaranteed, ExpnId, Span};
1818

19+
use crate::middle::eii::EiiMapping;
1920
use crate::query::Providers;
2021
use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
2122

@@ -223,6 +224,10 @@ pub fn provide(providers: &mut Providers) {
223224
}) = tcx.hir_node(tcx.local_def_id_to_hir_id(def_id))
224225
{
225226
idents
227+
} else if let Some(EiiMapping { chosen_impl, .. }) =
228+
tcx.get_externally_implementable_item_impls(()).get(&def_id)
229+
{
230+
tcx.fn_arg_names(chosen_impl)
226231
} else {
227232
span_bug!(
228233
tcx.hir_span(tcx.local_def_id_to_hir_id(def_id)),
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use rustc_data_structures::fx::FxIndexMap;
2+
use rustc_hir::def_id::{DefId, LocalDefId};
3+
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
4+
5+
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
6+
#[derive(TyEncodable, TyDecodable, HashStable)]
7+
pub struct EiiMapping {
8+
pub extern_item: DefId,
9+
pub chosen_impl: DefId,
10+
}
11+
12+
pub type EiiMap = FxIndexMap<LocalDefId, EiiMapping>;

compiler/rustc_middle/src/middle/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub mod lib_features {
3030
}
3131
}
3232
}
33+
pub mod eii;
3334
pub mod privacy;
3435
pub mod region;
3536
pub mod resolve_bound_vars;

compiler/rustc_middle/src/mir/mono.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,11 @@ impl<'tcx> MonoItem<'tcx> {
181181
return opt_incr_drop_glue_mode(tcx, ty);
182182
}
183183

184-
// eii shims are only generated in the final crate.
185-
// As such, they will be both globally shared and unique.
184+
// Eii shims are only generated in the final crate because we need to resolve defaults.
185+
// Specifically, only when making the final crate we know whether there was an explicit
186+
// implementation given *somewhere* and if not we then have to decide whether there is
187+
// a default which we need to insert. That default needs to be shared between all
188+
// dependencies; hence globally shared.
186189
if let InstanceKind::EiiShim { .. } = instance.def {
187190
return InstantiationMode::GloballyShared { may_conflict: false };
188191
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ use crate::lint::LintExpectation;
5252
use crate::metadata::ModChild;
5353
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
5454
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
55+
use crate::middle::eii::EiiMap;
5556
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
5657
use crate::middle::lib_features::LibFeatures;
5758
use crate::middle::privacy::EffectiveVisibilities;
@@ -1105,7 +1106,7 @@ rustc_queries! {
11051106
desc { |tcx| "checking loops in {}", describe_as_module(key, tcx) }
11061107
}
11071108

1108-
query get_externally_implementable_item_impls(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexMap<DefId, (DefId, LocalDefId)> {
1109+
query get_externally_implementable_item_impls(_: ()) -> &'tcx EiiMap {
11091110
desc { "check externally implementable items" }
11101111
}
11111112

@@ -1711,11 +1712,6 @@ rustc_queries! {
17111712
desc { "checking if the crate has_alloc_error_handler" }
17121713
separate_provide_extern
17131714
}
1714-
query has_panic_handler(_: CrateNum) -> bool {
1715-
fatal_cycle
1716-
desc { "checking if the crate has_panic_handler" }
1717-
separate_provide_extern
1718-
}
17191715
query is_profiler_runtime(_: CrateNum) -> bool {
17201716
fatal_cycle
17211717
desc { "checking if a crate is `#![profiler_runtime]`" }

compiler/rustc_middle/src/ty/context.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3370,10 +3370,6 @@ pub fn provide(providers: &mut Providers) {
33703370
|tcx, LocalCrate| contains_name(tcx.hir_krate_attrs(), sym::panic_runtime);
33713371
providers.is_compiler_builtins =
33723372
|tcx, LocalCrate| contains_name(tcx.hir_krate_attrs(), sym::compiler_builtins);
3373-
providers.has_panic_handler = |tcx, LocalCrate| {
3374-
// We want to check if the panic handler was defined in this crate
3375-
tcx.lang_items().panic_impl().is_some_and(|did| did.is_local())
3376-
};
33773373
providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
33783374
}
33793375

compiler/rustc_mir_transform/src/shim.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,22 +78,29 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
7878
receiver_by_ref,
7979
} => build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id, receiver_by_ref),
8080

81-
e @ ty::InstanceKind::EiiShim { def_id: _, extern_item: _, chosen_impl } => {
81+
e @ ty::InstanceKind::EiiShim { def_id: _, extern_item, chosen_impl } => {
8282
let source = MirSource::from_instance(e);
8383

84-
let fn_sig = tcx.fn_sig(chosen_impl).instantiate_identity().skip_binder();
85-
let func_ty = Ty::new_fn_def(tcx, chosen_impl, GenericArgs::empty());
84+
// get the signature for the new function this shim is creating
85+
let shim_fn_sig = tcx.fn_sig(extern_item).instantiate_identity();
86+
let shim_fn_sig = tcx.instantiate_bound_regions_with_erased(shim_fn_sig);
8687

8788
let span = tcx.def_span(chosen_impl);
8889
let source_info = SourceInfo::outermost(span);
8990

91+
// we want to generate a call to this function
92+
let args = ty::GenericArgs::identity_for_item(tcx, chosen_impl);
93+
let chosen_fn_ty = Ty::new_fn_def(tcx, chosen_impl, args);
94+
9095
let func = Operand::Constant(Box::new(ConstOperand {
9196
span,
9297
user_ty: None,
93-
const_: Const::zero_sized(func_ty),
98+
const_: Const::zero_sized(chosen_fn_ty),
9499
}));
95100

96-
let locals = local_decls_for_sig(&fn_sig, span);
101+
// println!("generating EII shim for extern item {extern_item:?} and impl {chosen_impl:?}");
102+
103+
let locals = local_decls_for_sig(&shim_fn_sig, span);
97104
let mut blocks = IndexVec::new();
98105

99106
let return_block = BasicBlock::new(1);
@@ -126,7 +133,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
126133
is_cleanup: false,
127134
});
128135

129-
new_body(source, blocks, locals, fn_sig.inputs().len(), span)
136+
new_body(source, blocks, locals, shim_fn_sig.inputs().len(), span)
130137
}
131138

132139
ty::InstanceKind::DropGlue(def_id, ty) => {

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@
207207
208208
use std::path::PathBuf;
209209

210-
use rustc_attr_parsing::{AttributeKind, EIIDecl, InlineAttr, find_attr};
210+
use rustc_attr_parsing::InlineAttr;
211211
use rustc_data_structures::fx::FxIndexMap;
212212
use rustc_data_structures::sync::{MTLock, par_for_each_in};
213213
use rustc_data_structures::unord::{UnordMap, UnordSet};
@@ -216,6 +216,7 @@ use rustc_hir::def::DefKind;
216216
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
217217
use rustc_hir::lang_items::LangItem;
218218
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
219+
use rustc_middle::middle::eii::EiiMapping;
219220
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, GlobalAlloc, Scalar};
220221
use rustc_middle::mir::mono::{CollectionMode, InstantiationMode, MonoItem};
221222
use rustc_middle::mir::visit::Visitor as MirVisitor;
@@ -1593,26 +1594,20 @@ impl<'v> RootCollector<'_, 'v> {
15931594
/// For each externally implementable item, we should generate an alias MonoItem that
15941595
/// determines what implementation is called. This could be a default implementation.
15951596
fn push_extra_eii_roots(&mut self) {
1596-
for (decl, (chosen_impl, shim_did)) in self.tcx.get_externally_implementable_item_impls(())
1597+
for (shim_did, &EiiMapping { extern_item, chosen_impl, .. }) in
1598+
self.tcx.get_externally_implementable_item_impls(())
15971599
{
1598-
let Some((eii_extern_item, span)) = find_attr!(
1599-
self.tcx.get_all_attrs(*decl),
1600-
AttributeKind::EiiMacroFor(EIIDecl { eii_extern_item, span, .. }) => (*eii_extern_item, *span)
1601-
) else {
1602-
bug!("missing attr on EII macro");
1603-
};
1604-
16051600
self.output.push(create_fn_mono_item(
16061601
self.tcx,
16071602
ty::Instance {
16081603
def: ty::InstanceKind::EiiShim {
16091604
def_id: (*shim_did).into(),
1610-
extern_item: eii_extern_item,
1611-
chosen_impl: *chosen_impl,
1605+
extern_item,
1606+
chosen_impl,
16121607
},
16131608
args: ty::GenericArgs::empty(),
16141609
},
1615-
span,
1610+
DUMMY_SP,
16161611
));
16171612
}
16181613
}

0 commit comments

Comments
 (0)