Skip to main content

rustc_trait_selection/error_reporting/
mod.rs

1use std::ops::Deref;
2
3use rustc_errors::DiagCtxtHandle;
4use rustc_infer::infer::InferCtxt;
5use rustc_infer::traits::PredicateObligations;
6use rustc_macros::extension;
7use rustc_middle::bug;
8use rustc_middle::ty::{self, Ty};
9
10pub mod infer;
11pub mod traits;
12
13/// A helper for building type related errors. The `typeck_results`
14/// field is only populated during an in-progress typeck.
15/// Get an instance by calling `InferCtxt::err_ctxt` or `FnCtxt::err_ctxt`.
16///
17/// You must only create this if you intend to actually emit an error (or
18/// perhaps a warning, though preferably not.) It provides a lot of utility
19/// methods which should not be used during the happy path.
20pub struct TypeErrCtxt<'a, 'tcx> {
21    pub infcx: &'a InferCtxt<'tcx>,
22    pub param_env: Option<ty::ParamEnv<'tcx>>,
23
24    pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
25    pub diverging_fallback_has_occurred: bool,
26
27    pub autoderef_steps: Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, PredicateObligations<'tcx>)> + 'a>,
28    pub infer_closure_kind: Box<
29        dyn Fn(
30                rustc_hir::def_id::LocalDefId,
31            ) -> Option<(
32                ty::ClosureKind,
33                Option<(rustc_span::Span, rustc_middle::hir::place::Place<'tcx>)>,
34            )> + 'a,
35    >,
36}
37
38pub trait InferCtxtErrorExt<'tcx> {
    #[doc = " Creates a `TypeErrCtxt` for emitting various inference errors."]
    #[doc = " During typeck, use `FnCtxt::err_ctxt` instead."]
    fn err_ctxt(&self)
    -> TypeErrCtxt<'_, 'tcx>;
}
impl<'tcx> InferCtxtErrorExt<'tcx> for InferCtxt<'tcx> {
    #[doc = " Creates a `TypeErrCtxt` for emitting various inference errors."]
    #[doc = " During typeck, use `FnCtxt::err_ctxt` instead."]
    fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
        TypeErrCtxt {
            infcx: self,
            param_env: None,
            typeck_results: None,
            diverging_fallback_has_occurred: false,
            autoderef_steps: Box::new(|ty|
                    {
                        if true {
                            if !false {
                                {
                                    ::core::panicking::panic_fmt(format_args!("shouldn\'t be using autoderef_steps outside of typeck"));
                                }
                            };
                        };
                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                [(ty, PredicateObligations::new())]))
                    }),
            infer_closure_kind: Box::new(|_| None),
        }
    }
}#[extension(pub trait InferCtxtErrorExt<'tcx>)]
39impl<'tcx> InferCtxt<'tcx> {
40    /// Creates a `TypeErrCtxt` for emitting various inference errors.
41    /// During typeck, use `FnCtxt::err_ctxt` instead.
42    fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
43        TypeErrCtxt {
44            infcx: self,
45            param_env: None,
46            typeck_results: None,
47            diverging_fallback_has_occurred: false,
48            autoderef_steps: Box::new(|ty| {
49                debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck");
50                vec![(ty, PredicateObligations::new())]
51            }),
52            infer_closure_kind: Box::new(|_| None),
53        }
54    }
55}
56
57impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
58    pub fn dcx(&self) -> DiagCtxtHandle<'a> {
59        self.infcx.dcx()
60    }
61
62    /// This is just to avoid a potential footgun of accidentally
63    /// dropping `typeck_results` by calling `InferCtxt::err_ctxt`
64    #[deprecated(note = "you already have a `TypeErrCtxt`")]
65    #[allow(unused)]
66    pub fn err_ctxt(&self) -> ! {
67        ::rustc_middle::util::bug::bug_fmt(format_args!("called `err_ctxt` on `TypeErrCtxt`. Try removing the call"));bug!("called `err_ctxt` on `TypeErrCtxt`. Try removing the call");
68    }
69}
70
71impl<'tcx> Deref for TypeErrCtxt<'_, 'tcx> {
72    type Target = InferCtxt<'tcx>;
73    fn deref(&self) -> &InferCtxt<'tcx> {
74        self.infcx
75    }
76}