1use std::borrow::Cow;
7use std::iter;
8
9use rustc_data_structures::fx::FxIndexSet;
10use rustc_errors::{Applicability, E0806, struct_span_code_err};
11use rustc_hir::attrs::EiiImplResolution;
12use rustc_hir::def::DefKind;
13use rustc_hir::def_id::{DefId, LocalDefId};
14use rustc_hir::{self as hir, FnSig, HirId, ItemKind, find_attr};
15use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
16use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
17use rustc_middle::ty::error::{ExpectedFound, TypeError};
18use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode};
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::errors::{EiiWithGenerics, LifetimesOrBoundsMismatchOnEii};
30
31pub(crate) fn compare_eii_function_types<'tcx>(
35 tcx: TyCtxt<'tcx>,
36 external_impl: LocalDefId,
37 foreign_item: DefId,
38 eii_name: Symbol,
39 eii_attr_span: Span,
40) -> Result<(), ErrorGuaranteed> {
41 if !is_foreign_function(tcx, foreign_item) {
46 return Ok(());
47 }
48
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();
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 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("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(&["declaration_sig"],
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&declaration_sig)
as &dyn 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).instantiate(
83 tcx,
84 infcx.fresh_args_for_item(external_impl_span, external_impl.to_def_id()),
85 ),
86 );
87 let external_impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_external_impl_sig);
88 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/check/compare_eii.rs:88",
"rustc_hir_analysis::check::compare_eii",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/check/compare_eii.rs"),
::tracing_core::__macro_support::Option::Some(88u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::check::compare_eii"),
::tracing_core::field::FieldSet::new(&["external_impl_sig"],
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&external_impl_sig)
as &dyn Value))])
});
} else { ; }
};debug!(?external_impl_sig);
89
90 wf_tys.extend(declaration_sig.inputs_and_output.iter());
94 let declaration_sig = ocx.normalize(&norm_cause, param_env, declaration_sig);
95 wf_tys.extend(external_impl_sig.inputs_and_output.iter());
98
99 let result = ocx.sup(&cause, param_env, declaration_sig, external_impl_sig);
107
108 if let Err(terr) = result {
109 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/check/compare_eii.rs:109",
"rustc_hir_analysis::check::compare_eii",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/check/compare_eii.rs"),
::tracing_core::__macro_support::Option::Some(109u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::check::compare_eii"),
::tracing_core::field::FieldSet::new(&["message",
"external_impl_sig", "declaration_sig", "terr"],
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("sub_types failed")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&external_impl_sig)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&declaration_sig)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&terr) as
&dyn Value))])
});
} else { ; }
};debug!(?external_impl_sig, ?declaration_sig, ?terr, "sub_types failed");
110
111 let emitted = report_eii_mismatch(
112 infcx,
113 cause,
114 param_env,
115 terr,
116 (foreign_item, declaration_sig),
117 (external_impl, external_impl_sig),
118 eii_attr_span,
119 eii_name,
120 );
121 return Err(emitted);
122 }
123
124 if !(declaration_sig, external_impl_sig).references_error() {
125 for ty in unnormalized_external_impl_sig.inputs_and_output {
126 ocx.register_obligation(traits::Obligation::new(
127 infcx.tcx,
128 cause.clone(),
129 param_env,
130 ty::ClauseKind::WellFormed(ty.into()),
131 ));
132 }
133 }
134
135 let errors = ocx.evaluate_obligations_error_on_ambiguity();
138 if !errors.is_empty() {
139 let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
140 return Err(reported);
141 }
142
143 let errors = infcx.resolve_regions(external_impl, param_env, wf_tys);
146 if !errors.is_empty() {
147 return Err(infcx
148 .tainted_by_errors()
149 .unwrap_or_else(|| infcx.err_ctxt().report_region_errors(external_impl, &errors)));
150 }
151
152 Ok(())
153}
154
155fn check_is_structurally_compatible<'tcx>(
161 tcx: TyCtxt<'tcx>,
162 external_impl: LocalDefId,
163 declaration: DefId,
164 eii_name: Symbol,
165 eii_attr_span: Span,
166) -> Result<(), ErrorGuaranteed> {
167 check_no_generics(tcx, external_impl, declaration, eii_name, eii_attr_span)?;
168 check_number_of_arguments(tcx, external_impl, declaration, eii_name, eii_attr_span)?;
169 check_early_region_bounds(tcx, external_impl, declaration, eii_attr_span)?;
170 Ok(())
171}
172
173fn check_no_generics<'tcx>(
175 tcx: TyCtxt<'tcx>,
176 external_impl: LocalDefId,
177 _declaration: DefId,
178 eii_name: Symbol,
179 eii_attr_span: Span,
180) -> Result<(), ErrorGuaranteed> {
181 let generics = tcx.generics_of(external_impl);
182 if generics.own_requires_monomorphization()
183 && {
#[allow(deprecated)]
{
{
'done:
{
for i in tcx.get_all_attrs(external_impl) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(EiiImpls(impls)) if
impls.iter().any(|i|
#[allow(non_exhaustive_omitted_patterns)] match i.resolution
{
EiiImplResolution::Macro(_) => true,
_ => false,
}) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}
}.is_some()find_attr!(tcx, external_impl, EiiImpls(impls) if impls.iter().any(|i| matches!(i.resolution, EiiImplResolution::Macro(_)))
190 )
191 {
192 tcx.dcx().emit_err(EiiWithGenerics {
193 span: tcx.def_span(external_impl),
194 attr: eii_attr_span,
195 eii_name,
196 impl_name: tcx.item_name(external_impl),
197 });
198 }
199
200 Ok(())
201}
202
203fn check_early_region_bounds<'tcx>(
204 tcx: TyCtxt<'tcx>,
205 external_impl: LocalDefId,
206 declaration: DefId,
207 eii_attr_span: Span,
208) -> Result<(), ErrorGuaranteed> {
209 let external_impl_generics = tcx.generics_of(external_impl.to_def_id());
210 let external_impl_params = external_impl_generics.own_counts().lifetimes;
211
212 let declaration_generics = tcx.generics_of(declaration);
213 let declaration_params = declaration_generics.own_counts().lifetimes;
214
215 let Err(CheckNumberOfEarlyBoundRegionsError { span, generics_span, bounds_span, where_span }) =
216 check_number_of_early_bound_regions(
217 tcx,
218 external_impl,
219 declaration,
220 external_impl_generics,
221 external_impl_params,
222 declaration_generics,
223 declaration_params,
224 )
225 else {
226 return Ok(());
227 };
228
229 let mut diag = tcx.dcx().create_err(LifetimesOrBoundsMismatchOnEii {
230 span,
231 ident: tcx.item_name(external_impl.to_def_id()),
232 generics_span,
233 bounds_span,
234 where_span,
235 });
236
237 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"));
238 return Err(diag.emit());
239}
240
241fn check_number_of_arguments<'tcx>(
242 tcx: TyCtxt<'tcx>,
243 external_impl: LocalDefId,
244 declaration: DefId,
245 eii_name: Symbol,
246 eii_attr_span: Span,
247) -> Result<(), ErrorGuaranteed> {
248 let external_impl_fty = tcx.fn_sig(external_impl);
249 let declaration_fty = tcx.fn_sig(declaration);
250 let declaration_number_args = declaration_fty.skip_binder().inputs().skip_binder().len();
251 let external_impl_number_args = external_impl_fty.skip_binder().inputs().skip_binder().len();
252
253 if declaration_number_args == external_impl_number_args {
255 Ok(())
256 } else {
257 Err(report_number_of_arguments_mismatch(
258 tcx,
259 external_impl,
260 declaration,
261 eii_name,
262 eii_attr_span,
263 declaration_number_args,
264 external_impl_number_args,
265 ))
266 }
267}
268
269fn report_number_of_arguments_mismatch<'tcx>(
270 tcx: TyCtxt<'tcx>,
271 external_impl: LocalDefId,
272 declaration: DefId,
273 eii_name: Symbol,
274 eii_attr_span: Span,
275 declaration_number_args: usize,
276 external_impl_number_args: usize,
277) -> ErrorGuaranteed {
278 let external_impl_name = tcx.item_name(external_impl.to_def_id());
279
280 let declaration_span = declaration
281 .as_local()
282 .and_then(|def_id| {
283 let declaration_sig = get_declaration_sig(tcx, def_id).expect("foreign item sig");
284 let pos = declaration_number_args.saturating_sub(1);
285 declaration_sig.decl.inputs.get(pos).map(|arg| {
286 if pos == 0 {
287 arg.span
288 } else {
289 arg.span.with_lo(declaration_sig.decl.inputs[0].span.lo())
290 }
291 })
292 })
293 .or_else(|| tcx.hir_span_if_local(declaration))
294 .unwrap_or_else(|| tcx.def_span(declaration));
295
296 let (_, external_impl_sig, _, _) = &tcx.hir_expect_item(external_impl).expect_fn();
297 let pos = external_impl_number_args.saturating_sub(1);
298 let impl_span = external_impl_sig
299 .decl
300 .inputs
301 .get(pos)
302 .map(|arg| {
303 if pos == 0 {
304 arg.span
305 } else {
306 arg.span.with_lo(external_impl_sig.decl.inputs[0].span.lo())
307 }
308 })
309 .unwrap_or_else(|| tcx.def_span(external_impl));
310
311 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!(
312 tcx.dcx(),
313 impl_span,
314 E0806,
315 "`{external_impl_name}` has {} but #[{eii_name}] requires it to have {}",
316 potentially_plural_count(external_impl_number_args, "parameter"),
317 declaration_number_args
318 );
319
320 err.span_label(
321 declaration_span,
322 ::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")),
323 );
324
325 err.span_label(
326 impl_span,
327 ::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!(
328 "expected {}, found {}",
329 potentially_plural_count(declaration_number_args, "parameter"),
330 external_impl_number_args
331 ),
332 );
333
334 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"));
335
336 err.emit()
337}
338
339fn report_eii_mismatch<'tcx>(
340 infcx: &InferCtxt<'tcx>,
341 mut cause: ObligationCause<'tcx>,
342 param_env: ty::ParamEnv<'tcx>,
343 terr: TypeError<'tcx>,
344 (declaration_did, declaration_sig): (DefId, ty::FnSig<'tcx>),
345 (external_impl_did, external_impl_sig): (LocalDefId, ty::FnSig<'tcx>),
346 eii_attr_span: Span,
347 eii_name: Symbol,
348) -> ErrorGuaranteed {
349 let tcx = infcx.tcx;
350 let (impl_err_span, trait_err_span, external_impl_name) =
351 extract_spans_for_error_reporting(infcx, terr, &cause, declaration_did, external_impl_did);
352
353 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!(
354 tcx.dcx(),
355 impl_err_span,
356 E0806,
357 "function `{}` has a type that is incompatible with the declaration of `#[{eii_name}]`",
358 external_impl_name
359 );
360
361 diag.span_note(eii_attr_span, "expected this because of this attribute");
362
363 match &terr {
364 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
365 if declaration_sig.inputs().len() == *i {
366 if let ItemKind::Fn { sig, .. } = &tcx.hir_expect_item(external_impl_did).kind
369 && !sig.header.asyncness.is_async()
370 {
371 let msg = "change the output type to match the declaration";
372 let ap = Applicability::MachineApplicable;
373 match sig.decl.output {
374 hir::FnRetTy::DefaultReturn(sp) => {
375 let sugg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" -> {0}",
declaration_sig.output()))
})format!(" -> {}", declaration_sig.output());
376 diag.span_suggestion_verbose(sp, msg, sugg, ap);
377 }
378 hir::FnRetTy::Return(hir_ty) => {
379 let sugg = declaration_sig.output();
380 diag.span_suggestion_verbose(hir_ty.span, msg, sugg, ap);
381 }
382 };
383 };
384 } else if let Some(trait_ty) = declaration_sig.inputs().get(*i) {
385 diag.span_suggestion_verbose(
386 impl_err_span,
387 "change the parameter type to match the declaration",
388 trait_ty,
389 Applicability::MachineApplicable,
390 );
391 }
392 }
393 _ => {}
394 }
395
396 cause.span = impl_err_span;
397 infcx.err_ctxt().note_type_err(
398 &mut diag,
399 &cause,
400 trait_err_span.map(|sp| (sp, Cow::from("type in declaration"), false)),
401 Some(param_env.and(infer::ValuePairs::PolySigs(ExpectedFound {
402 expected: ty::Binder::dummy(declaration_sig),
403 found: ty::Binder::dummy(external_impl_sig),
404 }))),
405 terr,
406 false,
407 None,
408 );
409
410 diag.emit()
411}
412
413#[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("compiler/rustc_hir_analysis/src/check/compare_eii.rs"),
::tracing_core::__macro_support::Option::Some(413u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::check::compare_eii"),
::tracing_core::field::FieldSet::new(&["terr", "cause",
"declaration", "external_impl"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&terr)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cause)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&declaration)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&external_impl)
as &dyn 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))]
414fn extract_spans_for_error_reporting<'tcx>(
415 infcx: &infer::InferCtxt<'tcx>,
416 terr: TypeError<'_>,
417 cause: &ObligationCause<'tcx>,
418 declaration: DefId,
419 external_impl: LocalDefId,
420) -> (Span, Option<Span>, Ident) {
421 let tcx = infcx.tcx;
422 let (mut external_impl_args, external_impl_name) = {
423 let item = tcx.hir_expect_item(external_impl);
424 let (ident, sig, _, _) = item.expect_fn();
425 (sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())), ident)
426 };
427
428 let declaration_args = declaration.as_local().map(|def_id| {
429 if let Some(sig) = get_declaration_sig(tcx, def_id) {
430 sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
431 } else {
432 panic!("expected {def_id:?} to be a foreign function");
433 }
434 });
435
436 match terr {
437 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => (
438 external_impl_args.nth(i).unwrap(),
439 declaration_args.and_then(|mut args| args.nth(i)),
440 external_impl_name,
441 ),
442 _ => (
443 cause.span,
444 tcx.hir_span_if_local(declaration).or_else(|| Some(tcx.def_span(declaration))),
445 external_impl_name,
446 ),
447 }
448}
449
450fn get_declaration_sig<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<&'tcx FnSig<'tcx>> {
451 let hir_id: HirId = tcx.local_def_id_to_hir_id(def_id);
452 tcx.hir_fn_sig_by_hir_id(hir_id)
453}
454
455fn is_foreign_function(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
456 tcx.is_foreign_item(def_id) && #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(def_id) {
DefKind::Fn => true,
_ => false,
}matches!(tcx.def_kind(def_id), DefKind::Fn)
457}