rapx/analysis/core/api_dependency/
extract.rs1extern 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 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!("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}