rapx/analysis/core/api_dependency/
extract.rs

1extern crate rustc_infer;
2use crate::rap_debug;
3use rustc_hir::def_id::DefId;
4use rustc_infer::infer::region_constraints::Constraint;
5use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
6use rustc_infer::traits::ObligationCause;
7use rustc_middle::ty::{self, TyCtxt, TypeFoldable, TypingMode};
8
9use rustc_span::Span;
10struct FreeVarFolder<'tcx, 'a> {
11    cx: TyCtxt<'tcx>,
12    free_var_cnt: usize,
13    infcx: &'a InferCtxt<'tcx>,
14    span: Span,
15}
16
17impl<'tcx, 'a> FreeVarFolder<'tcx, 'a> {
18    pub fn new(
19        cx: TyCtxt<'tcx>,
20        infcx: &'a InferCtxt<'tcx>,
21        span: Span,
22    ) -> FreeVarFolder<'tcx, 'a> {
23        FreeVarFolder {
24            cx,
25            free_var_cnt: 0,
26            infcx,
27            span,
28        }
29    }
30}
31
32impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for FreeVarFolder<'tcx, '_> {
33    fn cx(&self) -> TyCtxt<'tcx> {
34        self.cx
35    }
36    fn fold_region(&mut self, _: ty::Region<'tcx>) -> ty::Region<'tcx> {
37        self.free_var_cnt += 1;
38        self.infcx
39            .next_region_var(infer::RegionVariableOrigin::BorrowRegion(self.span))
40    }
41}
42
43fn region_vid_str(vid: ty::RegionVid) -> String {
44    format!("{:?}", vid)
45}
46
47fn region_str(region: ty::Region<'_>) -> String {
48    region.get_name_or_anon().to_string()
49}
50
51fn constraint_str<'tcx>(constraint: Constraint<'tcx>, _tcx: TyCtxt<'tcx>) -> String {
52    let (a, b) = match constraint {
53        Constraint::VarSubVar(a, b) => (region_vid_str(a), region_vid_str(b)),
54        Constraint::RegSubVar(a, b) => (region_str(a), region_vid_str(b)),
55        Constraint::VarSubReg(a, b) => (region_vid_str(a), region_str(b)),
56        Constraint::RegSubReg(a, b) => (region_str(a), region_str(b)),
57    };
58    format!("{} <= {}", a, b)
59}
60
61pub fn extract_constraints(fn_did: DefId, tcx: TyCtxt<'_>) {
62    let early_fn_sig = tcx.fn_sig(fn_did);
63    let span = tcx.def_span(fn_did);
64    let binder_fn_sig = early_fn_sig.instantiate_identity();
65
66    let param_env = tcx.param_env(fn_did);
67    rap_debug!("param_env: {param_env:?}");
68
69    // obtain subtyping contraints
70    let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
71    let mut folder = FreeVarFolder::new(tcx, &infcx, span);
72    let fn_sig = tcx.liberate_late_bound_regions(fn_did, binder_fn_sig);
73    let binder_with_free_vars = fn_sig.fold_with(&mut folder);
74
75    let res = infcx
76        .at(&ObligationCause::dummy(), param_env)
77        .sub(infer::DefineOpaqueTypes::Yes, fn_sig, binder_with_free_vars)
78        .unwrap();
79    res.obligations.into_iter().for_each(|obligation| {
80        rap_debug!("obligation: {obligation:?}");
81    });
82
83    // rap_debug!("binder: {binder_with_vars:?}");
84    rap_debug!("free binder: {binder_with_free_vars:?}");
85    let region_constraint_data = infcx.take_and_reset_region_constraints();
86    for (constraint, _origin) in region_constraint_data.constraints {
87        rap_debug!("constraint: {}", constraint_str(constraint, tcx));
88    }
89}