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>;

0 commit comments

Comments
 (0)