1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use crate::hir;
use crate::hir::destruc;
use crate::ty;
use crate::ty::list_iter::ListIterator;
use crate::ty::Ty;
pub fn type_for_decl_list_destruc(
list: &destruc::List<hir::Lowered>,
mut guide_type_iter: Option<ListIterator<'_, ty::Poly>>,
) -> ty::List<ty::Poly> {
let fixed_polys = list
.fixed()
.iter()
.map(|fixed_destruc| {
let guide_type = if let Some(guide_type_iter) = guide_type_iter.as_mut() {
guide_type_iter.next()
} else {
None
};
type_for_decl_destruc(fixed_destruc, guide_type)
})
.collect();
let rest_poly = match list.rest() {
Some(rest) => match rest.ty() {
hir::DeclTy::Known(poly) => poly.clone(),
hir::DeclTy::Free => guide_type_iter
.map(ListIterator::collect_rest)
.unwrap_or_else(|| Ty::Any.into()),
},
None => Ty::never().into(),
};
ty::List::new(fixed_polys, rest_poly)
}
pub fn type_for_decl_destruc(
destruc: &destruc::Destruc<hir::Lowered>,
guide_type: Option<&ty::Ref<ty::Poly>>,
) -> ty::Ref<ty::Poly> {
match destruc {
destruc::Destruc::Scalar(_, scalar) => match scalar.ty() {
hir::DeclTy::Known(poly) => poly.clone(),
hir::DeclTy::Free => guide_type.cloned().unwrap_or_else(|| Ty::Any.into()),
},
destruc::Destruc::List(_, list) => {
let guide_type_iter =
guide_type.and_then(|guide_type| ListIterator::try_new_from_ty_ref(guide_type));
type_for_decl_list_destruc(list, guide_type_iter).into()
}
}
}
fn visit_scalar_locals<F>(scalar: &destruc::Scalar<hir::Lowered>, visitor: &mut F)
where
F: FnMut(hir::LocalId, &hir::DeclTy),
{
if let Some(local_id) = scalar.local_id() {
visitor(*local_id, scalar.ty());
}
}
pub fn visit_locals<F>(
destruc: &destruc::Destruc<hir::Lowered>,
visitor: &mut F,
) -> Option<hir::LocalId>
where
F: FnMut(hir::LocalId, &hir::DeclTy),
{
match destruc {
destruc::Destruc::Scalar(_, ref scalar) => {
visit_scalar_locals(scalar, visitor);
*scalar.local_id()
}
destruc::Destruc::List(_, ref list) => {
for fixed in list.fixed() {
visit_locals(fixed, visitor);
}
if let Some(rest) = list.rest() {
visit_scalar_locals(rest, visitor);
}
None
}
}
}