1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 # Standalone Tests for the Inference Module
15 Note: This module is only compiled when doing unit testing.
19 use driver::diagnostic;
20 use driver::driver::{optgroups, build_session_options, build_session};
21 use driver::driver::{str_input, build_configuration};
22 use middle::lang_items::{LanguageItems, language_items};
23 use middle::ty::{FnTyBase, FnMeta, FnSig};
24 use util::ppaux::ty_to_str;
26 use extra::oldmap::HashMap;
27 use getopts::{optopt, optmulti, optflag, optflagopt, getopts};
28 use getopts::opt_present;
29 use syntax::codemap::DUMMY_SP;
30 use syntax::parse::parse_crate_from_source_str;
31 use syntax::{ast, attr, parse};
36 infcx: infer::infer_ctxt,
37 err_messages: @DVec<String>
45 static EMPTY_SOURCE_STR: &str = "/* Hello, world! */";
47 fn setup_env(test_name: &str, source_string: &str) -> Env {
48 let messages = @DVec();
49 let matches = getopts(vec!("-Z".to_string(), "verbose".to_string()), optgroups()).get();
50 let diag = diagnostic::collect(messages);
51 let sessopts = build_session_options("rustc".to_string(), &matches, diag);
52 let sess = build_session(sessopts, None, diag);
53 let cfg = build_configuration(sess, "whatever".to_string(), str_input("".to_string()));
56 let freevars = HashMap();
57 let region_paramd_items = HashMap();
58 let region_map = HashMap();
59 let lang_items = LanguageItems::new();
61 let parse_sess = parse::new_parse_sess(None);
62 let krate = parse_crate_from_source_str(
63 test_name.to_str(), @source_string.to_str(),
66 let tcx = ty::mk_ctxt(sess, dm, amap, freevars, region_map,
67 region_paramd_items, lang_items);
69 let infcx = infer::new_infer_ctxt(tcx);
71 return Env {krate: krate,
74 err_messages: messages};
78 pub fn create_region_hierarchy(&self, rh: &RH) {
79 for child_rh in rh.sub.iter() {
80 self.create_region_hierarchy(child_rh);
81 self.tcx.region_map.insert(child_rh.id, rh.id);
85 pub fn create_simple_region_hierarchy(&self) {
86 // creates a region hierarchy where 1 is root, 10 and 11 are
88 self.create_region_hierarchy(
96 pub fn lookup_item(&self, names: &[String]) -> ast::node_id {
97 return match search_mod(self, &self.krate.node.module, 0, names) {
100 fail!("no item found: `%s`", names.connect("::"));
104 fn search_mod(self: &Env,
107 names: &[String]) -> Option<ast::node_id> {
108 assert!(idx < names.len());
109 for item in m.items.iter() {
110 if self.tcx.sess.str_of(item.ident) == names[idx] {
111 return search(self, *item, idx+1, names);
117 fn search(self: &Env,
120 names: &[String]) -> Option<ast::node_id> {
121 if idx == names.len() {
125 return match it.node {
126 ast::ItemConst(..) | ast::ItemFn(..) |
127 ast::ItemForeignMod(..) | ast::ItemTy(..) => {
131 ast::ItemEnum(..) | ast::ItemStruct(..) |
132 ast::ItemTrait(..) | ast::ItemImpl(..) |
133 ast::ItemMac(..) => {
137 ast::ItemMod(ref m) => {
138 search_mod(self, m, idx, names)
144 pub fn is_subtype(&self, a: ty::t, b: ty::t) -> bool {
145 match infer::can_mk_subty(self.infcx, a, b) {
151 pub fn assert_subtype(&self, a: ty::t, b: ty::t) {
152 if !self.is_subtype(a, b) {
153 fail!("%s is not a subtype of %s, but it should be",
159 pub fn assert_not_subtype(&self, a: ty::t, b: ty::t) {
160 if self.is_subtype(a, b) {
161 fail!("%s is a subtype of %s, but it shouldn't be",
167 pub fn assert_strict_subtype(&self, a: ty::t, b: ty::t) {
168 self.assert_subtype(a, b);
169 self.assert_not_subtype(b, a);
172 pub fn assert_eq(&self, a: ty::t, b: ty::t) {
173 self.assert_subtype(a, b);
174 self.assert_subtype(b, a);
177 pub fn ty_to_str(&self, a: ty::t) -> String {
178 ty_to_str(self.tcx, a)
181 pub fn t_fn(&self, input_tys: &[ty::t], output_ty: ty::t) -> ty::t {
182 let inputs = input_tys.map(|t| {mode: ast::expl(ast::by_copy),
184 ty::mk_fn(self.tcx, FnTyBase {
185 meta: FnMeta {fn_style: ast::NormalFn,
186 proto: ast::ProtoBare,
188 region: ty::ReStatic,
189 bounds: @Vec::new()},
198 pub fn t_int(&self) -> ty::t {
202 pub fn t_rptr_bound(&self, id: uint) -> ty::t {
203 ty::mk_imm_rptr(self.tcx, ty::re_bound(ty::BrAnon(id)), self.t_int())
206 pub fn t_rptr_scope(&self, id: ast::node_id) -> ty::t {
207 ty::mk_imm_rptr(self.tcx, ty::ReScope(id), self.t_int())
210 pub fn t_rptr_free(&self, nid: ast::node_id, id: uint) -> ty::t {
211 ty::mk_imm_rptr(self.tcx,
212 ty::ReFree(ty::FreeRegion {scope_id: nid,
213 bound_region: ty::BrAnon(id)}),
217 pub fn t_rptr_static(&self) -> ty::t {
218 ty::mk_imm_rptr(self.tcx, ty::ReStatic, self.t_int())
221 pub fn lub() -> Lub { Lub(self.infcx.combine_fields(true, DUMMY_SP)) }
223 pub fn glb() -> Glb { Glb(self.infcx.combine_fields(true, DUMMY_SP)) }
225 pub fn resolve_regions(exp_count: uint) {
226 debug!("resolve_regions(%u)", exp_count);
228 self.infcx.resolve_regions();
229 if self.err_messages.len() != exp_count {
230 for msg in self.err_messages.iter() {
231 debug!("Error encountered: %s", *msg);
233 format!("resolving regions encountered %u errors but expected %u!",
234 self.err_messages.len(),
239 /// Checks that `LUB(t1,t2) == t_lub`
240 pub fn check_lub(&self, t1: ty::t, t2: ty::t, t_lub: ty::t) {
241 match self.lub().tys(t1, t2) {
243 fail!("unexpected error computing LUB: %?", e)
246 self.assert_eq(t, t_lub);
248 // sanity check for good measure:
249 self.assert_subtype(t1, t);
250 self.assert_subtype(t2, t);
252 self.resolve_regions(0);
257 /// Checks that `GLB(t1,t2) == t_glb`
258 pub fn check_glb(&self, t1: ty::t, t2: ty::t, t_glb: ty::t) {
259 debug!("check_glb(t1=%s, t2=%s, t_glb=%s)",
262 self.ty_to_str(t_glb));
263 match self.glb().tys(t1, t2) {
265 fail!("unexpected error computing LUB: %?", e)
268 self.assert_eq(t, t_glb);
270 // sanity check for good measure:
271 self.assert_subtype(t, t1);
272 self.assert_subtype(t, t2);
274 self.resolve_regions(0);
279 /// Checks that `LUB(t1,t2)` is undefined
280 pub fn check_no_lub(&self, t1: ty::t, t2: ty::t) {
281 match self.lub().tys(t1, t2) {
284 fail!("unexpected success computing LUB: %?", self.ty_to_str(t))
289 /// Checks that `GLB(t1,t2)` is undefined
290 pub fn check_no_glb(&self, t1: ty::t, t2: ty::t) {
291 match self.glb().tys(t1, t2) {
294 fail!("unexpected success computing GLB: %?", self.ty_to_str(t))
301 fn contravariant_region_ptr() {
302 let env = setup_env("contravariant_region_ptr", EMPTY_SOURCE_STR);
303 env.create_simple_region_hierarchy();
304 let t_rptr1 = env.t_rptr_scope(1);
305 let t_rptr10 = env.t_rptr_scope(10);
306 env.assert_eq(t_rptr1, t_rptr1);
307 env.assert_eq(t_rptr10, t_rptr10);
308 env.assert_strict_subtype(t_rptr1, t_rptr10);
312 fn lub_bound_bound() {
313 let env = setup_env("lub_bound_bound", EMPTY_SOURCE_STR);
314 let t_rptr_bound1 = env.t_rptr_bound(1);
315 let t_rptr_bound2 = env.t_rptr_bound(2);
316 env.check_lub(env.t_fn([t_rptr_bound1], env.t_int()),
317 env.t_fn([t_rptr_bound2], env.t_int()),
318 env.t_fn([t_rptr_bound1], env.t_int()));
322 fn lub_bound_free() {
323 let env = setup_env("lub_bound_free", EMPTY_SOURCE_STR);
324 let t_rptr_bound1 = env.t_rptr_bound(1);
325 let t_rptr_free1 = env.t_rptr_free(0, 1);
326 env.check_lub(env.t_fn([t_rptr_bound1], env.t_int()),
327 env.t_fn([t_rptr_free1], env.t_int()),
328 env.t_fn([t_rptr_free1], env.t_int()));
332 fn lub_bound_static() {
333 let env = setup_env("lub_bound_static", EMPTY_SOURCE_STR);
334 let t_rptr_bound1 = env.t_rptr_bound(1);
335 let t_rptr_static = env.t_rptr_static();
336 env.check_lub(env.t_fn([t_rptr_bound1], env.t_int()),
337 env.t_fn([t_rptr_static], env.t_int()),
338 env.t_fn([t_rptr_static], env.t_int()));
342 fn lub_bound_bound_inverse_order() {
343 let env = setup_env("lub_bound_bound_inverse_order", EMPTY_SOURCE_STR);
344 let t_rptr_bound1 = env.t_rptr_bound(1);
345 let t_rptr_bound2 = env.t_rptr_bound(2);
346 env.check_lub(env.t_fn([t_rptr_bound1, t_rptr_bound2], t_rptr_bound1),
347 env.t_fn([t_rptr_bound2, t_rptr_bound1], t_rptr_bound1),
348 env.t_fn([t_rptr_bound1, t_rptr_bound1], t_rptr_bound1));
353 let env = setup_env("lub_free_free", EMPTY_SOURCE_STR);
354 let t_rptr_free1 = env.t_rptr_free(0, 1);
355 let t_rptr_free2 = env.t_rptr_free(0, 2);
356 let t_rptr_static = env.t_rptr_static();
357 env.check_lub(env.t_fn([t_rptr_free1], env.t_int()),
358 env.t_fn([t_rptr_free2], env.t_int()),
359 env.t_fn([t_rptr_static], env.t_int()));
363 fn lub_returning_scope() {
364 let env = setup_env("lub_returning_scope", EMPTY_SOURCE_STR);
365 let t_rptr_scope10 = env.t_rptr_scope(10);
366 let t_rptr_scope11 = env.t_rptr_scope(11);
367 env.check_no_lub(env.t_fn([], t_rptr_scope10),
368 env.t_fn([], t_rptr_scope11));
372 fn glb_free_free_with_common_scope() {
373 let env = setup_env("glb_free_free", EMPTY_SOURCE_STR);
374 let t_rptr_free1 = env.t_rptr_free(0, 1);
375 let t_rptr_free2 = env.t_rptr_free(0, 2);
376 let t_rptr_scope = env.t_rptr_scope(0);
377 env.check_glb(env.t_fn([t_rptr_free1], env.t_int()),
378 env.t_fn([t_rptr_free2], env.t_int()),
379 env.t_fn([t_rptr_scope], env.t_int()));
383 fn glb_bound_bound() {
384 let env = setup_env("glb_bound_bound", EMPTY_SOURCE_STR);
385 let t_rptr_bound1 = env.t_rptr_bound(1);
386 let t_rptr_bound2 = env.t_rptr_bound(2);
387 env.check_glb(env.t_fn([t_rptr_bound1], env.t_int()),
388 env.t_fn([t_rptr_bound2], env.t_int()),
389 env.t_fn([t_rptr_bound1], env.t_int()));
393 fn glb_bound_free() {
394 let env = setup_env("glb_bound_free", EMPTY_SOURCE_STR);
395 let t_rptr_bound1 = env.t_rptr_bound(1);
396 let t_rptr_free1 = env.t_rptr_free(0, 1);
397 env.check_glb(env.t_fn([t_rptr_bound1], env.t_int()),
398 env.t_fn([t_rptr_free1], env.t_int()),
399 env.t_fn([t_rptr_bound1], env.t_int()));
403 fn glb_bound_static() {
404 let env = setup_env("glb_bound_static", EMPTY_SOURCE_STR);
405 let t_rptr_bound1 = env.t_rptr_bound(1);
406 let t_rptr_static = env.t_rptr_static();
407 env.check_glb(env.t_fn([t_rptr_bound1], env.t_int()),
408 env.t_fn([t_rptr_static], env.t_int()),
409 env.t_fn([t_rptr_bound1], env.t_int()));