1use std::borrow::Cow;
7use std::iter;
8
9use rustc_attr_ir::{EiiImplResolution, find_attr};
10use rustc_data_structures::fx::FxIndexSet;
11use rustc_errors::{Applicability, E0806, struct_span_code_err};
12use rustc_hir::def::DefKind;
13use rustc_hir::def_id::{DefId, LocalDefId};
14use rustc_hir::{self as hir, FnSig, HirId, ItemKind};
15use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
16use rustc_infer::traits::{ObligationCause, ObligationCauseCode, TraitErrors};
17use rustc_middle::ty::error::{ExpectedFound, TypeError};
18use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized};
19use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
20use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
21use rustc_trait_selection::regions::InferCtxtRegionExt;
22use rustc_trait_selection::traits::{self, ObligationCtxt};
23use tracing::{debug, instrument};
24
25use super::potentially_plural_count;
26use crate::check::compare_impl_item::{
27 CheckNumberOfEarlyBoundRegionsError, check_number_of_early_bound_regions,
28};
29use crate::diagnostics::{
30 EiiDefkindMismatch, EiiDefkindMismatchStaticMutability, EiiDefkindMismatchStaticSafety,
31 EiiWithGenerics, LifetimesOrBoundsMismatchOnEii,
32};
33
34pub(crate) fn compare_eii_function_types<'tcx>(
38 tcx: TyCtxt<'tcx>,
39 external_impl: LocalDefId,
40 foreign_item: DefId,
41 eii_name: Symbol,
42 eii_attr_span: Span,
43) -> Result<(), ErrorGuaranteed> {
44 if tcx.generics_of(foreign_item).own_requires_monomorphization() {
46 return Err(tcx.dcx().delayed_bug("compared an EII impl against a generic declaration"));
47 }
48 check_eii_target(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?;
49 check_is_structurally_compatible(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?;
50
51 let external_impl_span = tcx.def_span(external_impl);
52 let cause = ObligationCause::new(
53 external_impl_span,
54 external_impl,
55 ObligationCauseCode::CompareEii { external_impl, declaration: foreign_item },
56 );
57
58 let param_env = tcx.param_env(foreign_item);
60
61 let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
62 let ocx = ObligationCtxt::new_with_diagnostics(infcx);
63
64 let mut wf_tys = FxIndexSet::default();
73 let norm_cause = ObligationCause::misc(external_impl_span, external_impl);
74
75 let declaration_sig = tcx.fn_sig(foreign_item).instantiate_identity().skip_norm_wip();
76 let declaration_sig = tcx.liberate_late_bound_regions(external_impl.into(), declaration_sig);
77 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_hir_analysis/src/check/compare_eii.rs:77",
"rustc_hir_analysis::check::compare_eii",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_hir_analysis/src/check/compare_eii.rs"),
::tracing_core::__macro_support::Option::Some(77u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::check::compare_eii"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("declaration_sig")
}> =
::tracing::__macro_support::FieldName::new("declaration_sig");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&declaration_sig)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?declaration_sig);
78
79 let unnormalized_external_impl_sig = infcx.instantiate_binder_with_fresh_vars(
80 external_impl_span,
81 infer::BoundRegionConversionTime::HigherRankedType,
82 tcx.fn_sig(external_impl)
83 .instantiate(
84 tcx,
85 infcx.fresh_args_for_item(external_impl_span, external_impl.to_def_id()),
86 )
87 .skip_norm_wip(),
88 );
89 let external_impl_sig = ocx.normalize(
90 &norm_cause,
91 param_env,
92 Unnormalized::new_wip(unnormalized_external_impl_sig),
93 );
94 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_hir_analysis/src/check/compare_eii.rs:94",
"rustc_hir_analysis::check::compare_eii",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_hir_analysis/src/check/compare_eii.rs"),
::tracing_core::__macro_support::Option::Some(94u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::check::compare_eii"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("external_impl_sig")
}> =
::tracing::__macro_support::FieldName::new("external_impl_sig");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&external_impl_sig)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?external_impl_sig);
95
96 wf_tys.extend(declaration_sig.inputs_and_output.iter());
100 let declaration_sig =
101 ocx.normalize(&norm_cause, param_env, Unnormalized::new_wip(declaration_sig));
102 wf_tys.extend(external_impl_sig.inputs_and_output.iter());
105
106 let result = ocx.sup(&cause, param_env, declaration_sig, external_impl_sig);
114
115 if let Err(terr) = result {
116 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_hir_analysis/src/check/compare_eii.rs:116",
"rustc_hir_analysis::check::compare_eii",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_hir_analysis/src/check/compare_eii.rs"),
::tracing_core::__macro_support::Option::Some(116u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::check::compare_eii"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("external_impl_sig")
}> =
::tracing::__macro_support::FieldName::new("external_impl_sig");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("declaration_sig")
}> =
::tracing::__macro_support::FieldName::new("declaration_sig");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("terr")
}> =
::tracing::__macro_support::FieldName::new("terr");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("sub_types failed")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&external_impl_sig)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&declaration_sig)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&terr)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?external_impl_sig, ?declaration_sig, ?terr, "sub_types failed");
117
118 let emitted = report_eii_mismatch(
119 infcx,
120 cause,
121 param_env,
122 terr,
123 (foreign_item, declaration_sig),
124 (external_impl, external_impl_sig),
125 eii_attr_span,
126 eii_name,
127 );
128 return Err(emitted);
129 }
130
131 if !(declaration_sig, external_impl_sig).references_error() {
132 for ty in unnormalized_external_impl_sig.inputs_and_output {
133 ocx.register_obligation(traits::Obligation::new(
134 infcx.tcx,
135 cause.clone(),
136 param_env,
137 ty::ClauseKind::WellFormed(ty.into()),
138 ));
139 }
140 }
141
142 let errors = ocx.evaluate_obligations_error_on_ambiguity();
145 if let TraitErrors::HasErrors(errors) = errors {
146 let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
147 return Err(reported);
148 }
149
150 let errors = infcx.resolve_regions(external_impl, param_env, wf_tys);
153 if !errors.is_empty() {
154 return Err(infcx
155 .tainted_by_errors()
156 .unwrap_or_else(|| infcx.err_ctxt().report_region_errors(external_impl, &errors)));
157 }
158
159 Ok(())
160}
161
162pub(crate) fn compare_eii_statics<'tcx>(
163 tcx: TyCtxt<'tcx>,
164 external_impl: LocalDefId,
165 external_impl_ty: Ty<'tcx>,
166 foreign_item: DefId,
167 eii_name: Symbol,
168 eii_attr_span: Span,
169) -> Result<(), ErrorGuaranteed> {
170 check_eii_target(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?;
171
172 let external_impl_span = tcx.def_span(external_impl);
173 let cause = ObligationCause::new(
174 external_impl_span,
175 external_impl,
176 ObligationCauseCode::CompareEii { external_impl, declaration: foreign_item },
177 );
178
179 let param_env = ParamEnv::empty();
180
181 let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
182 let ocx = ObligationCtxt::new_with_diagnostics(infcx);
183
184 let declaration_ty = tcx.type_of(foreign_item).instantiate_identity().skip_norm_wip();
185 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_hir_analysis/src/check/compare_eii.rs:185",
"rustc_hir_analysis::check::compare_eii",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_hir_analysis/src/check/compare_eii.rs"),
::tracing_core::__macro_support::Option::Some(185u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::check::compare_eii"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("declaration_ty")
}> =
::tracing::__macro_support::FieldName::new("declaration_ty");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&declaration_ty)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?declaration_ty);
186
187 let result = ocx.sup(&cause, param_env, declaration_ty, external_impl_ty);
195
196 if let Err(terr) = result {
197 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_hir_analysis/src/check/compare_eii.rs:197",
"rustc_hir_analysis::check::compare_eii",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_hir_analysis/src/check/compare_eii.rs"),
::tracing_core::__macro_support::Option::Some(197u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::check::compare_eii"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("external_impl_ty")
}> =
::tracing::__macro_support::FieldName::new("external_impl_ty");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("declaration_ty")
}> =
::tracing::__macro_support::FieldName::new("declaration_ty");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("terr")
}> =
::tracing::__macro_support::FieldName::new("terr");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("sub_types failed")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&external_impl_ty)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&declaration_ty)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&terr)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?external_impl_ty, ?declaration_ty, ?terr, "sub_types failed");
198
199 let mut diag = {
tcx.dcx().struct_span_err(cause.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("static `{0}` has a type that is incompatible with the declaration of `#[{1}]`",
tcx.item_name(external_impl), eii_name))
})).with_code(E0806)
}struct_span_code_err!(
200 tcx.dcx(),
201 cause.span,
202 E0806,
203 "static `{}` has a type that is incompatible with the declaration of `#[{eii_name}]`",
204 tcx.item_name(external_impl)
205 );
206 diag.span_note(eii_attr_span, "expected this because of this attribute");
207
208 return Err(diag.emit_err());
209 }
210
211 let errors = ocx.evaluate_obligations_error_on_ambiguity();
214 if let TraitErrors::HasErrors(errors) = errors {
215 let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
216 return Err(reported);
217 }
218
219 let errors = infcx.resolve_regions(external_impl, param_env, []);
222 if !errors.is_empty() {
223 return Err(infcx
224 .tainted_by_errors()
225 .unwrap_or_else(|| infcx.err_ctxt().report_region_errors(external_impl, &errors)));
226 }
227
228 Ok(())
229}
230
231fn check_eii_target(
232 tcx: TyCtxt<'_>,
233 external_impl: LocalDefId,
234 foreign_item: DefId,
235 eii_name: Symbol,
236 eii_attr_span: Span,
237) -> Result<(), ErrorGuaranteed> {
238 if !tcx.is_foreign_item(foreign_item) {
243 return Err(tcx.dcx().delayed_bug("EII is a foreign item"));
244 }
245 let expected_kind = tcx.def_kind(foreign_item);
246 let actual_kind = tcx.def_kind(external_impl);
247
248 match expected_kind {
249 _ if expected_kind == actual_kind => Ok(()),
251 DefKind::Static { mutability: m1, safety: s1, .. }
252 if let DefKind::Static { mutability: m2, safety: s2, .. } = actual_kind =>
253 {
254 Err(if s1 != s2 {
255 tcx.dcx().emit_err(EiiDefkindMismatchStaticSafety { span: eii_attr_span, eii_name })
256 } else if m1 != m2 {
257 tcx.dcx()
258 .emit_err(EiiDefkindMismatchStaticMutability { span: eii_attr_span, eii_name })
259 } else {
260 ::core::panicking::unreachable_default_msg()unreachable!()
261 })
262 }
263 DefKind::Fn | DefKind::Static { .. } => Err(tcx.dcx().emit_err(EiiDefkindMismatch {
265 span: eii_attr_span,
266 eii_name,
267 expected_kind: expected_kind.descr(foreign_item),
268 })),
269 _ => Err(tcx.dcx().delayed_bug("Attribute should not be allowed by target checking")),
271 }
272}
273
274fn check_is_structurally_compatible<'tcx>(
280 tcx: TyCtxt<'tcx>,
281 external_impl: LocalDefId,
282 declaration: DefId,
283 eii_name: Symbol,
284 eii_attr_span: Span,
285) -> Result<(), ErrorGuaranteed> {
286 check_no_generics(tcx, external_impl, declaration, eii_name, eii_attr_span)?;
287 check_number_of_arguments(tcx, external_impl, declaration, eii_name, eii_attr_span)?;
288 check_early_region_bounds(tcx, external_impl, declaration, eii_attr_span)?;
289 Ok(())
290}
291
292fn check_no_generics<'tcx>(
294 tcx: TyCtxt<'tcx>,
295 external_impl: LocalDefId,
296 declaration: DefId,
297 eii_name: Symbol,
298 eii_attr_span: Span,
299) -> Result<(), ErrorGuaranteed> {
300 if tcx.generics_of(declaration).own_requires_monomorphization() {
302 return Err(tcx.dcx().delayed_bug("compared an EII impl against a generic declaration"));
303 }
304
305 let generics = tcx.generics_of(external_impl);
306 if generics.own_requires_monomorphization()
307 && {
{
'done:
{
for i in
::rustc_attr_ir::HasAttrs::get_attrs(external_impl, &tcx) {
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(EiiImpl(i)) if
#[allow(non_exhaustive_omitted_patterns)] match i.resolution
{
EiiImplResolution::Macro(_) => true,
_ => false,
} => {
break 'done Some(());
}
::rustc_attr_ir::Attribute::Tool(..) |
::rustc_attr_ir::Attribute::DeriveHelper(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some()find_attr!(tcx, external_impl, EiiImpl(i) if matches!(i.resolution, EiiImplResolution::Macro(_)))
314 {
315 tcx.dcx().emit_err(EiiWithGenerics {
316 span: tcx.def_span(external_impl),
317 attr: eii_attr_span,
318 eii_name,
319 impl_name: tcx.item_name(external_impl),
320 });
321 }
322
323 Ok(())
324}
325
326fn check_early_region_bounds<'tcx>(
327 tcx: TyCtxt<'tcx>,
328 external_impl: LocalDefId,
329 declaration: DefId,
330 eii_attr_span: Span,
331) -> Result<(), ErrorGuaranteed> {
332 let external_impl_generics = tcx.generics_of(external_impl.to_def_id());
333 let external_impl_params = external_impl_generics.own_counts().lifetimes;
334
335 let declaration_generics = tcx.generics_of(declaration);
336 let declaration_params = declaration_generics.own_counts().lifetimes;
337
338 let Err(CheckNumberOfEarlyBoundRegionsError { span, generics_span, bounds_span, where_span }) =
339 check_number_of_early_bound_regions(
340 tcx,
341 external_impl,
342 declaration,
343 external_impl_generics,
344 external_impl_params,
345 declaration_generics,
346 declaration_params,
347 )
348 else {
349 return Ok(());
350 };
351
352 let mut diag = tcx.dcx().create_err(LifetimesOrBoundsMismatchOnEii {
353 span,
354 ident: tcx.item_name(external_impl.to_def_id()),
355 generics_span,
356 bounds_span,
357 where_span,
358 });
359
360 diag.span_label(eii_attr_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required because of this attribute"))
})format!("required because of this attribute"));
361 return Err(diag.emit_err());
362}
363
364fn check_number_of_arguments<'tcx>(
365 tcx: TyCtxt<'tcx>,
366 external_impl: LocalDefId,
367 declaration: DefId,
368 eii_name: Symbol,
369 eii_attr_span: Span,
370) -> Result<(), ErrorGuaranteed> {
371 let external_impl_fty = tcx.fn_sig(external_impl);
372 let declaration_fty = tcx.fn_sig(declaration);
373 let declaration_number_args = declaration_fty.skip_binder().inputs().skip_binder().len();
374 let external_impl_number_args = external_impl_fty.skip_binder().inputs().skip_binder().len();
375
376 if declaration_number_args == external_impl_number_args {
378 Ok(())
379 } else {
380 Err(report_number_of_arguments_mismatch(
381 tcx,
382 external_impl,
383 declaration,
384 eii_name,
385 eii_attr_span,
386 declaration_number_args,
387 external_impl_number_args,
388 ))
389 }
390}
391
392fn report_number_of_arguments_mismatch<'tcx>(
393 tcx: TyCtxt<'tcx>,
394 external_impl: LocalDefId,
395 declaration: DefId,
396 eii_name: Symbol,
397 eii_attr_span: Span,
398 declaration_number_args: usize,
399 external_impl_number_args: usize,
400) -> ErrorGuaranteed {
401 let external_impl_name = tcx.item_name(external_impl.to_def_id());
402
403 let declaration_span = declaration
404 .as_local()
405 .and_then(|def_id| {
406 let declaration_sig = get_declaration_sig(tcx, def_id).expect("foreign item sig");
407 let pos = declaration_number_args.saturating_sub(1);
408 declaration_sig.decl.inputs.get(pos).map(|arg| {
409 if pos == 0 {
410 arg.span
411 } else {
412 arg.span.with_lo(declaration_sig.decl.inputs[0].span.lo())
413 }
414 })
415 })
416 .or_else(|| tcx.hir_span_if_local(declaration))
417 .unwrap_or_else(|| tcx.def_span(declaration));
418
419 let (_, external_impl_sig, _, _) = &tcx.hir_expect_item(external_impl).expect_fn();
420 let pos = external_impl_number_args.saturating_sub(1);
421 let impl_span = external_impl_sig
422 .decl
423 .inputs
424 .get(pos)
425 .map(|arg| {
426 if pos == 0 {
427 arg.span
428 } else {
429 arg.span.with_lo(external_impl_sig.decl.inputs[0].span.lo())
430 }
431 })
432 .unwrap_or_else(|| tcx.def_span(external_impl));
433
434 let mut err = {
tcx.dcx().struct_span_err(impl_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{2}` has {0} but #[{3}] requires it to have {1}",
potentially_plural_count(external_impl_number_args,
"parameter"), declaration_number_args, external_impl_name,
eii_name))
})).with_code(E0806)
}struct_span_code_err!(
435 tcx.dcx(),
436 impl_span,
437 E0806,
438 "`{external_impl_name}` has {} but #[{eii_name}] requires it to have {}",
439 potentially_plural_count(external_impl_number_args, "parameter"),
440 declaration_number_args
441 );
442
443 err.span_label(
444 declaration_span,
445 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("requires {0}",
potentially_plural_count(declaration_number_args,
"parameter")))
})format!("requires {}", potentially_plural_count(declaration_number_args, "parameter")),
446 );
447
448 err.span_label(
449 impl_span,
450 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected {0}, found {1}",
potentially_plural_count(declaration_number_args,
"parameter"), external_impl_number_args))
})format!(
451 "expected {}, found {}",
452 potentially_plural_count(declaration_number_args, "parameter"),
453 external_impl_number_args
454 ),
455 );
456
457 err.span_label(eii_attr_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required because of this attribute"))
})format!("required because of this attribute"));
458
459 err.emit_err()
460}
461
462fn report_eii_mismatch<'tcx>(
463 infcx: &InferCtxt<'tcx>,
464 mut cause: ObligationCause<'tcx>,
465 param_env: ty::ParamEnv<'tcx>,
466 terr: TypeError<'tcx>,
467 (declaration_did, declaration_sig): (DefId, ty::FnSig<'tcx>),
468 (external_impl_did, external_impl_sig): (LocalDefId, ty::FnSig<'tcx>),
469 eii_attr_span: Span,
470 eii_name: Symbol,
471) -> ErrorGuaranteed {
472 let tcx = infcx.tcx;
473 let (impl_err_span, trait_err_span, external_impl_name) =
474 extract_spans_for_error_reporting(infcx, terr, &cause, declaration_did, external_impl_did);
475
476 let mut diag = {
tcx.dcx().struct_span_err(impl_err_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("function `{0}` has a type that is incompatible with the declaration of `#[{1}]`",
external_impl_name, eii_name))
})).with_code(E0806)
}struct_span_code_err!(
477 tcx.dcx(),
478 impl_err_span,
479 E0806,
480 "function `{}` has a type that is incompatible with the declaration of `#[{eii_name}]`",
481 external_impl_name
482 );
483
484 diag.span_note(eii_attr_span, "expected this because of this attribute");
485
486 match &terr {
487 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
488 if declaration_sig.inputs().len() == *i {
489 if let ItemKind::Fn { sig, .. } = &tcx.hir_expect_item(external_impl_did).kind
492 && !sig.header.asyncness.is_async()
493 {
494 let msg = "change the output type to match the declaration";
495 let ap = Applicability::MachineApplicable;
496 match sig.decl.output {
497 hir::FnRetTy::DefaultReturn(sp) => {
498 let sugg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" -> {0}",
declaration_sig.output()))
})format!(" -> {}", declaration_sig.output());
499 diag.span_suggestion_verbose(sp, msg, sugg, ap);
500 }
501 hir::FnRetTy::Return(hir_ty) => {
502 let sugg = declaration_sig.output();
503 diag.span_suggestion_verbose(hir_ty.span, msg, sugg, ap);
504 }
505 };
506 };
507 } else if let Some(trait_ty) = declaration_sig.inputs().get(*i) {
508 diag.span_suggestion_verbose(
509 impl_err_span,
510 "change the parameter type to match the declaration",
511 trait_ty,
512 Applicability::MachineApplicable,
513 );
514 }
515 }
516 _ => {}
517 }
518
519 cause.span = impl_err_span;
520 infcx.err_ctxt().note_type_err(
521 &mut diag,
522 &cause,
523 trait_err_span.map(|sp| (sp.into(), Cow::from("type in declaration"), false)),
524 Some(param_env.and(infer::ValuePairs::PolySigs(ExpectedFound {
525 expected: ty::Binder::dummy(declaration_sig),
526 found: ty::Binder::dummy(external_impl_sig),
527 }))),
528 terr,
529 false,
530 None,
531 );
532
533 diag.emit_err()
534}
535
536{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("extract_spans_for_error_reporting",
"rustc_hir_analysis::check::compare_eii",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/708c94ef093ecc42fb8851e17d8383d999727abc/compiler/rustc_hir_analysis/src/check/compare_eii.rs"),
::tracing_core::__macro_support::Option::Some(536u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::check::compare_eii"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("terr")
}> =
::tracing::__macro_support::FieldName::new("terr");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("cause")
}> =
::tracing::__macro_support::FieldName::new("cause");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("declaration")
}> =
::tracing::__macro_support::FieldName::new("declaration");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("external_impl")
}> =
::tracing::__macro_support::FieldName::new("external_impl");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&terr)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cause)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&declaration)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&external_impl)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: (Span, Option<Span>, Ident) =
loop {};
return __tracing_attr_fake_return;
}
{
let tcx = infcx.tcx;
let (mut external_impl_args, external_impl_name) =
{
let item = tcx.hir_expect_item(external_impl);
let (ident, sig, _, _) = item.expect_fn();
(sig.decl.inputs.iter().map(|t|
t.span).chain(iter::once(sig.decl.output.span())), ident)
};
let declaration_args =
declaration.as_local().map(|def_id|
{
if let Some(sig) = get_declaration_sig(tcx, def_id) {
sig.decl.inputs.iter().map(|t|
t.span).chain(iter::once(sig.decl.output.span()))
} else {
{
::core::panicking::panic_fmt(format_args!("expected {0:?} to be a foreign function",
def_id));
};
}
});
match terr {
TypeError::ArgumentMutability(i) |
TypeError::ArgumentSorts(ExpectedFound { .. }, i) =>
(external_impl_args.nth(i).unwrap(),
declaration_args.and_then(|mut args| args.nth(i)),
external_impl_name),
_ =>
(cause.span,
tcx.hir_span_if_local(declaration).or_else(||
Some(tcx.def_span(declaration))), external_impl_name),
}
}
}
}#[instrument(level = "debug", skip(infcx))]
537fn extract_spans_for_error_reporting<'tcx>(
538 infcx: &infer::InferCtxt<'tcx>,
539 terr: TypeError<'_>,
540 cause: &ObligationCause<'tcx>,
541 declaration: DefId,
542 external_impl: LocalDefId,
543) -> (Span, Option<Span>, Ident) {
544 let tcx = infcx.tcx;
545 let (mut external_impl_args, external_impl_name) = {
546 let item = tcx.hir_expect_item(external_impl);
547 let (ident, sig, _, _) = item.expect_fn();
548 (sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())), ident)
549 };
550
551 let declaration_args = declaration.as_local().map(|def_id| {
552 if let Some(sig) = get_declaration_sig(tcx, def_id) {
553 sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
554 } else {
555 panic!("expected {def_id:?} to be a foreign function");
556 }
557 });
558
559 match terr {
560 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => (
561 external_impl_args.nth(i).unwrap(),
562 declaration_args.and_then(|mut args| args.nth(i)),
563 external_impl_name,
564 ),
565 _ => (
566 cause.span,
567 tcx.hir_span_if_local(declaration).or_else(|| Some(tcx.def_span(declaration))),
568 external_impl_name,
569 ),
570 }
571}
572
573fn get_declaration_sig<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<&'tcx FnSig<'tcx>> {
574 let hir_id: HirId = tcx.local_def_id_to_hir_id(def_id);
575 tcx.hir_fn_sig_by_hir_id(hir_id)
576}