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, 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::errors::{
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 check_eii_target(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?;
45 check_is_structurally_compatible(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?;
46
47 let external_impl_span = tcx.def_span(external_impl);
48 let cause = ObligationCause::new(
49 external_impl_span,
50 external_impl,
51 ObligationCauseCode::CompareEii { external_impl, declaration: foreign_item },
52 );
53
54 let param_env = tcx.param_env(foreign_item);
56
57 let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
58 let ocx = ObligationCtxt::new_with_diagnostics(infcx);
59
60 let mut wf_tys = FxIndexSet::default();
69 let norm_cause = ObligationCause::misc(external_impl_span, external_impl);
70
71 let declaration_sig = tcx.fn_sig(foreign_item).instantiate_identity().skip_norm_wip();
72 let declaration_sig = tcx.liberate_late_bound_regions(external_impl.into(), declaration_sig);
73 {
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:73",
"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(73u32),
::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);
74
75 let unnormalized_external_impl_sig = infcx.instantiate_binder_with_fresh_vars(
76 external_impl_span,
77 infer::BoundRegionConversionTime::HigherRankedType,
78 tcx.fn_sig(external_impl)
79 .instantiate(
80 tcx,
81 infcx.fresh_args_for_item(external_impl_span, external_impl.to_def_id()),
82 )
83 .skip_norm_wip(),
84 );
85 let external_impl_sig = ocx.normalize(
86 &norm_cause,
87 param_env,
88 Unnormalized::new_wip(unnormalized_external_impl_sig),
89 );
90 {
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:90",
"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(90u32),
::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);
91
92 wf_tys.extend(declaration_sig.inputs_and_output.iter());
96 let declaration_sig =
97 ocx.normalize(&norm_cause, param_env, Unnormalized::new_wip(declaration_sig));
98 wf_tys.extend(external_impl_sig.inputs_and_output.iter());
101
102 let result = ocx.sup(&cause, param_env, declaration_sig, external_impl_sig);
110
111 if let Err(terr) = result {
112 {
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:112",
"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(112u32),
::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");
113
114 let emitted = report_eii_mismatch(
115 infcx,
116 cause,
117 param_env,
118 terr,
119 (foreign_item, declaration_sig),
120 (external_impl, external_impl_sig),
121 eii_attr_span,
122 eii_name,
123 );
124 return Err(emitted);
125 }
126
127 if !(declaration_sig, external_impl_sig).references_error() {
128 for ty in unnormalized_external_impl_sig.inputs_and_output {
129 ocx.register_obligation(traits::Obligation::new(
130 infcx.tcx,
131 cause.clone(),
132 param_env,
133 ty::ClauseKind::WellFormed(ty.into()),
134 ));
135 }
136 }
137
138 let errors = ocx.evaluate_obligations_error_on_ambiguity();
141 if !errors.is_empty() {
142 let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
143 return Err(reported);
144 }
145
146 let errors = infcx.resolve_regions(external_impl, param_env, wf_tys);
149 if !errors.is_empty() {
150 return Err(infcx
151 .tainted_by_errors()
152 .unwrap_or_else(|| infcx.err_ctxt().report_region_errors(external_impl, &errors)));
153 }
154
155 Ok(())
156}
157
158pub(crate) fn compare_eii_statics<'tcx>(
159 tcx: TyCtxt<'tcx>,
160 external_impl: LocalDefId,
161 external_impl_ty: Ty<'tcx>,
162 foreign_item: DefId,
163 eii_name: Symbol,
164 eii_attr_span: Span,
165) -> Result<(), ErrorGuaranteed> {
166 check_eii_target(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?;
167
168 let external_impl_span = tcx.def_span(external_impl);
169 let cause = ObligationCause::new(
170 external_impl_span,
171 external_impl,
172 ObligationCauseCode::CompareEii { external_impl, declaration: foreign_item },
173 );
174
175 let param_env = ParamEnv::empty();
176
177 let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
178 let ocx = ObligationCtxt::new_with_diagnostics(infcx);
179
180 let declaration_ty = tcx.type_of(foreign_item).instantiate_identity().skip_norm_wip();
181 {
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:181",
"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(181u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::check::compare_eii"),
::tracing_core::field::FieldSet::new(&["declaration_ty"],
::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_ty)
as &dyn Value))])
});
} else { ; }
};debug!(?declaration_ty);
182
183 let result = ocx.sup(&cause, param_env, declaration_ty, external_impl_ty);
191
192 if let Err(terr) = result {
193 {
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:193",
"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(193u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::check::compare_eii"),
::tracing_core::field::FieldSet::new(&["message",
"external_impl_ty", "declaration_ty", "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_ty)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&declaration_ty)
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_ty, ?declaration_ty, ?terr, "sub_types failed");
194
195 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!(
196 tcx.dcx(),
197 cause.span,
198 E0806,
199 "static `{}` has a type that is incompatible with the declaration of `#[{eii_name}]`",
200 tcx.item_name(external_impl)
201 );
202 diag.span_note(eii_attr_span, "expected this because of this attribute");
203
204 return Err(diag.emit());
205 }
206
207 let errors = ocx.evaluate_obligations_error_on_ambiguity();
210 if !errors.is_empty() {
211 let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
212 return Err(reported);
213 }
214
215 let errors = infcx.resolve_regions(external_impl, param_env, []);
218 if !errors.is_empty() {
219 return Err(infcx
220 .tainted_by_errors()
221 .unwrap_or_else(|| infcx.err_ctxt().report_region_errors(external_impl, &errors)));
222 }
223
224 Ok(())
225}
226
227fn check_eii_target(
228 tcx: TyCtxt<'_>,
229 external_impl: LocalDefId,
230 foreign_item: DefId,
231 eii_name: Symbol,
232 eii_attr_span: Span,
233) -> Result<(), ErrorGuaranteed> {
234 if !tcx.is_foreign_item(foreign_item) {
239 return Err(tcx.dcx().delayed_bug("EII is a foreign item"));
240 }
241 let expected_kind = tcx.def_kind(foreign_item);
242 let actual_kind = tcx.def_kind(external_impl);
243
244 match expected_kind {
245 _ if expected_kind == actual_kind => Ok(()),
247 DefKind::Static { mutability: m1, safety: s1, .. }
248 if let DefKind::Static { mutability: m2, safety: s2, .. } = actual_kind =>
249 {
250 Err(if s1 != s2 {
251 tcx.dcx().emit_err(EiiDefkindMismatchStaticSafety { span: eii_attr_span, eii_name })
252 } else if m1 != m2 {
253 tcx.dcx()
254 .emit_err(EiiDefkindMismatchStaticMutability { span: eii_attr_span, eii_name })
255 } else {
256 ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
257 })
258 }
259 DefKind::Fn | DefKind::Static { .. } => Err(tcx.dcx().emit_err(EiiDefkindMismatch {
261 span: eii_attr_span,
262 eii_name,
263 expected_kind: expected_kind.descr(foreign_item),
264 })),
265 _ => Err(tcx.dcx().delayed_bug("Attribute should not be allowed by target checking")),
267 }
268}
269
270fn check_is_structurally_compatible<'tcx>(
276 tcx: TyCtxt<'tcx>,
277 external_impl: LocalDefId,
278 declaration: DefId,
279 eii_name: Symbol,
280 eii_attr_span: Span,
281) -> Result<(), ErrorGuaranteed> {
282 check_no_generics(tcx, external_impl, declaration, eii_name, eii_attr_span)?;
283 check_number_of_arguments(tcx, external_impl, declaration, eii_name, eii_attr_span)?;
284 check_early_region_bounds(tcx, external_impl, declaration, eii_attr_span)?;
285 Ok(())
286}
287
288fn check_no_generics<'tcx>(
290 tcx: TyCtxt<'tcx>,
291 external_impl: LocalDefId,
292 _declaration: DefId,
293 eii_name: Symbol,
294 eii_attr_span: Span,
295) -> Result<(), ErrorGuaranteed> {
296 let generics = tcx.generics_of(external_impl);
297 if generics.own_requires_monomorphization()
298 && {
{
'done:
{
for i in
::rustc_hir::attrs::HasAttrs::get_attrs(external_impl, &tcx)
{
#[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(_)))
305 )
306 {
307 tcx.dcx().emit_err(EiiWithGenerics {
308 span: tcx.def_span(external_impl),
309 attr: eii_attr_span,
310 eii_name,
311 impl_name: tcx.item_name(external_impl),
312 });
313 }
314
315 Ok(())
316}
317
318fn check_early_region_bounds<'tcx>(
319 tcx: TyCtxt<'tcx>,
320 external_impl: LocalDefId,
321 declaration: DefId,
322 eii_attr_span: Span,
323) -> Result<(), ErrorGuaranteed> {
324 let external_impl_generics = tcx.generics_of(external_impl.to_def_id());
325 let external_impl_params = external_impl_generics.own_counts().lifetimes;
326
327 let declaration_generics = tcx.generics_of(declaration);
328 let declaration_params = declaration_generics.own_counts().lifetimes;
329
330 let Err(CheckNumberOfEarlyBoundRegionsError { span, generics_span, bounds_span, where_span }) =
331 check_number_of_early_bound_regions(
332 tcx,
333 external_impl,
334 declaration,
335 external_impl_generics,
336 external_impl_params,
337 declaration_generics,
338 declaration_params,
339 )
340 else {
341 return Ok(());
342 };
343
344 let mut diag = tcx.dcx().create_err(LifetimesOrBoundsMismatchOnEii {
345 span,
346 ident: tcx.item_name(external_impl.to_def_id()),
347 generics_span,
348 bounds_span,
349 where_span,
350 });
351
352 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"));
353 return Err(diag.emit());
354}
355
356fn check_number_of_arguments<'tcx>(
357 tcx: TyCtxt<'tcx>,
358 external_impl: LocalDefId,
359 declaration: DefId,
360 eii_name: Symbol,
361 eii_attr_span: Span,
362) -> Result<(), ErrorGuaranteed> {
363 let external_impl_fty = tcx.fn_sig(external_impl);
364 let declaration_fty = tcx.fn_sig(declaration);
365 let declaration_number_args = declaration_fty.skip_binder().inputs().skip_binder().len();
366 let external_impl_number_args = external_impl_fty.skip_binder().inputs().skip_binder().len();
367
368 if declaration_number_args == external_impl_number_args {
370 Ok(())
371 } else {
372 Err(report_number_of_arguments_mismatch(
373 tcx,
374 external_impl,
375 declaration,
376 eii_name,
377 eii_attr_span,
378 declaration_number_args,
379 external_impl_number_args,
380 ))
381 }
382}
383
384fn report_number_of_arguments_mismatch<'tcx>(
385 tcx: TyCtxt<'tcx>,
386 external_impl: LocalDefId,
387 declaration: DefId,
388 eii_name: Symbol,
389 eii_attr_span: Span,
390 declaration_number_args: usize,
391 external_impl_number_args: usize,
392) -> ErrorGuaranteed {
393 let external_impl_name = tcx.item_name(external_impl.to_def_id());
394
395 let declaration_span = declaration
396 .as_local()
397 .and_then(|def_id| {
398 let declaration_sig = get_declaration_sig(tcx, def_id).expect("foreign item sig");
399 let pos = declaration_number_args.saturating_sub(1);
400 declaration_sig.decl.inputs.get(pos).map(|arg| {
401 if pos == 0 {
402 arg.span
403 } else {
404 arg.span.with_lo(declaration_sig.decl.inputs[0].span.lo())
405 }
406 })
407 })
408 .or_else(|| tcx.hir_span_if_local(declaration))
409 .unwrap_or_else(|| tcx.def_span(declaration));
410
411 let (_, external_impl_sig, _, _) = &tcx.hir_expect_item(external_impl).expect_fn();
412 let pos = external_impl_number_args.saturating_sub(1);
413 let impl_span = external_impl_sig
414 .decl
415 .inputs
416 .get(pos)
417 .map(|arg| {
418 if pos == 0 {
419 arg.span
420 } else {
421 arg.span.with_lo(external_impl_sig.decl.inputs[0].span.lo())
422 }
423 })
424 .unwrap_or_else(|| tcx.def_span(external_impl));
425
426 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!(
427 tcx.dcx(),
428 impl_span,
429 E0806,
430 "`{external_impl_name}` has {} but #[{eii_name}] requires it to have {}",
431 potentially_plural_count(external_impl_number_args, "parameter"),
432 declaration_number_args
433 );
434
435 err.span_label(
436 declaration_span,
437 ::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")),
438 );
439
440 err.span_label(
441 impl_span,
442 ::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!(
443 "expected {}, found {}",
444 potentially_plural_count(declaration_number_args, "parameter"),
445 external_impl_number_args
446 ),
447 );
448
449 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"));
450
451 err.emit()
452}
453
454fn report_eii_mismatch<'tcx>(
455 infcx: &InferCtxt<'tcx>,
456 mut cause: ObligationCause<'tcx>,
457 param_env: ty::ParamEnv<'tcx>,
458 terr: TypeError<'tcx>,
459 (declaration_did, declaration_sig): (DefId, ty::FnSig<'tcx>),
460 (external_impl_did, external_impl_sig): (LocalDefId, ty::FnSig<'tcx>),
461 eii_attr_span: Span,
462 eii_name: Symbol,
463) -> ErrorGuaranteed {
464 let tcx = infcx.tcx;
465 let (impl_err_span, trait_err_span, external_impl_name) =
466 extract_spans_for_error_reporting(infcx, terr, &cause, declaration_did, external_impl_did);
467
468 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!(
469 tcx.dcx(),
470 impl_err_span,
471 E0806,
472 "function `{}` has a type that is incompatible with the declaration of `#[{eii_name}]`",
473 external_impl_name
474 );
475
476 diag.span_note(eii_attr_span, "expected this because of this attribute");
477
478 match &terr {
479 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
480 if declaration_sig.inputs().len() == *i {
481 if let ItemKind::Fn { sig, .. } = &tcx.hir_expect_item(external_impl_did).kind
484 && !sig.header.asyncness.is_async()
485 {
486 let msg = "change the output type to match the declaration";
487 let ap = Applicability::MachineApplicable;
488 match sig.decl.output {
489 hir::FnRetTy::DefaultReturn(sp) => {
490 let sugg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" -> {0}",
declaration_sig.output()))
})format!(" -> {}", declaration_sig.output());
491 diag.span_suggestion_verbose(sp, msg, sugg, ap);
492 }
493 hir::FnRetTy::Return(hir_ty) => {
494 let sugg = declaration_sig.output();
495 diag.span_suggestion_verbose(hir_ty.span, msg, sugg, ap);
496 }
497 };
498 };
499 } else if let Some(trait_ty) = declaration_sig.inputs().get(*i) {
500 diag.span_suggestion_verbose(
501 impl_err_span,
502 "change the parameter type to match the declaration",
503 trait_ty,
504 Applicability::MachineApplicable,
505 );
506 }
507 }
508 _ => {}
509 }
510
511 cause.span = impl_err_span;
512 infcx.err_ctxt().note_type_err(
513 &mut diag,
514 &cause,
515 trait_err_span.map(|sp| (sp, Cow::from("type in declaration"), false)),
516 Some(param_env.and(infer::ValuePairs::PolySigs(ExpectedFound {
517 expected: ty::Binder::dummy(declaration_sig),
518 found: ty::Binder::dummy(external_impl_sig),
519 }))),
520 terr,
521 false,
522 None,
523 );
524
525 diag.emit()
526}
527
528#[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(528u32),
::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))]
529fn extract_spans_for_error_reporting<'tcx>(
530 infcx: &infer::InferCtxt<'tcx>,
531 terr: TypeError<'_>,
532 cause: &ObligationCause<'tcx>,
533 declaration: DefId,
534 external_impl: LocalDefId,
535) -> (Span, Option<Span>, Ident) {
536 let tcx = infcx.tcx;
537 let (mut external_impl_args, external_impl_name) = {
538 let item = tcx.hir_expect_item(external_impl);
539 let (ident, sig, _, _) = item.expect_fn();
540 (sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())), ident)
541 };
542
543 let declaration_args = declaration.as_local().map(|def_id| {
544 if let Some(sig) = get_declaration_sig(tcx, def_id) {
545 sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
546 } else {
547 panic!("expected {def_id:?} to be a foreign function");
548 }
549 });
550
551 match terr {
552 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => (
553 external_impl_args.nth(i).unwrap(),
554 declaration_args.and_then(|mut args| args.nth(i)),
555 external_impl_name,
556 ),
557 _ => (
558 cause.span,
559 tcx.hir_span_if_local(declaration).or_else(|| Some(tcx.def_span(declaration))),
560 external_impl_name,
561 ),
562 }
563}
564
565fn get_declaration_sig<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<&'tcx FnSig<'tcx>> {
566 let hir_id: HirId = tcx.local_def_id_to_hir_id(def_id);
567 tcx.hir_fn_sig_by_hir_id(hir_id)
568}