rustc_hir_analysis/check/
check.rs

1use std::cell::LazyCell;
2use std::ops::ControlFlow;
3
4use rustc_abi::FieldIdx;
5use rustc_data_structures::unord::{UnordMap, UnordSet};
6use rustc_errors::MultiSpan;
7use rustc_errors::codes::*;
8use rustc_hir::def::{CtorKind, DefKind};
9use rustc_hir::{LangItem, Node, intravisit};
10use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
11use rustc_infer::traits::{Obligation, ObligationCauseCode};
12use rustc_lint_defs::builtin::{
13    REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS,
14};
15use rustc_middle::hir::nested_filter;
16use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
17use rustc_middle::middle::stability::EvalResult;
18use rustc_middle::span_bug;
19use rustc_middle::ty::error::TypeErrorToStringExt;
20use rustc_middle::ty::fold::{BottomUpFolder, fold_regions};
21use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
22use rustc_middle::ty::util::{Discr, IntTypeExt};
23use rustc_middle::ty::{
24    AdtDef, GenericArgKind, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
25};
26use rustc_session::lint::builtin::UNINHABITED_STATIC;
27use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
28use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
29use rustc_trait_selection::traits;
30use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
31use rustc_type_ir::fold::TypeFoldable;
32use tracing::{debug, instrument};
33use ty::TypingMode;
34use {rustc_attr_parsing as attr, rustc_hir as hir};
35
36use super::compare_impl_item::check_type_bounds;
37use super::*;
38use crate::check::intrinsicck::InlineAsmCtxt;
39
40pub fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: ExternAbi) {
41    if !tcx.sess.target.is_abi_supported(abi) {
42        struct_span_code_err!(
43            tcx.dcx(),
44            span,
45            E0570,
46            "`{abi}` is not a supported ABI for the current target",
47        )
48        .emit();
49    }
50}
51
52pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi) {
53    if !tcx.sess.target.is_abi_supported(abi) {
54        tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| {
55            lint.primary_message(format!(
56                "the calling convention {abi} is not supported on this target"
57            ));
58        });
59    }
60}
61
62fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
63    let def = tcx.adt_def(def_id);
64    let span = tcx.def_span(def_id);
65    def.destructor(tcx); // force the destructor to be evaluated
66
67    if def.repr().simd() {
68        check_simd(tcx, span, def_id);
69    }
70
71    check_transparent(tcx, def);
72    check_packed(tcx, span, def);
73    check_unsafe_fields(tcx, def_id);
74}
75
76fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
77    let def = tcx.adt_def(def_id);
78    let span = tcx.def_span(def_id);
79    def.destructor(tcx); // force the destructor to be evaluated
80    check_transparent(tcx, def);
81    check_union_fields(tcx, span, def_id);
82    check_packed(tcx, span, def);
83}
84
85fn allowed_union_or_unsafe_field<'tcx>(
86    tcx: TyCtxt<'tcx>,
87    ty: Ty<'tcx>,
88    typing_env: ty::TypingEnv<'tcx>,
89    span: Span,
90) -> bool {
91    // HACK (not that bad of a hack don't worry): Some codegen tests don't even define proper
92    // impls for `Copy`. Let's short-circuit here for this validity check, since a lot of them
93    // use unions. We should eventually fix all the tests to define that lang item or use
94    // minicore stubs.
95    if ty.is_trivially_pure_clone_copy() {
96        return true;
97    }
98    // If `BikeshedGuaranteedNoDrop` is not defined in a `#[no_core]` test, fall back to `Copy`.
99    // This is an underapproximation of `BikeshedGuaranteedNoDrop`,
100    let def_id = tcx
101        .lang_items()
102        .get(LangItem::BikeshedGuaranteedNoDrop)
103        .unwrap_or_else(|| tcx.require_lang_item(LangItem::Copy, Some(span)));
104    let Ok(ty) = tcx.try_normalize_erasing_regions(typing_env, ty) else {
105        tcx.dcx().span_delayed_bug(span, "could not normalize field type");
106        return true;
107    };
108    let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
109    infcx.predicate_must_hold_modulo_regions(&Obligation::new(
110        tcx,
111        ObligationCause::dummy_with_span(span),
112        param_env,
113        ty::TraitRef::new(tcx, def_id, [ty]),
114    ))
115}
116
117/// Check that the fields of the `union` do not need dropping.
118fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool {
119    let def = tcx.adt_def(item_def_id);
120    assert!(def.is_union());
121
122    let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id);
123    let args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
124
125    for field in &def.non_enum_variant().fields {
126        if !allowed_union_or_unsafe_field(tcx, field.ty(tcx, args), typing_env, span) {
127            let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
128                // We are currently checking the type this field came from, so it must be local.
129                Some(Node::Field(field)) => (field.span, field.ty.span),
130                _ => unreachable!("mir field has to correspond to hir field"),
131            };
132            tcx.dcx().emit_err(errors::InvalidUnionField {
133                field_span,
134                sugg: errors::InvalidUnionFieldSuggestion {
135                    lo: ty_span.shrink_to_lo(),
136                    hi: ty_span.shrink_to_hi(),
137                },
138                note: (),
139            });
140            return false;
141        }
142    }
143
144    true
145}
146
147/// Check that the unsafe fields do not need dropping.
148fn check_unsafe_fields(tcx: TyCtxt<'_>, item_def_id: LocalDefId) {
149    let span = tcx.def_span(item_def_id);
150    let def = tcx.adt_def(item_def_id);
151
152    let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id);
153    let args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
154
155    for field in def.all_fields() {
156        if !field.safety.is_unsafe() {
157            continue;
158        }
159
160        if !allowed_union_or_unsafe_field(tcx, field.ty(tcx, args), typing_env, span) {
161            let hir::Node::Field(field) = tcx.hir_node_by_def_id(field.did.expect_local()) else {
162                unreachable!("field has to correspond to hir field")
163            };
164            let ty_span = field.ty.span;
165            tcx.dcx().emit_err(errors::InvalidUnsafeField {
166                field_span: field.span,
167                sugg: errors::InvalidUnsafeFieldSuggestion {
168                    lo: ty_span.shrink_to_lo(),
169                    hi: ty_span.shrink_to_hi(),
170                },
171                note: (),
172            });
173        }
174    }
175}
176
177/// Check that a `static` is inhabited.
178fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
179    // Make sure statics are inhabited.
180    // Other parts of the compiler assume that there are no uninhabited places. In principle it
181    // would be enough to check this for `extern` statics, as statics with an initializer will
182    // have UB during initialization if they are uninhabited, but there also seems to be no good
183    // reason to allow any statics to be uninhabited.
184    let ty = tcx.type_of(def_id).instantiate_identity();
185    let span = tcx.def_span(def_id);
186    let layout = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) {
187        Ok(l) => l,
188        // Foreign statics that overflow their allowed size should emit an error
189        Err(LayoutError::SizeOverflow(_))
190            if matches!(tcx.def_kind(def_id), DefKind::Static{ .. }
191                if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) =>
192        {
193            tcx.dcx().emit_err(errors::TooLargeStatic { span });
194            return;
195        }
196        // Generic statics are rejected, but we still reach this case.
197        Err(e) => {
198            tcx.dcx().span_delayed_bug(span, format!("{e:?}"));
199            return;
200        }
201    };
202    if layout.is_uninhabited() {
203        tcx.node_span_lint(
204            UNINHABITED_STATIC,
205            tcx.local_def_id_to_hir_id(def_id),
206            span,
207            |lint| {
208                lint.primary_message("static of uninhabited type");
209                lint
210                .note("uninhabited statics cannot be initialized, and any access would be an immediate error");
211            },
212        );
213    }
214}
215
216/// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
217/// projections that would result in "inheriting lifetimes".
218fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
219    let hir::OpaqueTy { origin, .. } = *tcx.hir().expect_opaque_ty(def_id);
220
221    // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
222    // `async-std` (and `pub async fn` in general).
223    // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
224    // See https://github.com/rust-lang/rust/issues/75100
225    if tcx.sess.opts.actually_rustdoc {
226        return;
227    }
228
229    if tcx.type_of(def_id).instantiate_identity().references_error() {
230        return;
231    }
232    if check_opaque_for_cycles(tcx, def_id).is_err() {
233        return;
234    }
235
236    let _ = check_opaque_meets_bounds(tcx, def_id, origin);
237}
238
239/// Checks that an opaque type does not contain cycles.
240pub(super) fn check_opaque_for_cycles<'tcx>(
241    tcx: TyCtxt<'tcx>,
242    def_id: LocalDefId,
243) -> Result<(), ErrorGuaranteed> {
244    let args = GenericArgs::identity_for_item(tcx, def_id);
245
246    // First, try to look at any opaque expansion cycles, considering coroutine fields
247    // (even though these aren't necessarily true errors).
248    if tcx.try_expand_impl_trait_type(def_id.to_def_id(), args).is_err() {
249        let reported = opaque_type_cycle_error(tcx, def_id);
250        return Err(reported);
251    }
252
253    Ok(())
254}
255
256/// Check that the concrete type behind `impl Trait` actually implements `Trait`.
257///
258/// This is mostly checked at the places that specify the opaque type, but we
259/// check those cases in the `param_env` of that function, which may have
260/// bounds not on this opaque type:
261///
262/// ```ignore (illustrative)
263/// type X<T> = impl Clone;
264/// fn f<T: Clone>(t: T) -> X<T> {
265///     t
266/// }
267/// ```
268///
269/// Without this check the above code is incorrectly accepted: we would ICE if
270/// some tried, for example, to clone an `Option<X<&mut ()>>`.
271#[instrument(level = "debug", skip(tcx))]
272fn check_opaque_meets_bounds<'tcx>(
273    tcx: TyCtxt<'tcx>,
274    def_id: LocalDefId,
275    origin: hir::OpaqueTyOrigin<LocalDefId>,
276) -> Result<(), ErrorGuaranteed> {
277    let (span, definition_def_id) =
278        if let Some((span, def_id)) = best_definition_site_of_opaque(tcx, def_id, origin) {
279            (span, Some(def_id))
280        } else {
281            (tcx.def_span(def_id), None)
282        };
283
284    let defining_use_anchor = match origin {
285        hir::OpaqueTyOrigin::FnReturn { parent, .. }
286        | hir::OpaqueTyOrigin::AsyncFn { parent, .. }
287        | hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent,
288    };
289    let param_env = tcx.param_env(defining_use_anchor);
290
291    // FIXME(#132279): Once `PostBorrowckAnalysis` is supported in the old solver, this branch should be removed.
292    let infcx = tcx.infer_ctxt().build(if tcx.next_trait_solver_globally() {
293        TypingMode::post_borrowck_analysis(tcx, defining_use_anchor)
294    } else {
295        TypingMode::analysis_in_body(tcx, defining_use_anchor)
296    });
297    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
298
299    let args = match origin {
300        hir::OpaqueTyOrigin::FnReturn { parent, .. }
301        | hir::OpaqueTyOrigin::AsyncFn { parent, .. }
302        | hir::OpaqueTyOrigin::TyAlias { parent, .. } => GenericArgs::identity_for_item(
303            tcx, parent,
304        )
305        .extend_to(tcx, def_id.to_def_id(), |param, _| {
306            tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into()
307        }),
308    };
309
310    let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
311
312    // `ReErased` regions appear in the "parent_args" of closures/coroutines.
313    // We're ignoring them here and replacing them with fresh region variables.
314    // See tests in ui/type-alias-impl-trait/closure_{parent_args,wf_outlives}.rs.
315    //
316    // FIXME: Consider wrapping the hidden type in an existential `Binder` and instantiating it
317    // here rather than using ReErased.
318    let hidden_ty = tcx.type_of(def_id.to_def_id()).instantiate(tcx, args);
319    let hidden_ty = fold_regions(tcx, hidden_ty, |re, _dbi| match re.kind() {
320        ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)),
321        _ => re,
322    });
323
324    // HACK: We eagerly instantiate some bounds to report better errors for them...
325    // This isn't necessary for correctness, since we register these bounds when
326    // equating the opaque below, but we should clean this up in the new solver.
327    for (predicate, pred_span) in
328        tcx.explicit_item_bounds(def_id).iter_instantiated_copied(tcx, args)
329    {
330        let predicate = predicate.fold_with(&mut BottomUpFolder {
331            tcx,
332            ty_op: |ty| if ty == opaque_ty { hidden_ty } else { ty },
333            lt_op: |lt| lt,
334            ct_op: |ct| ct,
335        });
336
337        ocx.register_obligation(Obligation::new(
338            tcx,
339            ObligationCause::new(
340                span,
341                def_id,
342                ObligationCauseCode::OpaqueTypeBound(pred_span, definition_def_id),
343            ),
344            param_env,
345            predicate,
346        ));
347    }
348
349    let misc_cause = ObligationCause::misc(span, def_id);
350    // FIXME: We should just register the item bounds here, rather than equating.
351    // FIXME(const_trait_impl): When we do that, please make sure to also register
352    // the `~const` bounds.
353    match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) {
354        Ok(()) => {}
355        Err(ty_err) => {
356            // Some types may be left "stranded" if they can't be reached
357            // from a lowered rustc_middle bound but they're mentioned in the HIR.
358            // This will happen, e.g., when a nested opaque is inside of a non-
359            // existent associated type, like `impl Trait<Missing = impl Trait>`.
360            // See <tests/ui/impl-trait/stranded-opaque.rs>.
361            let ty_err = ty_err.to_string(tcx);
362            let guar = tcx.dcx().span_delayed_bug(
363                span,
364                format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
365            );
366            return Err(guar);
367        }
368    }
369
370    // Additionally require the hidden type to be well-formed with only the generics of the opaque type.
371    // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
372    // hidden type is well formed even without those bounds.
373    let predicate =
374        ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(hidden_ty.into())));
375    ocx.register_obligation(Obligation::new(tcx, misc_cause.clone(), param_env, predicate));
376
377    // Check that all obligations are satisfied by the implementation's
378    // version.
379    let errors = ocx.select_all_or_error();
380    if !errors.is_empty() {
381        let guar = infcx.err_ctxt().report_fulfillment_errors(errors);
382        return Err(guar);
383    }
384
385    let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, defining_use_anchor)?;
386    ocx.resolve_regions_and_report_errors(defining_use_anchor, param_env, wf_tys)?;
387
388    if infcx.next_trait_solver() {
389        Ok(())
390    } else if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } =
391        origin
392    {
393        // HACK: this should also fall through to the hidden type check below, but the original
394        // implementation had a bug where equivalent lifetimes are not identical. This caused us
395        // to reject existing stable code that is otherwise completely fine. The real fix is to
396        // compare the hidden types via our type equivalence/relation infra instead of doing an
397        // identity check.
398        let _ = infcx.take_opaque_types();
399        Ok(())
400    } else {
401        // Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
402        for (mut key, mut ty) in infcx.take_opaque_types() {
403            ty.ty = infcx.resolve_vars_if_possible(ty.ty);
404            key = infcx.resolve_vars_if_possible(key);
405            sanity_check_found_hidden_type(tcx, key, ty)?;
406        }
407        Ok(())
408    }
409}
410
411fn best_definition_site_of_opaque<'tcx>(
412    tcx: TyCtxt<'tcx>,
413    opaque_def_id: LocalDefId,
414    origin: hir::OpaqueTyOrigin<LocalDefId>,
415) -> Option<(Span, LocalDefId)> {
416    struct TaitConstraintLocator<'tcx> {
417        opaque_def_id: LocalDefId,
418        tcx: TyCtxt<'tcx>,
419    }
420    impl<'tcx> TaitConstraintLocator<'tcx> {
421        fn check(&self, item_def_id: LocalDefId) -> ControlFlow<(Span, LocalDefId)> {
422            if !self.tcx.has_typeck_results(item_def_id) {
423                return ControlFlow::Continue(());
424            }
425
426            if let Some(hidden_ty) =
427                self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id)
428            {
429                ControlFlow::Break((hidden_ty.span, item_def_id))
430            } else {
431                ControlFlow::Continue(())
432            }
433        }
434    }
435    impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
436        type NestedFilter = nested_filter::All;
437        type Result = ControlFlow<(Span, LocalDefId)>;
438        fn nested_visit_map(&mut self) -> Self::Map {
439            self.tcx.hir()
440        }
441        fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result {
442            if let hir::ExprKind::Closure(closure) = ex.kind {
443                self.check(closure.def_id)?;
444            }
445            intravisit::walk_expr(self, ex)
446        }
447        fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) -> Self::Result {
448            self.check(it.owner_id.def_id)?;
449            intravisit::walk_item(self, it)
450        }
451        fn visit_impl_item(&mut self, it: &'tcx hir::ImplItem<'tcx>) -> Self::Result {
452            self.check(it.owner_id.def_id)?;
453            intravisit::walk_impl_item(self, it)
454        }
455        fn visit_trait_item(&mut self, it: &'tcx hir::TraitItem<'tcx>) -> Self::Result {
456            self.check(it.owner_id.def_id)?;
457            intravisit::walk_trait_item(self, it)
458        }
459        fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) -> Self::Result {
460            intravisit::walk_foreign_item(self, it)
461        }
462    }
463
464    let mut locator = TaitConstraintLocator { tcx, opaque_def_id };
465    match origin {
466        hir::OpaqueTyOrigin::FnReturn { parent, .. }
467        | hir::OpaqueTyOrigin::AsyncFn { parent, .. } => locator.check(parent).break_value(),
468        hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty: true } => {
469            let impl_def_id = tcx.local_parent(parent);
470            for assoc in tcx.associated_items(impl_def_id).in_definition_order() {
471                match assoc.kind {
472                    ty::AssocKind::Const | ty::AssocKind::Fn => {
473                        if let ControlFlow::Break(span) = locator.check(assoc.def_id.expect_local())
474                        {
475                            return Some(span);
476                        }
477                    }
478                    ty::AssocKind::Type => {}
479                }
480            }
481
482            None
483        }
484        hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
485            let scope = tcx.hir().get_defining_scope(tcx.local_def_id_to_hir_id(opaque_def_id));
486            let found = if scope == hir::CRATE_HIR_ID {
487                tcx.hir().walk_toplevel_module(&mut locator)
488            } else {
489                match tcx.hir_node(scope) {
490                    Node::Item(it) => locator.visit_item(it),
491                    Node::ImplItem(it) => locator.visit_impl_item(it),
492                    Node::TraitItem(it) => locator.visit_trait_item(it),
493                    Node::ForeignItem(it) => locator.visit_foreign_item(it),
494                    other => bug!("{:?} is not a valid scope for an opaque type item", other),
495                }
496            };
497            found.break_value()
498        }
499    }
500}
501
502fn sanity_check_found_hidden_type<'tcx>(
503    tcx: TyCtxt<'tcx>,
504    key: ty::OpaqueTypeKey<'tcx>,
505    mut ty: ty::OpaqueHiddenType<'tcx>,
506) -> Result<(), ErrorGuaranteed> {
507    if ty.ty.is_ty_var() {
508        // Nothing was actually constrained.
509        return Ok(());
510    }
511    if let ty::Alias(ty::Opaque, alias) = ty.ty.kind() {
512        if alias.def_id == key.def_id.to_def_id() && alias.args == key.args {
513            // Nothing was actually constrained, this is an opaque usage that was
514            // only discovered to be opaque after inference vars resolved.
515            return Ok(());
516        }
517    }
518    let strip_vars = |ty: Ty<'tcx>| {
519        ty.fold_with(&mut BottomUpFolder {
520            tcx,
521            ty_op: |t| t,
522            ct_op: |c| c,
523            lt_op: |l| match l.kind() {
524                RegionKind::ReVar(_) => tcx.lifetimes.re_erased,
525                _ => l,
526            },
527        })
528    };
529    // Closures frequently end up containing erased lifetimes in their final representation.
530    // These correspond to lifetime variables that never got resolved, so we patch this up here.
531    ty.ty = strip_vars(ty.ty);
532    // Get the hidden type.
533    let hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args);
534    let hidden_ty = strip_vars(hidden_ty);
535
536    // If the hidden types differ, emit a type mismatch diagnostic.
537    if hidden_ty == ty.ty {
538        Ok(())
539    } else {
540        let span = tcx.def_span(key.def_id);
541        let other = ty::OpaqueHiddenType { ty: hidden_ty, span };
542        Err(ty.build_mismatch_error(&other, tcx)?.emit())
543    }
544}
545
546/// Check that the opaque's precise captures list is valid (if present).
547/// We check this for regular `impl Trait`s and also RPITITs, even though the latter
548/// are technically GATs.
549///
550/// This function is responsible for:
551/// 1. Checking that all type/const params are mention in the captures list.
552/// 2. Checking that all lifetimes that are implicitly captured are mentioned.
553/// 3. Asserting that all parameters mentioned in the captures list are invariant.
554fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDefId) {
555    let hir::OpaqueTy { bounds, .. } = *tcx.hir_node_by_def_id(opaque_def_id).expect_opaque_ty();
556    let Some(precise_capturing_args) = bounds.iter().find_map(|bound| match *bound {
557        hir::GenericBound::Use(bounds, ..) => Some(bounds),
558        _ => None,
559    }) else {
560        // No precise capturing args; nothing to validate
561        return;
562    };
563
564    let mut expected_captures = UnordSet::default();
565    let mut shadowed_captures = UnordSet::default();
566    let mut seen_params = UnordMap::default();
567    let mut prev_non_lifetime_param = None;
568    for arg in precise_capturing_args {
569        let (hir_id, ident) = match *arg {
570            hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg {
571                hir_id,
572                ident,
573                ..
574            }) => {
575                if prev_non_lifetime_param.is_none() {
576                    prev_non_lifetime_param = Some(ident);
577                }
578                (hir_id, ident)
579            }
580            hir::PreciseCapturingArg::Lifetime(&hir::Lifetime { hir_id, ident, .. }) => {
581                if let Some(prev_non_lifetime_param) = prev_non_lifetime_param {
582                    tcx.dcx().emit_err(errors::LifetimesMustBeFirst {
583                        lifetime_span: ident.span,
584                        name: ident.name,
585                        other_span: prev_non_lifetime_param.span,
586                    });
587                }
588                (hir_id, ident)
589            }
590        };
591
592        let ident = ident.normalize_to_macros_2_0();
593        if let Some(span) = seen_params.insert(ident, ident.span) {
594            tcx.dcx().emit_err(errors::DuplicatePreciseCapture {
595                name: ident.name,
596                first_span: span,
597                second_span: ident.span,
598            });
599        }
600
601        match tcx.named_bound_var(hir_id) {
602            Some(ResolvedArg::EarlyBound(def_id)) => {
603                expected_captures.insert(def_id.to_def_id());
604
605                // Make sure we allow capturing these lifetimes through `Self` and
606                // `T::Assoc` projection syntax, too. These will occur when we only
607                // see lifetimes are captured after hir-lowering -- this aligns with
608                // the cases that were stabilized with the `impl_trait_projection`
609                // feature -- see <https://github.com/rust-lang/rust/pull/115659>.
610                if let DefKind::LifetimeParam = tcx.def_kind(def_id)
611                    && let Some(def_id) = tcx
612                        .map_opaque_lifetime_to_parent_lifetime(def_id)
613                        .opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id()))
614                {
615                    shadowed_captures.insert(def_id);
616                }
617            }
618            _ => {
619                tcx.dcx().span_delayed_bug(
620                    tcx.hir().span(hir_id),
621                    "parameter should have been resolved",
622                );
623            }
624        }
625    }
626
627    let variances = tcx.variances_of(opaque_def_id);
628    let mut def_id = Some(opaque_def_id.to_def_id());
629    while let Some(generics) = def_id {
630        let generics = tcx.generics_of(generics);
631        def_id = generics.parent;
632
633        for param in &generics.own_params {
634            if expected_captures.contains(&param.def_id) {
635                assert_eq!(
636                    variances[param.index as usize],
637                    ty::Invariant,
638                    "precise captured param should be invariant"
639                );
640                continue;
641            }
642            // If a param is shadowed by a early-bound (duplicated) lifetime, then
643            // it may or may not be captured as invariant, depending on if it shows
644            // up through `Self` or `T::Assoc` syntax.
645            if shadowed_captures.contains(&param.def_id) {
646                continue;
647            }
648
649            match param.kind {
650                ty::GenericParamDefKind::Lifetime => {
651                    let use_span = tcx.def_span(param.def_id);
652                    let opaque_span = tcx.def_span(opaque_def_id);
653                    // Check if the lifetime param was captured but isn't named in the precise captures list.
654                    if variances[param.index as usize] == ty::Invariant {
655                        if let DefKind::OpaqueTy = tcx.def_kind(tcx.parent(param.def_id))
656                            && let Some(def_id) = tcx
657                                .map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local())
658                                .opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id()))
659                        {
660                            tcx.dcx().emit_err(errors::LifetimeNotCaptured {
661                                opaque_span,
662                                use_span,
663                                param_span: tcx.def_span(def_id),
664                            });
665                        } else {
666                            if tcx.def_kind(tcx.parent(param.def_id)) == DefKind::Trait {
667                                tcx.dcx().emit_err(errors::LifetimeImplicitlyCaptured {
668                                    opaque_span,
669                                    param_span: tcx.def_span(param.def_id),
670                                });
671                            } else {
672                                // If the `use_span` is actually just the param itself, then we must
673                                // have not duplicated the lifetime but captured the original.
674                                // The "effective" `use_span` will be the span of the opaque itself,
675                                // and the param span will be the def span of the param.
676                                tcx.dcx().emit_err(errors::LifetimeNotCaptured {
677                                    opaque_span,
678                                    use_span: opaque_span,
679                                    param_span: use_span,
680                                });
681                            }
682                        }
683                        continue;
684                    }
685                }
686                ty::GenericParamDefKind::Type { .. } => {
687                    if matches!(tcx.def_kind(param.def_id), DefKind::Trait | DefKind::TraitAlias) {
688                        // FIXME(precise_capturing): Structured suggestion for this would be useful
689                        tcx.dcx().emit_err(errors::SelfTyNotCaptured {
690                            trait_span: tcx.def_span(param.def_id),
691                            opaque_span: tcx.def_span(opaque_def_id),
692                        });
693                    } else {
694                        // FIXME(precise_capturing): Structured suggestion for this would be useful
695                        tcx.dcx().emit_err(errors::ParamNotCaptured {
696                            param_span: tcx.def_span(param.def_id),
697                            opaque_span: tcx.def_span(opaque_def_id),
698                            kind: "type",
699                        });
700                    }
701                }
702                ty::GenericParamDefKind::Const { .. } => {
703                    // FIXME(precise_capturing): Structured suggestion for this would be useful
704                    tcx.dcx().emit_err(errors::ParamNotCaptured {
705                        param_span: tcx.def_span(param.def_id),
706                        opaque_span: tcx.def_span(opaque_def_id),
707                        kind: "const",
708                    });
709                }
710            }
711        }
712    }
713}
714
715fn is_enum_of_nonnullable_ptr<'tcx>(
716    tcx: TyCtxt<'tcx>,
717    adt_def: AdtDef<'tcx>,
718    args: GenericArgsRef<'tcx>,
719) -> bool {
720    if adt_def.repr().inhibit_enum_layout_opt() {
721        return false;
722    }
723
724    let [var_one, var_two] = &adt_def.variants().raw[..] else {
725        return false;
726    };
727    let (([], [field]) | ([field], [])) = (&var_one.fields.raw[..], &var_two.fields.raw[..]) else {
728        return false;
729    };
730    matches!(field.ty(tcx, args).kind(), ty::FnPtr(..) | ty::Ref(..))
731}
732
733fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
734    if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() {
735        if match tcx.type_of(def_id).instantiate_identity().kind() {
736            ty::RawPtr(_, _) => false,
737            ty::Adt(adt_def, args) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *args),
738            _ => true,
739        } {
740            tcx.dcx().emit_err(errors::LinkageType { span: tcx.def_span(def_id) });
741        }
742    }
743}
744
745pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
746    match tcx.def_kind(def_id) {
747        DefKind::Static { .. } => {
748            tcx.ensure_ok().typeck(def_id);
749            maybe_check_static_with_link_section(tcx, def_id);
750            check_static_inhabited(tcx, def_id);
751            check_static_linkage(tcx, def_id);
752        }
753        DefKind::Const => {
754            tcx.ensure_ok().typeck(def_id);
755        }
756        DefKind::Enum => {
757            check_enum(tcx, def_id);
758        }
759        DefKind::Fn => {
760            if let Some(i) = tcx.intrinsic(def_id) {
761                intrinsic::check_intrinsic_type(
762                    tcx,
763                    def_id,
764                    tcx.def_ident_span(def_id).unwrap(),
765                    i.name,
766                    ExternAbi::Rust,
767                )
768            }
769            // Everything else is checked entirely within check_item_body
770        }
771        DefKind::Impl { of_trait } => {
772            if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
773                if tcx
774                    .ensure_ok()
775                    .coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id)
776                    .is_ok()
777                {
778                    check_impl_items_against_trait(tcx, def_id, impl_trait_header);
779                    check_on_unimplemented(tcx, def_id);
780                }
781            }
782        }
783        DefKind::Trait => {
784            let assoc_items = tcx.associated_items(def_id);
785            check_on_unimplemented(tcx, def_id);
786
787            for &assoc_item in assoc_items.in_definition_order() {
788                match assoc_item.kind {
789                    ty::AssocKind::Fn => {
790                        let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi();
791                        forbid_intrinsic_abi(tcx, assoc_item.ident(tcx).span, abi);
792                    }
793                    ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
794                        let trait_args = GenericArgs::identity_for_item(tcx, def_id);
795                        let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
796                            tcx,
797                            assoc_item,
798                            assoc_item,
799                            ty::TraitRef::new_from_args(tcx, def_id.to_def_id(), trait_args),
800                        );
801                    }
802                    _ => {}
803                }
804            }
805        }
806        DefKind::Struct => {
807            check_struct(tcx, def_id);
808        }
809        DefKind::Union => {
810            check_union(tcx, def_id);
811        }
812        DefKind::OpaqueTy => {
813            check_opaque_precise_captures(tcx, def_id);
814
815            let origin = tcx.local_opaque_ty_origin(def_id);
816            if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
817            | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = origin
818                && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id)
819                && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
820            {
821                // Skip opaques from RPIT in traits with no default body.
822            } else {
823                check_opaque(tcx, def_id);
824            }
825        }
826        DefKind::TyAlias => {
827            check_type_alias_type_params_are_used(tcx, def_id);
828        }
829        DefKind::ForeignMod => {
830            let it = tcx.hir().expect_item(def_id);
831            let hir::ItemKind::ForeignMod { abi, items } = it.kind else {
832                return;
833            };
834            check_abi(tcx, it.span, abi);
835
836            match abi {
837                ExternAbi::RustIntrinsic => {
838                    for item in items {
839                        intrinsic::check_intrinsic_type(
840                            tcx,
841                            item.id.owner_id.def_id,
842                            item.span,
843                            item.ident.name,
844                            abi,
845                        );
846                    }
847                }
848
849                _ => {
850                    for item in items {
851                        let def_id = item.id.owner_id.def_id;
852                        let generics = tcx.generics_of(def_id);
853                        let own_counts = generics.own_counts();
854                        if generics.own_params.len() - own_counts.lifetimes != 0 {
855                            let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts)
856                            {
857                                (_, 0) => ("type", "types", Some("u32")),
858                                // We don't specify an example value, because we can't generate
859                                // a valid value for any type.
860                                (0, _) => ("const", "consts", None),
861                                _ => ("type or const", "types or consts", None),
862                            };
863                            struct_span_code_err!(
864                                tcx.dcx(),
865                                item.span,
866                                E0044,
867                                "foreign items may not have {kinds} parameters",
868                            )
869                            .with_span_label(item.span, format!("can't have {kinds} parameters"))
870                            .with_help(
871                                // FIXME: once we start storing spans for type arguments, turn this
872                                // into a suggestion.
873                                format!(
874                                    "replace the {} parameters with concrete {}{}",
875                                    kinds,
876                                    kinds_pl,
877                                    egs.map(|egs| format!(" like `{egs}`")).unwrap_or_default(),
878                                ),
879                            )
880                            .emit();
881                        }
882
883                        let item = tcx.hir().foreign_item(item.id);
884                        match &item.kind {
885                            hir::ForeignItemKind::Fn(sig, _, _) => {
886                                require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span);
887                            }
888                            hir::ForeignItemKind::Static(..) => {
889                                check_static_inhabited(tcx, def_id);
890                                check_static_linkage(tcx, def_id);
891                            }
892                            _ => {}
893                        }
894                    }
895                }
896            }
897        }
898        DefKind::GlobalAsm => {
899            let it = tcx.hir().expect_item(def_id);
900            let hir::ItemKind::GlobalAsm(asm) = it.kind else {
901                span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it)
902            };
903            InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, def_id);
904        }
905        _ => {}
906    }
907}
908
909pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, def_id: LocalDefId) {
910    // an error would be reported if this fails.
911    let _ = OnUnimplementedDirective::of_item(tcx, def_id.to_def_id());
912}
913
914pub(super) fn check_specialization_validity<'tcx>(
915    tcx: TyCtxt<'tcx>,
916    trait_def: &ty::TraitDef,
917    trait_item: ty::AssocItem,
918    impl_id: DefId,
919    impl_item: DefId,
920) {
921    let Ok(ancestors) = trait_def.ancestors(tcx, impl_id) else { return };
922    let mut ancestor_impls = ancestors.skip(1).filter_map(|parent| {
923        if parent.is_from_trait() {
924            None
925        } else {
926            Some((parent, parent.item(tcx, trait_item.def_id)))
927        }
928    });
929
930    let opt_result = ancestor_impls.find_map(|(parent_impl, parent_item)| {
931        match parent_item {
932            // Parent impl exists, and contains the parent item we're trying to specialize, but
933            // doesn't mark it `default`.
934            Some(parent_item) if traits::impl_item_is_final(tcx, &parent_item) => {
935                Some(Err(parent_impl.def_id()))
936            }
937
938            // Parent impl contains item and makes it specializable.
939            Some(_) => Some(Ok(())),
940
941            // Parent impl doesn't mention the item. This means it's inherited from the
942            // grandparent. In that case, if parent is a `default impl`, inherited items use the
943            // "defaultness" from the grandparent, else they are final.
944            None => {
945                if tcx.defaultness(parent_impl.def_id()).is_default() {
946                    None
947                } else {
948                    Some(Err(parent_impl.def_id()))
949                }
950            }
951        }
952    });
953
954    // If `opt_result` is `None`, we have only encountered `default impl`s that don't contain the
955    // item. This is allowed, the item isn't actually getting specialized here.
956    let result = opt_result.unwrap_or(Ok(()));
957
958    if let Err(parent_impl) = result {
959        if !tcx.is_impl_trait_in_trait(impl_item) {
960            report_forbidden_specialization(tcx, impl_item, parent_impl);
961        } else {
962            tcx.dcx().delayed_bug(format!("parent item: {parent_impl:?} not marked as default"));
963        }
964    }
965}
966
967fn check_impl_items_against_trait<'tcx>(
968    tcx: TyCtxt<'tcx>,
969    impl_id: LocalDefId,
970    impl_trait_header: ty::ImplTraitHeader<'tcx>,
971) {
972    let trait_ref = impl_trait_header.trait_ref.instantiate_identity();
973    // If the trait reference itself is erroneous (so the compilation is going
974    // to fail), skip checking the items here -- the `impl_item` table in `tcx`
975    // isn't populated for such impls.
976    if trait_ref.references_error() {
977        return;
978    }
979
980    let impl_item_refs = tcx.associated_item_def_ids(impl_id);
981
982    // Negative impls are not expected to have any items
983    match impl_trait_header.polarity {
984        ty::ImplPolarity::Reservation | ty::ImplPolarity::Positive => {}
985        ty::ImplPolarity::Negative => {
986            if let [first_item_ref, ..] = impl_item_refs {
987                let first_item_span = tcx.def_span(first_item_ref);
988                struct_span_code_err!(
989                    tcx.dcx(),
990                    first_item_span,
991                    E0749,
992                    "negative impls cannot have any items"
993                )
994                .emit();
995            }
996            return;
997        }
998    }
999
1000    let trait_def = tcx.trait_def(trait_ref.def_id);
1001
1002    for &impl_item in impl_item_refs {
1003        let ty_impl_item = tcx.associated_item(impl_item);
1004        let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
1005            tcx.associated_item(trait_item_id)
1006        } else {
1007            // Checked in `associated_item`.
1008            tcx.dcx().span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait");
1009            continue;
1010        };
1011
1012        let res = tcx.ensure_ok().compare_impl_item(impl_item.expect_local());
1013
1014        if res.is_ok() {
1015            match ty_impl_item.kind {
1016                ty::AssocKind::Fn => {
1017                    compare_impl_item::refine::check_refining_return_position_impl_trait_in_trait(
1018                        tcx,
1019                        ty_impl_item,
1020                        ty_trait_item,
1021                        tcx.impl_trait_ref(ty_impl_item.container_id(tcx))
1022                            .unwrap()
1023                            .instantiate_identity(),
1024                    );
1025                }
1026                ty::AssocKind::Const => {}
1027                ty::AssocKind::Type => {}
1028            }
1029        }
1030
1031        check_specialization_validity(
1032            tcx,
1033            trait_def,
1034            ty_trait_item,
1035            impl_id.to_def_id(),
1036            impl_item,
1037        );
1038    }
1039
1040    if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id.to_def_id()) {
1041        // Check for missing items from trait
1042        let mut missing_items = Vec::new();
1043
1044        let mut must_implement_one_of: Option<&[Ident]> =
1045            trait_def.must_implement_one_of.as_deref();
1046
1047        for &trait_item_id in tcx.associated_item_def_ids(trait_ref.def_id) {
1048            let leaf_def = ancestors.leaf_def(tcx, trait_item_id);
1049
1050            let is_implemented = leaf_def
1051                .as_ref()
1052                .is_some_and(|node_item| node_item.item.defaultness(tcx).has_value());
1053
1054            if !is_implemented && tcx.defaultness(impl_id).is_final() {
1055                missing_items.push(tcx.associated_item(trait_item_id));
1056            }
1057
1058            // true if this item is specifically implemented in this impl
1059            let is_implemented_here =
1060                leaf_def.as_ref().is_some_and(|node_item| !node_item.defining_node.is_from_trait());
1061
1062            if !is_implemented_here {
1063                let full_impl_span = tcx.hir().span_with_body(tcx.local_def_id_to_hir_id(impl_id));
1064                match tcx.eval_default_body_stability(trait_item_id, full_impl_span) {
1065                    EvalResult::Deny { feature, reason, issue, .. } => default_body_is_unstable(
1066                        tcx,
1067                        full_impl_span,
1068                        trait_item_id,
1069                        feature,
1070                        reason,
1071                        issue,
1072                    ),
1073
1074                    // Unmarked default bodies are considered stable (at least for now).
1075                    EvalResult::Allow | EvalResult::Unmarked => {}
1076                }
1077            }
1078
1079            if let Some(required_items) = &must_implement_one_of {
1080                if is_implemented_here {
1081                    let trait_item = tcx.associated_item(trait_item_id);
1082                    if required_items.contains(&trait_item.ident(tcx)) {
1083                        must_implement_one_of = None;
1084                    }
1085                }
1086            }
1087
1088            if let Some(leaf_def) = &leaf_def
1089                && !leaf_def.is_final()
1090                && let def_id = leaf_def.item.def_id
1091                && tcx.impl_method_has_trait_impl_trait_tys(def_id)
1092            {
1093                let def_kind = tcx.def_kind(def_id);
1094                let descr = tcx.def_kind_descr(def_kind, def_id);
1095                let (msg, feature) = if tcx.asyncness(def_id).is_async() {
1096                    (
1097                        format!("async {descr} in trait cannot be specialized"),
1098                        "async functions in traits",
1099                    )
1100                } else {
1101                    (
1102                        format!(
1103                            "{descr} with return-position `impl Trait` in trait cannot be specialized"
1104                        ),
1105                        "return position `impl Trait` in traits",
1106                    )
1107                };
1108                tcx.dcx()
1109                    .struct_span_err(tcx.def_span(def_id), msg)
1110                    .with_note(format!(
1111                        "specialization behaves in inconsistent and surprising ways with \
1112                        {feature}, and for now is disallowed"
1113                    ))
1114                    .emit();
1115            }
1116        }
1117
1118        if !missing_items.is_empty() {
1119            let full_impl_span = tcx.hir().span_with_body(tcx.local_def_id_to_hir_id(impl_id));
1120            missing_items_err(tcx, impl_id, &missing_items, full_impl_span);
1121        }
1122
1123        if let Some(missing_items) = must_implement_one_of {
1124            let attr_span = tcx
1125                .get_attr(trait_ref.def_id, sym::rustc_must_implement_one_of)
1126                .map(|attr| attr.span);
1127
1128            missing_items_must_implement_one_of_err(
1129                tcx,
1130                tcx.def_span(impl_id),
1131                missing_items,
1132                attr_span,
1133            );
1134        }
1135    }
1136}
1137
1138fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
1139    let t = tcx.type_of(def_id).instantiate_identity();
1140    if let ty::Adt(def, args) = t.kind()
1141        && def.is_struct()
1142    {
1143        let fields = &def.non_enum_variant().fields;
1144        if fields.is_empty() {
1145            struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit();
1146            return;
1147        }
1148
1149        let array_field = &fields[FieldIdx::ZERO];
1150        let array_ty = array_field.ty(tcx, args);
1151        let ty::Array(element_ty, len_const) = array_ty.kind() else {
1152            struct_span_code_err!(
1153                tcx.dcx(),
1154                sp,
1155                E0076,
1156                "SIMD vector's only field must be an array"
1157            )
1158            .with_span_label(tcx.def_span(array_field.did), "not an array")
1159            .emit();
1160            return;
1161        };
1162
1163        if let Some(second_field) = fields.get(FieldIdx::from_u32(1)) {
1164            struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot have multiple fields")
1165                .with_span_label(tcx.def_span(second_field.did), "excess field")
1166                .emit();
1167            return;
1168        }
1169
1170        // FIXME(repr_simd): This check is nice, but perhaps unnecessary due to the fact
1171        // we do not expect users to implement their own `repr(simd)` types. If they could,
1172        // this check is easily side-steppable by hiding the const behind normalization.
1173        // The consequence is that the error is, in general, only observable post-mono.
1174        if let Some(len) = len_const.try_to_target_usize(tcx) {
1175            if len == 0 {
1176                struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit();
1177                return;
1178            } else if len > MAX_SIMD_LANES {
1179                struct_span_code_err!(
1180                    tcx.dcx(),
1181                    sp,
1182                    E0075,
1183                    "SIMD vector cannot have more than {MAX_SIMD_LANES} elements",
1184                )
1185                .emit();
1186                return;
1187            }
1188        }
1189
1190        // Check that we use types valid for use in the lanes of a SIMD "vector register"
1191        // These are scalar types which directly match a "machine" type
1192        // Yes: Integers, floats, "thin" pointers
1193        // No: char, "wide" pointers, compound types
1194        match element_ty.kind() {
1195            ty::Param(_) => (), // pass struct<T>([T; 4]) through, let monomorphization catch errors
1196            ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct([u8; 4]) is ok
1197            _ => {
1198                struct_span_code_err!(
1199                    tcx.dcx(),
1200                    sp,
1201                    E0077,
1202                    "SIMD vector element type should be a \
1203                        primitive scalar (integer/float/pointer) type"
1204                )
1205                .emit();
1206                return;
1207            }
1208        }
1209    }
1210}
1211
1212pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
1213    let repr = def.repr();
1214    if repr.packed() {
1215        for attr in tcx.get_attrs(def.did(), sym::repr) {
1216            for r in attr::parse_repr_attr(tcx.sess, attr) {
1217                if let attr::ReprPacked(pack) = r
1218                    && let Some(repr_pack) = repr.pack
1219                    && pack != repr_pack
1220                {
1221                    struct_span_code_err!(
1222                        tcx.dcx(),
1223                        sp,
1224                        E0634,
1225                        "type has conflicting packed representation hints"
1226                    )
1227                    .emit();
1228                }
1229            }
1230        }
1231        if repr.align.is_some() {
1232            struct_span_code_err!(
1233                tcx.dcx(),
1234                sp,
1235                E0587,
1236                "type has conflicting packed and align representation hints"
1237            )
1238            .emit();
1239        } else if let Some(def_spans) = check_packed_inner(tcx, def.did(), &mut vec![]) {
1240            let mut err = struct_span_code_err!(
1241                tcx.dcx(),
1242                sp,
1243                E0588,
1244                "packed type cannot transitively contain a `#[repr(align)]` type"
1245            );
1246
1247            err.span_note(
1248                tcx.def_span(def_spans[0].0),
1249                format!("`{}` has a `#[repr(align)]` attribute", tcx.item_name(def_spans[0].0)),
1250            );
1251
1252            if def_spans.len() > 2 {
1253                let mut first = true;
1254                for (adt_def, span) in def_spans.iter().skip(1).rev() {
1255                    let ident = tcx.item_name(*adt_def);
1256                    err.span_note(
1257                        *span,
1258                        if first {
1259                            format!(
1260                                "`{}` contains a field of type `{}`",
1261                                tcx.type_of(def.did()).instantiate_identity(),
1262                                ident
1263                            )
1264                        } else {
1265                            format!("...which contains a field of type `{ident}`")
1266                        },
1267                    );
1268                    first = false;
1269                }
1270            }
1271
1272            err.emit();
1273        }
1274    }
1275}
1276
1277pub(super) fn check_packed_inner(
1278    tcx: TyCtxt<'_>,
1279    def_id: DefId,
1280    stack: &mut Vec<DefId>,
1281) -> Option<Vec<(DefId, Span)>> {
1282    if let ty::Adt(def, args) = tcx.type_of(def_id).instantiate_identity().kind() {
1283        if def.is_struct() || def.is_union() {
1284            if def.repr().align.is_some() {
1285                return Some(vec![(def.did(), DUMMY_SP)]);
1286            }
1287
1288            stack.push(def_id);
1289            for field in &def.non_enum_variant().fields {
1290                if let ty::Adt(def, _) = field.ty(tcx, args).kind()
1291                    && !stack.contains(&def.did())
1292                    && let Some(mut defs) = check_packed_inner(tcx, def.did(), stack)
1293                {
1294                    defs.push((def.did(), field.ident(tcx).span));
1295                    return Some(defs);
1296                }
1297            }
1298            stack.pop();
1299        }
1300    }
1301
1302    None
1303}
1304
1305pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) {
1306    if !adt.repr().transparent() {
1307        return;
1308    }
1309
1310    if adt.is_union() && !tcx.features().transparent_unions() {
1311        feature_err(
1312            &tcx.sess,
1313            sym::transparent_unions,
1314            tcx.def_span(adt.did()),
1315            "transparent unions are unstable",
1316        )
1317        .emit();
1318    }
1319
1320    if adt.variants().len() != 1 {
1321        bad_variant_count(tcx, adt, tcx.def_span(adt.did()), adt.did());
1322        // Don't bother checking the fields.
1323        return;
1324    }
1325
1326    // For each field, figure out if it's known to have "trivial" layout (i.e., is a 1-ZST), with
1327    // "known" respecting #[non_exhaustive] attributes.
1328    let field_infos = adt.all_fields().map(|field| {
1329        let ty = field.ty(tcx, GenericArgs::identity_for_item(tcx, field.did));
1330        let typing_env = ty::TypingEnv::non_body_analysis(tcx, field.did);
1331        let layout = tcx.layout_of(typing_env.as_query_input(ty));
1332        // We are currently checking the type this field came from, so it must be local
1333        let span = tcx.hir().span_if_local(field.did).unwrap();
1334        let trivial = layout.is_ok_and(|layout| layout.is_1zst());
1335        if !trivial {
1336            return (span, trivial, None);
1337        }
1338        // Even some 1-ZST fields are not allowed though, if they have `non_exhaustive`.
1339
1340        fn check_non_exhaustive<'tcx>(
1341            tcx: TyCtxt<'tcx>,
1342            t: Ty<'tcx>,
1343        ) -> ControlFlow<(&'static str, DefId, GenericArgsRef<'tcx>, bool)> {
1344            match t.kind() {
1345                ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)),
1346                ty::Array(ty, _) => check_non_exhaustive(tcx, *ty),
1347                ty::Adt(def, args) => {
1348                    if !def.did().is_local() && !tcx.has_attr(def.did(), sym::rustc_pub_transparent)
1349                    {
1350                        let non_exhaustive = def.is_variant_list_non_exhaustive()
1351                            || def
1352                                .variants()
1353                                .iter()
1354                                .any(ty::VariantDef::is_field_list_non_exhaustive);
1355                        let has_priv = def.all_fields().any(|f| !f.vis.is_public());
1356                        if non_exhaustive || has_priv {
1357                            return ControlFlow::Break((
1358                                def.descr(),
1359                                def.did(),
1360                                args,
1361                                non_exhaustive,
1362                            ));
1363                        }
1364                    }
1365                    def.all_fields()
1366                        .map(|field| field.ty(tcx, args))
1367                        .try_for_each(|t| check_non_exhaustive(tcx, t))
1368                }
1369                _ => ControlFlow::Continue(()),
1370            }
1371        }
1372
1373        (span, trivial, check_non_exhaustive(tcx, ty).break_value())
1374    });
1375
1376    let non_trivial_fields = field_infos
1377        .clone()
1378        .filter_map(|(span, trivial, _non_exhaustive)| if !trivial { Some(span) } else { None });
1379    let non_trivial_count = non_trivial_fields.clone().count();
1380    if non_trivial_count >= 2 {
1381        bad_non_zero_sized_fields(
1382            tcx,
1383            adt,
1384            non_trivial_count,
1385            non_trivial_fields,
1386            tcx.def_span(adt.did()),
1387        );
1388        return;
1389    }
1390    let mut prev_non_exhaustive_1zst = false;
1391    for (span, _trivial, non_exhaustive_1zst) in field_infos {
1392        if let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive_1zst {
1393            // If there are any non-trivial fields, then there can be no non-exhaustive 1-zsts.
1394            // Otherwise, it's only an issue if there's >1 non-exhaustive 1-zst.
1395            if non_trivial_count > 0 || prev_non_exhaustive_1zst {
1396                tcx.node_span_lint(
1397                    REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
1398                    tcx.local_def_id_to_hir_id(adt.did().expect_local()),
1399                    span,
1400                    |lint| {
1401                        lint.primary_message(
1402                            "zero-sized fields in `repr(transparent)` cannot \
1403                             contain external non-exhaustive types",
1404                        );
1405                        let note = if non_exhaustive {
1406                            "is marked with `#[non_exhaustive]`"
1407                        } else {
1408                            "contains private fields"
1409                        };
1410                        let field_ty = tcx.def_path_str_with_args(def_id, args);
1411                        lint.note(format!(
1412                            "this {descr} contains `{field_ty}`, which {note}, \
1413                                and makes it not a breaking change to become \
1414                                non-zero-sized in the future."
1415                        ));
1416                    },
1417                )
1418            } else {
1419                prev_non_exhaustive_1zst = true;
1420            }
1421        }
1422    }
1423}
1424
1425#[allow(trivial_numeric_casts)]
1426fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
1427    let def = tcx.adt_def(def_id);
1428    def.destructor(tcx); // force the destructor to be evaluated
1429
1430    if def.variants().is_empty() {
1431        if let Some(attr) = tcx.get_attrs(def_id, sym::repr).next() {
1432            struct_span_code_err!(
1433                tcx.dcx(),
1434                attr.span,
1435                E0084,
1436                "unsupported representation for zero-variant enum"
1437            )
1438            .with_span_label(tcx.def_span(def_id), "zero-variant enum")
1439            .emit();
1440        }
1441    }
1442
1443    let repr_type_ty = def.repr().discr_type().to_ty(tcx);
1444    if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 {
1445        if !tcx.features().repr128() {
1446            feature_err(
1447                &tcx.sess,
1448                sym::repr128,
1449                tcx.def_span(def_id),
1450                "repr with 128-bit type is unstable",
1451            )
1452            .emit();
1453        }
1454    }
1455
1456    for v in def.variants() {
1457        if let ty::VariantDiscr::Explicit(discr_def_id) = v.discr {
1458            tcx.ensure_ok().typeck(discr_def_id.expect_local());
1459        }
1460    }
1461
1462    if def.repr().int.is_none() {
1463        let is_unit = |var: &ty::VariantDef| matches!(var.ctor_kind(), Some(CtorKind::Const));
1464        let has_disr = |var: &ty::VariantDef| matches!(var.discr, ty::VariantDiscr::Explicit(_));
1465
1466        let has_non_units = def.variants().iter().any(|var| !is_unit(var));
1467        let disr_units = def.variants().iter().any(|var| is_unit(var) && has_disr(var));
1468        let disr_non_unit = def.variants().iter().any(|var| !is_unit(var) && has_disr(var));
1469
1470        if disr_non_unit || (disr_units && has_non_units) {
1471            struct_span_code_err!(
1472                tcx.dcx(),
1473                tcx.def_span(def_id),
1474                E0732,
1475                "`#[repr(inttype)]` must be specified"
1476            )
1477            .emit();
1478        }
1479    }
1480
1481    detect_discriminant_duplicate(tcx, def);
1482    check_transparent(tcx, def);
1483    check_unsafe_fields(tcx, def_id);
1484}
1485
1486/// Part of enum check. Given the discriminants of an enum, errors if two or more discriminants are equal
1487fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) {
1488    // Helper closure to reduce duplicate code. This gets called everytime we detect a duplicate.
1489    // Here `idx` refers to the order of which the discriminant appears, and its index in `vs`
1490    let report = |dis: Discr<'tcx>, idx, err: &mut Diag<'_>| {
1491        let var = adt.variant(idx); // HIR for the duplicate discriminant
1492        let (span, display_discr) = match var.discr {
1493            ty::VariantDiscr::Explicit(discr_def_id) => {
1494                // In the case the discriminant is both a duplicate and overflowed, let the user know
1495                if let hir::Node::AnonConst(expr) =
1496                    tcx.hir_node_by_def_id(discr_def_id.expect_local())
1497                    && let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind
1498                    && let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node
1499                    && *lit_value != dis.val
1500                {
1501                    (tcx.def_span(discr_def_id), format!("`{dis}` (overflowed from `{lit_value}`)"))
1502                } else {
1503                    // Otherwise, format the value as-is
1504                    (tcx.def_span(discr_def_id), format!("`{dis}`"))
1505                }
1506            }
1507            // This should not happen.
1508            ty::VariantDiscr::Relative(0) => (tcx.def_span(var.def_id), format!("`{dis}`")),
1509            ty::VariantDiscr::Relative(distance_to_explicit) => {
1510                // At this point we know this discriminant is a duplicate, and was not explicitly
1511                // assigned by the user. Here we iterate backwards to fetch the HIR for the last
1512                // explicitly assigned discriminant, and letting the user know that this was the
1513                // increment startpoint, and how many steps from there leading to the duplicate
1514                if let Some(explicit_idx) =
1515                    idx.as_u32().checked_sub(distance_to_explicit).map(VariantIdx::from_u32)
1516                {
1517                    let explicit_variant = adt.variant(explicit_idx);
1518                    let ve_ident = var.name;
1519                    let ex_ident = explicit_variant.name;
1520                    let sp = if distance_to_explicit > 1 { "variants" } else { "variant" };
1521
1522                    err.span_label(
1523                        tcx.def_span(explicit_variant.def_id),
1524                        format!(
1525                            "discriminant for `{ve_ident}` incremented from this startpoint \
1526                            (`{ex_ident}` + {distance_to_explicit} {sp} later \
1527                             => `{ve_ident}` = {dis})"
1528                        ),
1529                    );
1530                }
1531
1532                (tcx.def_span(var.def_id), format!("`{dis}`"))
1533            }
1534        };
1535
1536        err.span_label(span, format!("{display_discr} assigned here"));
1537    };
1538
1539    let mut discrs = adt.discriminants(tcx).collect::<Vec<_>>();
1540
1541    // Here we loop through the discriminants, comparing each discriminant to another.
1542    // When a duplicate is detected, we instantiate an error and point to both
1543    // initial and duplicate value. The duplicate discriminant is then discarded by swapping
1544    // it with the last element and decrementing the `vec.len` (which is why we have to evaluate
1545    // `discrs.len()` anew every iteration, and why this could be tricky to do in a functional
1546    // style as we are mutating `discrs` on the fly).
1547    let mut i = 0;
1548    while i < discrs.len() {
1549        let var_i_idx = discrs[i].0;
1550        let mut error: Option<Diag<'_, _>> = None;
1551
1552        let mut o = i + 1;
1553        while o < discrs.len() {
1554            let var_o_idx = discrs[o].0;
1555
1556            if discrs[i].1.val == discrs[o].1.val {
1557                let err = error.get_or_insert_with(|| {
1558                    let mut ret = struct_span_code_err!(
1559                        tcx.dcx(),
1560                        tcx.def_span(adt.did()),
1561                        E0081,
1562                        "discriminant value `{}` assigned more than once",
1563                        discrs[i].1,
1564                    );
1565
1566                    report(discrs[i].1, var_i_idx, &mut ret);
1567
1568                    ret
1569                });
1570
1571                report(discrs[o].1, var_o_idx, err);
1572
1573                // Safe to unwrap here, as we wouldn't reach this point if `discrs` was empty
1574                discrs[o] = *discrs.last().unwrap();
1575                discrs.pop();
1576            } else {
1577                o += 1;
1578            }
1579        }
1580
1581        if let Some(e) = error {
1582            e.emit();
1583        }
1584
1585        i += 1;
1586    }
1587}
1588
1589fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
1590    if tcx.type_alias_is_lazy(def_id) {
1591        // Since we compute the variances for lazy type aliases and already reject bivariant
1592        // parameters as unused, we can and should skip this check for lazy type aliases.
1593        return;
1594    }
1595
1596    let generics = tcx.generics_of(def_id);
1597    if generics.own_counts().types == 0 {
1598        return;
1599    }
1600
1601    let ty = tcx.type_of(def_id).instantiate_identity();
1602    if ty.references_error() {
1603        // If there is already another error, do not emit an error for not using a type parameter.
1604        return;
1605    }
1606
1607    // Lazily calculated because it is only needed in case of an error.
1608    let bounded_params = LazyCell::new(|| {
1609        tcx.explicit_predicates_of(def_id)
1610            .predicates
1611            .iter()
1612            .filter_map(|(predicate, span)| {
1613                let bounded_ty = match predicate.kind().skip_binder() {
1614                    ty::ClauseKind::Trait(pred) => pred.trait_ref.self_ty(),
1615                    ty::ClauseKind::TypeOutlives(pred) => pred.0,
1616                    _ => return None,
1617                };
1618                if let ty::Param(param) = bounded_ty.kind() {
1619                    Some((param.index, span))
1620                } else {
1621                    None
1622                }
1623            })
1624            // FIXME: This assumes that elaborated `Sized` bounds come first (which does hold at the
1625            // time of writing). This is a bit fragile since we later use the span to detect elaborated
1626            // `Sized` bounds. If they came last for example, this would break `Trait + /*elab*/Sized`
1627            // since it would overwrite the span of the user-written bound. This could be fixed by
1628            // folding the spans with `Span::to` which requires a bit of effort I think.
1629            .collect::<FxIndexMap<_, _>>()
1630    });
1631
1632    let mut params_used = DenseBitSet::new_empty(generics.own_params.len());
1633    for leaf in ty.walk() {
1634        if let GenericArgKind::Type(leaf_ty) = leaf.unpack()
1635            && let ty::Param(param) = leaf_ty.kind()
1636        {
1637            debug!("found use of ty param {:?}", param);
1638            params_used.insert(param.index);
1639        }
1640    }
1641
1642    for param in &generics.own_params {
1643        if !params_used.contains(param.index)
1644            && let ty::GenericParamDefKind::Type { .. } = param.kind
1645        {
1646            let span = tcx.def_span(param.def_id);
1647            let param_name = Ident::new(param.name, span);
1648
1649            // The corresponding predicates are post-`Sized`-elaboration. Therefore we
1650            // * check for emptiness to detect lone user-written `?Sized` bounds
1651            // * compare the param span to the pred span to detect lone user-written `Sized` bounds
1652            let has_explicit_bounds = bounded_params.is_empty()
1653                || (*bounded_params).get(&param.index).is_some_and(|&&pred_sp| pred_sp != span);
1654            let const_param_help = !has_explicit_bounds;
1655
1656            let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter {
1657                span,
1658                param_name,
1659                param_def_kind: tcx.def_descr(param.def_id),
1660                help: errors::UnusedGenericParameterHelp::TyAlias { param_name },
1661                usage_spans: vec![],
1662                const_param_help,
1663            });
1664            diag.code(E0091);
1665            diag.emit();
1666        }
1667    }
1668}
1669
1670/// Emit an error for recursive opaque types.
1671///
1672/// If this is a return `impl Trait`, find the item's return expressions and point at them. For
1673/// direct recursion this is enough, but for indirect recursion also point at the last intermediary
1674/// `impl Trait`.
1675///
1676/// If all the return expressions evaluate to `!`, then we explain that the error will go away
1677/// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
1678fn opaque_type_cycle_error(tcx: TyCtxt<'_>, opaque_def_id: LocalDefId) -> ErrorGuaranteed {
1679    let span = tcx.def_span(opaque_def_id);
1680    let mut err = struct_span_code_err!(tcx.dcx(), span, E0720, "cannot resolve opaque type");
1681
1682    let mut label = false;
1683    if let Some((def_id, visitor)) = get_owner_return_paths(tcx, opaque_def_id) {
1684        let typeck_results = tcx.typeck(def_id);
1685        if visitor
1686            .returns
1687            .iter()
1688            .filter_map(|expr| typeck_results.node_type_opt(expr.hir_id))
1689            .all(|ty| matches!(ty.kind(), ty::Never))
1690        {
1691            let spans = visitor
1692                .returns
1693                .iter()
1694                .filter(|expr| typeck_results.node_type_opt(expr.hir_id).is_some())
1695                .map(|expr| expr.span)
1696                .collect::<Vec<Span>>();
1697            let span_len = spans.len();
1698            if span_len == 1 {
1699                err.span_label(spans[0], "this returned value is of `!` type");
1700            } else {
1701                let mut multispan: MultiSpan = spans.clone().into();
1702                for span in spans {
1703                    multispan.push_span_label(span, "this returned value is of `!` type");
1704                }
1705                err.span_note(multispan, "these returned values have a concrete \"never\" type");
1706            }
1707            err.help("this error will resolve once the item's body returns a concrete type");
1708        } else {
1709            let mut seen = FxHashSet::default();
1710            seen.insert(span);
1711            err.span_label(span, "recursive opaque type");
1712            label = true;
1713            for (sp, ty) in visitor
1714                .returns
1715                .iter()
1716                .filter_map(|e| typeck_results.node_type_opt(e.hir_id).map(|t| (e.span, t)))
1717                .filter(|(_, ty)| !matches!(ty.kind(), ty::Never))
1718            {
1719                #[derive(Default)]
1720                struct OpaqueTypeCollector {
1721                    opaques: Vec<DefId>,
1722                    closures: Vec<DefId>,
1723                }
1724                impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector {
1725                    fn visit_ty(&mut self, t: Ty<'tcx>) {
1726                        match *t.kind() {
1727                            ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
1728                                self.opaques.push(def);
1729                            }
1730                            ty::Closure(def_id, ..) | ty::Coroutine(def_id, ..) => {
1731                                self.closures.push(def_id);
1732                                t.super_visit_with(self);
1733                            }
1734                            _ => t.super_visit_with(self),
1735                        }
1736                    }
1737                }
1738
1739                let mut visitor = OpaqueTypeCollector::default();
1740                ty.visit_with(&mut visitor);
1741                for def_id in visitor.opaques {
1742                    let ty_span = tcx.def_span(def_id);
1743                    if !seen.contains(&ty_span) {
1744                        let descr = if ty.is_impl_trait() { "opaque " } else { "" };
1745                        err.span_label(ty_span, format!("returning this {descr}type `{ty}`"));
1746                        seen.insert(ty_span);
1747                    }
1748                    err.span_label(sp, format!("returning here with type `{ty}`"));
1749                }
1750
1751                for closure_def_id in visitor.closures {
1752                    let Some(closure_local_did) = closure_def_id.as_local() else {
1753                        continue;
1754                    };
1755                    let typeck_results = tcx.typeck(closure_local_did);
1756
1757                    let mut label_match = |ty: Ty<'_>, span| {
1758                        for arg in ty.walk() {
1759                            if let ty::GenericArgKind::Type(ty) = arg.unpack()
1760                                && let ty::Alias(
1761                                    ty::Opaque,
1762                                    ty::AliasTy { def_id: captured_def_id, .. },
1763                                ) = *ty.kind()
1764                                && captured_def_id == opaque_def_id.to_def_id()
1765                            {
1766                                err.span_label(
1767                                    span,
1768                                    format!(
1769                                        "{} captures itself here",
1770                                        tcx.def_descr(closure_def_id)
1771                                    ),
1772                                );
1773                            }
1774                        }
1775                    };
1776
1777                    // Label any closure upvars that capture the opaque
1778                    for capture in typeck_results.closure_min_captures_flattened(closure_local_did)
1779                    {
1780                        label_match(capture.place.ty(), capture.get_path_span(tcx));
1781                    }
1782                    // Label any coroutine locals that capture the opaque
1783                    if tcx.is_coroutine(closure_def_id)
1784                        && let Some(coroutine_layout) = tcx.mir_coroutine_witnesses(closure_def_id)
1785                    {
1786                        for interior_ty in &coroutine_layout.field_tys {
1787                            label_match(interior_ty.ty, interior_ty.source_info.span);
1788                        }
1789                    }
1790                }
1791            }
1792        }
1793    }
1794    if !label {
1795        err.span_label(span, "cannot resolve opaque type");
1796    }
1797    err.emit()
1798}
1799
1800pub(super) fn check_coroutine_obligations(
1801    tcx: TyCtxt<'_>,
1802    def_id: LocalDefId,
1803) -> Result<(), ErrorGuaranteed> {
1804    debug_assert!(!tcx.is_typeck_child(def_id.to_def_id()));
1805
1806    let typeck_results = tcx.typeck(def_id);
1807    let param_env = tcx.param_env(def_id);
1808
1809    debug!(?typeck_results.coroutine_stalled_predicates);
1810
1811    let mode = if tcx.next_trait_solver_globally() {
1812        TypingMode::post_borrowck_analysis(tcx, def_id)
1813    } else {
1814        TypingMode::analysis_in_body(tcx, def_id)
1815    };
1816
1817    let infcx = tcx
1818        .infer_ctxt()
1819        // typeck writeback gives us predicates with their regions erased.
1820        // As borrowck already has checked lifetimes, we do not need to do it again.
1821        .ignoring_regions()
1822        .build(mode);
1823
1824    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
1825    for (predicate, cause) in &typeck_results.coroutine_stalled_predicates {
1826        ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, *predicate));
1827    }
1828
1829    let errors = ocx.select_all_or_error();
1830    debug!(?errors);
1831    if !errors.is_empty() {
1832        return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
1833    }
1834
1835    if !tcx.next_trait_solver_globally() {
1836        // Check that any hidden types found when checking these stalled coroutine obligations
1837        // are valid.
1838        for (key, ty) in infcx.take_opaque_types() {
1839            let hidden_type = infcx.resolve_vars_if_possible(ty);
1840            let key = infcx.resolve_vars_if_possible(key);
1841            sanity_check_found_hidden_type(tcx, key, hidden_type)?;
1842        }
1843    }
1844
1845    Ok(())
1846}