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