1use std::collections::hash_map::Entry;
2use std::hash::Hash;
3use std::iter;
4
5use rustc_abi::{FieldIdx, VariantIdx};
6use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
7use rustc_data_structures::unord::{ExtendUnord, UnordItems, UnordSet};
8use rustc_errors::ErrorGuaranteed;
9use rustc_hir::def::{DefKind, Res};
10use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
11use rustc_hir::hir_id::OwnerId;
12use rustc_hir::{
13 self as hir, BindingMode, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability,
14};
15use rustc_index::IndexVec;
16use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
17use rustc_session::Session;
18use rustc_span::Span;
19
20use super::RvalueScopes;
21use crate::hir::place::Place as HirPlace;
22use crate::infer::canonical::Canonical;
23use crate::mir::FakeReadCause;
24use crate::traits::ObligationCause;
25use crate::ty::{
26 self, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, GenericArgKind, GenericArgs,
27 GenericArgsRef, Ty, UserArgs, tls,
28};
29
30#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
31pub struct TypeckResults<'tcx> {
32 pub hir_owner: OwnerId,
34
35 type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
38
39 field_indices: ItemLocalMap<FieldIdx>,
44
45 node_types: ItemLocalMap<Ty<'tcx>>,
49
50 node_args: ItemLocalMap<GenericArgsRef<'tcx>>,
55
56 user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
66
67 pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
70
71 adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
72
73 pat_binding_modes: ItemLocalMap<BindingMode>,
75
76 rust_2024_migration_desugared_pats: ItemLocalMap<Rust2024IncompatiblePatInfo>,
79
80 pat_adjustments: ItemLocalMap<Vec<ty::adjustment::PatAdjustment<'tcx>>>,
103
104 skipped_ref_pats: ItemLocalSet,
107
108 closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
111
112 liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
147
148 fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
153
154 coercion_casts: ItemLocalSet,
157
158 pub used_trait_imports: UnordSet<LocalDefId>,
161
162 pub tainted_by_errors: Option<ErrorGuaranteed>,
165
166 pub concrete_opaque_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
171
172 pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
175
176 pub closure_fake_reads: LocalDefIdMap<Vec<(HirPlace<'tcx>, FakeReadCause, HirId)>>,
199
200 pub rvalue_scopes: RvalueScopes,
204
205 pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
208
209 pub potentially_region_dependent_goals:
217 FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
218
219 pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>,
222
223 pub transmutes_to_check: Vec<(Ty<'tcx>, Ty<'tcx>, HirId)>,
227
228 offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)>,
230}
231
232impl<'tcx> TypeckResults<'tcx> {
233 pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
234 TypeckResults {
235 hir_owner,
236 type_dependent_defs: Default::default(),
237 field_indices: Default::default(),
238 user_provided_types: Default::default(),
239 user_provided_sigs: Default::default(),
240 node_types: Default::default(),
241 node_args: Default::default(),
242 adjustments: Default::default(),
243 pat_binding_modes: Default::default(),
244 pat_adjustments: Default::default(),
245 rust_2024_migration_desugared_pats: Default::default(),
246 skipped_ref_pats: Default::default(),
247 closure_kind_origins: Default::default(),
248 liberated_fn_sigs: Default::default(),
249 fru_field_types: Default::default(),
250 coercion_casts: Default::default(),
251 used_trait_imports: Default::default(),
252 tainted_by_errors: None,
253 concrete_opaque_types: Default::default(),
254 closure_min_captures: Default::default(),
255 closure_fake_reads: Default::default(),
256 rvalue_scopes: Default::default(),
257 coroutine_stalled_predicates: Default::default(),
258 potentially_region_dependent_goals: Default::default(),
259 closure_size_eval: Default::default(),
260 transmutes_to_check: Default::default(),
261 offset_of_data: Default::default(),
262 }
263 }
264
265 pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: HirId) -> Res {
267 match *qpath {
268 hir::QPath::Resolved(_, path) => path.res,
269 hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
270 .type_dependent_def(id)
271 .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
272 }
273 }
274
275 pub fn type_dependent_defs(
276 &self,
277 ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
278 LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
279 }
280
281 pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
282 validate_hir_id_for_typeck_results(self.hir_owner, id);
283 self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
284 }
285
286 pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
287 self.type_dependent_def(id).map(|(_, def_id)| def_id)
288 }
289
290 pub fn type_dependent_defs_mut(
291 &mut self,
292 ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
293 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
294 }
295
296 pub fn field_indices(&self) -> LocalTableInContext<'_, FieldIdx> {
297 LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
298 }
299
300 pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, FieldIdx> {
301 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
302 }
303
304 pub fn field_index(&self, id: HirId) -> FieldIdx {
305 self.field_indices().get(id).cloned().expect("no index for a field")
306 }
307
308 pub fn opt_field_index(&self, id: HirId) -> Option<FieldIdx> {
309 self.field_indices().get(id).cloned()
310 }
311
312 pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
313 LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
314 }
315
316 pub fn user_provided_types_mut(
317 &mut self,
318 ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
319 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
320 }
321
322 pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
323 LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
324 }
325
326 pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
327 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
328 }
329
330 pub fn node_type(&self, id: HirId) -> Ty<'tcx> {
331 self.node_type_opt(id).unwrap_or_else(|| {
332 bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir_id_to_string(id)))
333 })
334 }
335
336 pub fn node_type_opt(&self, id: HirId) -> Option<Ty<'tcx>> {
337 validate_hir_id_for_typeck_results(self.hir_owner, id);
338 self.node_types.get(&id.local_id).cloned()
339 }
340
341 pub fn node_args_mut(&mut self) -> LocalTableInContextMut<'_, GenericArgsRef<'tcx>> {
342 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_args }
343 }
344
345 pub fn node_args(&self, id: HirId) -> GenericArgsRef<'tcx> {
346 validate_hir_id_for_typeck_results(self.hir_owner, id);
347 self.node_args.get(&id.local_id).cloned().unwrap_or_else(|| GenericArgs::empty())
348 }
349
350 pub fn node_args_opt(&self, id: HirId) -> Option<GenericArgsRef<'tcx>> {
351 validate_hir_id_for_typeck_results(self.hir_owner, id);
352 self.node_args.get(&id.local_id).cloned()
353 }
354
355 pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
360 self.node_type(pat.hir_id)
361 }
362
363 pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
374 self.node_type(expr.hir_id)
375 }
376
377 pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
378 self.node_type_opt(expr.hir_id)
379 }
380
381 pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
382 LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
383 }
384
385 pub fn adjustments_mut(
386 &mut self,
387 ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
388 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
389 }
390
391 pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
392 validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
393 self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
394 }
395
396 pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
399 self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
400 }
401
402 pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
403 self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
404 }
405
406 pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
407 if let hir::ExprKind::Path(_) = expr.kind {
410 return false;
411 }
412
413 matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
414 }
415
416 pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> BindingMode {
419 self.pat_binding_modes().get(id).copied().unwrap_or_else(|| {
420 s.dcx().span_bug(sp, "missing binding mode");
421 })
422 }
423
424 pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
425 LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
426 }
427
428 pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
429 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
430 }
431
432 pub fn pat_adjustments(
433 &self,
434 ) -> LocalTableInContext<'_, Vec<ty::adjustment::PatAdjustment<'tcx>>> {
435 LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
436 }
437
438 pub fn pat_adjustments_mut(
439 &mut self,
440 ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::PatAdjustment<'tcx>>> {
441 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
442 }
443
444 pub fn rust_2024_migration_desugared_pats(
445 &self,
446 ) -> LocalTableInContext<'_, Rust2024IncompatiblePatInfo> {
447 LocalTableInContext {
448 hir_owner: self.hir_owner,
449 data: &self.rust_2024_migration_desugared_pats,
450 }
451 }
452
453 pub fn rust_2024_migration_desugared_pats_mut(
454 &mut self,
455 ) -> LocalTableInContextMut<'_, Rust2024IncompatiblePatInfo> {
456 LocalTableInContextMut {
457 hir_owner: self.hir_owner,
458 data: &mut self.rust_2024_migration_desugared_pats,
459 }
460 }
461
462 pub fn skipped_ref_pats(&self) -> LocalSetInContext<'_> {
463 LocalSetInContext { hir_owner: self.hir_owner, data: &self.skipped_ref_pats }
464 }
465
466 pub fn skipped_ref_pats_mut(&mut self) -> LocalSetInContextMut<'_> {
467 LocalSetInContextMut { hir_owner: self.hir_owner, data: &mut self.skipped_ref_pats }
468 }
469
470 pub fn pat_has_ref_mut_binding(&self, pat: &hir::Pat<'_>) -> bool {
479 let mut has_ref_mut = false;
480 pat.walk(|pat| {
481 if let hir::PatKind::Binding(_, id, _, _) = pat.kind
482 && let Some(BindingMode(ByRef::Yes(Mutability::Mut), _)) =
483 self.pat_binding_modes().get(id)
484 {
485 has_ref_mut = true;
486 false
488 } else {
489 true
490 }
491 });
492 has_ref_mut
493 }
494
495 pub fn deref_pat_borrow_mode(&self, pointer_ty: Ty<'_>, inner: &hir::Pat<'_>) -> ByRef {
502 if pointer_ty.is_box() {
503 ByRef::No
504 } else {
505 let mutable = self.pat_has_ref_mut_binding(inner);
506 ByRef::Yes(if mutable { Mutability::Mut } else { Mutability::Not })
507 }
508 }
509
510 pub fn closure_min_captures_flattened(
513 &self,
514 closure_def_id: LocalDefId,
515 ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
516 self.closure_min_captures
517 .get(&closure_def_id)
518 .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
519 .into_iter()
520 .flatten()
521 }
522
523 pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
524 LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
525 }
526
527 pub fn closure_kind_origins_mut(
528 &mut self,
529 ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
530 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
531 }
532
533 pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
534 LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
535 }
536
537 pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
538 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
539 }
540
541 pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
542 LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
543 }
544
545 pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
546 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
547 }
548
549 pub fn is_coercion_cast(&self, hir_id: HirId) -> bool {
550 validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
551 self.coercion_casts.contains(&hir_id.local_id)
552 }
553
554 pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
555 self.coercion_casts.insert(id);
556 }
557
558 pub fn coercion_casts(&self) -> &ItemLocalSet {
559 &self.coercion_casts
560 }
561
562 pub fn offset_of_data(
563 &self,
564 ) -> LocalTableInContext<'_, (Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)> {
565 LocalTableInContext { hir_owner: self.hir_owner, data: &self.offset_of_data }
566 }
567
568 pub fn offset_of_data_mut(
569 &mut self,
570 ) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)> {
571 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.offset_of_data }
572 }
573}
574
575#[inline]
583fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: HirId) {
584 if hir_id.owner != hir_owner {
585 invalid_hir_id_for_typeck_results(hir_owner, hir_id);
586 }
587}
588
589#[cold]
590#[inline(never)]
591fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: HirId) {
592 ty::tls::with(|tcx| {
593 bug!(
594 "node {} cannot be placed in TypeckResults with hir_owner {:?}",
595 tcx.hir_id_to_string(hir_id),
596 hir_owner
597 )
598 });
599}
600
601pub struct LocalTableInContext<'a, V> {
602 hir_owner: OwnerId,
603 data: &'a ItemLocalMap<V>,
604}
605
606impl<'a, V> LocalTableInContext<'a, V> {
607 pub fn contains_key(&self, id: HirId) -> bool {
608 validate_hir_id_for_typeck_results(self.hir_owner, id);
609 self.data.contains_key(&id.local_id)
610 }
611
612 pub fn get(&self, id: HirId) -> Option<&'a V> {
613 validate_hir_id_for_typeck_results(self.hir_owner, id);
614 self.data.get(&id.local_id)
615 }
616
617 pub fn items(
618 &self,
619 ) -> UnordItems<(hir::ItemLocalId, &'a V), impl Iterator<Item = (hir::ItemLocalId, &'a V)>>
620 {
621 self.data.items().map(|(id, value)| (*id, value))
622 }
623
624 pub fn items_in_stable_order(&self) -> Vec<(ItemLocalId, &'a V)> {
625 self.data.items().map(|(&k, v)| (k, v)).into_sorted_stable_ord_by_key(|(k, _)| k)
626 }
627}
628
629impl<'a, V> ::std::ops::Index<HirId> for LocalTableInContext<'a, V> {
630 type Output = V;
631
632 fn index(&self, key: HirId) -> &V {
633 self.get(key).unwrap_or_else(|| {
634 bug!("LocalTableInContext({:?}): key {:?} not found", self.hir_owner, key)
635 })
636 }
637}
638
639pub struct LocalTableInContextMut<'a, V> {
640 hir_owner: OwnerId,
641 data: &'a mut ItemLocalMap<V>,
642}
643
644impl<'a, V> LocalTableInContextMut<'a, V> {
645 pub fn get_mut(&mut self, id: HirId) -> Option<&mut V> {
646 validate_hir_id_for_typeck_results(self.hir_owner, id);
647 self.data.get_mut(&id.local_id)
648 }
649
650 pub fn get(&mut self, id: HirId) -> Option<&V> {
651 validate_hir_id_for_typeck_results(self.hir_owner, id);
652 self.data.get(&id.local_id)
653 }
654
655 pub fn entry(&mut self, id: HirId) -> Entry<'_, hir::ItemLocalId, V> {
656 validate_hir_id_for_typeck_results(self.hir_owner, id);
657 self.data.entry(id.local_id)
658 }
659
660 pub fn insert(&mut self, id: HirId, val: V) -> Option<V> {
661 validate_hir_id_for_typeck_results(self.hir_owner, id);
662 self.data.insert(id.local_id, val)
663 }
664
665 pub fn remove(&mut self, id: HirId) -> Option<V> {
666 validate_hir_id_for_typeck_results(self.hir_owner, id);
667 self.data.remove(&id.local_id)
668 }
669
670 pub fn extend(&mut self, items: UnordItems<(HirId, V), impl Iterator<Item = (HirId, V)>>) {
671 self.data.extend_unord(items.map(|(id, value)| {
672 validate_hir_id_for_typeck_results(self.hir_owner, id);
673 (id.local_id, value)
674 }))
675 }
676}
677
678#[derive(Clone, Copy, Debug)]
679pub struct LocalSetInContext<'a> {
680 hir_owner: OwnerId,
681 data: &'a ItemLocalSet,
682}
683
684impl<'a> LocalSetInContext<'a> {
685 pub fn is_empty(&self) -> bool {
686 self.data.is_empty()
687 }
688
689 pub fn contains(&self, id: hir::HirId) -> bool {
690 validate_hir_id_for_typeck_results(self.hir_owner, id);
691 self.data.contains(&id.local_id)
692 }
693}
694
695#[derive(Debug)]
696pub struct LocalSetInContextMut<'a> {
697 hir_owner: OwnerId,
698 data: &'a mut ItemLocalSet,
699}
700
701impl<'a> LocalSetInContextMut<'a> {
702 pub fn is_empty(&self) -> bool {
703 self.data.is_empty()
704 }
705
706 pub fn contains(&self, id: hir::HirId) -> bool {
707 validate_hir_id_for_typeck_results(self.hir_owner, id);
708 self.data.contains(&id.local_id)
709 }
710 pub fn insert(&mut self, id: hir::HirId) -> bool {
711 validate_hir_id_for_typeck_results(self.hir_owner, id);
712 self.data.insert(id.local_id)
713 }
714
715 pub fn remove(&mut self, id: hir::HirId) -> bool {
716 validate_hir_id_for_typeck_results(self.hir_owner, id);
717 self.data.remove(&id.local_id)
718 }
719}
720
721rustc_index::newtype_index! {
722 #[derive(HashStable)]
723 #[encodable]
724 #[debug_format = "UserType({})"]
725 pub struct UserTypeAnnotationIndex {
726 const START_INDEX = 0;
727 }
728}
729
730pub type CanonicalUserTypeAnnotations<'tcx> =
732 IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
733
734#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
735pub struct CanonicalUserTypeAnnotation<'tcx> {
736 #[type_foldable(identity)]
737 #[type_visitable(ignore)]
738 pub user_ty: Box<CanonicalUserType<'tcx>>,
739 pub span: Span,
740 pub inferred_ty: Ty<'tcx>,
741}
742
743pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
745
746#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
747#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)]
748pub struct UserType<'tcx> {
749 pub kind: UserTypeKind<'tcx>,
750 pub bounds: ty::Clauses<'tcx>,
751}
752
753impl<'tcx> UserType<'tcx> {
754 pub fn new(kind: UserTypeKind<'tcx>) -> UserType<'tcx> {
755 UserType { kind, bounds: ty::ListWithCachedTypeInfo::empty() }
756 }
757
758 pub fn new_with_bounds(kind: UserTypeKind<'tcx>, bounds: ty::Clauses<'tcx>) -> UserType<'tcx> {
761 UserType { kind, bounds }
762 }
763}
764
765#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
769#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)]
770pub enum UserTypeKind<'tcx> {
771 Ty(Ty<'tcx>),
772
773 TypeOf(DefId, UserArgs<'tcx>),
776}
777
778pub trait IsIdentity {
779 fn is_identity(&self) -> bool;
780}
781
782impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
783 fn is_identity(&self) -> bool {
786 if !self.value.bounds.is_empty() {
787 return false;
788 }
789
790 match self.value.kind {
791 UserTypeKind::Ty(_) => false,
792 UserTypeKind::TypeOf(_, user_args) => {
793 if user_args.user_self_ty.is_some() {
794 return false;
795 }
796
797 iter::zip(user_args.args, BoundVar::ZERO..).all(|(arg, cvar)| {
798 match arg.kind() {
799 GenericArgKind::Type(ty) => match ty.kind() {
800 ty::Bound(debruijn, b) => {
801 assert_eq!(*debruijn, ty::INNERMOST);
803 cvar == b.var
804 }
805 _ => false,
806 },
807
808 GenericArgKind::Lifetime(r) => match r.kind() {
809 ty::ReBound(debruijn, b) => {
810 assert_eq!(debruijn, ty::INNERMOST);
812 cvar == b.var
813 }
814 _ => false,
815 },
816
817 GenericArgKind::Const(ct) => match ct.kind() {
818 ty::ConstKind::Bound(debruijn, b) => {
819 assert_eq!(debruijn, ty::INNERMOST);
821 cvar == b.var
822 }
823 _ => false,
824 },
825 }
826 })
827 }
828 }
829 }
830}
831
832impl<'tcx> std::fmt::Display for UserType<'tcx> {
833 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
834 if self.bounds.is_empty() {
835 self.kind.fmt(f)
836 } else {
837 self.kind.fmt(f)?;
838 write!(f, " + ")?;
839 std::fmt::Debug::fmt(&self.bounds, f)
840 }
841 }
842}
843
844impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> {
845 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
846 match self {
847 Self::Ty(arg0) => {
848 ty::print::with_no_trimmed_paths!(write!(f, "Ty({})", arg0))
849 }
850 Self::TypeOf(arg0, arg1) => write!(f, "TypeOf({:?}, {:?})", arg0, arg1),
851 }
852 }
853}
854
855#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
858pub struct Rust2024IncompatiblePatInfo {
859 pub primary_labels: Vec<(Span, String)>,
861 pub bad_modifiers: bool,
863 pub bad_ref_pats: bool,
865 pub suggest_eliding_modes: bool,
867}