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