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_id::{DefId, LocalDefId};
13use rustc_hir::{self as hir, FnSig, HirId, ItemKind, find_attr};
14use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
15use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
16use rustc_middle::ty::error::{ExpectedFound, TypeError};
17use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode};
18use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
19use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
20use rustc_trait_selection::regions::InferCtxtRegionExt;
21use rustc_trait_selection::traits::{self, ObligationCtxt};
22use tracing::{debug, instrument};
23
24use super::potentially_plural_count;
25use crate::check::compare_impl_item::{
26 CheckNumberOfEarlyBoundRegionsError, check_number_of_early_bound_regions,
27};
28use crate::errors::{EiiWithGenerics, LifetimesOrBoundsMismatchOnEii};
29
30pub(crate) fn compare_eii_function_types<'tcx>(
34 tcx: TyCtxt<'tcx>,
35 external_impl: LocalDefId,
36 foreign_item: DefId,
37 eii_name: Symbol,
38 eii_attr_span: Span,
39) -> Result<(), ErrorGuaranteed> {
40 check_is_structurally_compatible(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?;
41
42 let external_impl_span = tcx.def_span(external_impl);
43 let cause = ObligationCause::new(
44 external_impl_span,
45 external_impl,
46 ObligationCauseCode::CompareEii { external_impl, declaration: foreign_item },
47 );
48
49 let param_env = tcx.param_env(foreign_item);
51
52 let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
53 let ocx = ObligationCtxt::new_with_diagnostics(infcx);
54
55 let mut wf_tys = FxIndexSet::default();
64 let norm_cause = ObligationCause::misc(external_impl_span, external_impl);
65
66 let declaration_sig = tcx.fn_sig(foreign_item).instantiate_identity();
67 let declaration_sig = tcx.liberate_late_bound_regions(external_impl.into(), declaration_sig);
68 {
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:68",
"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(68u32),
::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);
69
70 let unnormalized_external_impl_sig = infcx.instantiate_binder_with_fresh_vars(
71 external_impl_span,
72 infer::BoundRegionConversionTime::HigherRankedType,
73 tcx.fn_sig(external_impl).instantiate(
74 tcx,
75 infcx.fresh_args_for_item(external_impl_span, external_impl.to_def_id()),
76 ),
77 );
78 let external_impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_external_impl_sig);
79 {
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:79",
"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(79u32),
::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);
80
81 wf_tys.extend(declaration_sig.inputs_and_output.iter());
85 let declaration_sig = ocx.normalize(&norm_cause, param_env, declaration_sig);
86 wf_tys.extend(external_impl_sig.inputs_and_output.iter());
89
90 let result = ocx.sup(&cause, param_env, declaration_sig, external_impl_sig);
98
99 if let Err(terr) = result {
100 {
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:100",
"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(100u32),
::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");
101
102 let emitted = report_eii_mismatch(
103 infcx,
104 cause,
105 param_env,
106 terr,
107 (foreign_item, declaration_sig),
108 (external_impl, external_impl_sig),
109 eii_attr_span,
110 eii_name,
111 );
112 return Err(emitted);
113 }
114
115 if !(declaration_sig, external_impl_sig).references_error() {
116 for ty in unnormalized_external_impl_sig.inputs_and_output {
117 ocx.register_obligation(traits::Obligation::new(
118 infcx.tcx,
119 cause.clone(),
120 param_env,
121 ty::ClauseKind::WellFormed(ty.into()),
122 ));
123 }
124 }
125
126 let errors = ocx.evaluate_obligations_error_on_ambiguity();
129 if !errors.is_empty() {
130 let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
131 return Err(reported);
132 }
133
134 let errors = infcx.resolve_regions(external_impl, param_env, wf_tys);
137 if !errors.is_empty() {
138 return Err(infcx
139 .tainted_by_errors()
140 .unwrap_or_else(|| infcx.err_ctxt().report_region_errors(external_impl, &errors)));
141 }
142
143 Ok(())
144}
145
146fn check_is_structurally_compatible<'tcx>(
152 tcx: TyCtxt<'tcx>,
153 external_impl: LocalDefId,
154 declaration: DefId,
155 eii_name: Symbol,
156 eii_attr_span: Span,
157) -> Result<(), ErrorGuaranteed> {
158 check_no_generics(tcx, external_impl, declaration, eii_name, eii_attr_span)?;
159 check_number_of_arguments(tcx, external_impl, declaration, eii_name, eii_attr_span)?;
160 check_early_region_bounds(tcx, external_impl, declaration, eii_attr_span)?;
161 Ok(())
162}
163
164fn check_no_generics<'tcx>(
166 tcx: TyCtxt<'tcx>,
167 external_impl: LocalDefId,
168 _declaration: DefId,
169 eii_name: Symbol,
170 eii_attr_span: Span,
171) -> Result<(), ErrorGuaranteed> {
172 let generics = tcx.generics_of(external_impl);
173 if generics.own_requires_monomorphization()
174 && {
#[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(_)))
181 )
182 {
183 tcx.dcx().emit_err(EiiWithGenerics {
184 span: tcx.def_span(external_impl),
185 attr: eii_attr_span,
186 eii_name,
187 impl_name: tcx.item_name(external_impl),
188 });
189 }
190
191 Ok(())
192}
193
194fn check_early_region_bounds<'tcx>(
195 tcx: TyCtxt<'tcx>,
196 external_impl: LocalDefId,
197 declaration: DefId,
198 eii_attr_span: Span,
199) -> Result<(), ErrorGuaranteed> {
200 let external_impl_generics = tcx.generics_of(external_impl.to_def_id());
201 let external_impl_params = external_impl_generics.own_counts().lifetimes;
202
203 let declaration_generics = tcx.generics_of(declaration);
204 let declaration_params = declaration_generics.own_counts().lifetimes;
205
206 let Err(CheckNumberOfEarlyBoundRegionsError { span, generics_span, bounds_span, where_span }) =
207 check_number_of_early_bound_regions(
208 tcx,
209 external_impl,
210 declaration,
211 external_impl_generics,
212 external_impl_params,
213 declaration_generics,
214 declaration_params,
215 )
216 else {
217 return Ok(());
218 };
219
220 let mut diag = tcx.dcx().create_err(LifetimesOrBoundsMismatchOnEii {
221 span,
222 ident: tcx.item_name(external_impl.to_def_id()),
223 generics_span,
224 bounds_span,
225 where_span,
226 });
227
228 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"));
229 return Err(diag.emit());
230}
231
232fn check_number_of_arguments<'tcx>(
233 tcx: TyCtxt<'tcx>,
234 external_impl: LocalDefId,
235 declaration: DefId,
236 eii_name: Symbol,
237 eii_attr_span: Span,
238) -> Result<(), ErrorGuaranteed> {
239 let external_impl_fty = tcx.fn_sig(external_impl);
240 let declaration_fty = tcx.fn_sig(declaration);
241 let declaration_number_args = declaration_fty.skip_binder().inputs().skip_binder().len();
242 let external_impl_number_args = external_impl_fty.skip_binder().inputs().skip_binder().len();
243
244 if declaration_number_args == external_impl_number_args {
246 Ok(())
247 } else {
248 Err(report_number_of_arguments_mismatch(
249 tcx,
250 external_impl,
251 declaration,
252 eii_name,
253 eii_attr_span,
254 declaration_number_args,
255 external_impl_number_args,
256 ))
257 }
258}
259
260fn report_number_of_arguments_mismatch<'tcx>(
261 tcx: TyCtxt<'tcx>,
262 external_impl: LocalDefId,
263 declaration: DefId,
264 eii_name: Symbol,
265 eii_attr_span: Span,
266 declaration_number_args: usize,
267 external_impl_number_args: usize,
268) -> ErrorGuaranteed {
269 let external_impl_name = tcx.item_name(external_impl.to_def_id());
270
271 let declaration_span = declaration
272 .as_local()
273 .and_then(|def_id| {
274 let declaration_sig = get_declaration_sig(tcx, def_id).expect("foreign item sig");
275 let pos = declaration_number_args.saturating_sub(1);
276 declaration_sig.decl.inputs.get(pos).map(|arg| {
277 if pos == 0 {
278 arg.span
279 } else {
280 arg.span.with_lo(declaration_sig.decl.inputs[0].span.lo())
281 }
282 })
283 })
284 .or_else(|| tcx.hir_span_if_local(declaration))
285 .unwrap_or_else(|| tcx.def_span(declaration));
286
287 let (_, external_impl_sig, _, _) = &tcx.hir_expect_item(external_impl).expect_fn();
288 let pos = external_impl_number_args.saturating_sub(1);
289 let impl_span = external_impl_sig
290 .decl
291 .inputs
292 .get(pos)
293 .map(|arg| {
294 if pos == 0 {
295 arg.span
296 } else {
297 arg.span.with_lo(external_impl_sig.decl.inputs[0].span.lo())
298 }
299 })
300 .unwrap_or_else(|| tcx.def_span(external_impl));
301
302 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!(
303 tcx.dcx(),
304 impl_span,
305 E0806,
306 "`{external_impl_name}` has {} but #[{eii_name}] requires it to have {}",
307 potentially_plural_count(external_impl_number_args, "parameter"),
308 declaration_number_args
309 );
310
311 err.span_label(
312 declaration_span,
313 ::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")),
314 );
315
316 err.span_label(
317 impl_span,
318 ::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!(
319 "expected {}, found {}",
320 potentially_plural_count(declaration_number_args, "parameter"),
321 external_impl_number_args
322 ),
323 );
324
325 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"));
326
327 err.emit()
328}
329
330fn report_eii_mismatch<'tcx>(
331 infcx: &InferCtxt<'tcx>,
332 mut cause: ObligationCause<'tcx>,
333 param_env: ty::ParamEnv<'tcx>,
334 terr: TypeError<'tcx>,
335 (declaration_did, declaration_sig): (DefId, ty::FnSig<'tcx>),
336 (external_impl_did, external_impl_sig): (LocalDefId, ty::FnSig<'tcx>),
337 eii_attr_span: Span,
338 eii_name: Symbol,
339) -> ErrorGuaranteed {
340 let tcx = infcx.tcx;
341 let (impl_err_span, trait_err_span, external_impl_name) =
342 extract_spans_for_error_reporting(infcx, terr, &cause, declaration_did, external_impl_did);
343
344 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!(
345 tcx.dcx(),
346 impl_err_span,
347 E0806,
348 "function `{}` has a type that is incompatible with the declaration of `#[{eii_name}]`",
349 external_impl_name
350 );
351
352 diag.span_note(eii_attr_span, "expected this because of this attribute");
353
354 match &terr {
355 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
356 if declaration_sig.inputs().len() == *i {
357 if let ItemKind::Fn { sig, .. } = &tcx.hir_expect_item(external_impl_did).kind
360 && !sig.header.asyncness.is_async()
361 {
362 let msg = "change the output type to match the declaration";
363 let ap = Applicability::MachineApplicable;
364 match sig.decl.output {
365 hir::FnRetTy::DefaultReturn(sp) => {
366 let sugg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" -> {0}",
declaration_sig.output()))
})format!(" -> {}", declaration_sig.output());
367 diag.span_suggestion_verbose(sp, msg, sugg, ap);
368 }
369 hir::FnRetTy::Return(hir_ty) => {
370 let sugg = declaration_sig.output();
371 diag.span_suggestion_verbose(hir_ty.span, msg, sugg, ap);
372 }
373 };
374 };
375 } else if let Some(trait_ty) = declaration_sig.inputs().get(*i) {
376 diag.span_suggestion_verbose(
377 impl_err_span,
378 "change the parameter type to match the declaration",
379 trait_ty,
380 Applicability::MachineApplicable,
381 );
382 }
383 }
384 _ => {}
385 }
386
387 cause.span = impl_err_span;
388 infcx.err_ctxt().note_type_err(
389 &mut diag,
390 &cause,
391 trait_err_span.map(|sp| (sp, Cow::from("type in declaration"), false)),
392 Some(param_env.and(infer::ValuePairs::PolySigs(ExpectedFound {
393 expected: ty::Binder::dummy(declaration_sig),
394 found: ty::Binder::dummy(external_impl_sig),
395 }))),
396 terr,
397 false,
398 None,
399 );
400
401 diag.emit()
402}
403
404#[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(404u32),
::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))]
405fn extract_spans_for_error_reporting<'tcx>(
406 infcx: &infer::InferCtxt<'tcx>,
407 terr: TypeError<'_>,
408 cause: &ObligationCause<'tcx>,
409 declaration: DefId,
410 external_impl: LocalDefId,
411) -> (Span, Option<Span>, Ident) {
412 let tcx = infcx.tcx;
413 let (mut external_impl_args, external_impl_name) = {
414 let item = tcx.hir_expect_item(external_impl);
415 let (ident, sig, _, _) = item.expect_fn();
416 (sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())), ident)
417 };
418
419 let declaration_args = declaration.as_local().map(|def_id| {
420 if let Some(sig) = get_declaration_sig(tcx, def_id) {
421 sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
422 } else {
423 panic!("expected {def_id:?} to be a foreign function");
424 }
425 });
426
427 match terr {
428 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => (
429 external_impl_args.nth(i).unwrap(),
430 declaration_args.and_then(|mut args| args.nth(i)),
431 external_impl_name,
432 ),
433 _ => (
434 cause.span,
435 tcx.hir_span_if_local(declaration).or_else(|| Some(tcx.def_span(declaration))),
436 external_impl_name,
437 ),
438 }
439}
440
441fn get_declaration_sig<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<&'tcx FnSig<'tcx>> {
442 let hir_id: HirId = tcx.local_def_id_to_hir_id(def_id);
443 tcx.hir_fn_sig_by_hir_id(hir_id)
444}