1use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
2use rustc_data_structures::sorted_map::SortedMap;
3use rustc_data_structures::unord::UnordMap;
4use rustc_errors::codes::*;
5use rustc_errors::{
6 Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, listify, msg, pluralize,
7 struct_span_code_err,
8};
9use rustc_hir::def::{CtorOf, DefKind, Res};
10use rustc_hir::def_id::DefId;
11use rustc_hir::{self as hir, HirId};
12use rustc_middle::bug;
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::parse::feature_err;
20use rustc_span::edit_distance::find_best_match_for_name;
21use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, 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::errors::{
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(errors::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(
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<'tcx>>,
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_str = 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 = errors::AssocItemNotFound {
152 span: if is_dummy { span } else { assoc_ident.span },
153 assoc_ident,
154 assoc_kind: assoc_kind_str,
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(errors::AssocItemNotFoundLabel::NotFound { span });
165 return self.dcx().emit_err(err);
166 }
167
168 let all_candidate_names: Vec<_> = all_candidates()
169 .flat_map(|r| tcx.associated_items(r.def_id()).in_definition_order())
170 .filter_map(|item| {
171 if !item.is_impl_trait_in_trait() && item.tag() == assoc_tag {
172 item.opt_name()
173 } else {
174 None
175 }
176 })
177 .collect();
178
179 if let Some(suggested_name) =
180 find_best_match_for_name(&all_candidate_names, assoc_ident.name, None)
181 {
182 err.sugg = Some(errors::AssocItemNotFoundSugg::Similar {
183 span: assoc_ident.span,
184 assoc_kind: assoc_kind_str,
185 suggested_name,
186 });
187 return self.dcx().emit_err(err);
188 }
189
190 let visible_traits: Vec<_> = tcx
195 .visible_traits()
196 .filter(|trait_def_id| {
197 let viz = tcx.visibility(*trait_def_id);
198 let def_id = self.item_def_id();
199 viz.is_accessible_from(def_id, tcx)
200 })
201 .collect();
202
203 let wider_candidate_names: Vec<_> = visible_traits
204 .iter()
205 .flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order())
206 .filter_map(|item| {
207 (!item.is_impl_trait_in_trait() && item.tag() == assoc_tag).then(|| item.name())
208 })
209 .collect();
210
211 if let Some(suggested_name) =
212 find_best_match_for_name(&wider_candidate_names, assoc_ident.name, None)
213 {
214 if let [best_trait] = visible_traits
215 .iter()
216 .copied()
217 .filter(|trait_def_id| {
218 tcx.associated_items(trait_def_id)
219 .filter_by_name_unhygienic(suggested_name)
220 .any(|item| item.tag() == assoc_tag)
221 })
222 .collect::<Vec<_>>()[..]
223 {
224 let trait_name = tcx.def_path_str(best_trait);
225 err.label = Some(errors::AssocItemNotFoundLabel::FoundInOtherTrait {
226 span: assoc_ident.span,
227 assoc_kind: assoc_kind_str,
228 trait_name: &trait_name,
229 suggested_name,
230 identically_named: suggested_name == assoc_ident.name,
231 });
232 if let AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span) = qself
233 && let item_def_id =
237 tcx.hir_get_parent_item(tcx.local_def_id_to_hir_id(ty_param_def_id))
238 && let Some(generics) = tcx.hir_get_generics(item_def_id.def_id)
240 {
241 if generics
245 .bounds_for_param(ty_param_def_id)
246 .flat_map(|pred| pred.bounds.iter())
247 .any(|b| match b {
248 hir::GenericBound::Trait(t, ..) => {
249 t.trait_ref.trait_def_id() == Some(best_trait)
250 }
251 _ => false,
252 })
253 {
254 err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait {
257 span: assoc_ident.span,
258 trait_name: &trait_name,
259 assoc_kind: assoc_kind_str,
260 suggested_name,
261 });
262 return self.dcx().emit_err(err);
263 }
264
265 let trait_args = &ty::GenericArgs::identity_for_item(tcx, best_trait)[1..];
266 let mut trait_ref = trait_name.clone();
267 let applicability = if let [arg, args @ ..] = trait_args {
268 use std::fmt::Write;
269 trait_ref.write_fmt(format_args!("</* {0}", arg))write!(trait_ref, "</* {arg}").unwrap();
270 args.iter().try_for_each(|arg| trait_ref.write_fmt(format_args!(", {0}", arg))write!(trait_ref, ", {arg}")).unwrap();
271 trait_ref += " */>";
272 Applicability::HasPlaceholders
273 } else {
274 Applicability::MaybeIncorrect
275 };
276
277 let identically_named = suggested_name == assoc_ident.name;
278
279 if let DefKind::TyAlias = tcx.def_kind(item_def_id)
280 && !tcx.type_alias_is_lazy(item_def_id)
281 {
282 err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTraitQPath {
283 lo: ty_param_span.shrink_to_lo(),
284 mi: ty_param_span.shrink_to_hi(),
285 hi: (!identically_named).then_some(assoc_ident.span),
286 trait_ref,
287 identically_named,
288 suggested_name,
289 applicability,
290 });
291 } else {
292 let mut err = self.dcx().create_err(err);
293 if suggest_constraining_type_param(
294 tcx,
295 generics,
296 &mut err,
297 &qself_str,
298 &trait_ref,
299 Some(best_trait),
300 None,
301 ) && !identically_named
302 {
303 err.span_suggestion_verbose(
306 assoc_ident.span,
307 rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("...and changing the associated {$assoc_kind} name"))msg!("...and changing the associated {$assoc_kind} name"),
308 suggested_name,
309 Applicability::MaybeIncorrect,
310 );
311 }
312 return err.emit();
313 }
314 }
315 return self.dcx().emit_err(err);
316 }
317 }
318
319 if let [candidate_name] = all_candidate_names.as_slice() {
322 err.sugg = Some(errors::AssocItemNotFoundSugg::Other {
323 span: assoc_ident.span,
324 qself: &qself_str,
325 assoc_kind: assoc_kind_str,
326 suggested_name: *candidate_name,
327 });
328 } else {
329 err.label = Some(errors::AssocItemNotFoundLabel::NotFound { span: assoc_ident.span });
330 }
331
332 self.dcx().emit_err(err)
333 }
334
335 fn report_assoc_kind_mismatch(
336 &self,
337 assoc_item: &ty::AssocItem,
338 assoc_tag: ty::AssocTag,
339 ident: Ident,
340 span: Span,
341 constraint: Option<&hir::AssocItemConstraint<'tcx>>,
342 ) -> ErrorGuaranteed {
343 let tcx = self.tcx();
344
345 let bound_on_assoc_const_label = if let ty::AssocKind::Const { .. } = assoc_item.kind
346 && let Some(constraint) = constraint
347 && let hir::AssocItemConstraintKind::Bound { .. } = constraint.kind
348 {
349 let lo = if constraint.gen_args.span_ext.is_dummy() {
350 ident.span
351 } else {
352 constraint.gen_args.span_ext
353 };
354 Some(lo.between(span.shrink_to_hi()))
355 } else {
356 None
357 };
358
359 let wrap_in_braces_sugg = if let Some(constraint) = constraint
361 && let Some(hir_ty) = constraint.ty()
362 && let ty = self.lower_ty(hir_ty)
363 && (ty.is_enum() || ty.references_error())
364 && tcx.features().min_generic_const_args()
365 {
366 Some(errors::AssocKindMismatchWrapInBracesSugg {
367 lo: hir_ty.span.shrink_to_lo(),
368 hi: hir_ty.span.shrink_to_hi(),
369 })
370 } else {
371 None
372 };
373
374 let (span, expected_because_label, expected, got) = if let Some(constraint) = constraint
377 && let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
378 {
379 let span = match term {
380 hir::Term::Ty(ty) => ty.span,
381 hir::Term::Const(ct) => ct.span,
382 };
383 (span, Some(ident.span), assoc_item.tag(), assoc_tag)
384 } else {
385 (ident.span, None, assoc_tag, assoc_item.tag())
386 };
387
388 self.dcx().emit_err(errors::AssocKindMismatch {
389 span,
390 expected: assoc_tag_str(expected),
391 got: assoc_tag_str(got),
392 expected_because_label,
393 assoc_kind: assoc_tag_str(assoc_item.tag()),
394 def_span: tcx.def_span(assoc_item.def_id),
395 bound_on_assoc_const_label,
396 wrap_in_braces_sugg,
397 })
398 }
399
400 pub(crate) fn report_missing_self_ty_for_resolved_path(
401 &self,
402 trait_def_id: DefId,
403 span: Span,
404 item_segment: &hir::PathSegment<'tcx>,
405 assoc_tag: ty::AssocTag,
406 ) -> ErrorGuaranteed {
407 let tcx = self.tcx();
408 let path_str = tcx.def_path_str(trait_def_id);
409
410 let def_id = self.item_def_id();
411 {
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/hir_ty_lowering/errors.rs:411",
"rustc_hir_analysis::hir_ty_lowering::errors",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs"),
::tracing_core::__macro_support::Option::Some(411u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::errors"),
::tracing_core::field::FieldSet::new(&["item_def_id"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&def_id) as
&dyn Value))])
});
} else { ; }
};debug!(item_def_id = ?def_id);
412
413 let parent_def_id = tcx.hir_get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id();
415 {
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/hir_ty_lowering/errors.rs:415",
"rustc_hir_analysis::hir_ty_lowering::errors",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs"),
::tracing_core::__macro_support::Option::Some(415u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::errors"),
::tracing_core::field::FieldSet::new(&["parent_def_id"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&parent_def_id)
as &dyn Value))])
});
} else { ; }
};debug!(?parent_def_id);
416
417 let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id;
420 let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id;
421
422 let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
423 ::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()]
424 } else {
425 tcx.all_impls(trait_def_id)
427 .map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
428 .filter(|header| {
429 tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
431 && header.polarity != ty::ImplPolarity::Negative
432 })
433 .map(|header| header.trait_ref.instantiate_identity().self_ty())
434 .filter(|self_ty| !self_ty.has_non_region_param())
436 .map(|self_ty| tcx.erase_and_anonymize_regions(self_ty).to_string())
437 .collect()
438 };
439 self.report_ambiguous_assoc_item_path(
443 span,
444 &type_names,
445 &[path_str],
446 item_segment.ident,
447 assoc_tag,
448 )
449 }
450
451 pub(super) fn report_unresolved_type_relative_path(
452 &self,
453 self_ty: Ty<'tcx>,
454 hir_self_ty: &hir::Ty<'_>,
455 assoc_tag: ty::AssocTag,
456 ident: Ident,
457 qpath_hir_id: HirId,
458 span: Span,
459 variant_def_id: Option<DefId>,
460 ) -> ErrorGuaranteed {
461 let tcx = self.tcx();
462 let kind_str = assoc_tag_str(assoc_tag);
463 if variant_def_id.is_some() {
464 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}`");
466 self.dcx().span_err(span, msg)
467 } else if self_ty.is_enum() {
468 let mut err = self.dcx().create_err(errors::NoVariantNamed {
469 span: ident.span,
470 ident,
471 ty: self_ty,
472 });
473
474 let adt_def = self_ty.ty_adt_def().expect("enum is not an ADT");
475 if let Some(variant_name) = find_best_match_for_name(
476 &adt_def.variants().iter().map(|variant| variant.name).collect::<Vec<Symbol>>(),
477 ident.name,
478 None,
479 ) && let Some(variant) = adt_def.variants().iter().find(|s| s.name == variant_name)
480 {
481 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())];
482 if let hir::Node::Stmt(&hir::Stmt { kind: hir::StmtKind::Semi(expr), .. })
483 | hir::Node::Expr(expr) = tcx.parent_hir_node(qpath_hir_id)
484 && let hir::ExprKind::Struct(..) = expr.kind
485 {
486 match variant.ctor {
487 None => {
488 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![(
490 ident.span.with_hi(expr.span.hi()),
491 if variant.fields.is_empty() {
492 format!("{variant_name} {{}}")
493 } else {
494 format!(
495 "{variant_name} {{ {} }}",
496 variant
497 .fields
498 .iter()
499 .map(|f| format!("{}: /* value */", f.name))
500 .collect::<Vec<_>>()
501 .join(", ")
502 )
503 },
504 )];
505 }
506 Some((hir::def::CtorKind::Fn, def_id)) => {
507 let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
509 let inputs = fn_sig.inputs().skip_binder();
510 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![(
511 ident.span.with_hi(expr.span.hi()),
512 format!(
513 "{variant_name}({})",
514 inputs
515 .iter()
516 .map(|i| format!("/* {i} */"))
517 .collect::<Vec<_>>()
518 .join(", ")
519 ),
520 )];
521 }
522 Some((hir::def::CtorKind::Const, _)) => {
523 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![(
525 ident.span.with_hi(expr.span.hi()),
526 variant_name.to_string(),
527 )];
528 }
529 }
530 }
531 err.multipart_suggestion_verbose(
532 "there is a variant with a similar name",
533 suggestion,
534 Applicability::HasPlaceholders,
535 );
536 } else {
537 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}`"));
538 }
539
540 if let Some(sp) = tcx.hir_span_if_local(adt_def.did()) {
541 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"));
542 }
543
544 err.emit()
545 } else if let Err(reported) = self_ty.error_reported() {
546 reported
547 } else {
548 match self.maybe_report_similar_assoc_fn(span, self_ty, hir_self_ty) {
549 Ok(()) => {}
550 Err(reported) => return reported,
551 }
552
553 let traits: Vec<_> = self.probe_traits_that_match_assoc_ty(self_ty, ident);
554
555 self.report_ambiguous_assoc_item_path(
556 span,
557 &[self_ty.to_string()],
558 &traits,
559 ident,
560 assoc_tag,
561 )
562 }
563 }
564
565 pub(super) fn report_ambiguous_assoc_item_path(
566 &self,
567 span: Span,
568 types: &[String],
569 traits: &[String],
570 ident: Ident,
571 assoc_tag: ty::AssocTag,
572 ) -> ErrorGuaranteed {
573 let kind_str = assoc_tag_str(assoc_tag);
574 let mut err =
575 {
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}");
576 if self
577 .tcx()
578 .resolutions(())
579 .confused_type_with_std_module
580 .keys()
581 .any(|full_span| full_span.contains(span))
582 {
583 err.span_suggestion_verbose(
584 span.shrink_to_lo(),
585 "you are looking for the module in `std`, not the primitive type",
586 "std::",
587 Applicability::MachineApplicable,
588 );
589 } else {
590 let sugg_sp = span.until(ident.span);
591
592 let mut types = types.to_vec();
593 types.sort();
594 let mut traits = traits.to_vec();
595 traits.sort();
596 match (&types[..], &traits[..]) {
597 ([], []) => {
598 err.span_suggestion_verbose(
599 sugg_sp,
600 ::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!(
601 "if there were a type named `Type` that implements a trait named \
602 `Trait` with associated {kind_str} `{ident}`, you could use the \
603 fully-qualified path",
604 ),
605 "<Type as Trait>::",
606 Applicability::HasPlaceholders,
607 );
608 }
609 ([], [trait_str]) => {
610 err.span_suggestion_verbose(
611 sugg_sp,
612 ::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!(
613 "if there were a type named `Example` that implemented `{trait_str}`, \
614 you could use the fully-qualified path",
615 ),
616 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<Example as {0}>::", trait_str))
})format!("<Example as {trait_str}>::"),
617 Applicability::HasPlaceholders,
618 );
619 }
620 ([], traits) => {
621 err.span_suggestions_with_style(
622 sugg_sp,
623 ::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!(
624 "if there were a type named `Example` that implemented one of the \
625 traits with associated {kind_str} `{ident}`, you could use the \
626 fully-qualified path",
627 ),
628 traits.iter().map(|trait_str| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<Example as {0}>::", trait_str))
})format!("<Example as {trait_str}>::")),
629 Applicability::HasPlaceholders,
630 SuggestionStyle::ShowAlways,
631 );
632 }
633 ([type_str], []) => {
634 err.span_suggestion_verbose(
635 sugg_sp,
636 ::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!(
637 "if there were a trait named `Example` with associated {kind_str} `{ident}` \
638 implemented for `{type_str}`, you could use the fully-qualified path",
639 ),
640 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0} as Example>::", type_str))
})format!("<{type_str} as Example>::"),
641 Applicability::HasPlaceholders,
642 );
643 }
644 (types, []) => {
645 err.span_suggestions_with_style(
646 sugg_sp,
647 ::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!(
648 "if there were a trait named `Example` with associated {kind_str} `{ident}` \
649 implemented for one of the types, you could use the fully-qualified \
650 path",
651 ),
652 types
653 .into_iter()
654 .map(|type_str| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0} as Example>::", type_str))
})format!("<{type_str} as Example>::")),
655 Applicability::HasPlaceholders,
656 SuggestionStyle::ShowAlways,
657 );
658 }
659 (types, traits) => {
660 let mut suggestions = ::alloc::vec::Vec::new()vec![];
661 for type_str in types {
662 for trait_str in traits {
663 suggestions.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0} as {1}>::", type_str,
trait_str))
})format!("<{type_str} as {trait_str}>::"));
664 }
665 }
666 err.span_suggestions_with_style(
667 sugg_sp,
668 "use fully-qualified syntax",
669 suggestions,
670 Applicability::MachineApplicable,
671 SuggestionStyle::ShowAlways,
672 );
673 }
674 }
675 }
676 err.emit()
677 }
678
679 pub(crate) fn report_ambiguous_inherent_assoc_item(
680 &self,
681 name: Ident,
682 candidates: Vec<DefId>,
683 span: Span,
684 ) -> ErrorGuaranteed {
685 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!(
686 self.dcx(),
687 name.span,
688 E0034,
689 "multiple applicable items in scope"
690 );
691 err.span_label(name.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("multiple `{0}` found", name))
})format!("multiple `{name}` found"));
692 self.note_ambiguous_inherent_assoc_item(&mut err, candidates, span);
693 err.emit()
694 }
695
696 fn note_ambiguous_inherent_assoc_item(
698 &self,
699 err: &mut Diag<'_>,
700 candidates: Vec<DefId>,
701 span: Span,
702 ) {
703 let tcx = self.tcx();
704
705 let limit = if candidates.len() == 5 { 5 } else { 4 };
707
708 for (index, &item) in candidates.iter().take(limit).enumerate() {
709 let impl_ = tcx.parent(item);
710
711 let note_span = if item.is_local() {
712 Some(tcx.def_span(item))
713 } else if impl_.is_local() {
714 Some(tcx.def_span(impl_))
715 } else {
716 None
717 };
718
719 let title = if candidates.len() > 1 {
720 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("candidate #{0}", index + 1))
})format!("candidate #{}", index + 1)
721 } else {
722 "the candidate".into()
723 };
724
725 let impl_ty = tcx.at(span).type_of(impl_).instantiate_identity();
726 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}`");
727
728 if let Some(span) = note_span {
729 err.span_note(span, note);
730 } else {
731 err.note(note);
732 }
733 }
734 if candidates.len() > limit {
735 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("and {0} others",
candidates.len() - limit))
})format!("and {} others", candidates.len() - limit));
736 }
737 }
738
739 pub(crate) fn report_unresolved_inherent_assoc_item(
741 &self,
742 name: Ident,
743 self_ty: Ty<'tcx>,
744 candidates: Vec<InherentAssocCandidate>,
745 fulfillment_errors: Vec<FulfillmentError<'tcx>>,
746 span: Span,
747 assoc_tag: ty::AssocTag,
748 ) -> ErrorGuaranteed {
749 let tcx = self.tcx();
756
757 let assoc_tag_str = assoc_tag_str(assoc_tag);
758 let adt_did = self_ty.ty_adt_def().map(|def| def.did());
759 let add_def_label = |err: &mut Diag<'_>| {
760 if let Some(did) = adt_did {
761 err.span_label(
762 tcx.def_span(did),
763 ::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!(
764 "associated {assoc_tag_str} `{name}` not found for this {}",
765 tcx.def_descr(did)
766 ),
767 );
768 }
769 };
770
771 if fulfillment_errors.is_empty() {
772 let limit = if candidates.len() == 5 { 5 } else { 4 };
775 let type_candidates = candidates
776 .iter()
777 .take(limit)
778 .map(|cand| {
779 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("- `{0}`",
tcx.at(span).type_of(cand.impl_).instantiate_identity()))
})format!("- `{}`", tcx.at(span).type_of(cand.impl_).instantiate_identity())
780 })
781 .collect::<Vec<_>>()
782 .join("\n");
783 let additional_types = if candidates.len() > limit {
784 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("\nand {0} more types",
candidates.len() - limit))
})format!("\nand {} more types", candidates.len() - limit)
785 } else {
786 String::new()
787 };
788
789 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!(
790 self.dcx(),
791 name.span,
792 E0220,
793 "associated {assoc_tag_str} `{name}` not found for `{self_ty}` in the current scope"
794 );
795 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}`"));
796 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!(
797 "the associated {assoc_tag_str} was found for\n{type_candidates}{additional_types}",
798 ));
799 add_def_label(&mut err);
800 return err.emit();
801 }
802
803 let mut bound_spans: SortedMap<Span, Vec<String>> = Default::default();
804
805 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
806 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 });
807 match self_ty.kind() {
808 ty::Adt(def, _) => {
810 bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg)
811 }
812 ty::Dynamic(preds, _) => {
814 for pred in preds.iter() {
815 match pred.skip_binder() {
816 ty::ExistentialPredicate::Trait(tr) => {
817 bound_spans
818 .get_mut_or_insert_default(tcx.def_span(tr.def_id))
819 .push(msg.clone());
820 }
821 ty::ExistentialPredicate::Projection(_)
822 | ty::ExistentialPredicate::AutoTrait(_) => {}
823 }
824 }
825 }
826 ty::Closure(def_id, _) => {
828 bound_spans
829 .get_mut_or_insert_default(tcx.def_span(*def_id))
830 .push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", quiet))
})format!("`{quiet}`"));
831 }
832 _ => {}
833 }
834 };
835
836 let format_pred = |pred: ty::Predicate<'tcx>| {
837 let bound_predicate = pred.kind();
838 match bound_predicate.skip_binder() {
839 ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
840 let projection_term = pred.projection_term;
842 let quiet_projection_term = projection_term
843 .with_replaced_self_ty(tcx, Ty::new_var(tcx, ty::TyVid::ZERO));
844
845 let term = pred.term;
846 let obligation = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} = {1}", projection_term, term))
})format!("{projection_term} = {term}");
847 let quiet = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} = {1}", quiet_projection_term,
term))
})format!("{quiet_projection_term} = {term}");
848
849 bound_span_label(projection_term.self_ty(), &obligation, &quiet);
850 Some((obligation, projection_term.self_ty()))
851 }
852 ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => {
853 let p = poly_trait_ref.trait_ref;
854 let self_ty = p.self_ty();
855 let path = p.print_only_trait_path();
856 let obligation = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1}", self_ty, path))
})format!("{self_ty}: {path}");
857 let quiet = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("_: {0}", path))
})format!("_: {path}");
858 bound_span_label(self_ty, &obligation, &quiet);
859 Some((obligation, self_ty))
860 }
861 _ => None,
862 }
863 };
864
865 let mut bounds: Vec<_> = fulfillment_errors
868 .into_iter()
869 .map(|error| error.root_obligation.predicate)
870 .filter_map(format_pred)
871 .map(|(p, _)| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", p))
})format!("`{p}`"))
872 .collect();
873 bounds.sort();
874 bounds.dedup();
875
876 let mut err = self.dcx().struct_span_err(
877 name.span,
878 ::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")
879 );
880 if !bounds.is_empty() {
881 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the following trait bounds were not satisfied:\n{0}",
bounds.join("\n")))
})format!(
882 "the following trait bounds were not satisfied:\n{}",
883 bounds.join("\n")
884 ));
885 }
886 err.span_label(
887 name.span,
888 ::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")
889 );
890
891 for (span, mut bounds) in bound_spans {
892 if !tcx.sess.source_map().is_span_accessible(span) {
893 continue;
894 }
895 bounds.sort();
896 bounds.dedup();
897 let msg = match &bounds[..] {
898 [bound] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("doesn\'t satisfy {0}", bound))
})format!("doesn't satisfy {bound}"),
899 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()),
900 [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(", ")),
901 [] => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
902 };
903 err.span_label(span, msg);
904 }
905 add_def_label(&mut err);
906 err.emit()
907 }
908
909 pub(crate) fn check_for_required_assoc_items(
913 &self,
914 spans: SmallVec<[Span; 1]>,
915 missing_assoc_items: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>,
916 potential_assoc_items: Vec<usize>,
917 trait_bounds: &[hir::PolyTraitRef<'_>],
918 ) -> Result<(), ErrorGuaranteed> {
919 if missing_assoc_items.is_empty() {
920 return Ok(());
921 }
922
923 let tcx = self.tcx();
924 let principal_span = *spans.first().unwrap();
925
926 let missing_assoc_items: Vec<_> = missing_assoc_items
928 .into_iter()
929 .map(|(def_id, trait_ref)| (tcx.associated_item(def_id), trait_ref))
930 .collect();
931 let mut names: FxIndexMap<_, Vec<_>> = Default::default();
932 let mut names_len = 0;
933 let mut descr = None;
934
935 enum Descr {
936 Item,
937 Tag(ty::AssocTag),
938 }
939
940 for &(assoc_item, trait_ref) in &missing_assoc_items {
941 let violations =
949 dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), assoc_item);
950 if !violations.is_empty() {
951 return Err(report_dyn_incompatibility(
952 tcx,
953 principal_span,
954 None,
955 trait_ref.def_id(),
956 &violations,
957 )
958 .emit());
959 }
960
961 names.entry(trait_ref).or_default().push(assoc_item.name());
962 names_len += 1;
963
964 descr = match descr {
965 None => Some(Descr::Tag(assoc_item.tag())),
966 Some(Descr::Tag(tag)) if tag != assoc_item.tag() => Some(Descr::Item),
967 _ => continue,
968 };
969 }
970
971 let mut in_expr_or_pat = false;
973 if let ([], [bound]) = (&potential_assoc_items[..], &trait_bounds) {
974 let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id));
975 in_expr_or_pat = match grandparent {
976 hir::Node::Expr(_) | hir::Node::Pat(_) => true,
977 _ => false,
978 };
979 }
980
981 let bound_names: UnordMap<_, _> =
990 trait_bounds
991 .iter()
992 .filter_map(|poly_trait_ref| {
993 let path = poly_trait_ref.trait_ref.path.segments.last()?;
994 let args = path.args?;
995 let Res::Def(DefKind::Trait, trait_def_id) = path.res else { return None };
996
997 Some(args.constraints.iter().filter_map(move |constraint| {
998 let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
999 else {
1000 return None;
1001 };
1002 let tag = match term {
1003 hir::Term::Ty(_) => ty::AssocTag::Type,
1004 hir::Term::Const(_) => ty::AssocTag::Const,
1005 };
1006 let assoc_item = tcx
1007 .associated_items(trait_def_id)
1008 .find_by_ident_and_kind(tcx, constraint.ident, tag, trait_def_id)?;
1009 Some(((constraint.ident.name, tag), assoc_item.def_id))
1010 }))
1011 })
1012 .flatten()
1013 .collect();
1014
1015 let mut names: Vec<_> = names
1016 .into_iter()
1017 .map(|(trait_, mut assocs)| {
1018 assocs.sort();
1019 let trait_ = trait_.print_trait_sugared();
1020 ::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!(
1021 "{} in `{trait_}`",
1022 listify(&assocs[..], |a| format!("`{a}`")).unwrap_or_default()
1023 )
1024 })
1025 .collect();
1026 names.sort();
1027 let names = names.join(", ");
1028
1029 let descr = match descr.unwrap() {
1030 Descr::Item => "associated item",
1031 Descr::Tag(tag) => tag.descr(),
1032 };
1033 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!(
1034 self.dcx(),
1035 principal_span,
1036 E0191,
1037 "the value of the {descr}{s} {names} must be specified",
1038 s = pluralize!(names_len),
1039 );
1040 let mut suggestions = ::alloc::vec::Vec::new()vec![];
1041 let mut items_count = 0;
1042 let mut where_constraints = ::alloc::vec::Vec::new()vec![];
1043 let mut already_has_generics_args_suggestion = false;
1044
1045 let mut names: UnordMap<_, usize> = Default::default();
1046 for (item, _) in &missing_assoc_items {
1047 items_count += 1;
1048 *names.entry((item.name(), item.tag())).or_insert(0) += 1;
1049 }
1050 let mut dupes = false;
1051 let mut shadows = false;
1052 for (item, trait_ref) in &missing_assoc_items {
1053 let name = item.name();
1054 let key = (name, item.tag());
1055
1056 if names[&key] > 1 {
1057 dupes = true;
1058 } else if bound_names.get(&key).is_some_and(|&def_id| def_id != item.def_id) {
1059 shadows = true;
1060 }
1061
1062 let prefix = if dupes || shadows {
1063 ::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()))
1064 } else {
1065 String::new()
1066 };
1067 let mut is_shadowed = false;
1068
1069 if let Some(&def_id) = bound_names.get(&key)
1070 && def_id != item.def_id
1071 {
1072 is_shadowed = true;
1073
1074 let rename_message = if def_id.is_local() { ", consider renaming it" } else { "" };
1075 err.span_label(
1076 tcx.def_span(def_id),
1077 ::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}"),
1078 );
1079 }
1080
1081 let rename_message = if is_shadowed { ", consider renaming it" } else { "" };
1082
1083 if let Some(sp) = tcx.hir_span_if_local(item.def_id) {
1084 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}"));
1085 }
1086 }
1087 if potential_assoc_items.len() == missing_assoc_items.len() {
1088 already_has_generics_args_suggestion = true;
1092 } else if let (Ok(snippet), false, false) =
1093 (tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows)
1094 {
1095 let bindings: Vec<_> = missing_assoc_items
1096 .iter()
1097 .map(|(item, _)| {
1098 ::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::panic("internal error: entered unreachable code"),
}))
})format!(
1099 "{} = /* {} */",
1100 item.name(),
1101 match item.kind {
1102 ty::AssocKind::Const { .. } => "CONST",
1103 ty::AssocKind::Type { .. } => "Type",
1104 ty::AssocKind::Fn { .. } => unreachable!(),
1105 }
1106 )
1107 })
1108 .collect();
1109 let code = if let Some(snippet) = snippet.strip_suffix('>') {
1111 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}, {1}>", snippet,
bindings.join(", ")))
})format!("{}, {}>", snippet, bindings.join(", "))
1115 } else if in_expr_or_pat {
1116 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::<{1}>", snippet,
bindings.join(", ")))
})format!("{}::<{}>", snippet, bindings.join(", "))
1119 } else {
1120 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}<{1}>", snippet,
bindings.join(", ")))
})format!("{}<{}>", snippet, bindings.join(", "))
1123 };
1124 suggestions.push((principal_span, code));
1125 } else if dupes {
1126 where_constraints.push(principal_span);
1127 }
1128
1129 let where_msg = "consider introducing a new type parameter, adding `where` constraints \
1138 using the fully-qualified path to the associated types";
1139 if !where_constraints.is_empty() && suggestions.is_empty() {
1140 err.help(where_msg);
1144 }
1145 if suggestions.len() != 1 || already_has_generics_args_suggestion {
1146 let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
1148 for (item, _) in &missing_assoc_items {
1149 items_count += 1;
1150 *names.entry(item.name()).or_insert(0) += 1;
1151 }
1152 let mut label = ::alloc::vec::Vec::new()vec![];
1153 for (item, trait_ref) in &missing_assoc_items {
1154 let name = item.name();
1155 let postfix = if names[&name] > 1 {
1156 ::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())
1157 } else {
1158 String::new()
1159 };
1160 label.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`{1}", name, postfix))
})format!("`{}`{}", name, postfix));
1161 }
1162 if !label.is_empty() {
1163 err.span_label(
1164 principal_span,
1165 ::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!(
1166 "{descr}{s} {names} must be specified",
1167 s = pluralize!(label.len()),
1168 names = label.join(", "),
1169 ),
1170 );
1171 }
1172 }
1173 suggestions.sort_by_key(|&(span, _)| span);
1174 let overlaps = suggestions.windows(2).any(|pair| pair[0].0.overlaps(pair[1].0));
1187 if !suggestions.is_empty() && !overlaps {
1188 err.multipart_suggestion(
1189 ::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)),
1190 suggestions,
1191 Applicability::HasPlaceholders,
1192 );
1193 if !where_constraints.is_empty() {
1194 err.span_help(where_constraints, where_msg);
1195 }
1196 }
1197
1198 Err(err.emit())
1199 }
1200
1201 pub(crate) fn maybe_report_similar_assoc_fn(
1205 &self,
1206 span: Span,
1207 qself_ty: Ty<'tcx>,
1208 qself: &hir::Ty<'_>,
1209 ) -> Result<(), ErrorGuaranteed> {
1210 let tcx = self.tcx();
1211 if let Some((_, node)) = tcx.hir_parent_iter(qself.hir_id).skip(1).next()
1212 && let hir::Node::Expr(hir::Expr {
1213 kind:
1214 hir::ExprKind::Path(hir::QPath::TypeRelative(
1215 hir::Ty {
1216 kind:
1217 hir::TyKind::Path(hir::QPath::TypeRelative(
1218 _,
1219 hir::PathSegment { ident: ident2, .. },
1220 )),
1221 ..
1222 },
1223 hir::PathSegment { ident: ident3, .. },
1224 )),
1225 ..
1226 }) = node
1227 && let Some(inherent_impls) = qself_ty
1228 .ty_adt_def()
1229 .map(|adt_def| tcx.inherent_impls(adt_def.did()))
1230 .or_else(|| {
1231 simplify_type(tcx, qself_ty, TreatParams::InstantiateWithInfer)
1232 .map(|simple_ty| tcx.incoherent_impls(simple_ty))
1233 })
1234 && let name = Symbol::intern(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}_{1}", ident2, ident3))
})format!("{ident2}_{ident3}"))
1235 && let Some(item) = inherent_impls
1236 .iter()
1237 .flat_map(|inherent_impl| {
1238 tcx.associated_items(inherent_impl).filter_by_name_unhygienic(name)
1239 })
1240 .next()
1241 && item.is_fn()
1242 {
1243 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")
1244 .with_span_suggestion_verbose(
1245 ident2.span.to(ident3.span),
1246 ::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}`"),
1247 name,
1248 Applicability::MaybeIncorrect,
1249 )
1250 .emit())
1251 } else {
1252 Ok(())
1253 }
1254 }
1255
1256 pub fn report_prohibited_generic_args<'a>(
1257 &self,
1258 segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1259 args_visitors: impl Iterator<Item = &'a hir::GenericArg<'a>> + Clone,
1260 err_extend: GenericsArgsErrExtend<'a>,
1261 ) -> ErrorGuaranteed {
1262 #[derive(#[automatically_derived]
impl ::core::cmp::PartialEq for ProhibitGenericsArg {
#[inline]
fn eq(&self, other: &ProhibitGenericsArg) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ProhibitGenericsArg {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for ProhibitGenericsArg {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash)]
1263 enum ProhibitGenericsArg {
1264 Lifetime,
1265 Type,
1266 Const,
1267 Infer,
1268 }
1269
1270 let mut prohibit_args = FxIndexSet::default();
1271 args_visitors.for_each(|arg| {
1272 match arg {
1273 hir::GenericArg::Lifetime(_) => prohibit_args.insert(ProhibitGenericsArg::Lifetime),
1274 hir::GenericArg::Type(_) => prohibit_args.insert(ProhibitGenericsArg::Type),
1275 hir::GenericArg::Const(_) => prohibit_args.insert(ProhibitGenericsArg::Const),
1276 hir::GenericArg::Infer(_) => prohibit_args.insert(ProhibitGenericsArg::Infer),
1277 };
1278 });
1279
1280 let segments: Vec<_> = segments.collect();
1281 let types_and_spans: Vec<_> = segments
1282 .iter()
1283 .flat_map(|segment| {
1284 if segment.args().args.is_empty() {
1285 None
1286 } else {
1287 Some((
1288 match segment.res {
1289 Res::PrimTy(ty) => {
1290 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} `{1}`", segment.res.descr(),
ty.name()))
})format!("{} `{}`", segment.res.descr(), ty.name())
1291 }
1292 Res::Def(_, def_id)
1293 if let Some(name) = self.tcx().opt_item_name(def_id) =>
1294 {
1295 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} `{1}`", segment.res.descr(),
name))
})format!("{} `{name}`", segment.res.descr())
1296 }
1297 Res::Err => "this type".to_string(),
1298 _ => segment.res.descr().to_string(),
1299 },
1300 segment.ident.span,
1301 ))
1302 }
1303 })
1304 .collect();
1305 let this_type = listify(&types_and_spans, |(t, _)| t.to_string())
1306 .expect("expected one segment to deny");
1307
1308 let arg_spans: Vec<Span> =
1309 segments.iter().flat_map(|segment| segment.args().args).map(|arg| arg.span()).collect();
1310
1311 let mut kinds = Vec::with_capacity(4);
1312 prohibit_args.iter().for_each(|arg| match arg {
1313 ProhibitGenericsArg::Lifetime => kinds.push("lifetime"),
1314 ProhibitGenericsArg::Type => kinds.push("type"),
1315 ProhibitGenericsArg::Const => kinds.push("const"),
1316 ProhibitGenericsArg::Infer => kinds.push("generic"),
1317 });
1318
1319 let s = if kinds.len() == 1 { "" } else { "s" }pluralize!(kinds.len());
1320 let kind =
1321 listify(&kinds, |k| k.to_string()).expect("expected at least one generic to prohibit");
1322 let last_span = *arg_spans.last().unwrap();
1323 let span: MultiSpan = arg_spans.into();
1324 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!(
1325 self.dcx(),
1326 span,
1327 E0109,
1328 "{kind} arguments are not allowed on {this_type}",
1329 );
1330 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"));
1331 for (what, span) in types_and_spans {
1332 err.span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("not allowed on {0}", what))
})format!("not allowed on {what}"));
1333 }
1334 generics_args_err_extend(self.tcx(), segments.into_iter(), &mut err, err_extend);
1335 err.emit()
1336 }
1337
1338 pub fn report_trait_object_addition_traits(
1339 &self,
1340 regular_traits: &Vec<(ty::PolyTraitPredicate<'tcx>, SmallVec<[Span; 1]>)>,
1341 ) -> ErrorGuaranteed {
1342 let (&first_span, first_alias_spans) = regular_traits[0].1.split_last().unwrap();
1345 let (&second_span, second_alias_spans) = regular_traits[1].1.split_last().unwrap();
1346 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!(
1347 self.dcx(),
1348 *regular_traits[1].1.first().unwrap(),
1349 E0225,
1350 "only auto traits can be used as additional traits in a trait object"
1351 );
1352 err.span_label(first_span, "first non-auto trait");
1353 for &alias_span in first_alias_spans {
1354 err.span_label(alias_span, "first non-auto trait comes from this alias");
1355 }
1356 err.span_label(second_span, "additional non-auto trait");
1357 for &alias_span in second_alias_spans {
1358 err.span_label(alias_span, "second non-auto trait comes from this alias");
1359 }
1360 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!(
1361 "consider creating a new trait with all of these as supertraits and using that \
1362 trait here instead: `trait NewTrait: {} {{}}`",
1363 regular_traits
1364 .iter()
1365 .map(|(pred, _)| pred
1367 .map_bound(|pred| pred.trait_ref)
1368 .print_only_trait_path()
1369 .to_string())
1370 .collect::<Vec<_>>()
1371 .join(" + "),
1372 ));
1373 err.note(
1374 "auto-traits like `Send` and `Sync` are traits that have special properties; \
1375 for more information on them, visit \
1376 <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
1377 );
1378 err.emit()
1379 }
1380
1381 pub fn report_trait_object_with_no_traits(
1382 &self,
1383 span: Span,
1384 user_written_clauses: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
1385 ) -> ErrorGuaranteed {
1386 let tcx = self.tcx();
1387 let trait_alias_span = user_written_clauses
1388 .into_iter()
1389 .filter_map(|(clause, _)| clause.as_trait_clause())
1390 .find(|trait_ref| tcx.is_trait_alias(trait_ref.def_id()))
1391 .map(|trait_ref| tcx.def_span(trait_ref.def_id()));
1392
1393 self.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span })
1394 }
1395}
1396
1397pub fn prohibit_assoc_item_constraint(
1399 cx: &dyn HirTyLowerer<'_>,
1400 constraint: &hir::AssocItemConstraint<'_>,
1401 segment: Option<(DefId, &hir::PathSegment<'_>, Span)>,
1402) -> ErrorGuaranteed {
1403 let tcx = cx.tcx();
1404 let mut err = cx.dcx().create_err(AssocItemConstraintsNotAllowedHere {
1405 span: constraint.span,
1406 fn_trait_expansion: if let Some((_, segment, span)) = segment
1407 && segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar
1408 {
1409 Some(ParenthesizedFnTraitExpansion {
1410 span,
1411 expanded_type: fn_trait_to_string(tcx, segment, false),
1412 })
1413 } else {
1414 None
1415 },
1416 });
1417
1418 if let Some((def_id, segment, _)) = segment
1422 && segment.args().parenthesized == hir::GenericArgsParentheses::No
1423 {
1424 let suggest_removal = |e: &mut Diag<'_>| {
1426 let constraints = segment.args().constraints;
1427 let args = segment.args().args;
1428
1429 let Some(index) = constraints.iter().position(|b| b.hir_id == constraint.hir_id) else {
1441 ::rustc_middle::util::bug::bug_fmt(format_args!("a type binding exists but its HIR ID not found in generics"));bug!("a type binding exists but its HIR ID not found in generics");
1442 };
1443
1444 let preceding_span = if index > 0 {
1445 Some(constraints[index - 1].span)
1446 } else {
1447 args.last().map(|a| a.span())
1448 };
1449
1450 let next_span = constraints.get(index + 1).map(|constraint| constraint.span);
1451
1452 let removal_span = match (preceding_span, next_span) {
1453 (Some(prec), _) => constraint.span.with_lo(prec.hi()),
1454 (None, Some(next)) => constraint.span.with_hi(next.lo()),
1455 (None, None) => {
1456 let Some(generics_span) = segment.args().span_ext() else {
1457 ::rustc_middle::util::bug::bug_fmt(format_args!("a type binding exists but generic span is empty"));bug!("a type binding exists but generic span is empty");
1458 };
1459
1460 generics_span
1461 }
1462 };
1463
1464 e.span_suggestion_verbose(
1466 removal_span,
1467 ::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()),
1468 "",
1469 Applicability::MaybeIncorrect,
1470 );
1471 };
1472
1473 let suggest_direct_use = |e: &mut Diag<'_>, sp: Span| {
1476 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(sp) {
1477 e.span_suggestion_verbose(
1478 constraint.span,
1479 ::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"),
1480 snippet,
1481 Applicability::MaybeIncorrect,
1482 );
1483 }
1484 };
1485
1486 let generics = tcx.generics_of(def_id);
1489 let matching_param = generics.own_params.iter().find(|p| p.name == constraint.ident.name);
1490
1491 if let Some(matching_param) = matching_param {
1493 match (constraint.kind, &matching_param.kind) {
1494 (
1495 hir::AssocItemConstraintKind::Equality { term: hir::Term::Ty(ty) },
1496 GenericParamDefKind::Type { .. },
1497 ) => suggest_direct_use(&mut err, ty.span),
1498 (
1499 hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) },
1500 GenericParamDefKind::Const { .. },
1501 ) => {
1502 suggest_direct_use(&mut err, c.span);
1503 }
1504 (hir::AssocItemConstraintKind::Bound { bounds }, _) => {
1505 let impl_block = tcx
1511 .hir_parent_iter(constraint.hir_id)
1512 .find_map(|(_, node)| node.impl_block_of_trait(def_id));
1513
1514 let type_with_constraints =
1515 tcx.sess.source_map().span_to_snippet(constraint.span);
1516
1517 if let Some(impl_block) = impl_block
1518 && let Ok(type_with_constraints) = type_with_constraints
1519 {
1520 let lifetimes: String = bounds
1523 .iter()
1524 .filter_map(|bound| {
1525 if let hir::GenericBound::Outlives(lifetime) = bound {
1526 Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}, ", lifetime))
})format!("{lifetime}, "))
1527 } else {
1528 None
1529 }
1530 })
1531 .collect();
1532 let param_decl = if let Some(param_span) =
1535 impl_block.generics.span_for_param_suggestion()
1536 {
1537 (param_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(", {0}{1}", lifetimes,
type_with_constraints))
})format!(", {lifetimes}{type_with_constraints}"))
1538 } else {
1539 (
1540 impl_block.generics.span.shrink_to_lo(),
1541 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0}{1}>", lifetimes,
type_with_constraints))
})format!("<{lifetimes}{type_with_constraints}>"),
1542 )
1543 };
1544 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![
1545 param_decl,
1546 (constraint.span.with_lo(constraint.ident.span.hi()), String::new()),
1547 ];
1548
1549 err.multipart_suggestion_verbose(
1550 "declare the type parameter right after the `impl` keyword",
1551 suggestions,
1552 Applicability::MaybeIncorrect,
1553 );
1554 }
1555 }
1556 _ => suggest_removal(&mut err),
1557 }
1558 } else {
1559 suggest_removal(&mut err);
1560 }
1561 }
1562
1563 err.emit()
1564}
1565
1566pub(crate) fn fn_trait_to_string(
1567 tcx: TyCtxt<'_>,
1568 trait_segment: &hir::PathSegment<'_>,
1569 parenthesized: bool,
1570) -> String {
1571 let args = trait_segment
1572 .args
1573 .and_then(|args| args.args.first())
1574 .and_then(|arg| match arg {
1575 hir::GenericArg::Type(ty) => match ty.kind {
1576 hir::TyKind::Tup(t) => t
1577 .iter()
1578 .map(|e| tcx.sess.source_map().span_to_snippet(e.span))
1579 .collect::<Result<Vec<_>, _>>()
1580 .map(|a| a.join(", ")),
1581 _ => tcx.sess.source_map().span_to_snippet(ty.span),
1582 }
1583 .map(|s| {
1584 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},)") }
1586 })
1587 .ok(),
1588 _ => None,
1589 })
1590 .unwrap_or_else(|| "()".to_string());
1591
1592 let ret = trait_segment
1593 .args()
1594 .constraints
1595 .iter()
1596 .find_map(|c| {
1597 if c.ident.name == sym::Output
1598 && let Some(ty) = c.ty()
1599 && ty.span != tcx.hir_span(trait_segment.hir_id)
1600 {
1601 tcx.sess.source_map().span_to_snippet(ty.span).ok()
1602 } else {
1603 None
1604 }
1605 })
1606 .unwrap_or_else(|| "()".to_string());
1607
1608 if parenthesized {
1609 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1} -> {2}",
trait_segment.ident, args, ret))
})format!("{}{} -> {}", trait_segment.ident, args, ret)
1610 } else {
1611 ::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)
1612 }
1613}
1614
1615pub enum GenericsArgsErrExtend<'tcx> {
1617 EnumVariant {
1618 qself: &'tcx hir::Ty<'tcx>,
1619 assoc_segment: &'tcx hir::PathSegment<'tcx>,
1620 adt_def: AdtDef<'tcx>,
1621 },
1622 OpaqueTy,
1623 PrimTy(hir::PrimTy),
1624 SelfTyAlias {
1625 def_id: DefId,
1626 span: Span,
1627 },
1628 SelfTyParam(Span),
1629 Param(DefId),
1630 DefVariant(&'tcx [hir::PathSegment<'tcx>]),
1631 None,
1632}
1633
1634fn generics_args_err_extend<'a>(
1635 tcx: TyCtxt<'_>,
1636 segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1637 err: &mut Diag<'_>,
1638 err_extend: GenericsArgsErrExtend<'a>,
1639) {
1640 match err_extend {
1641 GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def } => {
1642 err.note("enum variants can't have type parameters");
1643 let type_name = tcx.item_name(adt_def.did());
1644 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!(
1645 "you might have meant to specify type parameters on enum \
1646 `{type_name}`"
1647 );
1648 let Some(args) = assoc_segment.args else {
1649 return;
1650 };
1651 let args_span = args.span_ext.with_lo(args.span_ext.lo() - BytePos(2));
1656 if tcx.generics_of(adt_def.did()).is_empty() {
1657 err.span_suggestion_verbose(
1660 args_span,
1661 ::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"),
1662 "",
1663 Applicability::MachineApplicable,
1664 );
1665 return;
1666 }
1667 let Ok(snippet) = tcx.sess.source_map().span_to_snippet(args_span) else {
1668 err.note(msg);
1669 return;
1670 };
1671 let (qself_sugg_span, is_self) =
1672 if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
1673 match &path.segments {
1676 [
1680 ..,
1681 hir::PathSegment {
1682 ident, args, res: Res::Def(DefKind::Enum, _), ..
1683 },
1684 _,
1685 ] => (
1686 ident
1689 .span
1690 .shrink_to_hi()
1691 .to(args.map_or(ident.span.shrink_to_hi(), |a| a.span_ext)),
1692 false,
1693 ),
1694 [segment] => {
1695 (
1696 segment.ident.span.shrink_to_hi().to(segment
1699 .args
1700 .map_or(segment.ident.span.shrink_to_hi(), |a| a.span_ext)),
1701 kw::SelfUpper == segment.ident.name,
1702 )
1703 }
1704 _ => {
1705 err.note(msg);
1706 return;
1707 }
1708 }
1709 } else {
1710 err.note(msg);
1711 return;
1712 };
1713 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![
1714 if is_self {
1715 (qself.span, format!("{type_name}{snippet}"))
1719 } else {
1720 (qself_sugg_span, snippet)
1721 },
1722 (args_span, String::new()),
1723 ];
1724 err.multipart_suggestion_verbose(msg, suggestion, Applicability::MaybeIncorrect);
1725 }
1726 GenericsArgsErrExtend::DefVariant(segments) => {
1727 let args: Vec<Span> = segments
1728 .iter()
1729 .filter_map(|segment| match segment.res {
1730 Res::Def(
1731 DefKind::Ctor(CtorOf::Variant, _) | DefKind::Variant | DefKind::Enum,
1732 _,
1733 ) => segment.args().span_ext().map(|s| s.with_lo(segment.ident.span.hi())),
1734 _ => None,
1735 })
1736 .collect();
1737 if args.len() > 1
1738 && let Some(span) = args.into_iter().next_back()
1739 {
1740 err.note(
1741 "generic arguments are not allowed on both an enum and its variant's path \
1742 segments simultaneously; they are only valid in one place or the other",
1743 );
1744 err.span_suggestion_verbose(
1745 span,
1746 "remove the generics arguments from one of the path segments",
1747 String::new(),
1748 Applicability::MaybeIncorrect,
1749 );
1750 }
1751 }
1752 GenericsArgsErrExtend::PrimTy(prim_ty) => {
1753 let name = prim_ty.name_str();
1754 for segment in segments {
1755 if let Some(args) = segment.args {
1756 err.span_suggestion_verbose(
1757 segment.ident.span.shrink_to_hi().to(args.span_ext),
1758 ::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"),
1759 "",
1760 Applicability::MaybeIncorrect,
1761 );
1762 }
1763 }
1764 }
1765 GenericsArgsErrExtend::OpaqueTy => {
1766 err.note("`impl Trait` types can't have type parameters");
1767 }
1768 GenericsArgsErrExtend::Param(def_id) => {
1769 let span = tcx.def_ident_span(def_id).unwrap();
1770 let kind = tcx.def_descr(def_id);
1771 let name = tcx.item_name(def_id);
1772 err.span_note(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} `{1}` defined here", kind,
name))
})format!("{kind} `{name}` defined here"));
1773 }
1774 GenericsArgsErrExtend::SelfTyParam(span) => {
1775 err.span_suggestion_verbose(
1776 span,
1777 "the `Self` type doesn't accept type parameters",
1778 "",
1779 Applicability::MaybeIncorrect,
1780 );
1781 }
1782 GenericsArgsErrExtend::SelfTyAlias { def_id, span } => {
1783 let ty = tcx.at(span).type_of(def_id).instantiate_identity();
1784 let span_of_impl = tcx.span_of_impl(def_id);
1785 let ty::Adt(self_def, _) = *ty.kind() else { return };
1786 let def_id = self_def.did();
1787
1788 let type_name = tcx.item_name(def_id);
1789 let span_of_ty = tcx.def_ident_span(def_id);
1790 let generics = tcx.generics_of(def_id).count();
1791
1792 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`Self` is of type `{0}`", ty))
})format!("`Self` is of type `{ty}`");
1793 if let (Ok(i_sp), Some(t_sp)) = (span_of_impl, span_of_ty) {
1794 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();
1795 span.push_span_label(
1796 i_sp,
1797 ::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`"),
1798 );
1799 let mut postfix = "";
1800 if generics == 0 {
1801 postfix = ", which doesn't have generic parameters";
1802 }
1803 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}"));
1804 err.span_note(span, msg);
1805 } else {
1806 err.note(msg);
1807 }
1808 for segment in segments {
1809 if let Some(args) = segment.args
1810 && segment.ident.name == kw::SelfUpper
1811 {
1812 if generics == 0 {
1813 err.span_suggestion_verbose(
1816 segment.ident.span.shrink_to_hi().to(args.span_ext),
1817 "the `Self` type doesn't accept type parameters",
1818 "",
1819 Applicability::MachineApplicable,
1820 );
1821 return;
1822 } else {
1823 err.span_suggestion_verbose(
1824 segment.ident.span,
1825 ::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!(
1826 "the `Self` type doesn't accept type parameters, use the \
1827 concrete type's name `{type_name}` instead if you want to \
1828 specify its type parameters"
1829 ),
1830 type_name,
1831 Applicability::MaybeIncorrect,
1832 );
1833 }
1834 }
1835 }
1836 }
1837 _ => {}
1838 }
1839}
1840
1841pub(crate) fn assoc_tag_str(assoc_tag: ty::AssocTag) -> &'static str {
1842 match assoc_tag {
1843 ty::AssocTag::Fn => "function",
1844 ty::AssocTag::Const => "constant",
1845 ty::AssocTag::Type => "type",
1846 }
1847}