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::{AttributeKind, 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 && {
{
'done:
{
for i in tcx.get_all_attrs(external_impl) {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::EiiImpls(impls))
if
impls.iter().any(|i|
#[allow(non_exhaustive_omitted_patterns)] match i.resolution
{
EiiImplResolution::Macro(_) => true,
_ => false,
}) => {
break 'done Some(());
}
_ => {}
}
}
None
}
}.is_some()
}find_attr!(
181 tcx.get_all_attrs(external_impl),
182 AttributeKind::EiiImpls(impls) if impls.iter().any(|i| matches!(i.resolution, EiiImplResolution::Macro(_)))
183 )
184 {
185 tcx.dcx().emit_err(EiiWithGenerics {
186 span: tcx.def_span(external_impl),
187 attr: eii_attr_span,
188 eii_name,
189 impl_name: tcx.item_name(external_impl),
190 });
191 }
192
193 Ok(())
194}
195
196fn check_early_region_bounds<'tcx>(
197 tcx: TyCtxt<'tcx>,
198 external_impl: LocalDefId,
199 declaration: DefId,
200 eii_attr_span: Span,
201) -> Result<(), ErrorGuaranteed> {
202 let external_impl_generics = tcx.generics_of(external_impl.to_def_id());
203 let external_impl_params = external_impl_generics.own_counts().lifetimes;
204
205 let declaration_generics = tcx.generics_of(declaration);
206 let declaration_params = declaration_generics.own_counts().lifetimes;
207
208 let Err(CheckNumberOfEarlyBoundRegionsError { span, generics_span, bounds_span, where_span }) =
209 check_number_of_early_bound_regions(
210 tcx,
211 external_impl,
212 declaration,
213 external_impl_generics,
214 external_impl_params,
215 declaration_generics,
216 declaration_params,
217 )
218 else {
219 return Ok(());
220 };
221
222 let mut diag = tcx.dcx().create_err(LifetimesOrBoundsMismatchOnEii {
223 span,
224 ident: tcx.item_name(external_impl.to_def_id()),
225 generics_span,
226 bounds_span,
227 where_span,
228 });
229
230 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"));
231 return Err(diag.emit());
232}
233
234fn check_number_of_arguments<'tcx>(
235 tcx: TyCtxt<'tcx>,
236 external_impl: LocalDefId,
237 declaration: DefId,
238 eii_name: Symbol,
239 eii_attr_span: Span,
240) -> Result<(), ErrorGuaranteed> {
241 let external_impl_fty = tcx.fn_sig(external_impl);
242 let declaration_fty = tcx.fn_sig(declaration);
243 let declaration_number_args = declaration_fty.skip_binder().inputs().skip_binder().len();
244 let external_impl_number_args = external_impl_fty.skip_binder().inputs().skip_binder().len();
245
246 if declaration_number_args == external_impl_number_args {
248 Ok(())
249 } else {
250 Err(report_number_of_arguments_mismatch(
251 tcx,
252 external_impl,
253 declaration,
254 eii_name,
255 eii_attr_span,
256 declaration_number_args,
257 external_impl_number_args,
258 ))
259 }
260}
261
262fn report_number_of_arguments_mismatch<'tcx>(
263 tcx: TyCtxt<'tcx>,
264 external_impl: LocalDefId,
265 declaration: DefId,
266 eii_name: Symbol,
267 eii_attr_span: Span,
268 declaration_number_args: usize,
269 external_impl_number_args: usize,
270) -> ErrorGuaranteed {
271 let external_impl_name = tcx.item_name(external_impl.to_def_id());
272
273 let declaration_span = declaration
274 .as_local()
275 .and_then(|def_id| {
276 let declaration_sig = get_declaration_sig(tcx, def_id).expect("foreign item sig");
277 let pos = declaration_number_args.saturating_sub(1);
278 declaration_sig.decl.inputs.get(pos).map(|arg| {
279 if pos == 0 {
280 arg.span
281 } else {
282 arg.span.with_lo(declaration_sig.decl.inputs[0].span.lo())
283 }
284 })
285 })
286 .or_else(|| tcx.hir_span_if_local(declaration))
287 .unwrap_or_else(|| tcx.def_span(declaration));
288
289 let (_, external_impl_sig, _, _) = &tcx.hir_expect_item(external_impl).expect_fn();
290 let pos = external_impl_number_args.saturating_sub(1);
291 let impl_span = external_impl_sig
292 .decl
293 .inputs
294 .get(pos)
295 .map(|arg| {
296 if pos == 0 {
297 arg.span
298 } else {
299 arg.span.with_lo(external_impl_sig.decl.inputs[0].span.lo())
300 }
301 })
302 .unwrap_or_else(|| tcx.def_span(external_impl));
303
304 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!(
305 tcx.dcx(),
306 impl_span,
307 E0806,
308 "`{external_impl_name}` has {} but #[{eii_name}] requires it to have {}",
309 potentially_plural_count(external_impl_number_args, "parameter"),
310 declaration_number_args
311 );
312
313 err.span_label(
314 declaration_span,
315 ::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")),
316 );
317
318 err.span_label(
319 impl_span,
320 ::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!(
321 "expected {}, found {}",
322 potentially_plural_count(declaration_number_args, "parameter"),
323 external_impl_number_args
324 ),
325 );
326
327 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"));
328
329 err.emit()
330}
331
332fn report_eii_mismatch<'tcx>(
333 infcx: &InferCtxt<'tcx>,
334 mut cause: ObligationCause<'tcx>,
335 param_env: ty::ParamEnv<'tcx>,
336 terr: TypeError<'tcx>,
337 (declaration_did, declaration_sig): (DefId, ty::FnSig<'tcx>),
338 (external_impl_did, external_impl_sig): (LocalDefId, ty::FnSig<'tcx>),
339 eii_attr_span: Span,
340 eii_name: Symbol,
341) -> ErrorGuaranteed {
342 let tcx = infcx.tcx;
343 let (impl_err_span, trait_err_span, external_impl_name) =
344 extract_spans_for_error_reporting(infcx, terr, &cause, declaration_did, external_impl_did);
345
346 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!(
347 tcx.dcx(),
348 impl_err_span,
349 E0806,
350 "function `{}` has a type that is incompatible with the declaration of `#[{eii_name}]`",
351 external_impl_name
352 );
353
354 diag.span_note(eii_attr_span, "expected this because of this attribute");
355
356 match &terr {
357 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
358 if declaration_sig.inputs().len() == *i {
359 if let ItemKind::Fn { sig, .. } = &tcx.hir_expect_item(external_impl_did).kind
362 && !sig.header.asyncness.is_async()
363 {
364 let msg = "change the output type to match the declaration";
365 let ap = Applicability::MachineApplicable;
366 match sig.decl.output {
367 hir::FnRetTy::DefaultReturn(sp) => {
368 let sugg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" -> {0}",
declaration_sig.output()))
})format!(" -> {}", declaration_sig.output());
369 diag.span_suggestion_verbose(sp, msg, sugg, ap);
370 }
371 hir::FnRetTy::Return(hir_ty) => {
372 let sugg = declaration_sig.output();
373 diag.span_suggestion_verbose(hir_ty.span, msg, sugg, ap);
374 }
375 };
376 };
377 } else if let Some(trait_ty) = declaration_sig.inputs().get(*i) {
378 diag.span_suggestion_verbose(
379 impl_err_span,
380 "change the parameter type to match the declaration",
381 trait_ty,
382 Applicability::MachineApplicable,
383 );
384 }
385 }
386 _ => {}
387 }
388
389 cause.span = impl_err_span;
390 infcx.err_ctxt().note_type_err(
391 &mut diag,
392 &cause,
393 trait_err_span.map(|sp| (sp, Cow::from("type in declaration"), false)),
394 Some(param_env.and(infer::ValuePairs::PolySigs(ExpectedFound {
395 expected: ty::Binder::dummy(declaration_sig),
396 found: ty::Binder::dummy(external_impl_sig),
397 }))),
398 terr,
399 false,
400 None,
401 );
402
403 diag.emit()
404}
405
406#[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(406u32),
::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))]
407fn extract_spans_for_error_reporting<'tcx>(
408 infcx: &infer::InferCtxt<'tcx>,
409 terr: TypeError<'_>,
410 cause: &ObligationCause<'tcx>,
411 declaration: DefId,
412 external_impl: LocalDefId,
413) -> (Span, Option<Span>, Ident) {
414 let tcx = infcx.tcx;
415 let (mut external_impl_args, external_impl_name) = {
416 let item = tcx.hir_expect_item(external_impl);
417 let (ident, sig, _, _) = item.expect_fn();
418 (sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())), ident)
419 };
420
421 let declaration_args = declaration.as_local().map(|def_id| {
422 if let Some(sig) = get_declaration_sig(tcx, def_id) {
423 sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
424 } else {
425 panic!("expected {def_id:?} to be a foreign function");
426 }
427 });
428
429 match terr {
430 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => (
431 external_impl_args.nth(i).unwrap(),
432 declaration_args.and_then(|mut args| args.nth(i)),
433 external_impl_name,
434 ),
435 _ => (
436 cause.span,
437 tcx.hir_span_if_local(declaration).or_else(|| Some(tcx.def_span(declaration))),
438 external_impl_name,
439 ),
440 }
441}
442
443fn get_declaration_sig<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<&'tcx FnSig<'tcx>> {
444 let hir_id: HirId = tcx.local_def_id_to_hir_id(def_id);
445 tcx.hir_fn_sig_by_hir_id(hir_id)
446}