1use std::cell::Cell;
18use std::iter;
19use std::ops::Bound;
20
21use rustc_abi::ExternAbi;
22use rustc_ast::Recovered;
23use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
24use rustc_data_structures::unord::UnordMap;
25use rustc_errors::{
26 Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey, struct_span_code_err,
27};
28use rustc_hir::def::DefKind;
29use rustc_hir::def_id::{DefId, LocalDefId};
30use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt, walk_generics};
31use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind};
32use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
33use rustc_infer::traits::ObligationCause;
34use rustc_middle::hir::nested_filter;
35use rustc_middle::query::Providers;
36use rustc_middle::ty::util::{Discr, IntTypeExt};
37use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode, fold_regions};
38use rustc_middle::{bug, span_bug};
39use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
40use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
41use rustc_trait_selection::infer::InferCtxtExt;
42use rustc_trait_selection::traits::ObligationCtxt;
43use tracing::{debug, instrument};
44
45use crate::check::intrinsic::intrinsic_operation_unsafety;
46use crate::errors;
47use crate::hir_ty_lowering::errors::assoc_kind_str;
48use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};
49
50pub(crate) mod dump;
51mod generics_of;
52mod item_bounds;
53mod predicates_of;
54mod resolve_bound_vars;
55mod type_of;
56
57pub(crate) fn provide(providers: &mut Providers) {
60 resolve_bound_vars::provide(providers);
61 *providers = Providers {
62 type_of: type_of::type_of,
63 type_of_opaque: type_of::type_of_opaque,
64 type_alias_is_lazy: type_of::type_alias_is_lazy,
65 item_bounds: item_bounds::item_bounds,
66 explicit_item_bounds: item_bounds::explicit_item_bounds,
67 item_self_bounds: item_bounds::item_self_bounds,
68 explicit_item_self_bounds: item_bounds::explicit_item_self_bounds,
69 item_non_self_bounds: item_bounds::item_non_self_bounds,
70 impl_super_outlives: item_bounds::impl_super_outlives,
71 generics_of: generics_of::generics_of,
72 predicates_of: predicates_of::predicates_of,
73 explicit_predicates_of: predicates_of::explicit_predicates_of,
74 explicit_super_predicates_of: predicates_of::explicit_super_predicates_of,
75 explicit_implied_predicates_of: predicates_of::explicit_implied_predicates_of,
76 explicit_supertraits_containing_assoc_item:
77 predicates_of::explicit_supertraits_containing_assoc_item,
78 trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
79 const_conditions: predicates_of::const_conditions,
80 explicit_implied_const_bounds: predicates_of::explicit_implied_const_bounds,
81 type_param_predicates: predicates_of::type_param_predicates,
82 trait_def,
83 adt_def,
84 fn_sig,
85 impl_trait_header,
86 coroutine_kind,
87 coroutine_for_closure,
88 opaque_ty_origin,
89 rendered_precise_capturing_args,
90 const_param_default,
91 ..*providers
92 };
93}
94
95pub(crate) struct ItemCtxt<'tcx> {
125 tcx: TyCtxt<'tcx>,
126 item_def_id: LocalDefId,
127 tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
128}
129
130#[derive(Default)]
133pub(crate) struct HirPlaceholderCollector {
134 pub spans: Vec<Span>,
135 pub may_contain_const_infer: bool,
138}
139
140impl<'v> Visitor<'v> for HirPlaceholderCollector {
141 fn visit_infer(&mut self, _inf_id: HirId, inf_span: Span, kind: InferKind<'v>) -> Self::Result {
142 self.spans.push(inf_span);
143
144 if let InferKind::Const(_) | InferKind::Ambig(_) = kind {
145 self.may_contain_const_infer = true;
146 }
147 }
148}
149
150pub(crate) struct CollectItemTypesVisitor<'tcx> {
151 pub tcx: TyCtxt<'tcx>,
152}
153
154pub(crate) fn placeholder_type_error<'tcx>(
158 cx: &dyn HirTyLowerer<'tcx>,
159 generics: Option<&hir::Generics<'_>>,
160 placeholder_types: Vec<Span>,
161 suggest: bool,
162 hir_ty: Option<&hir::Ty<'_>>,
163 kind: &'static str,
164) {
165 if placeholder_types.is_empty() {
166 return;
167 }
168
169 placeholder_type_error_diag(cx, generics, placeholder_types, vec![], suggest, hir_ty, kind)
170 .emit();
171}
172
173pub(crate) fn placeholder_type_error_diag<'cx, 'tcx>(
174 cx: &'cx dyn HirTyLowerer<'tcx>,
175 generics: Option<&hir::Generics<'_>>,
176 placeholder_types: Vec<Span>,
177 additional_spans: Vec<Span>,
178 suggest: bool,
179 hir_ty: Option<&hir::Ty<'_>>,
180 kind: &'static str,
181) -> Diag<'cx> {
182 if placeholder_types.is_empty() {
183 return bad_placeholder(cx, additional_spans, kind);
184 }
185
186 let params = generics.map(|g| g.params).unwrap_or_default();
187 let type_name = params.next_type_param_name(None);
188 let mut sugg: Vec<_> =
189 placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
190
191 if let Some(generics) = generics {
192 if let Some(span) = params.iter().find_map(|arg| match arg.name {
193 hir::ParamName::Plain(Ident { name: kw::Underscore, span }) => Some(span),
194 _ => None,
195 }) {
196 sugg.push((span, (*type_name).to_string()));
199 } else if let Some(span) = generics.span_for_param_suggestion() {
200 sugg.push((span, format!(", {type_name}")));
202 } else {
203 sugg.push((generics.span, format!("<{type_name}>")));
204 }
205 }
206
207 let mut err =
208 bad_placeholder(cx, placeholder_types.into_iter().chain(additional_spans).collect(), kind);
209
210 if suggest {
212 let mut is_fn = false;
213 let mut is_const_or_static = false;
214
215 if let Some(hir_ty) = hir_ty
216 && let hir::TyKind::BareFn(_) = hir_ty.kind
217 {
218 is_fn = true;
219
220 is_const_or_static = matches!(
222 cx.tcx().parent_hir_node(hir_ty.hir_id),
223 Node::Item(&hir::Item {
224 kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..),
225 ..
226 }) | Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. })
227 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. })
228 );
229 }
230
231 if !(is_fn && is_const_or_static) {
234 err.multipart_suggestion(
235 "use type parameters instead",
236 sugg,
237 Applicability::HasPlaceholders,
238 );
239 }
240 }
241
242 err
243}
244
245fn reject_placeholder_type_signatures_in_item<'tcx>(
246 tcx: TyCtxt<'tcx>,
247 item: &'tcx hir::Item<'tcx>,
248) {
249 let (generics, suggest) = match &item.kind {
250 hir::ItemKind::Union(_, _, generics)
251 | hir::ItemKind::Enum(_, _, generics)
252 | hir::ItemKind::TraitAlias(_, generics, _)
253 | hir::ItemKind::Trait(_, _, _, generics, ..)
254 | hir::ItemKind::Impl(hir::Impl { generics, .. })
255 | hir::ItemKind::Struct(_, _, generics) => (generics, true),
256 hir::ItemKind::TyAlias(_, _, generics) => (generics, false),
257 _ => return,
259 };
260
261 let mut visitor = HirPlaceholderCollector::default();
262 visitor.visit_item(item);
263
264 let icx = ItemCtxt::new(tcx, item.owner_id.def_id);
265
266 placeholder_type_error(
267 icx.lowerer(),
268 Some(generics),
269 visitor.spans,
270 suggest && !visitor.may_contain_const_infer,
271 None,
272 item.kind.descr(),
273 );
274}
275
276impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
277 type NestedFilter = nested_filter::OnlyBodies;
278
279 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
280 self.tcx
281 }
282
283 fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
284 lower_item(self.tcx, item.item_id());
285 reject_placeholder_type_signatures_in_item(self.tcx, item);
286 intravisit::walk_item(self, item);
287 }
288
289 fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
290 for param in generics.params {
291 match param.kind {
292 hir::GenericParamKind::Lifetime { .. } => {}
293 hir::GenericParamKind::Type { default: Some(_), .. } => {
294 self.tcx.ensure_ok().type_of(param.def_id);
295 }
296 hir::GenericParamKind::Type { .. } => {}
297 hir::GenericParamKind::Const { default, .. } => {
298 self.tcx.ensure_ok().type_of(param.def_id);
299 if let Some(default) = default {
300 self.tcx.ensure_ok().const_param_default(param.def_id);
302 if let hir::ConstArgKind::Anon(ac) = default.kind {
303 self.tcx.ensure_ok().type_of(ac.def_id);
304 }
305 }
306 }
307 }
308 }
309 intravisit::walk_generics(self, generics);
310 }
311
312 fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
313 if let hir::ExprKind::Closure(closure) = expr.kind {
314 self.tcx.ensure_ok().generics_of(closure.def_id);
315 self.tcx.ensure_ok().codegen_fn_attrs(closure.def_id);
316 }
320 intravisit::walk_expr(self, expr);
321 }
322
323 fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) {
326 let def_id = opaque.def_id;
327 self.tcx.ensure_ok().generics_of(def_id);
328 self.tcx.ensure_ok().predicates_of(def_id);
329 self.tcx.ensure_ok().explicit_item_bounds(def_id);
330 self.tcx.ensure_ok().explicit_item_self_bounds(def_id);
331 self.tcx.ensure_ok().item_bounds(def_id);
332 self.tcx.ensure_ok().item_self_bounds(def_id);
333 if self.tcx.is_conditionally_const(def_id) {
334 self.tcx.ensure_ok().explicit_implied_const_bounds(def_id);
335 self.tcx.ensure_ok().const_conditions(def_id);
336 }
337 intravisit::walk_opaque_ty(self, opaque);
338 }
339
340 fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
341 lower_trait_item(self.tcx, trait_item.trait_item_id());
342 intravisit::walk_trait_item(self, trait_item);
343 }
344
345 fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
346 lower_impl_item(self.tcx, impl_item.impl_item_id());
347 intravisit::walk_impl_item(self, impl_item);
348 }
349}
350
351fn bad_placeholder<'cx, 'tcx>(
355 cx: &'cx dyn HirTyLowerer<'tcx>,
356 mut spans: Vec<Span>,
357 kind: &'static str,
358) -> Diag<'cx> {
359 let kind = if kind.ends_with('s') { format!("{kind}es") } else { format!("{kind}s") };
360
361 spans.sort();
362 cx.dcx().create_err(errors::PlaceholderNotAllowedItemSignatures { spans, kind })
363}
364
365impl<'tcx> ItemCtxt<'tcx> {
366 pub(crate) fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
367 ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
368 }
369
370 pub(crate) fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
371 self.lowerer().lower_ty(hir_ty)
372 }
373
374 pub(crate) fn hir_id(&self) -> hir::HirId {
375 self.tcx.local_def_id_to_hir_id(self.item_def_id)
376 }
377
378 pub(crate) fn node(&self) -> hir::Node<'tcx> {
379 self.tcx.hir_node(self.hir_id())
380 }
381
382 fn check_tainted_by_errors(&self) -> Result<(), ErrorGuaranteed> {
383 match self.tainted_by_errors.get() {
384 Some(err) => Err(err),
385 None => Ok(()),
386 }
387 }
388}
389
390impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
391 fn tcx(&self) -> TyCtxt<'tcx> {
392 self.tcx
393 }
394
395 fn dcx(&self) -> DiagCtxtHandle<'_> {
396 self.tcx.dcx().taintable_handle(&self.tainted_by_errors)
397 }
398
399 fn item_def_id(&self) -> LocalDefId {
400 self.item_def_id
401 }
402
403 fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> {
404 if let RegionInferReason::ObjectLifetimeDefault = reason {
405 let e = struct_span_code_err!(
406 self.dcx(),
407 span,
408 E0228,
409 "the lifetime bound for this object type cannot be deduced \
410 from context; please supply an explicit bound"
411 )
412 .emit();
413 ty::Region::new_error(self.tcx(), e)
414 } else {
415 ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature")
417 }
418 }
419
420 fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
421 Ty::new_error_with_message(self.tcx(), span, "bad placeholder type")
422 }
423
424 fn ct_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
425 ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant")
426 }
427
428 fn register_trait_ascription_bounds(
429 &self,
430 _: Vec<(ty::Clause<'tcx>, Span)>,
431 _: HirId,
432 span: Span,
433 ) {
434 self.dcx().span_delayed_bug(span, "trait ascription type not allowed here");
435 }
436
437 fn probe_ty_param_bounds(
438 &self,
439 span: Span,
440 def_id: LocalDefId,
441 assoc_name: Ident,
442 ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
443 self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_name))
444 }
445
446 fn lower_assoc_shared(
447 &self,
448 span: Span,
449 item_def_id: DefId,
450 item_segment: &rustc_hir::PathSegment<'tcx>,
451 poly_trait_ref: ty::PolyTraitRef<'tcx>,
452 kind: ty::AssocKind,
453 ) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
454 if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
455 let item_args = self.lowerer().lower_generic_args_of_assoc_item(
456 span,
457 item_def_id,
458 item_segment,
459 trait_ref.args,
460 );
461 Ok((item_def_id, item_args))
462 } else {
463 let (mut mpart_sugg, mut inferred_sugg) = (None, None);
465 let mut bound = String::new();
466
467 match self.node() {
468 hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
469 let item = self
470 .tcx
471 .hir_expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id);
472 match &item.kind {
473 hir::ItemKind::Enum(_, _, generics)
474 | hir::ItemKind::Struct(_, _, generics)
475 | hir::ItemKind::Union(_, _, generics) => {
476 let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
477 let (lt_sp, sugg) = match generics.params {
478 [] => (generics.span, format!("<{lt_name}>")),
479 [bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")),
480 };
481 mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
482 fspan: lt_sp,
483 first: sugg,
484 sspan: span.with_hi(item_segment.ident.span.lo()),
485 second: format!(
486 "{}::",
487 self.tcx.instantiate_bound_regions_uncached(
489 poly_trait_ref,
490 |_| {
491 ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion {
492 index: 0,
493 name: Symbol::intern(<_name),
494 })
495 }
496 ),
497 ),
498 });
499 }
500 _ => {}
501 }
502 }
503 hir::Node::Item(hir::Item {
504 kind:
505 hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..),
506 ..
507 }) => {}
508 hir::Node::Item(_)
509 | hir::Node::ForeignItem(_)
510 | hir::Node::TraitItem(_)
511 | hir::Node::ImplItem(_) => {
512 inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo()));
513 bound = format!(
514 "{}::",
515 self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
517 );
518 }
519 _ => {}
520 }
521
522 Err(self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
523 span,
524 inferred_sugg,
525 bound,
526 mpart_sugg,
527 what: assoc_kind_str(kind),
528 }))
529 }
530 }
531
532 fn probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
533 ty.ty_adt_def()
535 }
536
537 fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
538 }
540
541 fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
542 None
543 }
544
545 fn lower_fn_sig(
546 &self,
547 decl: &hir::FnDecl<'tcx>,
548 generics: Option<&hir::Generics<'_>>,
549 hir_id: rustc_hir::HirId,
550 hir_ty: Option<&hir::Ty<'_>>,
551 ) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
552 let tcx = self.tcx();
553 let mut visitor = HirPlaceholderCollector::default();
555 let mut infer_replacements = vec![];
556
557 if let Some(generics) = generics {
558 walk_generics(&mut visitor, generics);
559 }
560
561 let input_tys = decl
562 .inputs
563 .iter()
564 .enumerate()
565 .map(|(i, a)| {
566 if let hir::TyKind::Infer(()) = a.kind {
567 if let Some(suggested_ty) =
568 self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
569 {
570 infer_replacements.push((a.span, suggested_ty.to_string()));
571 return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string());
572 }
573 }
574
575 visitor.visit_ty_unambig(a);
577 self.lowerer().lower_arg_ty(a, None)
578 })
579 .collect();
580
581 let output_ty = match decl.output {
582 hir::FnRetTy::Return(output) => {
583 if let hir::TyKind::Infer(()) = output.kind
584 && let Some(suggested_ty) =
585 self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
586 {
587 infer_replacements.push((output.span, suggested_ty.to_string()));
588 Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
589 } else {
590 visitor.visit_ty_unambig(output);
591 self.lower_ty(output)
592 }
593 }
594 hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
595 };
596
597 if !(visitor.spans.is_empty() && infer_replacements.is_empty()) {
598 let mut diag = crate::collect::placeholder_type_error_diag(
602 self,
603 generics,
604 visitor.spans,
605 infer_replacements.iter().map(|(s, _)| *s).collect(),
606 !visitor.may_contain_const_infer,
607 hir_ty,
608 "function",
609 );
610
611 if !infer_replacements.is_empty() {
612 diag.multipart_suggestion(
613 format!(
614 "try replacing `_` with the type{} in the corresponding trait method \
615 signature",
616 rustc_errors::pluralize!(infer_replacements.len()),
617 ),
618 infer_replacements,
619 Applicability::MachineApplicable,
620 );
621 }
622
623 diag.emit();
624 }
625
626 (input_tys, output_ty)
627 }
628}
629
630fn get_new_lifetime_name<'tcx>(
632 tcx: TyCtxt<'tcx>,
633 poly_trait_ref: ty::PolyTraitRef<'tcx>,
634 generics: &hir::Generics<'tcx>,
635) -> String {
636 let existing_lifetimes = tcx
637 .collect_referenced_late_bound_regions(poly_trait_ref)
638 .into_iter()
639 .filter_map(|lt| {
640 if let ty::BoundRegionKind::Named(_, name) = lt {
641 Some(name.as_str().to_string())
642 } else {
643 None
644 }
645 })
646 .chain(generics.params.iter().filter_map(|param| {
647 if let hir::GenericParamKind::Lifetime { .. } = ¶m.kind {
648 Some(param.name.ident().as_str().to_string())
649 } else {
650 None
651 }
652 }))
653 .collect::<FxHashSet<String>>();
654
655 let a_to_z_repeat_n = |n| {
656 (b'a'..=b'z').map(move |c| {
657 let mut s = '\''.to_string();
658 s.extend(std::iter::repeat(char::from(c)).take(n));
659 s
660 })
661 };
662
663 (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
665}
666
667#[instrument(level = "debug", skip_all)]
668fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
669 let it = tcx.hir_item(item_id);
670 debug!(item = ?it.kind.ident(), id = %it.hir_id());
671 let def_id = item_id.owner_id.def_id;
672 let icx = ItemCtxt::new(tcx, def_id);
673
674 match &it.kind {
675 hir::ItemKind::ExternCrate(..)
677 | hir::ItemKind::Use(..)
678 | hir::ItemKind::Macro(..)
679 | hir::ItemKind::Mod(..)
680 | hir::ItemKind::GlobalAsm { .. } => {}
681 hir::ItemKind::ForeignMod { items, .. } => {
682 for item in *items {
683 let item = tcx.hir_foreign_item(item.id);
684 tcx.ensure_ok().generics_of(item.owner_id);
685 tcx.ensure_ok().type_of(item.owner_id);
686 tcx.ensure_ok().predicates_of(item.owner_id);
687 if tcx.is_conditionally_const(def_id) {
688 tcx.ensure_ok().explicit_implied_const_bounds(def_id);
689 tcx.ensure_ok().const_conditions(def_id);
690 }
691 match item.kind {
692 hir::ForeignItemKind::Fn(..) => {
693 tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
694 tcx.ensure_ok().fn_sig(item.owner_id)
695 }
696 hir::ForeignItemKind::Static(..) => {
697 tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
698 let mut visitor = HirPlaceholderCollector::default();
699 visitor.visit_foreign_item(item);
700 placeholder_type_error(
701 icx.lowerer(),
702 None,
703 visitor.spans,
704 false,
705 None,
706 "static variable",
707 );
708 }
709 _ => (),
710 }
711 }
712 }
713 hir::ItemKind::Enum(..) => {
714 tcx.ensure_ok().generics_of(def_id);
715 tcx.ensure_ok().type_of(def_id);
716 tcx.ensure_ok().predicates_of(def_id);
717 lower_enum_variant_types(tcx, def_id.to_def_id());
718 }
719 hir::ItemKind::Impl { .. } => {
720 tcx.ensure_ok().generics_of(def_id);
721 tcx.ensure_ok().type_of(def_id);
722 tcx.ensure_ok().impl_trait_header(def_id);
723 tcx.ensure_ok().predicates_of(def_id);
724 tcx.ensure_ok().associated_items(def_id);
725 }
726 hir::ItemKind::Trait(..) => {
727 tcx.ensure_ok().generics_of(def_id);
728 tcx.ensure_ok().trait_def(def_id);
729 tcx.at(it.span).explicit_super_predicates_of(def_id);
730 tcx.ensure_ok().predicates_of(def_id);
731 tcx.ensure_ok().associated_items(def_id);
732 }
733 hir::ItemKind::TraitAlias(..) => {
734 tcx.ensure_ok().generics_of(def_id);
735 tcx.at(it.span).explicit_implied_predicates_of(def_id);
736 tcx.at(it.span).explicit_super_predicates_of(def_id);
737 tcx.ensure_ok().predicates_of(def_id);
738 }
739 hir::ItemKind::Struct(_, struct_def, _) | hir::ItemKind::Union(_, struct_def, _) => {
740 tcx.ensure_ok().generics_of(def_id);
741 tcx.ensure_ok().type_of(def_id);
742 tcx.ensure_ok().predicates_of(def_id);
743
744 for f in struct_def.fields() {
745 tcx.ensure_ok().generics_of(f.def_id);
746 tcx.ensure_ok().type_of(f.def_id);
747 tcx.ensure_ok().predicates_of(f.def_id);
748 }
749
750 if let Some(ctor_def_id) = struct_def.ctor_def_id() {
751 lower_variant_ctor(tcx, ctor_def_id);
752 }
753 }
754
755 hir::ItemKind::TyAlias(..) => {
756 tcx.ensure_ok().generics_of(def_id);
757 tcx.ensure_ok().type_of(def_id);
758 tcx.ensure_ok().predicates_of(def_id);
759 }
760
761 hir::ItemKind::Static(_, ty, ..) | hir::ItemKind::Const(_, ty, ..) => {
762 tcx.ensure_ok().generics_of(def_id);
763 tcx.ensure_ok().type_of(def_id);
764 tcx.ensure_ok().predicates_of(def_id);
765 if !ty.is_suggestable_infer_ty() {
766 let mut visitor = HirPlaceholderCollector::default();
767 visitor.visit_item(it);
768 placeholder_type_error(
769 icx.lowerer(),
770 None,
771 visitor.spans,
772 false,
773 None,
774 it.kind.descr(),
775 );
776 }
777 }
778
779 hir::ItemKind::Fn { .. } => {
780 tcx.ensure_ok().generics_of(def_id);
781 tcx.ensure_ok().type_of(def_id);
782 tcx.ensure_ok().predicates_of(def_id);
783 tcx.ensure_ok().fn_sig(def_id);
784 tcx.ensure_ok().codegen_fn_attrs(def_id);
785 }
786 }
787}
788
789fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
790 let trait_item = tcx.hir_trait_item(trait_item_id);
791 let def_id = trait_item_id.owner_id;
792 tcx.ensure_ok().generics_of(def_id);
793 let icx = ItemCtxt::new(tcx, def_id.def_id);
794
795 match trait_item.kind {
796 hir::TraitItemKind::Fn(..) => {
797 tcx.ensure_ok().codegen_fn_attrs(def_id);
798 tcx.ensure_ok().type_of(def_id);
799 tcx.ensure_ok().fn_sig(def_id);
800 }
801
802 hir::TraitItemKind::Const(ty, body_id) => {
803 tcx.ensure_ok().type_of(def_id);
804 if !tcx.dcx().has_stashed_diagnostic(ty.span, StashKey::ItemNoType)
805 && !(ty.is_suggestable_infer_ty() && body_id.is_some())
806 {
807 let mut visitor = HirPlaceholderCollector::default();
809 visitor.visit_trait_item(trait_item);
810 placeholder_type_error(
811 icx.lowerer(),
812 None,
813 visitor.spans,
814 false,
815 None,
816 "associated constant",
817 );
818 }
819 }
820
821 hir::TraitItemKind::Type(_, Some(_)) => {
822 tcx.ensure_ok().item_bounds(def_id);
823 tcx.ensure_ok().item_self_bounds(def_id);
824 tcx.ensure_ok().type_of(def_id);
825 let mut visitor = HirPlaceholderCollector::default();
827 visitor.visit_trait_item(trait_item);
828 placeholder_type_error(
829 icx.lowerer(),
830 None,
831 visitor.spans,
832 false,
833 None,
834 "associated type",
835 );
836 }
837
838 hir::TraitItemKind::Type(_, None) => {
839 tcx.ensure_ok().item_bounds(def_id);
840 tcx.ensure_ok().item_self_bounds(def_id);
841 let mut visitor = HirPlaceholderCollector::default();
844 visitor.visit_trait_item(trait_item);
845
846 placeholder_type_error(
847 icx.lowerer(),
848 None,
849 visitor.spans,
850 false,
851 None,
852 "associated type",
853 );
854 }
855 };
856
857 tcx.ensure_ok().predicates_of(def_id);
858}
859
860fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
861 let def_id = impl_item_id.owner_id;
862 tcx.ensure_ok().generics_of(def_id);
863 tcx.ensure_ok().type_of(def_id);
864 tcx.ensure_ok().predicates_of(def_id);
865 let impl_item = tcx.hir_impl_item(impl_item_id);
866 let icx = ItemCtxt::new(tcx, def_id.def_id);
867 match impl_item.kind {
868 hir::ImplItemKind::Fn(..) => {
869 tcx.ensure_ok().codegen_fn_attrs(def_id);
870 tcx.ensure_ok().fn_sig(def_id);
871 }
872 hir::ImplItemKind::Type(_) => {
873 let mut visitor = HirPlaceholderCollector::default();
875 visitor.visit_impl_item(impl_item);
876
877 placeholder_type_error(
878 icx.lowerer(),
879 None,
880 visitor.spans,
881 false,
882 None,
883 "associated type",
884 );
885 }
886 hir::ImplItemKind::Const(ty, _) => {
887 if !ty.is_suggestable_infer_ty() {
889 let mut visitor = HirPlaceholderCollector::default();
890 visitor.visit_impl_item(impl_item);
891 placeholder_type_error(
892 icx.lowerer(),
893 None,
894 visitor.spans,
895 false,
896 None,
897 "associated constant",
898 );
899 }
900 }
901 }
902}
903
904fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
905 tcx.ensure_ok().generics_of(def_id);
906 tcx.ensure_ok().type_of(def_id);
907 tcx.ensure_ok().predicates_of(def_id);
908}
909
910fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
911 let def = tcx.adt_def(def_id);
912 let repr_type = def.repr().discr_type();
913 let initial = repr_type.initial_discriminant(tcx);
914 let mut prev_discr = None::<Discr<'_>>;
915
916 for variant in def.variants() {
918 let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
919 prev_discr = Some(
920 if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr {
921 def.eval_explicit_discr(tcx, const_def_id).ok()
922 } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
923 Some(discr)
924 } else {
925 let span = tcx.def_span(variant.def_id);
926 tcx.dcx().emit_err(errors::EnumDiscriminantOverflowed {
927 span,
928 discr: prev_discr.unwrap().to_string(),
929 item_name: tcx.item_ident(variant.def_id),
930 wrapped_discr: wrapped_discr.to_string(),
931 });
932 None
933 }
934 .unwrap_or(wrapped_discr),
935 );
936
937 for f in &variant.fields {
938 tcx.ensure_ok().generics_of(f.did);
939 tcx.ensure_ok().type_of(f.did);
940 tcx.ensure_ok().predicates_of(f.did);
941 }
942
943 if let Some(ctor_def_id) = variant.ctor_def_id() {
945 lower_variant_ctor(tcx, ctor_def_id.expect_local());
946 }
947 }
948}
949
950#[derive(Clone, Copy)]
951struct NestedSpan {
952 span: Span,
953 nested_field_span: Span,
954}
955
956impl NestedSpan {
957 fn to_field_already_declared_nested_help(&self) -> errors::FieldAlreadyDeclaredNestedHelp {
958 errors::FieldAlreadyDeclaredNestedHelp { span: self.span }
959 }
960}
961
962#[derive(Clone, Copy)]
963enum FieldDeclSpan {
964 NotNested(Span),
965 Nested(NestedSpan),
966}
967
968impl From<Span> for FieldDeclSpan {
969 fn from(span: Span) -> Self {
970 Self::NotNested(span)
971 }
972}
973
974impl From<NestedSpan> for FieldDeclSpan {
975 fn from(span: NestedSpan) -> Self {
976 Self::Nested(span)
977 }
978}
979
980struct FieldUniquenessCheckContext<'tcx> {
981 tcx: TyCtxt<'tcx>,
982 seen_fields: FxIndexMap<Ident, FieldDeclSpan>,
983}
984
985impl<'tcx> FieldUniquenessCheckContext<'tcx> {
986 fn new(tcx: TyCtxt<'tcx>) -> Self {
987 Self { tcx, seen_fields: FxIndexMap::default() }
988 }
989
990 fn check_field_decl(&mut self, field_name: Ident, field_decl: FieldDeclSpan) {
992 use FieldDeclSpan::*;
993 let field_name = field_name.normalize_to_macros_2_0();
994 match (field_decl, self.seen_fields.get(&field_name).copied()) {
995 (NotNested(span), Some(NotNested(prev_span))) => {
996 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested {
997 field_name,
998 span,
999 prev_span,
1000 });
1001 }
1002 (NotNested(span), Some(Nested(prev))) => {
1003 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::PreviousNested {
1004 field_name,
1005 span,
1006 prev_span: prev.span,
1007 prev_nested_field_span: prev.nested_field_span,
1008 prev_help: prev.to_field_already_declared_nested_help(),
1009 });
1010 }
1011 (
1012 Nested(current @ NestedSpan { span, nested_field_span, .. }),
1013 Some(NotNested(prev_span)),
1014 ) => {
1015 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::CurrentNested {
1016 field_name,
1017 span,
1018 nested_field_span,
1019 help: current.to_field_already_declared_nested_help(),
1020 prev_span,
1021 });
1022 }
1023 (Nested(current @ NestedSpan { span, nested_field_span }), Some(Nested(prev))) => {
1024 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::BothNested {
1025 field_name,
1026 span,
1027 nested_field_span,
1028 help: current.to_field_already_declared_nested_help(),
1029 prev_span: prev.span,
1030 prev_nested_field_span: prev.nested_field_span,
1031 prev_help: prev.to_field_already_declared_nested_help(),
1032 });
1033 }
1034 (field_decl, None) => {
1035 self.seen_fields.insert(field_name, field_decl);
1036 }
1037 }
1038 }
1039}
1040
1041fn lower_variant<'tcx>(
1042 tcx: TyCtxt<'tcx>,
1043 variant_did: Option<LocalDefId>,
1044 ident: Ident,
1045 discr: ty::VariantDiscr,
1046 def: &hir::VariantData<'tcx>,
1047 adt_kind: ty::AdtKind,
1048 parent_did: LocalDefId,
1049) -> ty::VariantDef {
1050 let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx);
1051 let fields = def
1052 .fields()
1053 .iter()
1054 .inspect(|field| {
1055 field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into());
1056 })
1057 .map(|f| ty::FieldDef {
1058 did: f.def_id.to_def_id(),
1059 name: f.ident.name,
1060 vis: tcx.visibility(f.def_id),
1061 safety: f.safety,
1062 value: f.default.map(|v| v.def_id.to_def_id()),
1063 })
1064 .collect();
1065 let recovered = match def {
1066 hir::VariantData::Struct { recovered: Recovered::Yes(guar), .. } => Some(*guar),
1067 _ => None,
1068 };
1069 ty::VariantDef::new(
1070 ident.name,
1071 variant_did.map(LocalDefId::to_def_id),
1072 def.ctor().map(|(kind, _, def_id)| (kind, def_id.to_def_id())),
1073 discr,
1074 fields,
1075 parent_did.to_def_id(),
1076 recovered,
1077 adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive)
1078 || variant_did
1079 .is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
1080 )
1081}
1082
1083fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
1084 use rustc_hir::*;
1085
1086 let Node::Item(item) = tcx.hir_node_by_def_id(def_id) else {
1087 bug!("expected ADT to be an item");
1088 };
1089
1090 let repr = tcx.repr_options_of_def(def_id);
1091 let (kind, variants) = match &item.kind {
1092 ItemKind::Enum(_, def, _) => {
1093 let mut distance_from_explicit = 0;
1094 let variants = def
1095 .variants
1096 .iter()
1097 .map(|v| {
1098 let discr = if let Some(e) = &v.disr_expr {
1099 distance_from_explicit = 0;
1100 ty::VariantDiscr::Explicit(e.def_id.to_def_id())
1101 } else {
1102 ty::VariantDiscr::Relative(distance_from_explicit)
1103 };
1104 distance_from_explicit += 1;
1105
1106 lower_variant(
1107 tcx,
1108 Some(v.def_id),
1109 v.ident,
1110 discr,
1111 &v.data,
1112 AdtKind::Enum,
1113 def_id,
1114 )
1115 })
1116 .collect();
1117
1118 (AdtKind::Enum, variants)
1119 }
1120 ItemKind::Struct(ident, def, _) | ItemKind::Union(ident, def, _) => {
1121 let adt_kind = match item.kind {
1122 ItemKind::Struct(..) => AdtKind::Struct,
1123 _ => AdtKind::Union,
1124 };
1125 let variants = std::iter::once(lower_variant(
1126 tcx,
1127 None,
1128 *ident,
1129 ty::VariantDiscr::Relative(0),
1130 def,
1131 adt_kind,
1132 def_id,
1133 ))
1134 .collect();
1135
1136 (adt_kind, variants)
1137 }
1138 _ => bug!("{:?} is not an ADT", item.owner_id.def_id),
1139 };
1140 tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
1141}
1142
1143fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
1144 let item = tcx.hir_expect_item(def_id);
1145
1146 let (is_alias, is_auto, safety, items) = match item.kind {
1147 hir::ItemKind::Trait(is_auto, safety, .., items) => {
1148 (false, is_auto == hir::IsAuto::Yes, safety, items)
1149 }
1150 hir::ItemKind::TraitAlias(..) => (true, false, hir::Safety::Safe, &[][..]),
1151 _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
1152 };
1153
1154 let constness = if !is_alias && tcx.has_attr(def_id, sym::const_trait) {
1156 hir::Constness::Const
1157 } else {
1158 hir::Constness::NotConst
1159 };
1160
1161 let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
1162 if paren_sugar && !tcx.features().unboxed_closures() {
1163 tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
1164 }
1165
1166 let is_marker = !is_alias && tcx.has_attr(def_id, sym::marker);
1168
1169 let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive);
1170 let is_fundamental = tcx.has_attr(def_id, sym::fundamental);
1171
1172 let mut skip_array_during_method_dispatch = false;
1174 let mut skip_boxed_slice_during_method_dispatch = false;
1175 for attr in tcx.get_attrs(def_id, sym::rustc_skip_during_method_dispatch) {
1176 if let Some(lst) = attr.meta_item_list() {
1177 for item in lst {
1178 if let Some(ident) = item.ident() {
1179 match ident.as_str() {
1180 "array" => skip_array_during_method_dispatch = true,
1181 "boxed_slice" => skip_boxed_slice_during_method_dispatch = true,
1182 _ => (),
1183 }
1184 }
1185 }
1186 }
1187 }
1188
1189 let specialization_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
1190 ty::trait_def::TraitSpecializationKind::Marker
1191 } else if tcx.has_attr(def_id, sym::rustc_specialization_trait) {
1192 ty::trait_def::TraitSpecializationKind::AlwaysApplicable
1193 } else {
1194 ty::trait_def::TraitSpecializationKind::None
1195 };
1196 let must_implement_one_of = tcx
1197 .get_attr(def_id, sym::rustc_must_implement_one_of)
1198 .and_then(|attr| match attr.meta_item_list() {
1201 Some(items) if items.len() < 2 => {
1202 tcx.dcx().emit_err(errors::MustImplementOneOfAttribute { span: attr.span() });
1203
1204 None
1205 }
1206 Some(items) => items
1207 .into_iter()
1208 .map(|item| item.ident().ok_or(item.span()))
1209 .collect::<Result<Box<[_]>, _>>()
1210 .map_err(|span| {
1211 tcx.dcx().emit_err(errors::MustBeNameOfAssociatedFunction { span });
1212 })
1213 .ok()
1214 .zip(Some(attr.span())),
1215 None => None,
1217 })
1218 .and_then(|(list, attr_span)| {
1221 let errors = list.iter().filter_map(|ident| {
1222 let item = items.iter().find(|item| item.ident == *ident);
1223
1224 match item {
1225 Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => {
1226 if !tcx.defaultness(item.id.owner_id).has_value() {
1227 tcx.dcx().emit_err(errors::FunctionNotHaveDefaultImplementation {
1228 span: item.span,
1229 note_span: attr_span,
1230 });
1231
1232 return Some(());
1233 }
1234
1235 return None;
1236 }
1237 Some(item) => {
1238 tcx.dcx().emit_err(errors::MustImplementNotFunction {
1239 span: item.span,
1240 span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span },
1241 note: errors::MustImplementNotFunctionNote {},
1242 });
1243 }
1244 None => {
1245 tcx.dcx().emit_err(errors::FunctionNotFoundInTrait { span: ident.span });
1246 }
1247 }
1248
1249 Some(())
1250 });
1251
1252 (errors.count() == 0).then_some(list)
1253 })
1254 .and_then(|list| {
1256 let mut set: UnordMap<Symbol, Span> = Default::default();
1257 let mut no_dups = true;
1258
1259 for ident in &*list {
1260 if let Some(dup) = set.insert(ident.name, ident.span) {
1261 tcx.dcx()
1262 .emit_err(errors::FunctionNamesDuplicated { spans: vec![dup, ident.span] });
1263
1264 no_dups = false;
1265 }
1266 }
1267
1268 no_dups.then_some(list)
1269 });
1270
1271 let deny_explicit_impl = tcx.has_attr(def_id, sym::rustc_deny_explicit_impl);
1272 let implement_via_object = !tcx.has_attr(def_id, sym::rustc_do_not_implement_via_object);
1273
1274 ty::TraitDef {
1275 def_id: def_id.to_def_id(),
1276 safety,
1277 constness,
1278 paren_sugar,
1279 has_auto_impl: is_auto,
1280 is_marker,
1281 is_coinductive: rustc_coinductive || is_auto,
1282 is_fundamental,
1283 skip_array_during_method_dispatch,
1284 skip_boxed_slice_during_method_dispatch,
1285 specialization_kind,
1286 must_implement_one_of,
1287 implement_via_object,
1288 deny_explicit_impl,
1289 }
1290}
1291
1292#[instrument(level = "debug", skip(tcx), ret)]
1293fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> {
1294 use rustc_hir::Node::*;
1295 use rustc_hir::*;
1296
1297 let hir_id = tcx.local_def_id_to_hir_id(def_id);
1298
1299 let icx = ItemCtxt::new(tcx, def_id);
1300
1301 let output = match tcx.hir_node(hir_id) {
1302 TraitItem(hir::TraitItem {
1303 kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
1304 generics,
1305 ..
1306 })
1307 | Item(hir::Item { kind: ItemKind::Fn { sig, generics, .. }, .. }) => {
1308 lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
1309 }
1310
1311 ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
1312 if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = tcx.parent_hir_node(hir_id)
1314 && i.of_trait.is_some()
1315 {
1316 icx.lowerer().lower_fn_ty(
1317 hir_id,
1318 sig.header.safety(),
1319 sig.header.abi,
1320 sig.decl,
1321 Some(generics),
1322 None,
1323 )
1324 } else {
1325 lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
1326 }
1327 }
1328
1329 TraitItem(hir::TraitItem {
1330 kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
1331 generics,
1332 ..
1333 }) => icx.lowerer().lower_fn_ty(
1334 hir_id,
1335 header.safety(),
1336 header.abi,
1337 decl,
1338 Some(generics),
1339 None,
1340 ),
1341
1342 ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
1343 let abi = tcx.hir_get_foreign_abi(hir_id);
1344 compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
1345 }
1346
1347 Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
1348 let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id();
1349 let ty = tcx.type_of(adt_def_id).instantiate_identity();
1350 let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity());
1351 let safety = match tcx.layout_scalar_valid_range(adt_def_id) {
1353 (Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe,
1354 _ => hir::Safety::Unsafe,
1355 };
1356 ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, ExternAbi::Rust))
1357 }
1358
1359 Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
1360 bug!("to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",);
1371 }
1372
1373 x => {
1374 bug!("unexpected sort of node in fn_sig(): {:?}", x);
1375 }
1376 };
1377 ty::EarlyBinder::bind(output)
1378}
1379
1380fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
1381 icx: &ItemCtxt<'tcx>,
1382 sig: &'tcx hir::FnSig<'tcx>,
1383 generics: &'tcx hir::Generics<'tcx>,
1384 def_id: LocalDefId,
1385) -> ty::PolyFnSig<'tcx> {
1386 if let Some(infer_ret_ty) = sig.decl.output.is_suggestable_infer_ty() {
1387 return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
1388 }
1389
1390 icx.lowerer().lower_fn_ty(
1391 icx.tcx().local_def_id_to_hir_id(def_id),
1392 sig.header.safety(),
1393 sig.header.abi,
1394 sig.decl,
1395 Some(generics),
1396 None,
1397 )
1398}
1399
1400fn recover_infer_ret_ty<'tcx>(
1401 icx: &ItemCtxt<'tcx>,
1402 infer_ret_ty: &'tcx hir::Ty<'tcx>,
1403 generics: &'tcx hir::Generics<'tcx>,
1404 def_id: LocalDefId,
1405) -> ty::PolyFnSig<'tcx> {
1406 let tcx = icx.tcx;
1407 let hir_id = tcx.local_def_id_to_hir_id(def_id);
1408
1409 let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
1410
1411 let has_region_params = generics.params.iter().any(|param| match param.kind {
1416 GenericParamKind::Lifetime { .. } => true,
1417 _ => false,
1418 });
1419 let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r {
1420 ty::ReErased => {
1421 if has_region_params {
1422 ty::Region::new_error_with_message(
1423 tcx,
1424 DUMMY_SP,
1425 "erased region is not allowed here in return type",
1426 )
1427 } else {
1428 tcx.lifetimes.re_static
1429 }
1430 }
1431 _ => r,
1432 });
1433
1434 let mut visitor = HirPlaceholderCollector::default();
1435 visitor.visit_ty_unambig(infer_ret_ty);
1436
1437 let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type");
1438 let ret_ty = fn_sig.output();
1439
1440 let mut recovered_ret_ty = None;
1444 if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
1445 diag.span_suggestion(
1446 infer_ret_ty.span,
1447 "replace with the correct return type",
1448 suggestable_ret_ty,
1449 Applicability::MachineApplicable,
1450 );
1451 recovered_ret_ty = Some(suggestable_ret_ty);
1452 } else if let Some(sugg) = suggest_impl_trait(
1453 &tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
1454 tcx.param_env(def_id),
1455 ret_ty,
1456 ) {
1457 diag.span_suggestion(
1458 infer_ret_ty.span,
1459 "replace with an appropriate return type",
1460 sugg,
1461 Applicability::MachineApplicable,
1462 );
1463 } else if ret_ty.is_closure() {
1464 diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1465 }
1466
1467 if ret_ty.is_closure() {
1469 diag.note(
1470 "for more information on `Fn` traits and closure types, see \
1471 https://doc.rust-lang.org/book/ch13-01-closures.html",
1472 );
1473 }
1474 let guar = diag.emit();
1475 ty::Binder::dummy(tcx.mk_fn_sig(
1476 fn_sig.inputs().iter().copied(),
1477 recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
1478 fn_sig.c_variadic,
1479 fn_sig.safety,
1480 fn_sig.abi,
1481 ))
1482}
1483
1484pub fn suggest_impl_trait<'tcx>(
1485 infcx: &InferCtxt<'tcx>,
1486 param_env: ty::ParamEnv<'tcx>,
1487 ret_ty: Ty<'tcx>,
1488) -> Option<String> {
1489 let format_as_assoc: fn(_, _, _, _, _) -> _ =
1490 |tcx: TyCtxt<'tcx>,
1491 _: ty::GenericArgsRef<'tcx>,
1492 trait_def_id: DefId,
1493 assoc_item_def_id: DefId,
1494 item_ty: Ty<'tcx>| {
1495 let trait_name = tcx.item_name(trait_def_id);
1496 let assoc_name = tcx.item_name(assoc_item_def_id);
1497 Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
1498 };
1499 let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
1500 |tcx: TyCtxt<'tcx>,
1501 args: ty::GenericArgsRef<'tcx>,
1502 trait_def_id: DefId,
1503 _: DefId,
1504 item_ty: Ty<'tcx>| {
1505 let trait_name = tcx.item_name(trait_def_id);
1506 let args_tuple = args.type_at(1);
1507 let ty::Tuple(types) = *args_tuple.kind() else {
1508 return None;
1509 };
1510 let types = types.make_suggestable(tcx, false, None)?;
1511 let maybe_ret =
1512 if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
1513 Some(format!(
1514 "impl {trait_name}({}){maybe_ret}",
1515 types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
1516 ))
1517 };
1518
1519 for (trait_def_id, assoc_item_def_id, formatter) in [
1520 (
1521 infcx.tcx.get_diagnostic_item(sym::Iterator),
1522 infcx.tcx.get_diagnostic_item(sym::IteratorItem),
1523 format_as_assoc,
1524 ),
1525 (
1526 infcx.tcx.lang_items().future_trait(),
1527 infcx.tcx.lang_items().future_output(),
1528 format_as_assoc,
1529 ),
1530 (
1531 infcx.tcx.lang_items().fn_trait(),
1532 infcx.tcx.lang_items().fn_once_output(),
1533 format_as_parenthesized,
1534 ),
1535 (
1536 infcx.tcx.lang_items().fn_mut_trait(),
1537 infcx.tcx.lang_items().fn_once_output(),
1538 format_as_parenthesized,
1539 ),
1540 (
1541 infcx.tcx.lang_items().fn_once_trait(),
1542 infcx.tcx.lang_items().fn_once_output(),
1543 format_as_parenthesized,
1544 ),
1545 ] {
1546 let Some(trait_def_id) = trait_def_id else {
1547 continue;
1548 };
1549 let Some(assoc_item_def_id) = assoc_item_def_id else {
1550 continue;
1551 };
1552 if infcx.tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
1553 continue;
1554 }
1555 let sugg = infcx.probe(|_| {
1556 let args = ty::GenericArgs::for_item(infcx.tcx, trait_def_id, |param, _| {
1557 if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(DUMMY_SP, param) }
1558 });
1559 if !infcx
1560 .type_implements_trait(trait_def_id, args, param_env)
1561 .must_apply_modulo_regions()
1562 {
1563 return None;
1564 }
1565 let ocx = ObligationCtxt::new(&infcx);
1566 let item_ty = ocx.normalize(
1567 &ObligationCause::dummy(),
1568 param_env,
1569 Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args),
1570 );
1571 if ocx.select_where_possible().is_empty()
1573 && let item_ty = infcx.resolve_vars_if_possible(item_ty)
1574 && let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
1575 && let Some(sugg) = formatter(
1576 infcx.tcx,
1577 infcx.resolve_vars_if_possible(args),
1578 trait_def_id,
1579 assoc_item_def_id,
1580 item_ty,
1581 )
1582 {
1583 return Some(sugg);
1584 }
1585
1586 None
1587 });
1588
1589 if sugg.is_some() {
1590 return sugg;
1591 }
1592 }
1593 None
1594}
1595
1596fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> {
1597 let icx = ItemCtxt::new(tcx, def_id);
1598 let item = tcx.hir_expect_item(def_id);
1599 let impl_ = item.expect_impl();
1600 impl_.of_trait.as_ref().map(|ast_trait_ref| {
1601 let selfty = tcx.type_of(def_id).instantiate_identity();
1602
1603 check_impl_constness(tcx, impl_.constness, ast_trait_ref);
1604
1605 let trait_ref = icx.lowerer().lower_impl_trait_ref(ast_trait_ref, selfty);
1606
1607 ty::ImplTraitHeader {
1608 trait_ref: ty::EarlyBinder::bind(trait_ref),
1609 safety: impl_.safety,
1610 polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
1611 constness: impl_.constness,
1612 }
1613 })
1614}
1615
1616fn check_impl_constness(
1617 tcx: TyCtxt<'_>,
1618 constness: hir::Constness,
1619 hir_trait_ref: &hir::TraitRef<'_>,
1620) {
1621 if let hir::Constness::NotConst = constness {
1622 return;
1623 }
1624
1625 let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
1626 if tcx.is_const_trait(trait_def_id) {
1627 return;
1628 }
1629
1630 let trait_name = tcx.item_name(trait_def_id).to_string();
1631 let (local_trait_span, suggestion_pre) =
1632 match (trait_def_id.is_local(), tcx.sess.is_nightly_build()) {
1633 (true, true) => (
1634 Some(tcx.def_span(trait_def_id).shrink_to_lo()),
1635 if tcx.features().const_trait_impl() {
1636 ""
1637 } else {
1638 "enable `#![feature(const_trait_impl)]` in your crate and "
1639 },
1640 ),
1641 (false, _) | (_, false) => (None, ""),
1642 };
1643 tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
1644 trait_ref_span: hir_trait_ref.path.span,
1645 trait_name,
1646 local_trait_span,
1647 suggestion_pre,
1648 marking: (),
1649 adding: (),
1650 });
1651}
1652
1653fn polarity_of_impl(
1654 tcx: TyCtxt<'_>,
1655 def_id: LocalDefId,
1656 impl_: &hir::Impl<'_>,
1657 span: Span,
1658) -> ty::ImplPolarity {
1659 let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
1660 match &impl_ {
1661 hir::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => {
1662 if is_rustc_reservation {
1663 let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span));
1664 tcx.dcx().span_err(span, "reservation impls can't be negative");
1665 }
1666 ty::ImplPolarity::Negative
1667 }
1668 hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => {
1669 if is_rustc_reservation {
1670 tcx.dcx().span_err(span, "reservation impls can't be inherent");
1671 }
1672 ty::ImplPolarity::Positive
1673 }
1674 hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: Some(_), .. } => {
1675 if is_rustc_reservation {
1676 ty::ImplPolarity::Reservation
1677 } else {
1678 ty::ImplPolarity::Positive
1679 }
1680 }
1681 }
1682}
1683
1684fn early_bound_lifetimes_from_generics<'a, 'tcx>(
1690 tcx: TyCtxt<'tcx>,
1691 generics: &'a hir::Generics<'a>,
1692) -> impl Iterator<Item = &'a hir::GenericParam<'a>> {
1693 generics.params.iter().filter(move |param| match param.kind {
1694 GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
1695 _ => false,
1696 })
1697}
1698
1699fn compute_sig_of_foreign_fn_decl<'tcx>(
1700 tcx: TyCtxt<'tcx>,
1701 def_id: LocalDefId,
1702 decl: &'tcx hir::FnDecl<'tcx>,
1703 abi: ExternAbi,
1704 safety: hir::Safety,
1705) -> ty::PolyFnSig<'tcx> {
1706 let safety = if abi == ExternAbi::RustIntrinsic {
1707 intrinsic_operation_unsafety(tcx, def_id)
1708 } else {
1709 safety
1710 };
1711 let hir_id = tcx.local_def_id_to_hir_id(def_id);
1712 let fty =
1713 ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None);
1714
1715 if abi != ExternAbi::RustIntrinsic && !tcx.features().simd_ffi() {
1718 let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
1719 if ty.is_simd() {
1720 let snip = tcx
1721 .sess
1722 .source_map()
1723 .span_to_snippet(hir_ty.span)
1724 .map_or_else(|_| String::new(), |s| format!(" `{s}`"));
1725 tcx.dcx().emit_err(errors::SIMDFFIHighlyExperimental { span: hir_ty.span, snip });
1726 }
1727 };
1728 for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
1729 check(input, *ty)
1730 }
1731 if let hir::FnRetTy::Return(ty) = decl.output {
1732 check(ty, fty.output().skip_binder())
1733 }
1734 }
1735
1736 fty
1737}
1738
1739fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineKind> {
1740 match tcx.hir_node_by_def_id(def_id) {
1741 Node::Expr(&hir::Expr {
1742 kind:
1743 hir::ExprKind::Closure(&rustc_hir::Closure {
1744 kind: hir::ClosureKind::Coroutine(kind),
1745 ..
1746 }),
1747 ..
1748 }) => Some(kind),
1749 _ => None,
1750 }
1751}
1752
1753fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
1754 let &rustc_hir::Closure { kind: hir::ClosureKind::CoroutineClosure(_), body, .. } =
1755 tcx.hir_node_by_def_id(def_id).expect_closure()
1756 else {
1757 bug!()
1758 };
1759
1760 let &hir::Expr {
1761 kind:
1762 hir::ExprKind::Closure(&rustc_hir::Closure {
1763 def_id,
1764 kind: hir::ClosureKind::Coroutine(_),
1765 ..
1766 }),
1767 ..
1768 } = tcx.hir_body(body).value
1769 else {
1770 bug!()
1771 };
1772
1773 def_id.to_def_id()
1774}
1775
1776fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> {
1777 match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
1778 hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl } => {
1779 hir::OpaqueTyOrigin::FnReturn { parent: parent.to_def_id(), in_trait_or_impl }
1780 }
1781 hir::OpaqueTyOrigin::AsyncFn { parent, in_trait_or_impl } => {
1782 hir::OpaqueTyOrigin::AsyncFn { parent: parent.to_def_id(), in_trait_or_impl }
1783 }
1784 hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty } => {
1785 hir::OpaqueTyOrigin::TyAlias { parent: parent.to_def_id(), in_assoc_ty }
1786 }
1787 }
1788}
1789
1790fn rendered_precise_capturing_args<'tcx>(
1791 tcx: TyCtxt<'tcx>,
1792 def_id: LocalDefId,
1793) -> Option<&'tcx [PreciseCapturingArgKind<Symbol, Symbol>]> {
1794 if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
1795 tcx.opt_rpitit_info(def_id.to_def_id())
1796 {
1797 return tcx.rendered_precise_capturing_args(opaque_def_id);
1798 }
1799
1800 tcx.hir_node_by_def_id(def_id).expect_opaque_ty().bounds.iter().find_map(|bound| match bound {
1801 hir::GenericBound::Use(args, ..) => {
1802 Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| match arg {
1803 PreciseCapturingArgKind::Lifetime(_) => {
1804 PreciseCapturingArgKind::Lifetime(arg.name())
1805 }
1806 PreciseCapturingArgKind::Param(_) => PreciseCapturingArgKind::Param(arg.name()),
1807 })))
1808 }
1809 _ => None,
1810 })
1811}
1812
1813fn const_param_default<'tcx>(
1814 tcx: TyCtxt<'tcx>,
1815 def_id: LocalDefId,
1816) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1817 let default_ct = match tcx.hir_node_by_def_id(def_id) {
1818 hir::Node::GenericParam(hir::GenericParam {
1819 kind: hir::GenericParamKind::Const { default: Some(ct), .. },
1820 ..
1821 }) => ct,
1822 _ => span_bug!(
1823 tcx.def_span(def_id),
1824 "`const_param_default` expected a generic parameter with a constant"
1825 ),
1826 };
1827 let icx = ItemCtxt::new(tcx, def_id);
1828 let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
1829 let ct = icx
1830 .lowerer()
1831 .lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
1832 ty::EarlyBinder::bind(ct)
1833}