1use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
2use rustc_data_structures::sorted_map::SortedMap;
3use rustc_data_structures::thin_vec::ThinVec;
4use rustc_data_structures::unord::UnordMap;
5use rustc_errors::codes::*;
6use rustc_errors::{
7 Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, listify, msg, pluralize,
8 struct_span_code_err,
9};
10use rustc_hir::def::{CtorOf, DefKind, Res};
11use rustc_hir::def_id::DefId;
12use rustc_hir::{self as hir, HirId};
13use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
14use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
15use rustc_middle::ty::{
16 self, AdtDef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt,
17 suggest_constraining_type_param,
18};
19use rustc_session::diagnostics::feature_err;
20use rustc_span::edit_distance::find_best_match_for_name;
21use rustc_span::{BytePos, DUMMY_SP, Ident, OrdSpan, Span, Symbol, bug, kw, sym};
22use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
23use rustc_trait_selection::traits::{
24 FulfillmentError, dyn_compatibility_violations_for_assoc_item,
25};
26use smallvec::SmallVec;
27use tracing::debug;
28
29use super::InherentAssocCandidate;
30use crate::diagnostics::{
31 self, AssocItemConstraintsNotAllowedHere, ManualImplementation, ParenthesizedFnTraitExpansion,
32 TraitObjectDeclaredWithNoTraits,
33};
34use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
35
36impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
37 pub(crate) fn report_missing_generic_params(
38 &self,
39 missing_generic_params: Vec<(Symbol, ty::GenericParamDefKind)>,
40 def_id: DefId,
41 span: Span,
42 empty_generic_args: bool,
43 ) {
44 if missing_generic_params.is_empty() {
45 return;
46 }
47
48 self.dcx().emit_err(diagnostics::MissingGenericParams {
49 span,
50 def_span: self.tcx().def_span(def_id),
51 span_snippet: self.tcx().sess.source_map().span_to_snippet(span).ok(),
52 missing_generic_params,
53 empty_generic_args,
54 });
55 }
56
57 pub(crate) fn report_internal_fn_trait(
60 &self,
61 span: Span,
62 trait_def_id: DefId,
63 trait_segment: &'_ hir::PathSegment<'_>,
64 is_impl: bool,
65 ) {
66 if self.tcx().features().unboxed_closures() {
67 return;
68 }
69
70 let trait_def = self.tcx().trait_def(trait_def_id);
71 if !trait_def.paren_sugar {
72 if trait_segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar {
73 feature_err(
75 &self.tcx().sess,
76 sym::unboxed_closures,
77 span,
78 "parenthetical notation is only stable when used with `Fn`-family traits",
79 )
80 .emit();
81 }
82
83 return;
84 }
85
86 let sess = self.tcx().sess;
87
88 if trait_segment.args().parenthesized != hir::GenericArgsParentheses::ParenSugar {
89 let mut err = feature_err(
91 sess,
92 sym::unboxed_closures,
93 span,
94 "the precise format of `Fn`-family traits' type parameters is subject to change",
95 );
96 if !is_impl {
99 err.span_suggestion_verbose(
100 span,
101 "use parenthetical notation instead",
102 fn_trait_to_string(self.tcx(), trait_segment, true),
103 Applicability::MaybeIncorrect,
104 );
105 }
106 err.emit();
107 }
108
109 if is_impl {
110 let trait_name = self.tcx().def_path_str(trait_def_id);
111 self.dcx().emit_err(ManualImplementation { span, trait_name });
112 }
113 }
114
115 pub(super) fn report_unresolved_assoc_item<I>(
116 &self,
117 all_candidates: impl Fn() -> I,
118 qself: AssocItemQSelf,
119 assoc_tag: ty::AssocTag,
120 assoc_ident: Ident,
121 span: Span,
122 constraint: Option<&hir::AssocItemConstraint<'_>>,
123 ) -> ErrorGuaranteed
124 where
125 I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
126 {
127 let tcx = self.tcx();
128
129 if let Some(assoc_item) = all_candidates().find_map(|r| {
131 tcx.associated_items(r.def_id())
132 .filter_by_name_unhygienic(assoc_ident.name)
133 .find(|item| tcx.hygienic_eq(assoc_ident, item.ident(tcx), r.def_id()))
134 }) {
135 return self.report_assoc_kind_mismatch(
136 assoc_item,
137 assoc_tag,
138 assoc_ident,
139 span,
140 constraint,
141 );
142 }
143
144 let assoc_kind = assoc_tag_str(assoc_tag);
145 let qself_str = qself.to_string(tcx);
146
147 let is_dummy = assoc_ident.span == DUMMY_SP;
150
151 let mut err = diagnostics::AssocItemNotFound {
152 span: if is_dummy { span } else { assoc_ident.span },
153 assoc_ident,
154 assoc_kind,
155 qself: &qself_str,
156 label: None,
157 sugg: None,
158 within_macro_span: assoc_ident.span.within_macro(span, tcx.sess.source_map()),
161 };
162
163 if is_dummy {
164 err.label = Some(diagnostics::AssocItemNotFoundLabel::NotFound {
165 span,
166 assoc_ident,
167 assoc_kind,
168 });
169 return self.dcx().emit_err(err);
170 }
171
172 let all_candidate_names: Vec<_> = all_candidates()
173 .flat_map(|r| tcx.associated_items(r.def_id()).in_definition_order())
174 .filter_map(|item| {
175 if !item.is_impl_trait_in_trait() && item.tag() == assoc_tag {
176 item.opt_name()
177 } else {
178 None
179 }
180 })
181 .collect();
182
183 if let Some(suggested_name) =
184 find_best_match_for_name(&all_candidate_names, assoc_ident.name, None)
185 {
186 err.sugg = Some(diagnostics::AssocItemNotFoundSugg::Similar {
187 span: assoc_ident.span,
188 assoc_kind,
189 suggested_name,
190 });
191 return self.dcx().emit_err(err);
192 }
193
194 let visible_traits: Vec<_> = tcx
199 .visible_traits()
200 .filter(|trait_def_id| {
201 let viz = tcx.visibility(*trait_def_id);
202 viz.is_accessible_from(self.mod_id(), tcx)
203 })
204 .collect();
205
206 let wider_candidate_names: Vec<_> = visible_traits
207 .iter()
208 .flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order())
209 .filter_map(|item| {
210 (!item.is_impl_trait_in_trait() && item.tag() == assoc_tag).then(|| item.name())
211 })
212 .collect();
213
214 if let Some(suggested_name) =
215 find_best_match_for_name(&wider_candidate_names, assoc_ident.name, None)
216 {
217 if let [best_trait] = visible_traits
218 .iter()
219 .copied()
220 .filter(|&trait_def_id| {
221 tcx.associated_items(trait_def_id)
222 .filter_by_name_unhygienic(suggested_name)
223 .any(|item| item.tag() == assoc_tag)
224 })
225 .collect::<Vec<_>>()[..]
226 {
227 let trait_name = tcx.def_path_str(best_trait);
228 err.label = Some(diagnostics::AssocItemNotFoundLabel::FoundInOtherTrait {
229 span: assoc_ident.span,
230 assoc_kind,
231 trait_name: &trait_name,
232 suggested_name,
233 identically_named: suggested_name == assoc_ident.name,
234 });
235 if let AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span) = qself
236 && let item_def_id =
240 tcx.hir_get_parent_item(tcx.local_def_id_to_hir_id(ty_param_def_id))
241 && let Some(generics) = tcx.hir_get_generics(item_def_id.def_id)
243 {
244 if generics
248 .bounds_for_param(ty_param_def_id)
249 .flat_map(|pred| pred.bounds.iter())
250 .any(|b| match b {
251 hir::GenericBound::Trait(t, ..) => {
252 t.trait_ref.trait_def_id() == Some(best_trait)
253 }
254 _ => false,
255 })
256 {
257 err.sugg = Some(diagnostics::AssocItemNotFoundSugg::SimilarInOtherTrait {
260 span: assoc_ident.span,
261 trait_name: &trait_name,
262 assoc_kind,
263 suggested_name,
264 });
265 return self.dcx().emit_err(err);
266 }
267
268 let trait_args = &ty::GenericArgs::identity_for_item(tcx, best_trait)[1..];
269 let mut trait_ref = trait_name.clone();
270 let applicability = if let [arg, args @ ..] = trait_args {
271 use std::fmt::Write;
272 trait_ref.write_fmt(format_args!("</* {0}", arg))write!(trait_ref, "</* {arg}").unwrap();
273 args.iter().try_for_each(|arg| trait_ref.write_fmt(format_args!(", {0}", arg))write!(trait_ref, ", {arg}")).unwrap();
274 trait_ref += " */>";
275 Applicability::HasPlaceholders
276 } else {
277 Applicability::MaybeIncorrect
278 };
279
280 let identically_named = suggested_name == assoc_ident.name;
281
282 if let DefKind::TyAlias = tcx.def_kind(item_def_id)
283 && !tcx.type_alias_is_checked(item_def_id)
284 {
285 err.sugg =
286 Some(diagnostics::AssocItemNotFoundSugg::SimilarInOtherTraitQPath {
287 lo: ty_param_span.shrink_to_lo(),
288 mi: ty_param_span.shrink_to_hi(),
289 hi: (!identically_named).then_some(assoc_ident.span),
290 trait_ref,
291 identically_named,
292 suggested_name,
293 assoc_kind,
294 applicability,
295 });
296 } else {
297 let mut err = self.dcx().create_err(err);
298 if suggest_constraining_type_param(
299 tcx,
300 generics,
301 &mut err,
302 &qself_str,
303 &trait_ref,
304 Some(best_trait),
305 None,
306 ) && !identically_named
307 {
308 err.span_suggestion_verbose(
311 assoc_ident.span,
312 rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("...and changing the associated {$assoc_kind} name"))msg!("...and changing the associated {$assoc_kind} name"),
313 suggested_name,
314 Applicability::MaybeIncorrect,
315 );
316 }
317 return err.emit_err();
318 }
319 }
320 return self.dcx().emit_err(err);
321 }
322 }
323
324 if let [candidate_name] = all_candidate_names.as_slice() {
327 err.sugg = Some(diagnostics::AssocItemNotFoundSugg::Other {
328 span: assoc_ident.span,
329 qself: &qself_str,
330 assoc_kind,
331 suggested_name: *candidate_name,
332 });
333 } else {
334 err.label = Some(diagnostics::AssocItemNotFoundLabel::NotFound {
335 span: assoc_ident.span,
336 assoc_ident,
337 assoc_kind,
338 });
339 }
340
341 self.dcx().emit_err(err)
342 }
343
344 fn report_assoc_kind_mismatch(
345 &self,
346 assoc_item: &ty::AssocItem,
347 assoc_tag: ty::AssocTag,
348 ident: Ident,
349 span: Span,
350 constraint: Option<&hir::AssocItemConstraint<'_>>,
351 ) -> ErrorGuaranteed {
352 let tcx = self.tcx();
353
354 let bound_on_assoc_const_label = if let ty::AssocKind::Const { .. } = assoc_item.kind
355 && let Some(constraint) = constraint
356 && let hir::AssocItemConstraintKind::Bound { .. } = constraint.kind
357 {
358 let lo = if constraint.gen_args.span_ext.is_dummy() {
359 ident.span
360 } else {
361 constraint.gen_args.span_ext
362 };
363 Some(lo.between(span.shrink_to_hi()))
364 } else {
365 None
366 };
367
368 let wrap_in_braces_sugg = if let Some(constraint) = constraint
370 && let Some(hir_ty) = constraint.ty()
371 && let ty = self.lower_ty(hir_ty)
372 && (ty.is_enum() || ty.references_error())
373 && tcx.features().gca()
374 {
375 Some(diagnostics::AssocKindMismatchWrapInBracesSugg {
376 lo: hir_ty.span.shrink_to_lo(),
377 hi: hir_ty.span.shrink_to_hi(),
378 })
379 } else {
380 None
381 };
382
383 let (span, expected_because_label, expected, got) = if let Some(constraint) = constraint
386 && let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
387 {
388 let span = match term {
389 hir::Term::Ty(ty) => ty.span,
390 hir::Term::Const(ct) => ct.span,
391 };
392 (span, Some(ident.span), assoc_item.tag(), assoc_tag)
393 } else {
394 (ident.span, None, assoc_tag, assoc_item.tag())
395 };
396 let mut def_span: MultiSpan = tcx.def_span(assoc_item.def_id).into();
397 def_span.push_span_context(tcx.def_span(tcx.parent(assoc_item.def_id)));
398
399 let def_kind = tcx.def_kind(self.item_def_id());
400 let item_span = tcx.def_span(self.item_def_id()).shrink_to_lo();
401 let (item_span, enclosing_span) = match def_kind {
402 DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => (
403 item_span,
404 Some(tcx.def_span(tcx.parent(self.item_def_id().into())).shrink_to_lo()),
405 ),
406 DefKind::OpaqueTy => {
407 let item_span = tcx.def_span(tcx.parent(self.item_def_id().into())).shrink_to_lo();
408 let enclosing_span =
409 if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy =
410 tcx.def_kind(tcx.parent(self.item_def_id().into()))
411 {
412 Some(tcx.def_span(tcx.parent(self.item_def_id().into())).shrink_to_lo())
413 } else {
414 None
415 };
416 (item_span, enclosing_span)
417 }
418 _ => (item_span, None),
419 };
420 self.dcx().emit_err(diagnostics::AssocKindMismatch {
421 span,
422 item_span,
423 enclosing_span,
424 expected: assoc_tag_str(expected),
425 got: assoc_tag_str(got),
426 expected_because_label,
427 assoc_kind: assoc_tag_str(assoc_item.tag()),
428 def_span,
429 bound_on_assoc_const_label,
430 wrap_in_braces_sugg,
431 })
432 }
433
434 pub(super) fn report_ambiguous_assoc_item(
435 &self,
436 matching_candidates: &[ty::PolyTraitRef<'tcx>],
437 qself: AssocItemQSelf,
438 assoc_tag: ty::AssocTag,
439 assoc_ident: Ident,
440 span: Span,
441 constraint: Option<&hir::AssocItemConstraint<'_>>,
442 ) -> ErrorGuaranteed {
443 let tcx = self.tcx();
444
445 let assoc_kind_str = assoc_tag_str(assoc_tag);
446 let qself_str = qself.to_string(tcx);
447 let mut err = self.dcx().create_err(crate::diagnostics::AmbiguousAssocItem {
448 span,
449 assoc_kind: assoc_kind_str,
450 assoc_ident,
451 qself: &qself_str,
452 });
453 err.code(
455 if let Some(constraint) = constraint
456 && let hir::AssocItemConstraintKind::Equality { .. } = constraint.kind
457 {
458 E0222
459 } else {
460 E0221
461 },
462 );
463
464 let mut where_bounds = ::alloc::vec::Vec::new()vec![];
468 for &bound in matching_candidates {
469 let bound_id = bound.def_id();
470 let assoc_item = tcx.associated_items(bound_id).find_by_ident_and_kind(
471 tcx,
472 assoc_ident,
473 assoc_tag,
474 bound_id,
475 );
476 let bound_span = assoc_item.and_then(|item| tcx.hir_span_if_local(item.def_id));
477
478 if let Some(bound_span) = bound_span {
479 err.span_label(
480 bound_span,
481 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("ambiguous `{1}` from `{0}`",
bound.print_trait_sugared(), assoc_ident))
})format!("ambiguous `{assoc_ident}` from `{}`", bound.print_trait_sugared(),),
482 );
483 if let Some(constraint) = constraint {
484 match constraint.kind {
485 hir::AssocItemConstraintKind::Equality { term } => {
486 let term: ty::Term<'_> = match term {
487 hir::Term::Ty(ty) => self.lower_ty(ty).into(),
488 hir::Term::Const(ct) => {
489 let assoc_item =
490 assoc_item.expect("assoc_item should be present");
491 let projection_term = bound.map_bound(|trait_ref| {
492 let item_segment = hir::PathSegment {
493 ident: constraint.ident,
494 hir_id: constraint.hir_id,
495 res: Res::Err,
496 args: Some(constraint.gen_args),
497 infer_args: false,
498 delegation_child_segment: false,
499 };
500
501 let alias_args = self.lower_generic_args_of_assoc_item(
502 constraint.ident.span,
503 assoc_item.def_id,
504 &item_segment,
505 trait_ref.args,
506 );
507 let kind = ty::AliasTermKind::ProjectionConst {
508 def_id: assoc_item.def_id,
509 };
510 ty::AliasTerm::new_from_args(tcx, kind, alias_args)
511 });
512
513 let ty = projection_term.map_bound(|alias| {
516 alias.expect_ct().type_of(tcx).skip_norm_wip()
517 });
518 let ty = super::bounds::check_assoc_const_binding_type(
519 self,
520 constraint.ident,
521 ty,
522 constraint.hir_id,
523 );
524
525 self.lower_const_arg(ct, ty).into()
526 }
527 };
528 if term.references_error() {
529 continue;
530 }
531 where_bounds.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" T: {0}::{1} = {2}",
bound.print_only_trait_path(), assoc_ident, term))
})format!(
533 " T: {trait}::{assoc_ident} = {term}",
534 trait = bound.print_only_trait_path(),
535 ));
536 }
537 hir::AssocItemConstraintKind::Bound { bounds: _ } => {}
539 }
540 } else {
541 err.span_suggestion_verbose(
542 span.with_hi(assoc_ident.span.lo()),
543 "use fully-qualified syntax to disambiguate",
544 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{1} as {0}>::",
bound.print_only_trait_path(), qself_str))
})format!("<{qself_str} as {}>::", bound.print_only_trait_path()),
545 Applicability::MaybeIncorrect,
546 );
547 }
548 } else {
549 let trait_ = tcx.short_string(bound.print_only_trait_path(), err.long_ty_path());
550 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("associated {0} `{1}` could derive from `{2}`",
assoc_kind_str, assoc_ident, trait_))
})format!(
551 "associated {assoc_kind_str} `{assoc_ident}` could derive from `{trait_}`",
552 ));
553 }
554 }
555 if !where_bounds.is_empty() {
556 err.help(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider introducing a new type parameter `T` and adding `where` constraints:\n where\n T: {1},\n{0}",
where_bounds.join(",\n"), qself_str))
})format!(
557 "consider introducing a new type parameter `T` and adding `where` constraints:\
558 \n where\n T: {qself_str},\n{}",
559 where_bounds.join(",\n"),
560 ));
561 }
562 err.emit_err()
563 }
564
565 pub(crate) fn report_missing_self_ty_for_resolved_path(
566 &self,
567 trait_def_id: DefId,
568 span: Span,
569 item_segment: &hir::PathSegment<'_>,
570 assoc_tag: ty::AssocTag,
571 ) -> ErrorGuaranteed {
572 let tcx = self.tcx();
573 let path_str = tcx.def_path_str(trait_def_id);
574
575 let def_id = self.item_def_id();
576 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs:576",
"rustc_hir_analysis::hir_ty_lowering::errors",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs"),
::tracing_core::__macro_support::Option::Some(576u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::errors"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("item_def_id")
}> =
::tracing::__macro_support::FieldName::new("item_def_id");
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(&def_id)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(item_def_id = ?def_id);
577
578 let parent_def_id = tcx.hir_get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id();
580 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs:580",
"rustc_hir_analysis::hir_ty_lowering::errors",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs"),
::tracing_core::__macro_support::Option::Some(580u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::errors"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("parent_def_id")
}> =
::tracing::__macro_support::FieldName::new("parent_def_id");
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(&parent_def_id)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?parent_def_id);
581
582 let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id;
585 let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id;
586
587 let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
588 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
["Self".to_string()]))vec!["Self".to_string()]
589 } else {
590 tcx.all_impls(trait_def_id)
592 .map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
593 .filter(|header| {
594 tcx.visibility(trait_def_id).is_accessible_from(self.mod_id(), tcx)
596 && header.polarity != ty::ImplPolarity::Negative
597 })
598 .map(|header| header.trait_ref.instantiate_identity().skip_norm_wip().self_ty())
599 .filter(|self_ty| !self_ty.has_non_region_param())
601 .map(|self_ty| tcx.erase_and_anonymize_regions(self_ty).to_string())
602 .collect()
603 };
604 self.report_ambiguous_assoc_item_path(
608 span,
609 &type_names,
610 &[path_str],
611 item_segment.ident,
612 assoc_tag,
613 )
614 }
615
616 pub(super) fn report_unresolved_type_relative_path(
617 &self,
618 self_ty: Ty<'tcx>,
619 hir_self_ty: &hir::Ty<'_>,
620 assoc_tag: ty::AssocTag,
621 ident: Ident,
622 qpath_hir_id: HirId,
623 span: Span,
624 variant_def_id: Option<DefId>,
625 ) -> ErrorGuaranteed {
626 let tcx = self.tcx();
627 let kind_str = assoc_tag_str(assoc_tag);
628 if variant_def_id.is_some() {
629 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected {0}, found variant `{1}`",
kind_str, ident))
})format!("expected {kind_str}, found variant `{ident}`");
631 self.dcx().span_err(span, msg)
632 } else if self_ty.is_enum() {
633 let mut err = self.dcx().create_err(diagnostics::NoVariantNamed {
634 span: ident.span,
635 ident,
636 ty: self_ty,
637 });
638
639 let adt_def = self_ty.ty_adt_def().expect("enum is not an ADT");
640 if let Some(variant_name) = find_best_match_for_name(
641 &adt_def.variants().iter().map(|variant| variant.name).collect::<Vec<Symbol>>(),
642 ident.name,
643 None,
644 ) && let Some(variant) = adt_def.variants().iter().find(|s| s.name == variant_name)
645 {
646 let mut suggestion = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(ident.span, variant_name.to_string())]))vec![(ident.span, variant_name.to_string())];
647 if let hir::Node::Stmt(&hir::Stmt { kind: hir::StmtKind::Semi(expr), .. })
648 | hir::Node::Expr(expr) = tcx.parent_hir_node(qpath_hir_id)
649 && let hir::ExprKind::Struct(..) = expr.kind
650 {
651 match variant.ctor {
652 None => {
653 suggestion = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(ident.span.with_hi(expr.span.hi()),
if variant.fields.is_empty() {
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {{}}", variant_name))
})
} else {
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{1} {{ {0} }}",
variant.fields.iter().map(|f|
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: /* value */",
f.name))
})).collect::<Vec<_>>().join(", "), variant_name))
})
})]))vec![(
655 ident.span.with_hi(expr.span.hi()),
656 if variant.fields.is_empty() {
657 format!("{variant_name} {{}}")
658 } else {
659 format!(
660 "{variant_name} {{ {} }}",
661 variant
662 .fields
663 .iter()
664 .map(|f| format!("{}: /* value */", f.name))
665 .collect::<Vec<_>>()
666 .join(", ")
667 )
668 },
669 )];
670 }
671 Some((hir::def::CtorKind::Fn, def_id)) => {
672 let fn_sig = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip();
674 let inputs = fn_sig.inputs().skip_binder();
675 suggestion = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(ident.span.with_hi(expr.span.hi()),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{1}({0})",
inputs.iter().map(|i|
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("/* {0} */", i))
})).collect::<Vec<_>>().join(", "), variant_name))
}))]))vec![(
676 ident.span.with_hi(expr.span.hi()),
677 format!(
678 "{variant_name}({})",
679 inputs
680 .iter()
681 .map(|i| format!("/* {i} */"))
682 .collect::<Vec<_>>()
683 .join(", ")
684 ),
685 )];
686 }
687 Some((hir::def::CtorKind::Const, _)) => {
688 suggestion = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(ident.span.with_hi(expr.span.hi()), variant_name.to_string())]))vec![(
690 ident.span.with_hi(expr.span.hi()),
691 variant_name.to_string(),
692 )];
693 }
694 }
695 }
696 err.multipart_suggestion(
697 "there is a variant with a similar name",
698 suggestion,
699 Applicability::HasPlaceholders,
700 );
701 } else {
702 err.span_label(ident.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("variant not found in `{0}`",
self_ty))
})format!("variant not found in `{self_ty}`"));
703 }
704
705 if let Some(sp) = tcx.hir_span_if_local(adt_def.did()) {
706 err.span_label(sp, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("variant `{0}` not found here",
ident))
})format!("variant `{ident}` not found here"));
707 }
708
709 err.emit_err()
710 } else if let Err(reported) = self_ty.error_reported() {
711 reported
712 } else {
713 match self.maybe_report_similar_assoc_fn(span, self_ty, hir_self_ty) {
714 Ok(()) => {}
715 Err(reported) => return reported,
716 }
717
718 let traits: Vec<_> = self.probe_traits_that_match_assoc_ty(self_ty, ident);
719
720 self.report_ambiguous_assoc_item_path(
721 span,
722 &[self_ty.to_string()],
723 &traits,
724 ident,
725 assoc_tag,
726 )
727 }
728 }
729
730 fn report_ambiguous_assoc_item_path(
731 &self,
732 span: Span,
733 types: &[String],
734 traits: &[String],
735 ident: Ident,
736 assoc_tag: ty::AssocTag,
737 ) -> ErrorGuaranteed {
738 let kind_str = assoc_tag_str(assoc_tag);
739 let mut err =
740 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("ambiguous associated {0}",
kind_str))
})).with_code(E0223)
}struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated {kind_str}");
741 if self
742 .tcx()
743 .resolutions(())
744 .confused_type_with_std_module
745 .keys()
746 .any(|full_span| full_span.contains(span))
747 {
748 err.span_suggestion_verbose(
749 span.shrink_to_lo(),
750 "you are looking for the module in `std`, not the primitive type",
751 "std::",
752 Applicability::MachineApplicable,
753 );
754 } else {
755 let sugg_sp = span.until(ident.span);
756
757 let mut types = types.to_vec();
758 types.sort();
759 let mut traits = traits.to_vec();
760 traits.sort();
761 match (&types[..], &traits[..]) {
762 ([], []) => {
763 err.span_suggestion_verbose(
764 sugg_sp,
765 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if there were a type named `Type` that implements a trait named `Trait` with associated {0} `{1}`, you could use the fully-qualified path",
kind_str, ident))
})format!(
766 "if there were a type named `Type` that implements a trait named \
767 `Trait` with associated {kind_str} `{ident}`, you could use the \
768 fully-qualified path",
769 ),
770 "<Type as Trait>::",
771 Applicability::HasPlaceholders,
772 );
773 }
774 ([], [trait_str]) => {
775 err.span_suggestion_verbose(
776 sugg_sp,
777 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if there were a type named `Example` that implemented `{0}`, you could use the fully-qualified path",
trait_str))
})format!(
778 "if there were a type named `Example` that implemented `{trait_str}`, \
779 you could use the fully-qualified path",
780 ),
781 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<Example as {0}>::", trait_str))
})format!("<Example as {trait_str}>::"),
782 Applicability::HasPlaceholders,
783 );
784 }
785 ([], traits) => {
786 err.span_suggestions_with_style(
787 sugg_sp,
788 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if there were a type named `Example` that implemented one of the traits with associated {0} `{1}`, you could use the fully-qualified path",
kind_str, ident))
})format!(
789 "if there were a type named `Example` that implemented one of the \
790 traits with associated {kind_str} `{ident}`, you could use the \
791 fully-qualified path",
792 ),
793 traits.iter().map(|trait_str| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<Example as {0}>::", trait_str))
})format!("<Example as {trait_str}>::")),
794 Applicability::HasPlaceholders,
795 SuggestionStyle::ShowAlways,
796 );
797 }
798 ([type_str], []) => {
799 err.span_suggestion_verbose(
800 sugg_sp,
801 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if there were a trait named `Example` with associated {0} `{1}` implemented for `{2}`, you could use the fully-qualified path",
kind_str, ident, type_str))
})format!(
802 "if there were a trait named `Example` with associated {kind_str} `{ident}` \
803 implemented for `{type_str}`, you could use the fully-qualified path",
804 ),
805 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0} as Example>::", type_str))
})format!("<{type_str} as Example>::"),
806 Applicability::HasPlaceholders,
807 );
808 }
809 (types, []) => {
810 err.span_suggestions_with_style(
811 sugg_sp,
812 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if there were a trait named `Example` with associated {0} `{1}` implemented for one of the types, you could use the fully-qualified path",
kind_str, ident))
})format!(
813 "if there were a trait named `Example` with associated {kind_str} `{ident}` \
814 implemented for one of the types, you could use the fully-qualified \
815 path",
816 ),
817 types
818 .into_iter()
819 .map(|type_str| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0} as Example>::", type_str))
})format!("<{type_str} as Example>::")),
820 Applicability::HasPlaceholders,
821 SuggestionStyle::ShowAlways,
822 );
823 }
824 (types, traits) => {
825 let mut suggestions = ::alloc::vec::Vec::new()vec![];
826 for type_str in types {
827 for trait_str in traits {
828 suggestions.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0} as {1}>::", type_str,
trait_str))
})format!("<{type_str} as {trait_str}>::"));
829 }
830 }
831 err.span_suggestions_with_style(
832 sugg_sp,
833 "use fully-qualified syntax",
834 suggestions,
835 Applicability::MachineApplicable,
836 SuggestionStyle::ShowAlways,
837 );
838 }
839 }
840 }
841 err.emit_err()
842 }
843
844 pub(crate) fn report_ambiguous_inherent_assoc_item(
845 &self,
846 name: Ident,
847 candidates: Vec<DefId>,
848 span: Span,
849 ) -> ErrorGuaranteed {
850 let mut err = {
self.dcx().struct_span_err(name.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("multiple applicable items in scope"))
})).with_code(E0034)
}struct_span_code_err!(
851 self.dcx(),
852 name.span,
853 E0034,
854 "multiple applicable items in scope"
855 );
856 err.span_label(name.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("multiple `{0}` found", name))
})format!("multiple `{name}` found"));
857 self.note_ambiguous_inherent_assoc_item(&mut err, candidates, span);
858 err.emit_err()
859 }
860
861 fn note_ambiguous_inherent_assoc_item(
863 &self,
864 err: &mut Diag<'_>,
865 candidates: Vec<DefId>,
866 span: Span,
867 ) {
868 let tcx = self.tcx();
869
870 let limit = if candidates.len() == 5 { 5 } else { 4 };
872
873 for (index, &item) in candidates.iter().take(limit).enumerate() {
874 let impl_ = tcx.parent(item);
875
876 let note_span = if item.is_local() {
877 Some(tcx.def_span(item))
878 } else if impl_.is_local() {
879 Some(tcx.def_span(impl_))
880 } else {
881 None
882 };
883
884 let title = if candidates.len() > 1 {
885 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("candidate #{0}", index + 1))
})format!("candidate #{}", index + 1)
886 } else {
887 "the candidate".into()
888 };
889
890 let impl_ty = tcx.at(span).type_of(impl_).instantiate_identity().skip_norm_wip();
891 let note = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} is defined in an impl for the type `{1}`",
title, impl_ty))
})format!("{title} is defined in an impl for the type `{impl_ty}`");
892
893 if let Some(span) = note_span {
894 err.span_note(span, note);
895 } else {
896 err.note(note);
897 }
898 }
899 if candidates.len() > limit {
900 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("and {0} others",
candidates.len() - limit))
})format!("and {} others", candidates.len() - limit));
901 }
902 }
903
904 pub(crate) fn report_unresolved_inherent_assoc_item(
906 &self,
907 name: Ident,
908 self_ty: Ty<'tcx>,
909 candidates: Vec<InherentAssocCandidate>,
910 fulfillment_errors: ThinVec<FulfillmentError<'tcx>>,
911 span: Span,
912 assoc_tag: ty::AssocTag,
913 ) -> ErrorGuaranteed {
914 let tcx = self.tcx();
921
922 let assoc_tag_str = assoc_tag_str(assoc_tag);
923 let adt_did = self_ty.ty_adt_def().map(|def| def.did());
924 let add_def_label = |err: &mut Diag<'_>| {
925 if let Some(did) = adt_did {
926 err.span_label(
927 tcx.def_span(did),
928 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("associated {1} `{2}` not found for this {0}",
tcx.def_descr(did), assoc_tag_str, name))
})format!(
929 "associated {assoc_tag_str} `{name}` not found for this {}",
930 tcx.def_descr(did)
931 ),
932 );
933 }
934 };
935
936 if fulfillment_errors.is_empty() {
937 let limit = if candidates.len() == 5 { 5 } else { 4 };
940 let type_candidates = candidates
941 .iter()
942 .take(limit)
943 .map(|cand| {
944 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("- `{0}`",
tcx.at(span).type_of(cand.impl_).instantiate_identity().skip_norm_wip()))
})format!(
945 "- `{}`",
946 tcx.at(span).type_of(cand.impl_).instantiate_identity().skip_norm_wip()
947 )
948 })
949 .collect::<Vec<_>>()
950 .join("\n");
951 let additional_types = if candidates.len() > limit {
952 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("\nand {0} more types",
candidates.len() - limit))
})format!("\nand {} more types", candidates.len() - limit)
953 } else {
954 String::new()
955 };
956
957 let mut err = {
self.dcx().struct_span_err(name.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("associated {0} `{1}` not found for `{2}` in the current scope",
assoc_tag_str, name, self_ty))
})).with_code(E0220)
}struct_span_code_err!(
958 self.dcx(),
959 name.span,
960 E0220,
961 "associated {assoc_tag_str} `{name}` not found for `{self_ty}` in the current scope"
962 );
963 err.span_label(name.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("associated item not found in `{0}`",
self_ty))
})format!("associated item not found in `{self_ty}`"));
964 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the associated {0} was found for\n{1}{2}",
assoc_tag_str, type_candidates, additional_types))
})format!(
965 "the associated {assoc_tag_str} was found for\n{type_candidates}{additional_types}",
966 ));
967 add_def_label(&mut err);
968 return err.emit_err();
969 }
970
971 let mut bound_spans: SortedMap<OrdSpan, Vec<String>> = Default::default();
972
973 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
974 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`",
if obligation.len() > 50 { quiet } else { obligation }))
})format!("`{}`", if obligation.len() > 50 { quiet } else { obligation });
975 match self_ty.kind() {
976 ty::Adt(def, _) => bound_spans
978 .get_mut_or_insert_default(OrdSpan(tcx.def_span(def.did())))
979 .push(msg),
980 ty::Dynamic(preds, _) => {
982 for pred in preds.iter() {
983 match pred.skip_binder() {
984 ty::ExistentialPredicate::Trait(tr) => {
985 bound_spans
986 .get_mut_or_insert_default(OrdSpan(tcx.def_span(tr.def_id)))
987 .push(msg.clone());
988 }
989 ty::ExistentialPredicate::Projection(_)
990 | ty::ExistentialPredicate::AutoTrait(_) => {}
991 }
992 }
993 }
994 ty::Closure(def_id, _) => {
996 bound_spans
997 .get_mut_or_insert_default(OrdSpan(tcx.def_span(*def_id)))
998 .push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", quiet))
})format!("`{quiet}`"));
999 }
1000 _ => {}
1001 }
1002 };
1003
1004 let format_pred = |pred: ty::Predicate<'tcx>| {
1005 let bound_predicate = pred.kind();
1006 match bound_predicate.skip_binder() {
1007 ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
1008 let projection_term = pred.projection_term;
1010 let term = pred.term;
1011 let self_ty = projection_term.args.get(0).and_then(|arg| arg.as_type())?;
1012
1013 let obligation = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} = {1}", projection_term, term))
})format!("{projection_term} = {term}");
1014 let quiet_projection_term = projection_term
1015 .with_replaced_self_ty(tcx, Ty::new_var(tcx, ty::TyVid::ZERO));
1016 let quiet = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} = {1}", quiet_projection_term,
term))
})format!("{quiet_projection_term} = {term}");
1017
1018 bound_span_label(self_ty, &obligation, &quiet);
1019
1020 Some(obligation)
1021 }
1022 ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => {
1023 let p = poly_trait_ref.trait_ref;
1024 let self_ty = p.self_ty();
1025 let path = p.print_only_trait_path();
1026 let obligation = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1}", self_ty, path))
})format!("{self_ty}: {path}");
1027 let quiet = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("_: {0}", path))
})format!("_: {path}");
1028 bound_span_label(self_ty, &obligation, &quiet);
1029 Some(obligation)
1030 }
1031 _ => None,
1032 }
1033 };
1034
1035 let mut bounds: Vec<_> = fulfillment_errors
1038 .into_iter()
1039 .map(|error| error.root_obligation.predicate)
1040 .filter_map(format_pred)
1041 .map(|p| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", p))
})format!("`{p}`"))
1042 .collect();
1043 bounds.sort();
1044 bounds.dedup();
1045
1046 let mut err = self.dcx().struct_span_err(
1047 name.span,
1048 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the associated {0} `{1}` exists for `{2}`, but its trait bounds were not satisfied",
assoc_tag_str, name, self_ty))
})format!("the associated {assoc_tag_str} `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
1049 );
1050 if !bounds.is_empty() {
1051 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the following trait bounds were not satisfied:\n{0}",
bounds.join("\n")))
})format!(
1052 "the following trait bounds were not satisfied:\n{}",
1053 bounds.join("\n")
1054 ));
1055 }
1056 err.span_label(
1057 name.span,
1058 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("associated {0} cannot be referenced on `{1}` due to unsatisfied trait bounds",
assoc_tag_str, self_ty))
})format!("associated {assoc_tag_str} cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
1059 );
1060
1061 for (span, mut bounds) in bound_spans {
1062 if !tcx.sess.source_map().is_span_accessible(span.0) {
1063 continue;
1064 }
1065 bounds.sort();
1066 bounds.dedup();
1067 let msg = match &bounds[..] {
1068 [bound] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("doesn\'t satisfy {0}", bound))
})format!("doesn't satisfy {bound}"),
1069 bounds if bounds.len() > 4 => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("doesn\'t satisfy {0} bounds",
bounds.len()))
})format!("doesn't satisfy {} bounds", bounds.len()),
1070 [bounds @ .., last] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("doesn\'t satisfy {0} or {1}",
bounds.join(", "), last))
})format!("doesn't satisfy {} or {last}", bounds.join(", ")),
1071 [] => ::core::panicking::unreachable_default_msg()unreachable!(),
1072 };
1073 err.span_label(span.0, msg);
1074 }
1075 add_def_label(&mut err);
1076 err.emit_err()
1077 }
1078
1079 pub(crate) fn check_for_required_assoc_items(
1083 &self,
1084 spans: SmallVec<[Span; 1]>,
1085 missing_assoc_items: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>,
1086 potential_assoc_items: Vec<usize>,
1087 trait_bounds: &[hir::PolyTraitRef<'_>],
1088 ) -> Result<(), ErrorGuaranteed> {
1089 if missing_assoc_items.is_empty() {
1090 return Ok(());
1091 }
1092
1093 let tcx = self.tcx();
1094 let principal_span = *spans.first().unwrap();
1095
1096 let missing_assoc_items: Vec<_> = missing_assoc_items
1098 .into_iter()
1099 .map(|(def_id, trait_ref)| (tcx.associated_item(def_id), trait_ref))
1100 .collect();
1101 let mut names: FxIndexMap<_, Vec<_>> = Default::default();
1102 let mut names_len = 0;
1103 let mut descr = None;
1104
1105 enum Descr {
1106 Item,
1107 Tag(ty::AssocTag),
1108 }
1109
1110 for &(assoc_item, trait_ref) in &missing_assoc_items {
1111 let violations =
1119 dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), assoc_item);
1120 if !violations.is_empty() {
1121 return Err(report_dyn_incompatibility(
1122 tcx,
1123 principal_span,
1124 None,
1125 trait_ref.def_id(),
1126 &violations,
1127 )
1128 .emit_err());
1129 }
1130
1131 names.entry(trait_ref).or_default().push(assoc_item.name());
1132 names_len += 1;
1133
1134 descr = match descr {
1135 None => Some(Descr::Tag(assoc_item.tag())),
1136 Some(Descr::Tag(tag)) if tag != assoc_item.tag() => Some(Descr::Item),
1137 _ => continue,
1138 };
1139 }
1140
1141 let mut in_expr_or_pat = false;
1143 if let ([], [bound]) = (&potential_assoc_items[..], &trait_bounds) {
1144 let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id));
1145 in_expr_or_pat = match grandparent {
1146 hir::Node::Expr(_) | hir::Node::Pat(_) => true,
1147 _ => false,
1148 };
1149 }
1150
1151 let bound_names: UnordMap<_, _> =
1160 trait_bounds
1161 .iter()
1162 .filter_map(|poly_trait_ref| {
1163 let path = poly_trait_ref.trait_ref.path.segments.last()?;
1164 let args = path.args?;
1165 let Res::Def(DefKind::Trait, trait_def_id) = path.res else { return None };
1166
1167 Some(args.constraints.iter().filter_map(move |constraint| {
1168 let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
1169 else {
1170 return None;
1171 };
1172 let tag = match term {
1173 hir::Term::Ty(_) => ty::AssocTag::Type,
1174 hir::Term::Const(_) => ty::AssocTag::Const,
1175 };
1176 let assoc_item = tcx
1177 .associated_items(trait_def_id)
1178 .find_by_ident_and_kind(tcx, constraint.ident, tag, trait_def_id)?;
1179 Some(((constraint.ident.name, tag), assoc_item.def_id))
1180 }))
1181 })
1182 .flatten()
1183 .collect();
1184
1185 let mut names: Vec<_> = names
1186 .into_iter()
1187 .map(|(trait_, mut assocs)| {
1188 assocs.sort();
1189 let trait_ = trait_.print_trait_sugared();
1190 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} in `{1}`",
listify(&assocs[..],
|a|
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", a))
})).unwrap_or_default(), trait_))
})format!(
1191 "{} in `{trait_}`",
1192 listify(&assocs[..], |a| format!("`{a}`")).unwrap_or_default()
1193 )
1194 })
1195 .collect();
1196 names.sort();
1197 let names = names.join(", ");
1198
1199 let descr = match descr.unwrap() {
1200 Descr::Item => "associated item",
1201 Descr::Tag(tag) => tag.descr(),
1202 };
1203 let mut err = {
self.dcx().struct_span_err(principal_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the value of the {1}{0} {2} must be specified",
if names_len == 1 { "" } else { "s" }, descr, names))
})).with_code(E0191)
}struct_span_code_err!(
1204 self.dcx(),
1205 principal_span,
1206 E0191,
1207 "the value of the {descr}{s} {names} must be specified",
1208 s = pluralize!(names_len),
1209 );
1210 let mut suggestions = ::alloc::vec::Vec::new()vec![];
1211 let mut items_count = 0;
1212 let mut where_constraints = ::alloc::vec::Vec::new()vec![];
1213 let mut already_has_generics_args_suggestion = false;
1214
1215 let mut names: UnordMap<_, usize> = Default::default();
1216 for (item, _) in &missing_assoc_items {
1217 items_count += 1;
1218 *names.entry((item.name(), item.tag())).or_insert(0) += 1;
1219 }
1220 let mut dupes = false;
1221 let mut shadows = false;
1222 for (item, trait_ref) in &missing_assoc_items {
1223 let name = item.name();
1224 let key = (name, item.tag());
1225
1226 if names[&key] > 1 {
1227 dupes = true;
1228 } else if bound_names.get(&key).is_some_and(|&def_id| def_id != item.def_id) {
1229 shadows = true;
1230 }
1231
1232 let prefix = if dupes || shadows {
1233 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::",
tcx.def_path_str(trait_ref.def_id())))
})format!("{}::", tcx.def_path_str(trait_ref.def_id()))
1234 } else {
1235 String::new()
1236 };
1237 let mut is_shadowed = false;
1238
1239 if let Some(&def_id) = bound_names.get(&key)
1240 && def_id != item.def_id
1241 {
1242 is_shadowed = true;
1243
1244 let rename_message = if def_id.is_local() { ", consider renaming it" } else { "" };
1245 err.span_label(
1246 tcx.def_span(def_id),
1247 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}{1}` shadowed here{2}", prefix,
name, rename_message))
})format!("`{prefix}{name}` shadowed here{rename_message}"),
1248 );
1249 }
1250
1251 let rename_message = if is_shadowed { ", consider renaming it" } else { "" };
1252
1253 if let Some(sp) = tcx.hir_span_if_local(item.def_id) {
1254 err.span_label(sp, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}{1}` defined here{2}", prefix,
name, rename_message))
})format!("`{prefix}{name}` defined here{rename_message}"));
1255 }
1256 }
1257 if potential_assoc_items.len() == missing_assoc_items.len() {
1258 already_has_generics_args_suggestion = true;
1262 } else if let (Ok(snippet), false, false) =
1263 (tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows)
1264 {
1265 let bindings: Vec<_> = missing_assoc_items
1266 .iter()
1267 .map(|(item, _)| {
1268 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} = /* {1} */", item.name(),
match item.kind {
ty::AssocKind::Const { .. } => "CONST",
ty::AssocKind::Type { .. } => "Type",
ty::AssocKind::Fn { .. } =>
::core::panicking::unreachable_default_msg(),
}))
})format!(
1269 "{} = /* {} */",
1270 item.name(),
1271 match item.kind {
1272 ty::AssocKind::Const { .. } => "CONST",
1273 ty::AssocKind::Type { .. } => "Type",
1274 ty::AssocKind::Fn { .. } => unreachable!(),
1275 }
1276 )
1277 })
1278 .collect();
1279 let code = if let Some(snippet) = snippet.strip_suffix("<>") {
1280 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{1}<{0}>", bindings.join(", "),
snippet))
})format!("{snippet}<{}>", bindings.join(", "))
1282 } else if let Some(snippet) = snippet.strip_suffix('>') {
1283 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{1}, {0}>", bindings.join(", "),
snippet))
})format!("{snippet}, {}>", bindings.join(", "))
1285 } else if in_expr_or_pat {
1286 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::<{1}>", snippet,
bindings.join(", ")))
})format!("{}::<{}>", snippet, bindings.join(", "))
1289 } else {
1290 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}<{1}>", snippet,
bindings.join(", ")))
})format!("{}<{}>", snippet, bindings.join(", "))
1293 };
1294 suggestions.push((principal_span, code));
1295 } else if dupes {
1296 where_constraints.push(principal_span);
1297 }
1298
1299 let where_msg = "consider introducing a new type parameter, adding `where` constraints \
1308 using the fully-qualified path to the associated types";
1309 if !where_constraints.is_empty() && suggestions.is_empty() {
1310 err.help(where_msg);
1314 }
1315 if suggestions.len() != 1 || already_has_generics_args_suggestion {
1316 let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
1318 for (item, _) in &missing_assoc_items {
1319 items_count += 1;
1320 *names.entry(item.name()).or_insert(0) += 1;
1321 }
1322 let mut label = ::alloc::vec::Vec::new()vec![];
1323 for (item, trait_ref) in &missing_assoc_items {
1324 let name = item.name();
1325 let postfix = if names[&name] > 1 {
1326 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" (from trait `{0}`)",
trait_ref.print_trait_sugared()))
})format!(" (from trait `{}`)", trait_ref.print_trait_sugared())
1327 } else {
1328 String::new()
1329 };
1330 label.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`{1}", name, postfix))
})format!("`{}`{}", name, postfix));
1331 }
1332 if !label.is_empty() {
1333 err.span_label(
1334 principal_span,
1335 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{2}{0} {1} must be specified",
if label.len() == 1 { "" } else { "s" }, label.join(", "),
descr))
})format!(
1336 "{descr}{s} {names} must be specified",
1337 s = pluralize!(label.len()),
1338 names = label.join(", "),
1339 ),
1340 );
1341 }
1342 }
1343 suggestions.sort_by_key(|&(span, _)| span.lo_hi());
1344 let overlaps = suggestions.windows(2).any(|pair| pair[0].0.overlaps(pair[1].0));
1357 if !suggestions.is_empty() && !overlaps {
1358 err.multipart_suggestion(
1359 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("specify the {1}{0}",
if items_count == 1 { "" } else { "s" }, descr))
})format!("specify the {descr}{s}", s = pluralize!(items_count)),
1360 suggestions,
1361 Applicability::HasPlaceholders,
1362 );
1363 if !where_constraints.is_empty() {
1364 err.span_help(where_constraints, where_msg);
1365 }
1366 }
1367
1368 Err(err.emit_err())
1369 }
1370
1371 pub(crate) fn maybe_report_similar_assoc_fn(
1375 &self,
1376 span: Span,
1377 qself_ty: Ty<'tcx>,
1378 qself: &hir::Ty<'_>,
1379 ) -> Result<(), ErrorGuaranteed> {
1380 let tcx = self.tcx();
1381 if let Some((_, node)) = tcx.hir_parent_iter(qself.hir_id).skip(1).next()
1382 && let hir::Node::Expr(hir::Expr {
1383 kind:
1384 hir::ExprKind::Path(hir::QPath::TypeRelative(
1385 hir::Ty {
1386 kind:
1387 hir::TyKind::Path(hir::QPath::TypeRelative(
1388 _,
1389 hir::PathSegment { ident: ident2, .. },
1390 )),
1391 ..
1392 },
1393 hir::PathSegment { ident: ident3, .. },
1394 )),
1395 ..
1396 }) = node
1397 && let Some(inherent_impls) = qself_ty
1398 .ty_adt_def()
1399 .map(|adt_def| tcx.inherent_impls(adt_def.did()))
1400 .or_else(|| {
1401 simplify_type(tcx, qself_ty, TreatParams::InstantiateWithInfer)
1402 .map(|simple_ty| tcx.incoherent_impls(simple_ty))
1403 })
1404 && let name = Symbol::intern(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}_{1}", ident2, ident3))
})format!("{ident2}_{ident3}"))
1405 && let Some(item) = inherent_impls
1406 .iter()
1407 .flat_map(|&inherent_impl| {
1408 tcx.associated_items(inherent_impl).filter_by_name_unhygienic(name)
1409 })
1410 .next()
1411 && item.is_fn()
1412 {
1413 Err({
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("ambiguous associated type"))
})).with_code(E0223)
}struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated type")
1414 .with_span_suggestion_verbose(
1415 ident2.span.to(ident3.span),
1416 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("there is an associated function with a similar name: `{0}`",
name))
})format!("there is an associated function with a similar name: `{name}`"),
1417 name,
1418 Applicability::MaybeIncorrect,
1419 )
1420 .emit_err())
1421 } else {
1422 Ok(())
1423 }
1424 }
1425
1426 pub fn report_prohibited_generic_args<'a>(
1427 &self,
1428 segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1429 args_visitors: impl Iterator<Item = &'a hir::GenericArg<'a>> + Clone,
1430 err_extend: GenericsArgsErrExtend<'a>,
1431 ) -> ErrorGuaranteed {
1432 #[derive(#[automatically_derived]impl ::core::marker::StructuralPartialEq for
ProhibitGenericsArg {
}
#[automatically_derived]impl ::core::cmp::PartialEq for ProhibitGenericsArg {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for ProhibitGenericsArg { }Eq, #[automatically_derived]impl ::core::hash::Hash for ProhibitGenericsArg {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
state)
}
}Hash)]
1433 enum ProhibitGenericsArg {
1434 Lifetime,
1435 Type,
1436 Const,
1437 Infer,
1438 }
1439
1440 let mut prohibit_args = FxIndexSet::default();
1441 args_visitors.for_each(|arg| {
1442 match arg {
1443 hir::GenericArg::Lifetime(_) => prohibit_args.insert(ProhibitGenericsArg::Lifetime),
1444 hir::GenericArg::Type(_) => prohibit_args.insert(ProhibitGenericsArg::Type),
1445 hir::GenericArg::Const(_) => prohibit_args.insert(ProhibitGenericsArg::Const),
1446 hir::GenericArg::Infer(_) => prohibit_args.insert(ProhibitGenericsArg::Infer),
1447 };
1448 });
1449
1450 let segments: Vec<_> = segments.collect();
1451 let types_and_spans: Vec<_> = segments
1452 .iter()
1453 .flat_map(|segment| {
1454 if segment.args().args.is_empty() {
1455 None
1456 } else {
1457 Some((
1458 match segment.res {
1459 Res::PrimTy(ty) => {
1460 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} `{1}`", segment.res.descr(),
ty.name()))
})format!("{} `{}`", segment.res.descr(), ty.name())
1461 }
1462 Res::Def(_, def_id)
1463 if let Some(name) = self.tcx().opt_item_name(def_id) =>
1464 {
1465 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} `{1}`", segment.res.descr(),
name))
})format!("{} `{name}`", segment.res.descr())
1466 }
1467 Res::Err => "this type".to_string(),
1468 _ => segment.res.descr().to_string(),
1469 },
1470 segment.ident.span,
1471 ))
1472 }
1473 })
1474 .collect();
1475 let this_type = listify(&types_and_spans, |(t, _)| t.to_string())
1476 .expect("expected one segment to deny");
1477
1478 let arg_spans: Vec<Span> =
1479 segments.iter().flat_map(|segment| segment.args().args).map(|arg| arg.span()).collect();
1480
1481 let mut kinds = Vec::with_capacity(4);
1482 prohibit_args.iter().for_each(|arg| match arg {
1483 ProhibitGenericsArg::Lifetime => kinds.push("lifetime"),
1484 ProhibitGenericsArg::Type => kinds.push("type"),
1485 ProhibitGenericsArg::Const => kinds.push("const"),
1486 ProhibitGenericsArg::Infer => kinds.push("generic"),
1487 });
1488
1489 let s = if kinds.len() == 1 { "" } else { "s" }pluralize!(kinds.len());
1490 let kind =
1491 listify(&kinds, |k| k.to_string()).expect("expected at least one generic to prohibit");
1492 let last_span = *arg_spans.last().unwrap();
1493 let span: MultiSpan = arg_spans.into();
1494 let mut err = {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} arguments are not allowed on {1}",
kind, this_type))
})).with_code(E0109)
}struct_span_code_err!(
1495 self.dcx(),
1496 span,
1497 E0109,
1498 "{kind} arguments are not allowed on {this_type}",
1499 );
1500 err.span_label(last_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} argument{1} not allowed", kind,
s))
})format!("{kind} argument{s} not allowed"));
1501 for (what, span) in types_and_spans {
1502 err.span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("not allowed on {0}", what))
})format!("not allowed on {what}"));
1503 }
1504 generics_args_err_extend(self.tcx(), segments.into_iter(), &mut err, err_extend);
1505 err.emit_err()
1506 }
1507
1508 pub fn report_trait_object_addition_traits(
1509 &self,
1510 regular_traits: &Vec<(ty::PolyTraitClause<'tcx>, SmallVec<[Span; 1]>)>,
1511 ) -> ErrorGuaranteed {
1512 let (&first_span, first_alias_spans) = regular_traits[0].1.split_last().unwrap();
1515 let (&second_span, second_alias_spans) = regular_traits[1].1.split_last().unwrap();
1516 let mut err = {
self.dcx().struct_span_err(*regular_traits[1].1.first().unwrap(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("only auto traits can be used as additional traits in a trait object"))
})).with_code(E0225)
}struct_span_code_err!(
1517 self.dcx(),
1518 *regular_traits[1].1.first().unwrap(),
1519 E0225,
1520 "only auto traits can be used as additional traits in a trait object"
1521 );
1522 err.span_label(first_span, "first non-auto trait");
1523 for &alias_span in first_alias_spans {
1524 err.span_label(alias_span, "first non-auto trait comes from this alias");
1525 }
1526 err.span_label(second_span, "additional non-auto trait");
1527 for &alias_span in second_alias_spans {
1528 err.span_label(alias_span, "second non-auto trait comes from this alias");
1529 }
1530 err.help(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: {0} {{}}`",
regular_traits.iter().map(|(pred, _)|
pred.map_bound(|pred|
pred.trait_ref).print_only_trait_path().to_string()).collect::<Vec<_>>().join(" + ")))
})format!(
1531 "consider creating a new trait with all of these as supertraits and using that \
1532 trait here instead: `trait NewTrait: {} {{}}`",
1533 regular_traits
1534 .iter()
1535 .map(|(pred, _)| pred
1537 .map_bound(|pred| pred.trait_ref)
1538 .print_only_trait_path()
1539 .to_string())
1540 .collect::<Vec<_>>()
1541 .join(" + "),
1542 ));
1543 err.note(
1544 "auto-traits like `Send` and `Sync` are traits that have special properties; \
1545 for more information on them, visit \
1546 <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
1547 );
1548 err.emit_err()
1549 }
1550
1551 pub fn report_trait_object_with_no_traits(
1552 &self,
1553 span: Span,
1554 user_written_clauses: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
1555 ) -> ErrorGuaranteed {
1556 let tcx = self.tcx();
1557 let trait_alias_span = user_written_clauses
1558 .into_iter()
1559 .filter_map(|(clause, _)| clause.as_trait_clause())
1560 .find(|trait_ref| tcx.is_trait_alias(trait_ref.def_id()))
1561 .map(|trait_ref| tcx.def_span(trait_ref.def_id()));
1562
1563 self.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span })
1564 }
1565}
1566
1567pub fn prohibit_assoc_item_constraint(
1569 cx: &dyn HirTyLowerer<'_>,
1570 constraint: &hir::AssocItemConstraint<'_>,
1571 segment: Option<(DefId, &hir::PathSegment<'_>, Span)>,
1572) -> ErrorGuaranteed {
1573 let tcx = cx.tcx();
1574 let mut err = cx.dcx().create_err(AssocItemConstraintsNotAllowedHere {
1575 span: constraint.span,
1576 fn_trait_expansion: if let Some((_, segment, span)) = segment
1577 && segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar
1578 {
1579 Some(ParenthesizedFnTraitExpansion {
1580 span,
1581 expanded_type: fn_trait_to_string(tcx, segment, false),
1582 })
1583 } else {
1584 None
1585 },
1586 });
1587
1588 if let hir::AssocItemConstraintKind::Bound {
1589 bounds: [hir::GenericBound::Trait(poly_trait_ref)],
1590 } = constraint.kind
1591 && let Res::Err = poly_trait_ref.trait_ref.path.res
1592 {
1593 err.downgrade_to_delayed_bug();
1596 }
1597
1598 if let Some((def_id, segment, _)) = segment
1602 && segment.args().parenthesized == hir::GenericArgsParentheses::No
1603 {
1604 let suggest_removal = |e: &mut Diag<'_>| {
1606 let constraints = segment.args().constraints;
1607 let args = segment.args().args;
1608
1609 let Some(index) = constraints.iter().position(|b| b.hir_id == constraint.hir_id) else {
1621 ::rustc_span::macros::bug_impl(None,
format_args!("a type binding exists but its HIR ID not found in generics"),
Location::caller());bug!("a type binding exists but its HIR ID not found in generics");
1622 };
1623
1624 let preceding_span = if index > 0 {
1625 Some(constraints[index - 1].span)
1626 } else {
1627 args.last().map(|a| a.span())
1628 };
1629
1630 let next_span = constraints.get(index + 1).map(|constraint| constraint.span);
1631
1632 let removal_span = match (preceding_span, next_span) {
1633 (Some(prec), _) => constraint.span.with_lo(prec.hi()),
1634 (None, Some(next)) => constraint.span.with_hi(next.lo()),
1635 (None, None) => {
1636 let Some(generics_span) = segment.args().span_ext() else {
1637 ::rustc_span::macros::bug_impl(None,
format_args!("a type binding exists but generic span is empty"),
Location::caller());bug!("a type binding exists but generic span is empty");
1638 };
1639
1640 generics_span
1641 }
1642 };
1643
1644 e.span_suggestion_verbose(
1646 removal_span,
1647 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider removing this associated item {0}",
constraint.kind.descr()))
})format!("consider removing this associated item {}", constraint.kind.descr()),
1648 "",
1649 Applicability::MaybeIncorrect,
1650 );
1651 };
1652
1653 let suggest_direct_use = |e: &mut Diag<'_>, sp: Span| {
1656 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(sp) {
1657 e.span_suggestion_verbose(
1658 constraint.span,
1659 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("to use `{0}` as a generic argument specify it directly",
snippet))
})format!("to use `{snippet}` as a generic argument specify it directly"),
1660 snippet,
1661 Applicability::MaybeIncorrect,
1662 );
1663 }
1664 };
1665
1666 let generics = tcx.generics_of(def_id);
1669 let matching_param = generics.own_params.iter().find(|p| p.name == constraint.ident.name);
1670
1671 if let Some(matching_param) = matching_param {
1673 match (constraint.kind, &matching_param.kind) {
1674 (
1675 hir::AssocItemConstraintKind::Equality { term: hir::Term::Ty(ty) },
1676 GenericParamDefKind::Type { .. },
1677 ) => suggest_direct_use(&mut err, ty.span),
1678 (
1679 hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) },
1680 GenericParamDefKind::Const { .. },
1681 ) => {
1682 suggest_direct_use(&mut err, c.span);
1683 }
1684 (hir::AssocItemConstraintKind::Bound { bounds }, _) => {
1685 let impl_block = tcx
1691 .hir_parent_iter(constraint.hir_id)
1692 .find_map(|(_, node)| node.impl_block_of_trait(def_id));
1693
1694 let type_with_constraints =
1695 tcx.sess.source_map().span_to_snippet(constraint.span);
1696
1697 if let Some(impl_block) = impl_block
1698 && let Ok(type_with_constraints) = type_with_constraints
1699 {
1700 let lifetimes: String = bounds
1703 .iter()
1704 .filter_map(|bound| {
1705 if let hir::GenericBound::Outlives(lifetime) = bound {
1706 Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}, ", lifetime))
})format!("{lifetime}, "))
1707 } else {
1708 None
1709 }
1710 })
1711 .collect();
1712 let param_decl = if let Some(param_span) =
1715 impl_block.generics.span_for_param_suggestion()
1716 {
1717 (param_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(", {0}{1}", lifetimes,
type_with_constraints))
})format!(", {lifetimes}{type_with_constraints}"))
1718 } else {
1719 (
1720 impl_block.generics.span.shrink_to_lo(),
1721 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0}{1}>", lifetimes,
type_with_constraints))
})format!("<{lifetimes}{type_with_constraints}>"),
1722 )
1723 };
1724 let suggestions = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[param_decl,
(constraint.span.with_lo(constraint.ident.span.hi()),
String::new())]))vec![
1725 param_decl,
1726 (constraint.span.with_lo(constraint.ident.span.hi()), String::new()),
1727 ];
1728
1729 err.multipart_suggestion(
1730 "declare the type parameter right after the `impl` keyword",
1731 suggestions,
1732 Applicability::MaybeIncorrect,
1733 );
1734 }
1735 }
1736 _ => suggest_removal(&mut err),
1737 }
1738 } else {
1739 suggest_removal(&mut err);
1740 }
1741 }
1742
1743 err.emit_err()
1744}
1745
1746pub(crate) fn fn_trait_to_string(
1747 tcx: TyCtxt<'_>,
1748 trait_segment: &hir::PathSegment<'_>,
1749 parenthesized: bool,
1750) -> String {
1751 let args = trait_segment
1752 .args
1753 .and_then(|args| args.args.first())
1754 .and_then(|arg| match arg {
1755 hir::GenericArg::Type(ty) => match ty.kind {
1756 hir::TyKind::Tup(t) => t
1757 .iter()
1758 .map(|e| tcx.sess.source_map().span_to_snippet(e.span))
1759 .collect::<Result<Vec<_>, _>>()
1760 .map(|a| a.join(", ")),
1761 _ => tcx.sess.source_map().span_to_snippet(ty.span),
1762 }
1763 .map(|s| {
1764 if parenthesized || s.is_empty() { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0})", s))
})format!("({s})") } else { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0},)", s))
})format!("({s},)") }
1766 })
1767 .ok(),
1768 _ => None,
1769 })
1770 .unwrap_or_else(|| "()".to_string());
1771
1772 let ret = trait_segment
1773 .args()
1774 .constraints
1775 .iter()
1776 .find_map(|c| {
1777 if c.ident.name == sym::Output
1778 && let Some(ty) = c.ty()
1779 && ty.span != tcx.hir_span(trait_segment.hir_id)
1780 {
1781 tcx.sess.source_map().span_to_snippet(ty.span).ok()
1782 } else {
1783 None
1784 }
1785 })
1786 .unwrap_or_else(|| "()".to_string());
1787
1788 if parenthesized {
1789 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1} -> {2}",
trait_segment.ident, args, ret))
})format!("{}{} -> {}", trait_segment.ident, args, ret)
1790 } else {
1791 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}<{1}, Output={2}>",
trait_segment.ident, args, ret))
})format!("{}<{}, Output={}>", trait_segment.ident, args, ret)
1792 }
1793}
1794
1795pub enum GenericsArgsErrExtend<'tcx> {
1797 EnumVariant {
1798 qself: &'tcx hir::Ty<'tcx>,
1799 assoc_segment: &'tcx hir::PathSegment<'tcx>,
1800 adt_def: AdtDef<'tcx>,
1801 },
1802 OpaqueTy,
1803 PrimTy(hir::PrimTy),
1804 SelfTyAlias {
1805 def_id: DefId,
1806 span: Span,
1807 },
1808 SelfTyParam(Span),
1809 Param(DefId),
1810 DefVariant(&'tcx [hir::PathSegment<'tcx>]),
1811 None,
1812}
1813
1814fn generics_args_err_extend<'a>(
1815 tcx: TyCtxt<'_>,
1816 segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1817 err: &mut Diag<'_>,
1818 err_extend: GenericsArgsErrExtend<'a>,
1819) {
1820 match err_extend {
1821 GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def } => {
1822 err.note("enum variants can't have type parameters");
1823 let type_name = tcx.item_name(adt_def.did());
1824 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you might have meant to specify type parameters on enum `{0}`",
type_name))
})format!(
1825 "you might have meant to specify type parameters on enum \
1826 `{type_name}`"
1827 );
1828 let Some(args) = assoc_segment.args else {
1829 return;
1830 };
1831 let args_span = args.span_ext.with_lo(args.span_ext.lo() - BytePos(2));
1836 if tcx.generics_of(adt_def.did()).is_empty() {
1837 err.span_suggestion_verbose(
1840 args_span,
1841 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} doesn\'t have generic parameters",
type_name))
})format!("{type_name} doesn't have generic parameters"),
1842 "",
1843 Applicability::MachineApplicable,
1844 );
1845 return;
1846 }
1847 let Ok(snippet) = tcx.sess.source_map().span_to_snippet(args_span) else {
1848 err.note(msg);
1849 return;
1850 };
1851 let (qself_sugg_span, is_self) =
1852 if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
1853 match &path.segments {
1856 [
1860 ..,
1861 hir::PathSegment {
1862 ident, args, res: Res::Def(DefKind::Enum, _), ..
1863 },
1864 _,
1865 ] => (
1866 ident
1869 .span
1870 .shrink_to_hi()
1871 .to(args.map_or(ident.span.shrink_to_hi(), |a| a.span_ext)),
1872 false,
1873 ),
1874 [segment] => {
1875 (
1876 segment.ident.span.shrink_to_hi().to(segment
1879 .args
1880 .map_or(segment.ident.span.shrink_to_hi(), |a| a.span_ext)),
1881 kw::SelfUpper == segment.ident.name,
1882 )
1883 }
1884 _ => {
1885 err.note(msg);
1886 return;
1887 }
1888 }
1889 } else {
1890 err.note(msg);
1891 return;
1892 };
1893 let suggestion = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[if is_self {
(qself.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}", type_name,
snippet))
}))
} else { (qself_sugg_span, snippet) },
(args_span, String::new())]))vec![
1894 if is_self {
1895 (qself.span, format!("{type_name}{snippet}"))
1899 } else {
1900 (qself_sugg_span, snippet)
1901 },
1902 (args_span, String::new()),
1903 ];
1904 err.multipart_suggestion(msg, suggestion, Applicability::MaybeIncorrect);
1905 }
1906 GenericsArgsErrExtend::DefVariant(segments) => {
1907 let args: Vec<Span> = segments
1908 .iter()
1909 .filter_map(|segment| match segment.res {
1910 Res::Def(
1911 DefKind::Ctor(CtorOf::Variant, _) | DefKind::Variant | DefKind::Enum,
1912 _,
1913 ) => segment.args().span_ext().map(|s| s.with_lo(segment.ident.span.hi())),
1914 _ => None,
1915 })
1916 .collect();
1917 if args.len() > 1
1918 && let Some(span) = args.into_iter().next_back()
1919 {
1920 err.note(
1921 "generic arguments are not allowed on both an enum and its variant's path \
1922 segments simultaneously; they are only valid in one place or the other",
1923 );
1924 err.span_suggestion_verbose(
1925 span,
1926 "remove the generics arguments from one of the path segments",
1927 String::new(),
1928 Applicability::MaybeIncorrect,
1929 );
1930 }
1931 }
1932 GenericsArgsErrExtend::PrimTy(prim_ty) => {
1933 let name = prim_ty.name_str();
1934 for segment in segments {
1935 if let Some(args) = segment.args {
1936 err.span_suggestion_verbose(
1937 segment.ident.span.shrink_to_hi().to(args.span_ext),
1938 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("primitive type `{0}` doesn\'t have generic parameters",
name))
})format!("primitive type `{name}` doesn't have generic parameters"),
1939 "",
1940 Applicability::MaybeIncorrect,
1941 );
1942 }
1943 }
1944 }
1945 GenericsArgsErrExtend::OpaqueTy => {
1946 err.note("`impl Trait` types can't have type parameters");
1947 }
1948 GenericsArgsErrExtend::Param(def_id) => {
1949 let span = tcx.def_ident_span(def_id).unwrap();
1950 let kind = tcx.def_descr(def_id);
1951 let name = tcx.item_name(def_id);
1952 err.span_note(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} `{1}` defined here", kind,
name))
})format!("{kind} `{name}` defined here"));
1953 }
1954 GenericsArgsErrExtend::SelfTyParam(span) => {
1955 err.span_suggestion_verbose(
1956 span,
1957 "the `Self` type doesn't accept type parameters",
1958 "",
1959 Applicability::MaybeIncorrect,
1960 );
1961 }
1962 GenericsArgsErrExtend::SelfTyAlias { def_id, span } => {
1963 let ty = tcx.at(span).type_of(def_id).instantiate_identity().skip_norm_wip();
1964 let span_of_impl = tcx.span_of_impl(def_id);
1965 let ty::Adt(self_def, _) = *ty.kind() else { return };
1966 let def_id = self_def.did();
1967
1968 let type_name = tcx.item_name(def_id);
1969 let span_of_ty = tcx.def_ident_span(def_id);
1970 let generics = tcx.generics_of(def_id).count();
1971
1972 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`Self` is of type `{0}`", ty))
})format!("`Self` is of type `{ty}`");
1973 if let (Ok(i_sp), Some(t_sp)) = (span_of_impl, span_of_ty) {
1974 let mut span: MultiSpan = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[t_sp]))vec![t_sp].into();
1975 span.push_span_label(
1976 i_sp,
1977 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`Self` is on type `{0}` in this `impl`",
type_name))
})format!("`Self` is on type `{type_name}` in this `impl`"),
1978 );
1979 let mut postfix = "";
1980 if generics == 0 {
1981 postfix = ", which doesn't have generic parameters";
1982 }
1983 span.push_span_label(t_sp, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`Self` corresponds to this type{0}",
postfix))
})format!("`Self` corresponds to this type{postfix}"));
1984 err.span_note(span, msg);
1985 } else {
1986 err.note(msg);
1987 }
1988 for segment in segments {
1989 if let Some(args) = segment.args
1990 && segment.ident.name == kw::SelfUpper
1991 {
1992 if generics == 0 {
1993 err.span_suggestion_verbose(
1996 segment.ident.span.shrink_to_hi().to(args.span_ext),
1997 "the `Self` type doesn't accept type parameters",
1998 "",
1999 Applicability::MachineApplicable,
2000 );
2001 return;
2002 } else {
2003 err.span_suggestion_verbose(
2004 segment.ident.span,
2005 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the `Self` type doesn\'t accept type parameters, use the concrete type\'s name `{0}` instead if you want to specify its type parameters",
type_name))
})format!(
2006 "the `Self` type doesn't accept type parameters, use the \
2007 concrete type's name `{type_name}` instead if you want to \
2008 specify its type parameters"
2009 ),
2010 type_name,
2011 Applicability::MaybeIncorrect,
2012 );
2013 }
2014 }
2015 }
2016 }
2017 _ => {}
2018 }
2019}
2020
2021pub(super) struct AmbiguityBetweenVariantAndAssocItem<'tcx> {
2022 pub(super) variant_def_id: DefId,
2023 pub(super) item_def_id: DefId,
2024 pub(super) span: Span,
2025 pub(super) segment_ident: Ident,
2026 pub(super) bound_def_id: DefId,
2027 pub(super) self_ty: Ty<'tcx>,
2028 pub(super) tcx: TyCtxt<'tcx>,
2029 pub(super) mode: super::LowerTypeRelativePathMode,
2030}
2031
2032impl<'a, 'tcx> rustc_errors::Diagnostic<'a> for AmbiguityBetweenVariantAndAssocItem<'tcx> {
2033 fn into_diag(
2034 self,
2035 dcx: rustc_errors::DiagCtxtHandle<'a>,
2036 level: rustc_errors::Level,
2037 ) -> Diag<'a> {
2038 let Self {
2039 variant_def_id,
2040 item_def_id,
2041 span,
2042 segment_ident,
2043 bound_def_id,
2044 self_ty,
2045 tcx,
2046 mode,
2047 } = self;
2048 let mut lint = Diag::new(dcx, level, "ambiguous associated item");
2049
2050 let mut could_refer_to = |kind: DefKind, def_id, also| {
2051 let note_msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` could{1} refer to the {2} defined here",
segment_ident, also, tcx.def_kind_descr(kind, def_id)))
})format!(
2052 "`{}` could{} refer to the {} defined here",
2053 segment_ident,
2054 also,
2055 tcx.def_kind_descr(kind, def_id)
2056 );
2057 lint.span_note(tcx.def_span(def_id), note_msg);
2058 };
2059
2060 could_refer_to(DefKind::Variant, variant_def_id, "");
2061 could_refer_to(mode.def_kind_for_diagnostics(), item_def_id, " also");
2062
2063 lint.span_suggestion_verbose(
2064 span,
2065 "use fully-qualified syntax",
2066 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0} as {1}>::{2}", self_ty,
tcx.item_name(bound_def_id), segment_ident))
})format!("<{} as {}>::{}", self_ty, tcx.item_name(bound_def_id), segment_ident),
2067 Applicability::MachineApplicable,
2068 );
2069 lint
2070 }
2071}
2072
2073fn assoc_tag_str(assoc_tag: ty::AssocTag) -> &'static str {
2074 match assoc_tag {
2075 ty::AssocTag::Fn => "function",
2076 ty::AssocTag::Const => "constant",
2077 ty::AssocTag::Type => "type",
2078 }
2079}
2080
2081pub(crate) fn eq_ctxt_suggestion_span(pat: Span, ty: Span) -> Option<Span> {
2086 if let Some(ty2) = ty.find_ancestor_in_same_ctxt(pat)
2087 && pat.hi() <= ty2.lo()
2088 {
2089 return Some(pat.between(ty2));
2090 }
2091 if let Some(pat2) = pat.find_ancestor_in_same_ctxt(ty)
2092 && pat2.hi() <= ty.lo()
2093 {
2094 return Some(pat2.between(ty));
2095 }
2096 None
2097}