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, ConstraintKind};
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<'tcx>(tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>) -> String {
48    region.get_name_or_anon(tcx).to_string()
49}
50
51fn constraint_str<'tcx>(constraint: Constraint<'tcx>, tcx: TyCtxt<'tcx>) -> String {
52    let (a, b) = match constraint.kind {
53        ConstraintKind::VarSubVar => (
54            region_vid_str(constraint.sub.as_var()),
55            region_vid_str(constraint.sup.as_var()),
56        ),
57        ConstraintKind::RegSubVar => (
58            region_str(tcx, constraint.sub),
59            region_vid_str(constraint.sup.as_var()),
60        ),
61        ConstraintKind::VarSubReg => (
62            region_vid_str(constraint.sub.as_var()),
63            region_str(tcx, constraint.sup),
64        ),
65        ConstraintKind::RegSubReg => (
66            region_str(tcx, constraint.sub),
67            region_str(tcx, constraint.sup),
68        ),
69    };
70    format!("{} <= {}", a, b)
71}
72
73pub fn extract_constraints(fn_did: DefId, tcx: TyCtxt<'_>) {
74    let early_fn_sig = tcx.fn_sig(fn_did);
75    let span = tcx.def_span(fn_did);
76    let binder_fn_sig = early_fn_sig.instantiate_identity();
77
78    let param_env = tcx.param_env(fn_did);
79    rap_debug!("param_env: {param_env:?}");
80
81    // obtain subtyping contraints
82    let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
83    let mut folder = FreeVarFolder::new(tcx, &infcx, span);
84    let fn_sig = tcx.liberate_late_bound_regions(fn_did, binder_fn_sig);
85    let binder_with_free_vars = fn_sig.fold_with(&mut folder);
86
87    let res = infcx
88        .at(&ObligationCause::dummy(), param_env)
89        .sub(infer::DefineOpaqueTypes::Yes, fn_sig, binder_with_free_vars)
90        .unwrap();
91    res.obligations.into_iter().for_each(|obligation| {
92        rap_debug!("obligation: {obligation:?}");
93    });
94
95    // rap_debug!("binder: {binder_with_vars:?}");
96    rap_debug!("free binder: {binder_with_free_vars:?}");
97    let region_constraint_data = infcx.take_and_reset_region_constraints();
98    for (constraint, _origin) in region_constraint_data.constraints {
99        rap_debug!("constraint: {}", constraint_str(constraint, tcx));
100    }
101}