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, TraitErrors};
17use rustc_middle::ty::error::{ExpectedFound, TypeError};
18use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized};
19use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
20use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
21use rustc_trait_selection::regions::InferCtxtRegionExt;
22use rustc_trait_selection::traits::{self, ObligationCtxt};
23use tracing::{debug, instrument};
24
25use super::potentially_plural_count;
26use crate::check::compare_impl_item::{
27 CheckNumberOfEarlyBoundRegionsError, check_number_of_early_bound_regions,
28};
29use crate::diagnostics::{
30 EiiDefkindMismatch, EiiDefkindMismatchStaticMutability, EiiDefkindMismatchStaticSafety,
31 EiiWithGenerics, LifetimesOrBoundsMismatchOnEii,
32};
33
34pub(crate) fn compare_eii_function_types<'tcx>(
38 tcx: TyCtxt<'tcx>,
39 external_impl: LocalDefId,
40 foreign_item: DefId,
41 eii_name: Symbol,
42 eii_attr_span: Span,
43) -> Result<(), ErrorGuaranteed> {
44 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(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("declaration_sig")
}> =
::tracing::__macro_support::FieldName::new("declaration_sig");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&declaration_sig)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?declaration_sig);
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(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("external_impl_sig")
}> =
::tracing::__macro_support::FieldName::new("external_impl_sig");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&external_impl_sig)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?external_impl_sig);
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",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("external_impl_sig")
}> =
::tracing::__macro_support::FieldName::new("external_impl_sig");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("declaration_sig")
}> =
::tracing::__macro_support::FieldName::new("declaration_sig");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("terr")
}> =
::tracing::__macro_support::FieldName::new("terr");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("sub_types failed")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&external_impl_sig)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&declaration_sig)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&terr)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?external_impl_sig, ?declaration_sig, ?terr, "sub_types failed");
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 let TraitErrors::HasErrors(errors) = errors {
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(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("declaration_ty")
}> =
::tracing::__macro_support::FieldName::new("declaration_ty");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&declaration_ty)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?declaration_ty);
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",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("external_impl_ty")
}> =
::tracing::__macro_support::FieldName::new("external_impl_ty");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("declaration_ty")
}> =
::tracing::__macro_support::FieldName::new("declaration_ty");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("terr")
}> =
::tracing::__macro_support::FieldName::new("terr");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("sub_types failed")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&external_impl_ty)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&declaration_ty)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&terr)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?external_impl_ty, ?declaration_ty, ?terr, "sub_types failed");
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 let TraitErrors::HasErrors(errors) = errors {
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_attr_ir::HasAttrs::get_attrs(external_impl, &tcx) {
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(EiiImpl(i)) if
#[allow(non_exhaustive_omitted_patterns)] match i.resolution
{
EiiImplResolution::Macro(_) => true,
_ => false,
} => {
break 'done Some(());
}
::rustc_attr_ir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some()find_attr!(tcx, external_impl, EiiImpl(i) if matches!(i.resolution, EiiImplResolution::Macro(_)))
305 {
306 tcx.dcx().emit_err(EiiWithGenerics {
307 span: tcx.def_span(external_impl),
308 attr: eii_attr_span,
309 eii_name,
310 impl_name: tcx.item_name(external_impl),
311 });
312 }
313
314 Ok(())
315}
316
317fn check_early_region_bounds<'tcx>(
318 tcx: TyCtxt<'tcx>,
319 external_impl: LocalDefId,
320 declaration: DefId,
321 eii_attr_span: Span,
322) -> Result<(), ErrorGuaranteed> {
323 let external_impl_generics = tcx.generics_of(external_impl.to_def_id());
324 let external_impl_params = external_impl_generics.own_counts().lifetimes;
325
326 let declaration_generics = tcx.generics_of(declaration);
327 let declaration_params = declaration_generics.own_counts().lifetimes;
328
329 let Err(CheckNumberOfEarlyBoundRegionsError { span, generics_span, bounds_span, where_span }) =
330 check_number_of_early_bound_regions(
331 tcx,
332 external_impl,
333 declaration,
334 external_impl_generics,
335 external_impl_params,
336 declaration_generics,
337 declaration_params,
338 )
339 else {
340 return Ok(());
341 };
342
343 let mut diag = tcx.dcx().create_err(LifetimesOrBoundsMismatchOnEii {
344 span,
345 ident: tcx.item_name(external_impl.to_def_id()),
346 generics_span,
347 bounds_span,
348 where_span,
349 });
350
351 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"));
352 return Err(diag.emit());
353}
354
355fn check_number_of_arguments<'tcx>(
356 tcx: TyCtxt<'tcx>,
357 external_impl: LocalDefId,
358 declaration: DefId,
359 eii_name: Symbol,
360 eii_attr_span: Span,
361) -> Result<(), ErrorGuaranteed> {
362 let external_impl_fty = tcx.fn_sig(external_impl);
363 let declaration_fty = tcx.fn_sig(declaration);
364 let declaration_number_args = declaration_fty.skip_binder().inputs().skip_binder().len();
365 let external_impl_number_args = external_impl_fty.skip_binder().inputs().skip_binder().len();
366
367 if declaration_number_args == external_impl_number_args {
369 Ok(())
370 } else {
371 Err(report_number_of_arguments_mismatch(
372 tcx,
373 external_impl,
374 declaration,
375 eii_name,
376 eii_attr_span,
377 declaration_number_args,
378 external_impl_number_args,
379 ))
380 }
381}
382
383fn report_number_of_arguments_mismatch<'tcx>(
384 tcx: TyCtxt<'tcx>,
385 external_impl: LocalDefId,
386 declaration: DefId,
387 eii_name: Symbol,
388 eii_attr_span: Span,
389 declaration_number_args: usize,
390 external_impl_number_args: usize,
391) -> ErrorGuaranteed {
392 let external_impl_name = tcx.item_name(external_impl.to_def_id());
393
394 let declaration_span = declaration
395 .as_local()
396 .and_then(|def_id| {
397 let declaration_sig = get_declaration_sig(tcx, def_id).expect("foreign item sig");
398 let pos = declaration_number_args.saturating_sub(1);
399 declaration_sig.decl.inputs.get(pos).map(|arg| {
400 if pos == 0 {
401 arg.span
402 } else {
403 arg.span.with_lo(declaration_sig.decl.inputs[0].span.lo())
404 }
405 })
406 })
407 .or_else(|| tcx.hir_span_if_local(declaration))
408 .unwrap_or_else(|| tcx.def_span(declaration));
409
410 let (_, external_impl_sig, _, _) = &tcx.hir_expect_item(external_impl).expect_fn();
411 let pos = external_impl_number_args.saturating_sub(1);
412 let impl_span = external_impl_sig
413 .decl
414 .inputs
415 .get(pos)
416 .map(|arg| {
417 if pos == 0 {
418 arg.span
419 } else {
420 arg.span.with_lo(external_impl_sig.decl.inputs[0].span.lo())
421 }
422 })
423 .unwrap_or_else(|| tcx.def_span(external_impl));
424
425 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!(
426 tcx.dcx(),
427 impl_span,
428 E0806,
429 "`{external_impl_name}` has {} but #[{eii_name}] requires it to have {}",
430 potentially_plural_count(external_impl_number_args, "parameter"),
431 declaration_number_args
432 );
433
434 err.span_label(
435 declaration_span,
436 ::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")),
437 );
438
439 err.span_label(
440 impl_span,
441 ::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!(
442 "expected {}, found {}",
443 potentially_plural_count(declaration_number_args, "parameter"),
444 external_impl_number_args
445 ),
446 );
447
448 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"));
449
450 err.emit()
451}
452
453fn report_eii_mismatch<'tcx>(
454 infcx: &InferCtxt<'tcx>,
455 mut cause: ObligationCause<'tcx>,
456 param_env: ty::ParamEnv<'tcx>,
457 terr: TypeError<'tcx>,
458 (declaration_did, declaration_sig): (DefId, ty::FnSig<'tcx>),
459 (external_impl_did, external_impl_sig): (LocalDefId, ty::FnSig<'tcx>),
460 eii_attr_span: Span,
461 eii_name: Symbol,
462) -> ErrorGuaranteed {
463 let tcx = infcx.tcx;
464 let (impl_err_span, trait_err_span, external_impl_name) =
465 extract_spans_for_error_reporting(infcx, terr, &cause, declaration_did, external_impl_did);
466
467 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!(
468 tcx.dcx(),
469 impl_err_span,
470 E0806,
471 "function `{}` has a type that is incompatible with the declaration of `#[{eii_name}]`",
472 external_impl_name
473 );
474
475 diag.span_note(eii_attr_span, "expected this because of this attribute");
476
477 match &terr {
478 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
479 if declaration_sig.inputs().len() == *i {
480 if let ItemKind::Fn { sig, .. } = &tcx.hir_expect_item(external_impl_did).kind
483 && !sig.header.asyncness.is_async()
484 {
485 let msg = "change the output type to match the declaration";
486 let ap = Applicability::MachineApplicable;
487 match sig.decl.output {
488 hir::FnRetTy::DefaultReturn(sp) => {
489 let sugg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" -> {0}",
declaration_sig.output()))
})format!(" -> {}", declaration_sig.output());
490 diag.span_suggestion_verbose(sp, msg, sugg, ap);
491 }
492 hir::FnRetTy::Return(hir_ty) => {
493 let sugg = declaration_sig.output();
494 diag.span_suggestion_verbose(hir_ty.span, msg, sugg, ap);
495 }
496 };
497 };
498 } else if let Some(trait_ty) = declaration_sig.inputs().get(*i) {
499 diag.span_suggestion_verbose(
500 impl_err_span,
501 "change the parameter type to match the declaration",
502 trait_ty,
503 Applicability::MachineApplicable,
504 );
505 }
506 }
507 _ => {}
508 }
509
510 cause.span = impl_err_span;
511 infcx.err_ctxt().note_type_err(
512 &mut diag,
513 &cause,
514 trait_err_span.map(|sp| (sp, Cow::from("type in declaration"), false)),
515 Some(param_env.and(infer::ValuePairs::PolySigs(ExpectedFound {
516 expected: ty::Binder::dummy(declaration_sig),
517 found: ty::Binder::dummy(external_impl_sig),
518 }))),
519 terr,
520 false,
521 None,
522 );
523
524 diag.emit()
525}
526
527#[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(527u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::check::compare_eii"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("terr")
}> =
::tracing::__macro_support::FieldName::new("terr");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("cause")
}> =
::tracing::__macro_support::FieldName::new("cause");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("declaration")
}> =
::tracing::__macro_support::FieldName::new("declaration");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("external_impl")
}> =
::tracing::__macro_support::FieldName::new("external_impl");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&terr)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cause)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&declaration)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&external_impl)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: (Span, Option<Span>, Ident) =
loop {};
return __tracing_attr_fake_return;
}
{
let tcx = infcx.tcx;
let (mut external_impl_args, external_impl_name) =
{
let item = tcx.hir_expect_item(external_impl);
let (ident, sig, _, _) = item.expect_fn();
(sig.decl.inputs.iter().map(|t|
t.span).chain(iter::once(sig.decl.output.span())), ident)
};
let declaration_args =
declaration.as_local().map(|def_id|
{
if let Some(sig) = get_declaration_sig(tcx, def_id) {
sig.decl.inputs.iter().map(|t|
t.span).chain(iter::once(sig.decl.output.span()))
} else {
{
::core::panicking::panic_fmt(format_args!("expected {0:?} to be a foreign function",
def_id));
};
}
});
match terr {
TypeError::ArgumentMutability(i) |
TypeError::ArgumentSorts(ExpectedFound { .. }, i) =>
(external_impl_args.nth(i).unwrap(),
declaration_args.and_then(|mut args| args.nth(i)),
external_impl_name),
_ =>
(cause.span,
tcx.hir_span_if_local(declaration).or_else(||
Some(tcx.def_span(declaration))), external_impl_name),
}
}
}
}#[instrument(level = "debug", skip(infcx))]
528fn extract_spans_for_error_reporting<'tcx>(
529 infcx: &infer::InferCtxt<'tcx>,
530 terr: TypeError<'_>,
531 cause: &ObligationCause<'tcx>,
532 declaration: DefId,
533 external_impl: LocalDefId,
534) -> (Span, Option<Span>, Ident) {
535 let tcx = infcx.tcx;
536 let (mut external_impl_args, external_impl_name) = {
537 let item = tcx.hir_expect_item(external_impl);
538 let (ident, sig, _, _) = item.expect_fn();
539 (sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())), ident)
540 };
541
542 let declaration_args = declaration.as_local().map(|def_id| {
543 if let Some(sig) = get_declaration_sig(tcx, def_id) {
544 sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
545 } else {
546 panic!("expected {def_id:?} to be a foreign function");
547 }
548 });
549
550 match terr {
551 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => (
552 external_impl_args.nth(i).unwrap(),
553 declaration_args.and_then(|mut args| args.nth(i)),
554 external_impl_name,
555 ),
556 _ => (
557 cause.span,
558 tcx.hir_span_if_local(declaration).or_else(|| Some(tcx.def_span(declaration))),
559 external_impl_name,
560 ),
561 }
562}
563
564fn get_declaration_sig<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<&'tcx FnSig<'tcx>> {
565 let hir_id: HirId = tcx.local_def_id_to_hir_id(def_id);
566 tcx.hir_fn_sig_by_hir_id(hir_id)
567}