dyon/lifetime/typecheck/
refine.rs1use super::*;
2use crate::Dfn;
3
4use std::sync::Arc;
5
6fn report(
7 i: usize,
8 found: bool,
9 ambiguous: bool,
10 count: usize,
11 nodes: &[Node],
12 todo: &mut Vec<usize>,
13) -> Result<(), Range<String>> {
14 if !found {
15 if ambiguous {
16 todo.push(i);
18 } else if count > 0 {
19 use std::io::Write;
20
21 let mut buf: Vec<u8> = vec![];
22 write!(&mut buf, "Type mismatch (#230):\nThe argument type `").unwrap();
23 for (i, arg) in nodes[i]
24 .children
25 .iter()
26 .filter(|&&arg| nodes[arg].kind == Kind::CallArg && !nodes[arg].children.is_empty())
27 .map(|&arg| nodes[arg].children[0])
28 .enumerate()
29 {
30 if let Some(ref arg_ty) = nodes[arg].ty {
31 if i != 0 {
32 write!(&mut buf, ", ").unwrap()
33 };
34 write!(&mut buf, "{}", arg_ty.description()).unwrap();
35 }
36 }
37 write!(
38 &mut buf,
39 "` does not work with `{}`",
40 nodes[i].name().expect("Expected name")
41 )
42 .unwrap();
43 return Err(nodes[i].source.wrap(String::from_utf8(buf).unwrap()));
44 }
45 }
46 Ok(())
47}
48
49pub(crate) fn declaration(
50 i: usize,
51 decl: usize,
52 nodes: &[Node],
53 todo: &mut Vec<usize>,
54 this_ty: &mut Option<Type>,
55) -> Result<(), Range<String>> {
56 let mut found = false;
58 let mut ambiguous = false;
59 let mut count = 0;
60 'outer: for &ty in nodes[decl]
61 .children
62 .iter()
63 .filter(|&&ty| nodes[ty].kind == Kind::Ty)
64 {
65 count += 1;
66 let mut all = true;
67 let mut ty_vars: Vec<Option<Arc<String>>> = vec![None; nodes[ty].names.len()];
68 for (arg_expr, &ty_arg) in nodes[i]
69 .children
70 .iter()
71 .filter(|&&arg| nodes[arg].kind == Kind::CallArg && !nodes[arg].children.is_empty())
72 .map(|&arg| nodes[arg].children[0])
73 .zip(
74 nodes[ty]
75 .children
76 .iter()
77 .filter(|&&ty_arg| nodes[ty_arg].kind == Kind::TyArg),
78 )
79 {
80 if nodes[arg_expr].ty.is_none() {
81 ambiguous = true;
82 break 'outer;
83 }
84 let found_arg =
85 if let (&Some(ref a), &Some(ref b)) = (&nodes[arg_expr].ty, &nodes[ty_arg].ty) {
86 let b = b
87 .bind_ty_vars(a, &nodes[ty].names, &mut ty_vars)
88 .map_err(|err| nodes[arg_expr].source.wrap(err))?;
89 if b.goes_with(a) {
90 if b.ambiguous(a) {
91 ambiguous = true;
92 break 'outer;
93 }
94 true
95 } else {
96 false
97 }
98 } else {
99 false
100 };
101 if !found_arg {
102 all = false;
103 break;
104 }
105 }
106 if all {
107 if let Some(&ind) = nodes[ty]
108 .children
109 .iter()
110 .find(|&&ty| nodes[ty].kind == Kind::TyRet)
111 {
112 let mut new_ty = nodes[ind].ty.clone();
113 if let Some(ref mut new_ty) = new_ty {
114 for i in 0..nodes[ty].names.len() {
115 if let Some(ref val) = ty_vars[i] {
116 new_ty.insert_var(&nodes[ty].names[i], val);
117 } else {
118 new_ty.insert_none_var(&nodes[ty].names[i]);
119 }
120 }
121 }
122 *this_ty = new_ty;
123 found = true;
124 break;
125 }
126 }
127 }
128
129 report(i, found, ambiguous, count, nodes, todo)
130}
131
132pub(crate) fn prelude(
133 i: usize,
134 f: &Dfn,
135 nodes: &[Node],
136 todo: &mut Vec<usize>,
137 this_ty: &mut Option<Type>,
138) -> Result<(), Range<String>> {
139 let mut found = false;
141 let mut ambiguous = false;
142 'outer: for ty in &f.ext {
143 let mut all = true;
144 let mut ty_vars: Vec<Option<Arc<String>>> = vec![None; ty.0.len()];
145 for (arg_expr, ty_arg) in nodes[i]
146 .children
147 .iter()
148 .filter(|&&arg| nodes[arg].kind == Kind::CallArg && !nodes[arg].children.is_empty())
149 .map(|&arg| nodes[arg].children[0])
150 .zip(ty.1.iter())
151 {
152 if nodes[arg_expr].ty.is_none() {
153 ambiguous = true;
154 break 'outer;
155 }
156 let found_arg = if let Some(ref a) = nodes[arg_expr].ty {
157 let ty_arg = ty_arg
158 .bind_ty_vars(a, &ty.0, &mut ty_vars)
159 .map_err(|err| nodes[arg_expr].source.wrap(err))?;
160 if ty_arg.goes_with(a) {
161 if ty_arg.ambiguous(a) {
162 ambiguous = true;
163 break 'outer;
164 }
165 true
166 } else {
167 false
168 }
169 } else {
170 false
171 };
172 if !found_arg {
173 all = false;
174 break;
175 }
176 }
177 if all {
178 let mut new_ty = ty.2.clone();
179 for i in 0..ty.0.len() {
180 if let Some(ref val) = ty_vars[i] {
181 new_ty.insert_var(&ty.0[i], val);
182 } else {
183 new_ty.insert_none_var(&ty.0[i]);
184 }
185 }
186
187 *this_ty = Some(new_ty);
188 found = true;
189 break;
190 }
191 }
192
193 report(i, found, ambiguous, f.ext.len(), nodes, todo)
194}