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.
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 how region references are
27 * handled. It has two methods which are used to resolve anonymous
28 * region references (e.g., `&T`) and named region references (e.g.,
29 * `&a.T`). There are numerous region scopes that can be used, but most
30 * commonly you want either `EmptyRscope`, which permits only the static
31 * region, or `TypeRscope`, which permits the self region if the type in
32 * question is parameterized by a region.
34 * Unlike the `AstConv` trait, the region scope can change as we descend
35 * the type. This is to accommodate the fact that (a) fn types are binding
36 * scopes and (b) the default region may change. To understand case (a),
37 * consider something like:
39 * type foo = { x: &a.int, y: &fn(&a.int) }
41 * The type of `x` is an error because there is no region `a` in scope.
42 * In the type of `y`, however, region `a` is considered a bound region
43 * as it does not already appear in scope.
45 * Case (b) says that if you have a type:
46 * type foo<'self> = ...;
47 * type bar = fn(&foo, &a.foo)
48 * The fully expanded version of type bar is:
49 * type bar = fn(&'foo &, &a.foo<'a>)
50 * Note that the self region for the `foo` defaulted to `&` in the first
51 * case but `&a` in the second. Basically, defaults that appear inside
52 * an rptr (`&r.T`) use the region `r` that appears in the rptr.
56 use middle::const_eval;
57 use middle::ty::{substs};
58 use middle::ty::{ty_param_substs_and_ty};
60 use middle::typeck::rscope::in_binding_rscope;
61 use middle::typeck::rscope::{RegionScope, RegionError};
62 use middle::typeck::rscope::RegionParamNames;
63 use middle::typeck::lookup_def_tcx;
66 use syntax::abi::AbiSet;
67 use syntax::{ast, ast_util};
68 use syntax::codemap::Span;
69 use syntax::opt_vec::OptVec;
71 use syntax::print::pprust::{lifetime_to_str, path_to_str};
72 use syntax::parse::token::special_idents;
73 use util::common::indenter;
76 fn tcx(&self) -> ty::ctxt;
77 fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty;
78 fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef;
80 // what type should we use when a type is omitted?
81 fn ty_infer(&self, span: Span) -> ty::t;
84 pub fn get_region_reporting_err(
87 a_r: &Option<ast::Lifetime>,
88 res: Result<ty::Region, RegionError>) -> ty::Region
92 result::Err(ref e) => {
93 let descr = match a_r {
94 &None => ~"anonymous lifetime",
95 &Some(ref a) => format!("lifetime {}",
96 lifetime_to_str(a, tcx.sess.intr()))
100 format!("Illegal {}: {}",
107 pub fn ast_region_to_region<AC:AstConv,RS:RegionScope + Clone + 'static>(
111 opt_lifetime: &Option<ast::Lifetime>) -> ty::Region
113 let (span, res) = match opt_lifetime {
115 (default_span, rscope.anon_region(default_span))
117 &Some(ref lifetime) if lifetime.ident == special_idents::statik => {
118 (lifetime.span, Ok(ty::re_static))
120 &Some(ref lifetime) if lifetime.ident == special_idents::self_ => {
121 (lifetime.span, rscope.self_region(lifetime.span))
123 &Some(ref lifetime) => {
124 (lifetime.span, rscope.named_region(lifetime.span,
129 get_region_reporting_err(this.tcx(), span, opt_lifetime, res)
132 fn ast_path_substs<AC:AstConv,RS:RegionScope + Clone + 'static>(
136 decl_generics: &ty::Generics,
137 self_ty: Option<ty::t>,
138 path: &ast::Path) -> ty::substs
142 * Given a path `path` that refers to an item `I` with the
143 * declared generics `decl_generics`, returns an appropriate
144 * set of substitutions for this particular reference to `I`.
147 let tcx = this.tcx();
149 // If the type is parameterized by the this region, then replace this
150 // region with the current anon region binding (in other words,
151 // whatever & would get replaced with).
152 let regions = match (&decl_generics.region_param,
153 &path.segments.last().lifetime) {
157 (&None, &Some(_)) => {
160 format!("no region bound is allowed on `{}`, \
161 which is not declared as containing region pointers",
162 ty::item_path_str(tcx, def_id)));
165 (&Some(_), &None) => {
166 let res = rscope.anon_region(path.span);
167 let r = get_region_reporting_err(this.tcx(), path.span, &None, res);
170 (&Some(_), &Some(_)) => {
172 ast_region_to_region(this,
175 &path.segments.last().lifetime))
179 // Convert the type parameters supplied by the user.
180 let supplied_type_parameter_count =
181 path.segments.iter().flat_map(|s| s.types.iter()).len();
182 if decl_generics.type_param_defs.len() != supplied_type_parameter_count {
183 this.tcx().sess.span_fatal(
185 format!("wrong number of type arguments: expected {} but found {}",
186 decl_generics.type_param_defs.len(),
187 supplied_type_parameter_count));
189 let tps = path.segments
191 .flat_map(|s| s.types.iter())
192 .map(|a_t| ast_ty_to_ty(this, rscope, a_t))
196 regions: ty::NonerasedRegions(regions),
202 pub fn ast_path_to_substs_and_ty<AC:AstConv,
203 RS:RegionScope + Clone + 'static>(
208 -> ty_param_substs_and_ty {
209 let tcx = this.tcx();
210 let ty::ty_param_bounds_and_ty {
213 } = this.get_item_ty(did);
215 let substs = ast_path_substs(this, rscope, did, &generics, None, path);
216 let ty = ty::subst(tcx, &substs, decl_ty);
217 ty_param_substs_and_ty { substs: substs, ty: ty }
220 pub fn ast_path_to_trait_ref<AC:AstConv,RS:RegionScope + Clone + 'static>(
223 trait_def_id: ast::DefId,
224 self_ty: Option<ty::t>,
225 path: &ast::Path) -> @ty::TraitRef
228 this.get_trait_def(trait_def_id);
233 trait_def.trait_ref.def_id,
238 @ty::TraitRef {def_id: trait_def_id,
243 pub fn ast_path_to_ty<AC:AstConv,RS:RegionScope + Clone + 'static>(
248 -> ty_param_substs_and_ty
250 // Look up the polytype of the item and then substitute the provided types
251 // for any type/region parameters.
252 let ty::ty_param_substs_and_ty {
255 } = ast_path_to_substs_and_ty(this, rscope, did, path);
256 ty_param_substs_and_ty { substs: substs, ty: ty }
259 pub static NO_REGIONS: uint = 1;
260 pub static NO_TPS: uint = 2;
262 // Parses the programmer's textual representation of a type into our
263 // internal notion of a type. `getter` is a function that returns the type
264 // corresponding to a definition ID:
265 pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope + Clone + 'static>(
266 this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> ty::t {
268 fn ast_mt_to_mt<AC:AstConv, RS:RegionScope + Clone + 'static>(
269 this: &AC, rscope: &RS, mt: &ast::mt) -> ty::mt {
271 ty::mt {ty: ast_ty_to_ty(this, rscope, mt.ty), mutbl: mt.mutbl}
274 // Handle @, ~, and & being able to mean estrs and evecs.
275 // If a_seq_ty is a str or a vec, make it an estr/evec.
276 // Also handle first-class trait types.
277 fn mk_pointer<AC:AstConv,RS:RegionScope + Clone + 'static>(
282 constr: &fn(ty::mt) -> ty::t) -> ty::t
284 let tcx = this.tcx();
286 match a_seq_ty.ty.node {
287 ast::ty_vec(ref mt) => {
288 let mut mt = ast_mt_to_mt(this, rscope, mt);
289 if a_seq_ty.mutbl == ast::MutMutable {
290 mt = ty::mt { ty: mt.ty, mutbl: a_seq_ty.mutbl };
292 return ty::mk_evec(tcx, mt, vst);
294 ast::ty_path(ref path, ref bounds, id) => {
295 // Note that the "bounds must be empty if path is not a trait"
296 // restriction is enforced in the below case for ty_path, which
297 // will run after this as long as the path isn't a trait.
298 match tcx.def_map.find(&id) {
299 Some(&ast::DefPrimTy(ast::ty_str)) if a_seq_ty.mutbl == ast::MutImmutable => {
300 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
301 return ty::mk_estr(tcx, vst);
303 Some(&ast::DefTrait(trait_def_id)) => {
304 let result = ast_path_to_trait_ref(
305 this, rscope, trait_def_id, None, path);
306 let trait_store = match vst {
307 ty::vstore_box => ty::BoxTraitStore,
308 ty::vstore_uniq => ty::UniqTraitStore,
309 ty::vstore_slice(r) => {
310 ty::RegionTraitStore(r)
312 ty::vstore_fixed(*) => {
315 "@trait, ~trait or &trait are the only supported \
316 forms of casting-to-trait");
320 let bounds = conv_builtin_bounds(this.tcx(), bounds, trait_store);
321 return ty::mk_trait(tcx,
323 result.substs.clone(),
334 let seq_ty = ast_mt_to_mt(this, rscope, a_seq_ty);
335 return constr(seq_ty);
338 fn check_path_args(tcx: ty::ctxt,
341 if (flags & NO_TPS) != 0u {
342 if !path.segments.iter().all(|s| s.types.is_empty()) {
345 "type parameters are not allowed on this type");
349 if (flags & NO_REGIONS) != 0u {
350 if path.segments.last().lifetime.is_some() {
353 "region parameters are not allowed on this type");
358 let tcx = this.tcx();
360 match tcx.ast_ty_to_ty_cache.find(&ast_ty.id) {
361 Some(&ty::atttce_resolved(ty)) => return ty,
362 Some(&ty::atttce_unresolved) => {
363 tcx.sess.span_fatal(ast_ty.span, "illegal recursive type; \
364 insert an enum in the cycle, if this is desired");
366 None => { /* go on */ }
369 tcx.ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved);
370 let typ = match ast_ty.node {
371 ast::ty_nil => ty::mk_nil(),
372 ast::ty_bot => ty::mk_bot(),
373 ast::ty_box(ref mt) => {
374 mk_pointer(this, rscope, mt, ty::vstore_box,
375 |tmt| ty::mk_box(tcx, tmt))
377 ast::ty_uniq(ref mt) => {
378 mk_pointer(this, rscope, mt, ty::vstore_uniq,
379 |tmt| ty::mk_uniq(tcx, tmt))
381 ast::ty_vec(ref mt) => {
382 tcx.sess.span_err(ast_ty.span, "bare `[]` is not a type");
383 // return /something/ so they can at least get more errors
384 ty::mk_evec(tcx, ast_mt_to_mt(this, rscope, mt), ty::vstore_uniq)
386 ast::ty_ptr(ref mt) => {
387 ty::mk_ptr(tcx, ast_mt_to_mt(this, rscope, mt))
389 ast::ty_rptr(ref region, ref mt) => {
390 let r = ast_region_to_region(this, rscope, ast_ty.span, region);
391 mk_pointer(this, rscope, mt, ty::vstore_slice(r),
392 |tmt| ty::mk_rptr(tcx, r, tmt))
394 ast::ty_tup(ref fields) => {
395 let flds = fields.map(|t| ast_ty_to_ty(this, rscope, t));
396 ty::mk_tup(tcx, flds)
398 ast::ty_bare_fn(ref bf) => {
399 if bf.decl.variadic && !bf.abis.is_c() {
400 tcx.sess.span_err(ast_ty.span, "variadic function must have C calling convention");
402 ty::mk_bare_fn(tcx, ty_of_bare_fn(this, rscope, bf.purity,
403 bf.abis, &bf.lifetimes, &bf.decl))
405 ast::ty_closure(ref f) => {
406 if f.sigil == ast::ManagedSigil {
407 tcx.sess.span_err(ast_ty.span,
408 "managed closures are not supported");
411 let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, match f.sigil {
412 // Use corresponding trait store to figure out default bounds
413 // if none were specified.
414 ast::BorrowedSigil => ty::RegionTraitStore(ty::re_empty), // dummy region
415 ast::OwnedSigil => ty::UniqTraitStore,
416 ast::ManagedSigil => ty::BoxTraitStore,
418 let fn_decl = ty_of_closure(this,
429 ty::mk_closure(tcx, fn_decl)
431 ast::ty_path(ref path, ref bounds, id) => {
432 let a_def = match tcx.def_map.find(&id) {
433 None => tcx.sess.span_fatal(
434 ast_ty.span, format!("unbound path {}",
435 path_to_str(path, tcx.sess.intr()))),
438 // Kind bounds on path types are only supported for traits.
440 // But don't emit the error if the user meant to do a trait anyway.
441 ast::DefTrait(*) => { },
442 _ if bounds.is_some() =>
443 tcx.sess.span_err(ast_ty.span,
444 "kind bounds can only be used on trait types"),
448 ast::DefTrait(_) => {
449 let path_str = path_to_str(path, tcx.sess.intr());
452 format!("reference to trait `{}` where a type is expected; \
453 try `@{}`, `~{}`, or `&{}`",
454 path_str, path_str, path_str, path_str));
457 ast::DefTy(did) | ast::DefStruct(did) => {
458 ast_path_to_ty(this, rscope, did, path).ty
460 ast::DefPrimTy(nty) => {
463 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
467 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
471 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
474 ast::ty_uint(uit) => {
475 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
476 ty::mk_mach_uint(uit)
478 ast::ty_float(ft) => {
479 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
480 ty::mk_mach_float(ft)
483 tcx.sess.span_err(ast_ty.span,
484 "bare `str` is not a type");
485 // return /something/ so they can at least get more errors
486 ty::mk_estr(tcx, ty::vstore_uniq)
490 ast::DefTyParam(id, n) => {
491 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
492 ty::mk_param(tcx, n, id)
494 ast::DefSelfTy(id) => {
495 // n.b.: resolve guarantees that the this type only appears in a
496 // trait, which we rely upon in various places when creating
498 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
499 let did = ast_util::local_def(id);
500 ty::mk_self(tcx, did)
503 tcx.sess.span_fatal(ast_ty.span,
504 format!("found value name used as a type: {:?}", a_def));
508 ast::ty_fixed_length_vec(ref a_mt, e) => {
509 match const_eval::eval_const_expr_partial(&tcx, e) {
512 const_eval::const_int(i) =>
513 ty::mk_evec(tcx, ast_mt_to_mt(this, rscope, a_mt),
514 ty::vstore_fixed(i as uint)),
515 const_eval::const_uint(i) =>
516 ty::mk_evec(tcx, ast_mt_to_mt(this, rscope, a_mt),
517 ty::vstore_fixed(i as uint)),
520 ast_ty.span, "expected constant expr for vector length");
527 format!("expected constant expr for vector length: {}", *r));
531 ast::ty_typeof(_e) => {
532 tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
535 // ty_infer should only appear as the type of arguments or return
536 // values in a fn_expr, or as the type of local variables. Both of
537 // these cases are handled specially and should not descend into this
539 this.tcx().sess.span_bug(
541 "found `ty_infer` in unexpected place");
544 tcx.sess.span_bug(ast_ty.span,
545 "found `ty_mac` in unexpected place");
549 tcx.ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_resolved(typ));
553 pub fn ty_of_arg<AC:AstConv,
554 RS:RegionScope + Clone + 'static>(
558 expected_ty: Option<ty::t>)
561 ast::ty_infer if expected_ty.is_some() => expected_ty.unwrap(),
562 ast::ty_infer => this.ty_infer(a.ty.span),
563 _ => ast_ty_to_ty(this, rscope, &a.ty),
567 pub fn bound_lifetimes<AC:AstConv>(
569 ast_lifetimes: &OptVec<ast::Lifetime>) -> OptVec<ast::Ident>
573 * Converts a list of lifetimes into a list of bound identifier
574 * names. Does not permit special names like 'static or 'this to
575 * be bound. Note that this function is for use in closures,
576 * methods, and fn definitions. It is legal to bind 'this in a
577 * type. Eventually this distinction should go away and the same
578 * rules should apply everywhere ('this would not be a special name
582 let special_idents = [special_idents::statik, special_idents::self_];
583 let mut bound_lifetime_names = opt_vec::Empty;
584 ast_lifetimes.map_to_vec(|ast_lifetime| {
585 if special_idents.iter().any(|&i| i == ast_lifetime.ident) {
586 this.tcx().sess.span_err(
588 format!("illegal lifetime parameter name: `{}`",
589 lifetime_to_str(ast_lifetime, this.tcx().sess.intr())));
591 bound_lifetime_names.push(ast_lifetime.ident);
598 untransformed_self_ty: ty::t,
599 explicit_self: ast::explicit_self
602 pub fn ty_of_method<AC:AstConv,RS:RegionScope + Clone + 'static>(
606 lifetimes: &OptVec<ast::Lifetime>,
607 untransformed_self_ty: ty::t,
608 explicit_self: ast::explicit_self,
609 decl: &ast::fn_decl) -> (Option<ty::t>, ty::BareFnTy)
611 let self_info = SelfInfo {
612 untransformed_self_ty: untransformed_self_ty,
613 explicit_self: explicit_self
615 let (a, b) = ty_of_method_or_bare_fn(
616 this, rscope, purity, AbiSet::Rust(), lifetimes, Some(&self_info), decl);
620 pub fn ty_of_bare_fn<AC:AstConv,RS:RegionScope + Clone + 'static>(
625 lifetimes: &OptVec<ast::Lifetime>,
626 decl: &ast::fn_decl) -> ty::BareFnTy
628 let (_, b) = ty_of_method_or_bare_fn(
629 this, rscope, purity, abi, lifetimes, None, decl);
633 fn ty_of_method_or_bare_fn<AC:AstConv,RS:RegionScope + Clone + 'static>(
638 lifetimes: &OptVec<ast::Lifetime>,
639 opt_self_info: Option<&SelfInfo>,
640 decl: &ast::fn_decl) -> (Option<Option<ty::t>>, ty::BareFnTy)
642 debug!("ty_of_bare_fn");
644 // new region names that appear inside of the fn decl are bound to
645 // that function type
646 let bound_lifetime_names = bound_lifetimes(this, lifetimes);
648 in_binding_rscope(rscope,
649 RegionParamNames(bound_lifetime_names.clone()));
651 let opt_transformed_self_ty = do opt_self_info.map |self_info| {
652 transform_self_ty(this, &rb, self_info)
655 let input_tys = decl.inputs.map(|a| ty_of_arg(this, &rb, a, None));
657 let output_ty = match decl.output.node {
658 ast::ty_infer => this.ty_infer(decl.output.span),
659 _ => ast_ty_to_ty(this, &rb, &decl.output)
662 return (opt_transformed_self_ty,
667 bound_lifetime_names: bound_lifetime_names,
670 variadic: decl.variadic
674 fn transform_self_ty<AC:AstConv,RS:RegionScope + Clone + 'static>(
677 self_info: &SelfInfo) -> Option<ty::t>
679 match self_info.explicit_self.node {
680 ast::sty_static => None,
681 ast::sty_value(_) => {
682 Some(self_info.untransformed_self_ty)
684 ast::sty_region(ref lifetime, mutability) => {
686 ast_region_to_region(this, rscope,
687 self_info.explicit_self.span,
689 Some(ty::mk_rptr(this.tcx(), region,
690 ty::mt {ty: self_info.untransformed_self_ty,
693 ast::sty_box(mutability) => {
694 Some(ty::mk_box(this.tcx(),
695 ty::mt {ty: self_info.untransformed_self_ty,
698 ast::sty_uniq(_) => {
699 Some(ty::mk_uniq(this.tcx(),
700 ty::mt {ty: self_info.untransformed_self_ty,
701 mutbl: ast::MutImmutable}))
707 pub fn ty_of_closure<AC:AstConv,RS:RegionScope + Clone + 'static>(
712 onceness: ast::Onceness,
713 bounds: ty::BuiltinBounds,
714 opt_lifetime: &Option<ast::Lifetime>,
716 expected_sig: Option<ty::FnSig>,
717 lifetimes: &OptVec<ast::Lifetime>,
721 // The caller should not both provide explicit bound lifetime
722 // names and expected types. Either we infer the bound lifetime
723 // names or they are provided, but not both.
724 assert!(lifetimes.is_empty() || expected_sig.is_none());
726 debug!("ty_of_fn_decl");
729 // resolve the function bound region in the original region
730 // scope `rscope`, not the scope of the function parameters
731 let bound_region = match opt_lifetime {
733 ast_region_to_region(this, rscope, span, opt_lifetime)
737 ast::OwnedSigil | ast::ManagedSigil => {
738 // @fn(), ~fn() default to static as the bound
742 ast::BorrowedSigil => {
743 // &fn() defaults as normal for an omitted lifetime:
744 ast_region_to_region(this, rscope, span, opt_lifetime)
750 // new region names that appear inside of the fn decl are bound to
751 // that function type
752 let bound_lifetime_names = bound_lifetimes(this, lifetimes);
754 in_binding_rscope(rscope,
755 RegionParamNames(bound_lifetime_names.clone()));
757 let input_tys = do decl.inputs.iter().enumerate().map |(i, a)| {
758 let expected_arg_ty = do expected_sig.as_ref().and_then |e| {
759 // no guarantee that the correct number of expected args
761 if i < e.inputs.len() {Some(e.inputs[i])} else {None}
763 ty_of_arg(this, &rb, a, expected_arg_ty)
766 let expected_ret_ty = expected_sig.map(|e| e.output);
767 let output_ty = match decl.output.node {
768 ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.unwrap(),
769 ast::ty_infer => this.ty_infer(decl.output.span),
770 _ => ast_ty_to_ty(this, &rb, &decl.output)
777 region: bound_region,
780 bound_lifetime_names: bound_lifetime_names,
783 variadic: decl.variadic
788 fn conv_builtin_bounds(tcx: ty::ctxt, ast_bounds: &Option<OptVec<ast::TyParamBound>>,
789 store: ty::TraitStore)
790 -> ty::BuiltinBounds {
791 //! Converts a list of bounds from the AST into a `BuiltinBounds`
792 //! struct. Reports an error if any of the bounds that appear
793 //! in the AST refer to general traits and not the built-in traits
794 //! like `Send`. Used to translate the bounds that
795 //! appear in closure and trait types, where only builtin bounds are
797 //! If no bounds were specified, we choose a "default" bound based on
798 //! the allocation type of the fn/trait, as per issue #7264. The user can
799 //! override this with an empty bounds list, e.g. "~fn:()" or "~Trait:".
801 match (ast_bounds, store) {
802 (&Some(ref bound_vec), _) => {
803 let mut builtin_bounds = ty::EmptyBuiltinBounds();
804 for ast_bound in bound_vec.iter() {
806 ast::TraitTyParamBound(ref b) => {
807 match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
808 ast::DefTrait(trait_did) => {
809 if ty::try_add_builtin_trait(tcx, trait_did,
810 &mut builtin_bounds) {
818 format!("only the builtin traits can be used \
819 as closure or object bounds"));
821 ast::RegionTyParamBound => {
822 builtin_bounds.add(ty::BoundStatic);
828 // ~Trait is sugar for ~Trait:Send.
829 (&None, ty::UniqTraitStore) => {
830 let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundSend); set
832 // @Trait is sugar for @Trait:'static.
833 // &'static Trait is sugar for &'static Trait:'static.
834 (&None, ty::BoxTraitStore) |
835 (&None, ty::RegionTraitStore(ty::re_static)) => {
836 let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundStatic); set
838 // &'r Trait is sugar for &'r Trait:<no-bounds>.
839 (&None, ty::RegionTraitStore(*)) => ty::EmptyBuiltinBounds(),