1 // Copyright 2012-2014 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.
12 * Conversion from AST representation of types to the ty.rs
13 * representation. The main routine here is `ast_ty_to_ty()`: each use
14 * is parameterized by an instance of `AstConv` and a `RegionScope`.
16 * The parameterization of `ast_ty_to_ty()` is because it behaves
17 * somewhat differently during the collect and check phases,
18 * particularly with respect to looking up the types of top-level
19 * items. In the collect phase, the crate context is used as the
20 * `AstConv` instance; in this phase, the `get_item_ty()` function
21 * triggers a recursive call to `ty_of_item()` (note that
22 * `ast_ty_to_ty()` will detect recursive types and report an error).
23 * In the check phase, when the @FnCtxt is used as the `AstConv`,
24 * `get_item_ty()` just looks up the item type in `tcx.tcache`.
26 * The `RegionScope` trait controls what happens when the user does
27 * not specify a region in some location where a region is required
28 * (e.g., if the user writes `&Foo` as a type rather than `&'a Foo`).
29 * See the `rscope` module for more details.
31 * Unlike the `AstConv` trait, the region scope can change as we descend
32 * the type. This is to accommodate the fact that (a) fn types are binding
33 * scopes and (b) the default region may change. To understand case (a),
34 * consider something like:
36 * type foo = { x: &a.int, y: |&a.int| }
38 * The type of `x` is an error because there is no region `a` in scope.
39 * In the type of `y`, however, region `a` is considered a bound region
40 * as it does not already appear in scope.
42 * Case (b) says that if you have a type:
44 * type bar = fn(&foo, &a.foo)
45 * The fully expanded version of type bar is:
46 * type bar = fn(&'foo &, &a.foo<'a>)
47 * Note that the self region for the `foo` defaulted to `&` in the first
48 * case but `&a` in the second. Basically, defaults that appear inside
49 * an rptr (`&r.T`) use the region `r` that appears in the rptr.
53 use middle::const_eval;
54 use middle::subst::Subst;
55 use middle::ty::{substs};
56 use middle::ty::{ty_param_substs_and_ty};
58 use middle::typeck::rscope;
59 use middle::typeck::rscope::{RegionScope};
60 use middle::typeck::lookup_def_tcx;
61 use util::ppaux::Repr;
64 use syntax::abi::AbiSet;
65 use syntax::{ast, ast_util};
66 use syntax::codemap::Span;
67 use syntax::opt_vec::OptVec;
69 use syntax::print::pprust::{lifetime_to_str, path_to_str};
72 fn tcx(&self) -> ty::ctxt;
73 fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty;
74 fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef;
76 // what type should we use when a type is omitted?
77 fn ty_infer(&self, span: Span) -> ty::t;
80 pub fn ast_region_to_region(tcx: ty::ctxt, lifetime: &ast::Lifetime)
82 let named_region_map = tcx.named_region_map.borrow();
83 let r = match named_region_map.get().find(&lifetime.id) {
85 // should have been recorded by the `resolve_lifetime` pass
86 tcx.sess.span_bug(lifetime.span, "unresolved lifetime");
89 Some(&ast::DefStaticRegion) => {
93 Some(&ast::DefLateBoundRegion(binder_id, _, id)) => {
94 ty::ReLateBound(binder_id, ty::BrNamed(ast_util::local_def(id),
98 Some(&ast::DefEarlyBoundRegion(index, id)) => {
99 ty::ReEarlyBound(id, index, lifetime.ident)
102 Some(&ast::DefFreeRegion(scope_id, id)) => {
103 ty::ReFree(ty::FreeRegion {
105 bound_region: ty::BrNamed(ast_util::local_def(id),
111 debug!("ast_region_to_region(lifetime={} id={}) yields {}",
112 lifetime_to_str(lifetime),
113 lifetime.id, r.repr(tcx));
118 fn opt_ast_region_to_region<AC:AstConv,RS:RegionScope>(
122 opt_lifetime: &Option<ast::Lifetime>) -> ty::Region
124 let r = match *opt_lifetime {
125 Some(ref lifetime) => {
126 ast_region_to_region(this.tcx(), lifetime)
130 match rscope.anon_regions(default_span, 1) {
132 debug!("optional region in illegal location");
133 this.tcx().sess.span_err(
134 default_span, "missing lifetime specifier");
145 debug!("opt_ast_region_to_region(opt_lifetime={:?}) yields {}",
146 opt_lifetime.as_ref().map(|e| lifetime_to_str(e)),
152 fn ast_path_substs<AC:AstConv,RS:RegionScope>(
155 decl_generics: &ty::Generics,
156 self_ty: Option<ty::t>,
157 path: &ast::Path) -> ty::substs
160 * Given a path `path` that refers to an item `I` with the
161 * declared generics `decl_generics`, returns an appropriate
162 * set of substitutions for this particular reference to `I`.
165 let tcx = this.tcx();
167 // If the type is parameterized by the this region, then replace this
168 // region with the current anon region binding (in other words,
169 // whatever & would get replaced with).
170 let expected_num_region_params = decl_generics.region_param_defs().len();
171 let supplied_num_region_params = path.segments.last().unwrap().lifetimes.len();
172 let regions = if expected_num_region_params == supplied_num_region_params {
173 path.segments.last().unwrap().lifetimes.map(
174 |l| ast_region_to_region(this.tcx(), l))
177 rscope.anon_regions(path.span, expected_num_region_params);
179 if supplied_num_region_params != 0 || anon_regions.is_err() {
182 format!("wrong number of lifetime parameters: \
183 expected {} but found {}",
184 expected_num_region_params,
185 supplied_num_region_params));
189 Ok(v) => opt_vec::from(v),
190 Err(()) => opt_vec::from(vec::from_fn(expected_num_region_params,
191 |_| ty::ReStatic)) // hokey
195 // Convert the type parameters supplied by the user.
196 let supplied_ty_param_count = path.segments.iter().flat_map(|s| s.types.iter()).len();
197 let formal_ty_param_count = decl_generics.type_param_defs().len();
198 let required_ty_param_count = decl_generics.type_param_defs().iter()
199 .take_while(|x| x.default.is_none())
201 if supplied_ty_param_count < required_ty_param_count {
202 let expected = if required_ty_param_count < formal_ty_param_count {
207 this.tcx().sess.span_fatal(path.span,
208 format!("wrong number of type arguments: {} {} but found {}",
209 expected, required_ty_param_count, supplied_ty_param_count));
210 } else if supplied_ty_param_count > formal_ty_param_count {
211 let expected = if required_ty_param_count < formal_ty_param_count {
216 this.tcx().sess.span_fatal(path.span,
217 format!("wrong number of type arguments: {} {} but found {}",
218 expected, formal_ty_param_count, supplied_ty_param_count));
221 if supplied_ty_param_count > required_ty_param_count
222 && !this.tcx().sess.features.default_type_params.get() {
223 this.tcx().sess.span_err(path.span, "default type parameters are \
224 experimental and possibly buggy");
225 this.tcx().sess.span_note(path.span, "add #[feature(default_type_params)] \
226 to the crate attributes to enable");
229 let tps = path.segments.iter().flat_map(|s| s.types.iter())
230 .map(|&a_t| ast_ty_to_ty(this, rscope, a_t))
233 let mut substs = substs {
234 regions: ty::NonerasedRegions(regions),
239 for param in decl_generics.type_param_defs()
240 .slice_from(supplied_ty_param_count).iter() {
241 let ty = param.default.unwrap().subst_spanned(tcx, &substs, Some(path.span));
248 pub fn ast_path_to_substs_and_ty<AC:AstConv,
254 -> ty_param_substs_and_ty {
255 let tcx = this.tcx();
256 let ty::ty_param_bounds_and_ty {
259 } = this.get_item_ty(did);
261 let substs = ast_path_substs(this, rscope, &generics, None, path);
262 let ty = ty::subst(tcx, &substs, decl_ty);
263 ty_param_substs_and_ty { substs: substs, ty: ty }
266 pub fn ast_path_to_trait_ref<AC:AstConv,RS:RegionScope>(
269 trait_def_id: ast::DefId,
270 self_ty: Option<ty::t>,
271 path: &ast::Path) -> @ty::TraitRef
274 this.get_trait_def(trait_def_id);
283 @ty::TraitRef {def_id: trait_def_id,
288 pub fn ast_path_to_ty<AC:AstConv,RS:RegionScope>(
293 -> ty_param_substs_and_ty
295 // Look up the polytype of the item and then substitute the provided types
296 // for any type/region parameters.
297 let ty::ty_param_substs_and_ty {
300 } = ast_path_to_substs_and_ty(this, rscope, did, path);
301 ty_param_substs_and_ty { substs: substs, ty: ty }
304 pub static NO_REGIONS: uint = 1;
305 pub static NO_TPS: uint = 2;
307 fn check_path_args(tcx: ty::ctxt,
310 if (flags & NO_TPS) != 0u {
311 if !path.segments.iter().all(|s| s.types.is_empty()) {
314 "type parameters are not allowed on this type");
318 if (flags & NO_REGIONS) != 0u {
319 if !path.segments.last().unwrap().lifetimes.is_empty() {
322 "region parameters are not allowed on this type");
327 pub fn ast_ty_to_prim_ty(tcx: ty::ctxt, ast_ty: &ast::Ty) -> Option<ty::t> {
329 ast::TyPath(ref path, _, id) => {
330 let def_map = tcx.def_map.borrow();
331 let a_def = match def_map.get().find(&id) {
332 None => tcx.sess.span_fatal(
333 ast_ty.span, format!("unbound path {}", path_to_str(path))),
337 ast::DefPrimTy(nty) => {
340 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
344 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
348 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
349 Some(ty::mk_mach_int(it))
351 ast::TyUint(uit) => {
352 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
353 Some(ty::mk_mach_uint(uit))
355 ast::TyFloat(ft) => {
356 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
357 Some(ty::mk_mach_float(ft))
360 tcx.sess.span_err(ast_ty.span,
361 "bare `str` is not a type");
362 // return /something/ so they can at least get more errors
363 Some(ty::mk_str(tcx, ty::vstore_uniq))
374 // Parses the programmer's textual representation of a type into our
375 // internal notion of a type.
376 pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
377 this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> ty::t {
379 fn ast_ty_to_mt<AC:AstConv, RS:RegionScope>(
380 this: &AC, rscope: &RS, ty: &ast::Ty) -> ty::mt {
382 ty::mt {ty: ast_ty_to_ty(this, rscope, ty), mutbl: ast::MutImmutable}
385 fn ast_mt_to_mt<AC:AstConv, RS:RegionScope>(
386 this: &AC, rscope: &RS, mt: &ast::MutTy) -> ty::mt {
388 ty::mt {ty: ast_ty_to_ty(this, rscope, mt.ty), mutbl: mt.mutbl}
396 fn expect_vstore(&self, tcx: ty::ctxt, span: Span, ty: &str) -> ty::vstore {
399 tcx.sess.span_err(span, format!("managed {} are not supported", ty));
400 // everything can be ~, so this is a worth substitute
408 // Handle ~, and & being able to mean strs and vecs.
409 // If a_seq_ty is a str or a vec, make it a str/vec.
410 // Also handle first-class trait types.
411 fn mk_pointer<AC:AstConv,
415 a_seq_ty: &ast::MutTy,
417 constr: |ty::mt| -> ty::t)
419 let tcx = this.tcx();
420 debug!("mk_pointer(ptr_ty={:?})", ptr_ty);
422 match a_seq_ty.ty.node {
424 let vst = ptr_ty.expect_vstore(tcx, a_seq_ty.ty.span, "vectors");
425 let mut mt = ast_ty_to_mt(this, rscope, ty);
426 if a_seq_ty.mutbl == ast::MutMutable {
427 mt.mutbl = ast::MutMutable;
429 debug!("&[]: vst={:?}", vst);
430 return ty::mk_vec(tcx, mt, vst);
432 ast::TyPath(ref path, ref bounds, id) => {
433 // Note that the "bounds must be empty if path is not a trait"
434 // restriction is enforced in the below case for ty_path, which
435 // will run after this as long as the path isn't a trait.
436 let def_map = tcx.def_map.borrow();
437 match def_map.get().find(&id) {
438 Some(&ast::DefPrimTy(ast::TyStr)) if
439 a_seq_ty.mutbl == ast::MutImmutable => {
440 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
441 let vst = ptr_ty.expect_vstore(tcx, path.span, "strings");
442 return ty::mk_str(tcx, vst);
444 Some(&ast::DefTrait(trait_def_id)) => {
445 let result = ast_path_to_trait_ref(
446 this, rscope, trait_def_id, None, path);
447 let trait_store = match ptr_ty {
448 VStore(ty::vstore_uniq) => ty::UniqTraitStore,
449 VStore(ty::vstore_slice(r)) => {
450 ty::RegionTraitStore(r)
455 "~trait or &trait are the only supported \
456 forms of casting-to-trait");
460 let bounds = conv_builtin_bounds(this.tcx(), bounds, trait_store);
461 return ty::mk_trait(tcx,
463 result.substs.clone(),
474 let seq_ty = ast_mt_to_mt(this, rscope, a_seq_ty);
475 return constr(seq_ty);
478 let tcx = this.tcx();
481 let mut ast_ty_to_ty_cache = tcx.ast_ty_to_ty_cache.borrow_mut();
482 match ast_ty_to_ty_cache.get().find(&ast_ty.id) {
483 Some(&ty::atttce_resolved(ty)) => return ty,
484 Some(&ty::atttce_unresolved) => {
485 tcx.sess.span_fatal(ast_ty.span,
486 "illegal recursive type; insert an enum \
487 or struct in the cycle, if this is \
490 None => { /* go on */ }
492 ast_ty_to_ty_cache.get().insert(ast_ty.id, ty::atttce_unresolved);
495 let typ = ast_ty_to_prim_ty(tcx, ast_ty).unwrap_or_else(|| match ast_ty.node {
496 ast::TyNil => ty::mk_nil(),
497 ast::TyBot => ty::mk_bot(),
499 let mt = ast::MutTy { ty: ty, mutbl: ast::MutImmutable };
500 mk_pointer(this, rscope, &mt, Box, |tmt| ty::mk_box(tcx, tmt.ty))
503 let mt = ast::MutTy { ty: ty, mutbl: ast::MutImmutable };
504 mk_pointer(this, rscope, &mt, VStore(ty::vstore_uniq),
505 |tmt| ty::mk_uniq(tcx, tmt.ty))
508 tcx.sess.span_err(ast_ty.span, "bare `[]` is not a type");
509 // return /something/ so they can at least get more errors
510 ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty), ty::vstore_uniq)
512 ast::TyPtr(ref mt) => {
513 ty::mk_ptr(tcx, ast_mt_to_mt(this, rscope, mt))
515 ast::TyRptr(ref region, ref mt) => {
516 let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
517 debug!("ty_rptr r={}", r.repr(this.tcx()));
518 mk_pointer(this, rscope, mt, VStore(ty::vstore_slice(r)),
519 |tmt| ty::mk_rptr(tcx, r, tmt))
521 ast::TyTup(ref fields) => {
522 let flds = fields.map(|&t| ast_ty_to_ty(this, rscope, t));
523 ty::mk_tup(tcx, flds)
525 ast::TyBareFn(ref bf) => {
526 if bf.decl.variadic && !bf.abis.is_c() {
527 tcx.sess.span_err(ast_ty.span,
528 "variadic function must have C calling convention");
530 ty::mk_bare_fn(tcx, ty_of_bare_fn(this, ast_ty.id, bf.purity,
533 ast::TyClosure(ref f) => {
534 if f.sigil == ast::ManagedSigil {
535 tcx.sess.span_err(ast_ty.span,
536 "managed closures are not supported");
539 let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, match f.sigil {
540 // Use corresponding trait store to figure out default bounds
541 // if none were specified.
542 ast::BorrowedSigil => ty::RegionTraitStore(ty::ReEmpty), // dummy region
543 ast::OwnedSigil => ty::UniqTraitStore,
544 ast::ManagedSigil => return ty::mk_err()
546 let fn_decl = ty_of_closure(this,
557 ty::mk_closure(tcx, fn_decl)
559 ast::TyPath(ref path, ref bounds, id) => {
560 let def_map = tcx.def_map.borrow();
561 let a_def = match def_map.get().find(&id) {
562 None => tcx.sess.span_fatal(
563 ast_ty.span, format!("unbound path {}", path_to_str(path))),
566 // Kind bounds on path types are only supported for traits.
568 // But don't emit the error if the user meant to do a trait anyway.
569 ast::DefTrait(..) => { },
570 _ if bounds.is_some() =>
571 tcx.sess.span_err(ast_ty.span,
572 "kind bounds can only be used on trait types"),
576 ast::DefTrait(_) => {
577 let path_str = path_to_str(path);
580 format!("reference to trait `{}` where a type is expected; \
581 try `@{}`, `~{}`, or `&{}`",
582 path_str, path_str, path_str, path_str));
585 ast::DefTy(did) | ast::DefStruct(did) => {
586 ast_path_to_ty(this, rscope, did, path).ty
588 ast::DefTyParam(id, n) => {
589 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
590 ty::mk_param(tcx, n, id)
592 ast::DefSelfTy(id) => {
593 // n.b.: resolve guarantees that the this type only appears in a
594 // trait, which we rely upon in various places when creating
596 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
597 let did = ast_util::local_def(id);
598 ty::mk_self(tcx, did)
601 tcx.sess.span_fatal(ast_ty.span,
602 format!("found module name used as a type: {}",
603 tcx.map.node_to_str(id.node)));
605 ast::DefPrimTy(_) => {
606 fail!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
609 tcx.sess.span_fatal(ast_ty.span,
610 format!("found value name used as a type: {:?}", a_def));
614 ast::TyFixedLengthVec(ty, e) => {
615 match const_eval::eval_const_expr_partial(&tcx, e) {
618 const_eval::const_int(i) =>
619 ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty),
620 ty::vstore_fixed(i as uint)),
621 const_eval::const_uint(i) =>
622 ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty),
623 ty::vstore_fixed(i as uint)),
626 ast_ty.span, "expected constant expr for vector length");
633 format!("expected constant expr for vector length: {}", *r));
637 ast::TyTypeof(_e) => {
638 tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
641 // ty_infer should only appear as the type of arguments or return
642 // values in a fn_expr, or as the type of local variables. Both of
643 // these cases are handled specially and should not descend into this
645 this.tcx().sess.span_bug(
647 "found `ty_infer` in unexpected place");
651 let mut ast_ty_to_ty_cache = tcx.ast_ty_to_ty_cache.borrow_mut();
652 ast_ty_to_ty_cache.get().insert(ast_ty.id, ty::atttce_resolved(typ));
656 pub fn ty_of_arg<AC: AstConv, RS: RegionScope>(this: &AC, rscope: &RS, a: &ast::Arg,
657 expected_ty: Option<ty::t>) -> ty::t {
659 ast::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
660 ast::TyInfer => this.ty_infer(a.ty.span),
661 _ => ast_ty_to_ty(this, rscope, a.ty),
666 untransformed_self_ty: ty::t,
667 explicit_self: ast::ExplicitSelf
670 pub fn ty_of_method<AC:AstConv>(
674 untransformed_self_ty: ty::t,
675 explicit_self: ast::ExplicitSelf,
676 decl: &ast::FnDecl) -> ty::BareFnTy {
677 ty_of_method_or_bare_fn(this, id, purity, AbiSet::Rust(), Some(SelfInfo {
678 untransformed_self_ty: untransformed_self_ty,
679 explicit_self: explicit_self
683 pub fn ty_of_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
684 purity: ast::Purity, abi: AbiSet,
685 decl: &ast::FnDecl) -> ty::BareFnTy {
686 ty_of_method_or_bare_fn(this, id, purity, abi, None, decl)
689 fn ty_of_method_or_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
690 purity: ast::Purity, abi: AbiSet,
691 opt_self_info: Option<SelfInfo>,
692 decl: &ast::FnDecl) -> ty::BareFnTy {
693 debug!("ty_of_method_or_bare_fn");
695 // new region names that appear inside of the fn decl are bound to
696 // that function type
697 let rb = rscope::BindingRscope::new(id);
699 let self_ty = opt_self_info.and_then(|self_info| {
700 match self_info.explicit_self.node {
701 ast::SelfStatic => None,
703 Some(self_info.untransformed_self_ty)
705 ast::SelfRegion(ref lifetime, mutability) => {
707 opt_ast_region_to_region(this, &rb,
708 self_info.explicit_self.span,
710 Some(ty::mk_rptr(this.tcx(), region,
711 ty::mt {ty: self_info.untransformed_self_ty,
715 Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty))
720 // HACK(eddyb) replace the fake self type in the AST with the actual type.
721 let input_tys = if self_ty.is_some() {
722 decl.inputs.slice_from(1)
724 decl.inputs.as_slice()
726 let input_tys = input_tys.iter().map(|a| ty_of_arg(this, &rb, a, None));
728 let self_and_input_tys = self_ty.move_iter().chain(input_tys).collect();
730 let output_ty = match decl.output.node {
731 ast::TyInfer => this.ty_infer(decl.output.span),
732 _ => ast_ty_to_ty(this, &rb, decl.output)
735 return ty::BareFnTy {
740 inputs: self_and_input_tys,
742 variadic: decl.variadic
747 pub fn ty_of_closure<AC:AstConv,RS:RegionScope>(
753 onceness: ast::Onceness,
754 bounds: ty::BuiltinBounds,
755 opt_lifetime: &Option<ast::Lifetime>,
757 expected_sig: Option<ty::FnSig>,
761 debug!("ty_of_fn_decl");
763 // resolve the function bound region in the original region
764 // scope `rscope`, not the scope of the function parameters
765 let bound_region = match opt_lifetime {
766 &Some(ref lifetime) => {
767 ast_region_to_region(this.tcx(), lifetime)
771 ast::OwnedSigil | ast::ManagedSigil => {
772 // @fn(), ~fn() default to static as the bound
776 ast::BorrowedSigil => {
777 // || defaults as normal for an omitted lifetime:
778 opt_ast_region_to_region(this, rscope, span, opt_lifetime)
784 // new region names that appear inside of the fn decl are bound to
785 // that function type
786 let rb = rscope::BindingRscope::new(id);
788 let input_tys = decl.inputs.iter().enumerate().map(|(i, a)| {
789 let expected_arg_ty = expected_sig.as_ref().and_then(|e| {
790 // no guarantee that the correct number of expected args
792 if i < e.inputs.len() {Some(e.inputs[i])} else {None}
794 ty_of_arg(this, &rb, a, expected_arg_ty)
797 let expected_ret_ty = expected_sig.map(|e| e.output);
798 let output_ty = match decl.output.node {
799 ast::TyInfer if expected_ret_ty.is_some() => expected_ret_ty.unwrap(),
800 ast::TyInfer => this.ty_infer(decl.output.span),
801 _ => ast_ty_to_ty(this, &rb, decl.output)
808 region: bound_region,
810 sig: ty::FnSig {binder_id: id,
813 variadic: decl.variadic}
817 fn conv_builtin_bounds(tcx: ty::ctxt, ast_bounds: &Option<OptVec<ast::TyParamBound>>,
818 store: ty::TraitStore)
819 -> ty::BuiltinBounds {
820 //! Converts a list of bounds from the AST into a `BuiltinBounds`
821 //! struct. Reports an error if any of the bounds that appear
822 //! in the AST refer to general traits and not the built-in traits
823 //! like `Send`. Used to translate the bounds that
824 //! appear in closure and trait types, where only builtin bounds are
826 //! If no bounds were specified, we choose a "default" bound based on
827 //! the allocation type of the fn/trait, as per issue #7264. The user can
828 //! override this with an empty bounds list, e.g. "~fn:()" or "~Trait:".
830 match (ast_bounds, store) {
831 (&Some(ref bound_vec), _) => {
832 let mut builtin_bounds = ty::EmptyBuiltinBounds();
833 for ast_bound in bound_vec.iter() {
835 ast::TraitTyParamBound(ref b) => {
836 match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
837 ast::DefTrait(trait_did) => {
838 if ty::try_add_builtin_trait(tcx, trait_did,
839 &mut builtin_bounds) {
847 format!("only the builtin traits can be used \
848 as closure or object bounds"));
850 ast::RegionTyParamBound => {
851 builtin_bounds.add(ty::BoundStatic);
857 // ~Trait is sugar for ~Trait:Send.
858 (&None, ty::UniqTraitStore) => {
859 let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundSend); set
861 // &'static Trait is sugar for &'static Trait:'static.
862 (&None, ty::RegionTraitStore(ty::ReStatic)) => {
863 let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundStatic); set
865 // &'r Trait is sugar for &'r Trait:<no-bounds>.
866 (&None, ty::RegionTraitStore(..)) => ty::EmptyBuiltinBounds(),