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 `region_scope`.
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 `region_scope` 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 `empty_rscope`, which permits only the static
31 * region, or `type_rscope`, 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::{region_scope, RegionError};
62 use middle::typeck::rscope::RegionParamNames;
63 use middle::typeck::lookup_def_tcx;
67 use syntax::abi::AbiSet;
68 use syntax::{ast, ast_util};
69 use syntax::codemap::span;
70 use syntax::opt_vec::OptVec;
72 use syntax::print::pprust::{lifetime_to_str, path_to_str};
73 use syntax::parse::token::special_idents;
74 use util::common::indenter;
77 fn tcx(&self) -> ty::ctxt;
78 fn get_item_ty(&self, id: ast::def_id) -> ty::ty_param_bounds_and_ty;
79 fn get_trait_def(&self, id: ast::def_id) -> @ty::TraitDef;
81 // what type should we use when a type is omitted?
82 fn ty_infer(&self, span: span) -> ty::t;
85 pub fn get_region_reporting_err(
88 a_r: &Option<ast::Lifetime>,
89 res: Result<ty::Region, RegionError>) -> ty::Region
93 result::Err(ref e) => {
94 let descr = match a_r {
95 &None => ~"anonymous lifetime",
96 &Some(ref a) => fmt!("lifetime %s",
97 lifetime_to_str(a, tcx.sess.intr()))
101 fmt!("Illegal %s: %s",
108 pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Clone + 'static>(
112 opt_lifetime: &Option<ast::Lifetime>) -> ty::Region
114 let (span, res) = match opt_lifetime {
116 (default_span, rscope.anon_region(default_span))
118 &Some(ref lifetime) if lifetime.ident == special_idents::statik => {
119 (lifetime.span, Ok(ty::re_static))
121 &Some(ref lifetime) if lifetime.ident == special_idents::self_ => {
122 (lifetime.span, rscope.self_region(lifetime.span))
124 &Some(ref lifetime) => {
125 (lifetime.span, rscope.named_region(lifetime.span,
130 get_region_reporting_err(this.tcx(), span, opt_lifetime, res)
133 fn ast_path_substs<AC:AstConv,RS:region_scope + Clone + 'static>(
137 decl_generics: &ty::Generics,
138 self_ty: Option<ty::t>,
139 path: &ast::Path) -> ty::substs
143 * Given a path `path` that refers to an item `I` with the
144 * declared generics `decl_generics`, returns an appropriate
145 * set of substitutions for this particular reference to `I`.
148 let tcx = this.tcx();
150 // If the type is parameterized by the this region, then replace this
151 // region with the current anon region binding (in other words,
152 // whatever & would get replaced with).
153 let regions = match (&decl_generics.region_param, &path.rp) {
157 (&None, &Some(_)) => {
160 fmt!("no region bound is allowed on `%s`, \
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, rscope, path.span, &path.rp))
176 // Convert the type parameters supplied by the user.
177 if !vec::same_length(*decl_generics.type_param_defs, path.types) {
178 this.tcx().sess.span_fatal(
180 fmt!("wrong number of type arguments: expected %u but found %u",
181 decl_generics.type_param_defs.len(), path.types.len()));
183 let tps = path.types.map(|a_t| ast_ty_to_ty(this, rscope, a_t));
185 substs {regions:ty::NonerasedRegions(regions), self_ty:self_ty, tps:tps}
188 pub fn ast_path_to_substs_and_ty<AC:AstConv,
189 RS:region_scope + Clone + 'static>(
194 -> ty_param_substs_and_ty {
195 let tcx = this.tcx();
196 let ty::ty_param_bounds_and_ty {
199 } = this.get_item_ty(did);
201 let substs = ast_path_substs(this, rscope, did, &generics, None, path);
202 let ty = ty::subst(tcx, &substs, decl_ty);
203 ty_param_substs_and_ty { substs: substs, ty: ty }
206 pub fn ast_path_to_trait_ref<AC:AstConv,RS:region_scope + Clone + 'static>(
209 trait_def_id: ast::def_id,
210 self_ty: Option<ty::t>,
211 path: &ast::Path) -> @ty::TraitRef
214 this.get_trait_def(trait_def_id);
219 trait_def.trait_ref.def_id,
224 @ty::TraitRef {def_id: trait_def_id,
229 pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Clone + 'static>(
234 -> ty_param_substs_and_ty
236 // Look up the polytype of the item and then substitute the provided types
237 // for any type/region parameters.
238 let ty::ty_param_substs_and_ty {
241 } = ast_path_to_substs_and_ty(this, rscope, did, path);
242 ty_param_substs_and_ty { substs: substs, ty: ty }
245 pub static NO_REGIONS: uint = 1;
246 pub static NO_TPS: uint = 2;
248 // Parses the programmer's textual representation of a type into our
249 // internal notion of a type. `getter` is a function that returns the type
250 // corresponding to a definition ID:
251 pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Clone + 'static>(
252 this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> ty::t {
254 fn ast_mt_to_mt<AC:AstConv, RS:region_scope + Clone + 'static>(
255 this: &AC, rscope: &RS, mt: &ast::mt) -> ty::mt {
257 ty::mt {ty: ast_ty_to_ty(this, rscope, mt.ty), mutbl: mt.mutbl}
260 // Handle @, ~, and & being able to mean estrs and evecs.
261 // If a_seq_ty is a str or a vec, make it an estr/evec.
262 // Also handle first-class trait types.
263 fn mk_pointer<AC:AstConv,RS:region_scope + Clone + 'static>(
268 constr: &fn(ty::mt) -> ty::t) -> ty::t
270 let tcx = this.tcx();
272 match a_seq_ty.ty.node {
273 ast::ty_vec(ref mt) => {
274 let mut mt = ast_mt_to_mt(this, rscope, mt);
275 if a_seq_ty.mutbl == ast::m_mutbl ||
276 a_seq_ty.mutbl == ast::m_const {
277 mt = ty::mt { ty: mt.ty, mutbl: a_seq_ty.mutbl };
279 return ty::mk_evec(tcx, mt, vst);
281 ast::ty_path(ref path, ref bounds, id) => {
282 // Note that the "bounds must be empty if path is not a trait"
283 // restriction is enforced in the below case for ty_path, which
284 // will run after this as long as the path isn't a trait.
285 match tcx.def_map.find(&id) {
286 Some(&ast::def_prim_ty(ast::ty_str)) if a_seq_ty.mutbl == ast::m_imm => {
287 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
288 return ty::mk_estr(tcx, vst);
290 Some(&ast::def_trait(trait_def_id)) => {
291 let result = ast_path_to_trait_ref(
292 this, rscope, trait_def_id, None, path);
293 let trait_store = match vst {
294 ty::vstore_box => ty::BoxTraitStore,
295 ty::vstore_uniq => ty::UniqTraitStore,
296 ty::vstore_slice(r) => {
297 ty::RegionTraitStore(r)
299 ty::vstore_fixed(*) => {
302 "@trait, ~trait or &trait are the only supported \
303 forms of casting-to-trait");
307 let bounds = conv_builtin_bounds(this.tcx(), bounds, trait_store);
308 return ty::mk_trait(tcx,
310 result.substs.clone(),
321 let seq_ty = ast_mt_to_mt(this, rscope, a_seq_ty);
322 return constr(seq_ty);
325 fn check_path_args(tcx: ty::ctxt,
328 if (flags & NO_TPS) != 0u {
329 if path.types.len() > 0u {
332 "type parameters are not allowed on this type");
336 if (flags & NO_REGIONS) != 0u {
337 if path.rp.is_some() {
340 "region parameters are not allowed on this type");
345 let tcx = this.tcx();
347 match tcx.ast_ty_to_ty_cache.find(&ast_ty.id) {
348 Some(&ty::atttce_resolved(ty)) => return ty,
349 Some(&ty::atttce_unresolved) => {
350 tcx.sess.span_fatal(ast_ty.span, "illegal recursive type; \
351 insert an enum in the cycle, if this is desired");
353 None => { /* go on */ }
356 tcx.ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved);
357 let typ = match ast_ty.node {
358 ast::ty_nil => ty::mk_nil(),
359 ast::ty_bot => ty::mk_bot(),
360 ast::ty_box(ref mt) => {
361 mk_pointer(this, rscope, mt, ty::vstore_box,
362 |tmt| ty::mk_box(tcx, tmt))
364 ast::ty_uniq(ref mt) => {
365 mk_pointer(this, rscope, mt, ty::vstore_uniq,
366 |tmt| ty::mk_uniq(tcx, tmt))
368 ast::ty_vec(ref mt) => {
369 tcx.sess.span_err(ast_ty.span, "bare `[]` is not a type");
370 // return /something/ so they can at least get more errors
371 ty::mk_evec(tcx, ast_mt_to_mt(this, rscope, mt), ty::vstore_uniq)
373 ast::ty_ptr(ref mt) => {
374 ty::mk_ptr(tcx, ast_mt_to_mt(this, rscope, mt))
376 ast::ty_rptr(ref region, ref mt) => {
377 let r = ast_region_to_region(this, rscope, ast_ty.span, region);
378 mk_pointer(this, rscope, mt, ty::vstore_slice(r),
379 |tmt| ty::mk_rptr(tcx, r, tmt))
381 ast::ty_tup(ref fields) => {
382 let flds = fields.map(|t| ast_ty_to_ty(this, rscope, t));
383 ty::mk_tup(tcx, flds)
385 ast::ty_bare_fn(ref bf) => {
386 ty::mk_bare_fn(tcx, ty_of_bare_fn(this, rscope, bf.purity,
387 bf.abis, &bf.lifetimes, &bf.decl))
389 ast::ty_closure(ref f) => {
390 let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, match f.sigil {
391 // Use corresponding trait store to figure out default bounds
392 // if none were specified.
393 ast::BorrowedSigil => ty::RegionTraitStore(ty::re_empty), // dummy region
394 ast::OwnedSigil => ty::UniqTraitStore,
395 ast::ManagedSigil => ty::BoxTraitStore,
397 let fn_decl = ty_of_closure(this,
408 ty::mk_closure(tcx, fn_decl)
410 ast::ty_path(ref path, ref bounds, id) => {
411 let a_def = match tcx.def_map.find(&id) {
412 None => tcx.sess.span_fatal(
413 ast_ty.span, fmt!("unbound path %s",
414 path_to_str(path, tcx.sess.intr()))),
417 // Kind bounds on path types are only supported for traits.
419 // But don't emit the error if the user meant to do a trait anyway.
420 ast::def_trait(*) => { },
421 _ if bounds.is_some() =>
422 tcx.sess.span_err(ast_ty.span,
423 "kind bounds can only be used on trait types"),
427 ast::def_trait(_) => {
428 let path_str = path_to_str(path, tcx.sess.intr());
431 fmt!("reference to trait `%s` where a type is expected; \
432 try `@%s`, `~%s`, or `&%s`",
433 path_str, path_str, path_str, path_str));
436 ast::def_ty(did) | ast::def_struct(did) => {
437 ast_path_to_ty(this, rscope, did, path).ty
439 ast::def_prim_ty(nty) => {
442 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
446 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
449 ast::ty_uint(uit) => {
450 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
451 ty::mk_mach_uint(uit)
453 ast::ty_float(ft) => {
454 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
455 ty::mk_mach_float(ft)
458 tcx.sess.span_err(ast_ty.span,
459 "bare `str` is not a type");
460 // return /something/ so they can at least get more errors
461 ty::mk_estr(tcx, ty::vstore_uniq)
465 ast::def_ty_param(id, n) => {
466 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
467 ty::mk_param(tcx, n, id)
469 ast::def_self_ty(id) => {
470 // n.b.: resolve guarantees that the this type only appears in a
471 // trait, which we rely upon in various places when creating
473 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
474 let did = ast_util::local_def(id);
475 ty::mk_self(tcx, did)
478 tcx.sess.span_fatal(ast_ty.span,
479 fmt!("found value name used as a type: %?", a_def));
483 ast::ty_fixed_length_vec(ref a_mt, e) => {
484 match const_eval::eval_const_expr_partial(&tcx, e) {
487 const_eval::const_int(i) =>
488 ty::mk_evec(tcx, ast_mt_to_mt(this, rscope, a_mt),
489 ty::vstore_fixed(i as uint)),
490 const_eval::const_uint(i) =>
491 ty::mk_evec(tcx, ast_mt_to_mt(this, rscope, a_mt),
492 ty::vstore_fixed(i as uint)),
495 ast_ty.span, "expected constant expr for vector length");
502 fmt!("expected constant expr for vector length: %s",
508 // ty_infer should only appear as the type of arguments or return
509 // values in a fn_expr, or as the type of local variables. Both of
510 // these cases are handled specially and should not descend into this
512 this.tcx().sess.span_bug(
514 "found `ty_infer` in unexpected place");
517 tcx.sess.span_bug(ast_ty.span,
518 "found `ty_mac` in unexpected place");
522 tcx.ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_resolved(typ));
526 pub fn ty_of_arg<AC:AstConv,
527 RS:region_scope + Clone + 'static>(
531 expected_ty: Option<ty::t>)
534 ast::ty_infer if expected_ty.is_some() => expected_ty.unwrap(),
535 ast::ty_infer => this.ty_infer(a.ty.span),
536 _ => ast_ty_to_ty(this, rscope, &a.ty),
540 pub fn bound_lifetimes<AC:AstConv>(
542 ast_lifetimes: &OptVec<ast::Lifetime>) -> OptVec<ast::ident>
546 * Converts a list of lifetimes into a list of bound identifier
547 * names. Does not permit special names like 'static or 'this to
548 * be bound. Note that this function is for use in closures,
549 * methods, and fn definitions. It is legal to bind 'this in a
550 * type. Eventually this distinction should go away and the same
551 * rules should apply everywhere ('this would not be a special name
555 let special_idents = [special_idents::statik, special_idents::self_];
556 let mut bound_lifetime_names = opt_vec::Empty;
557 ast_lifetimes.map_to_vec(|ast_lifetime| {
558 if special_idents.iter().any(|&i| i == ast_lifetime.ident) {
559 this.tcx().sess.span_err(
561 fmt!("illegal lifetime parameter name: `%s`",
562 lifetime_to_str(ast_lifetime, this.tcx().sess.intr())));
564 bound_lifetime_names.push(ast_lifetime.ident);
571 untransformed_self_ty: ty::t,
572 explicit_self: ast::explicit_self
575 pub fn ty_of_method<AC:AstConv,RS:region_scope + Clone + 'static>(
579 lifetimes: &OptVec<ast::Lifetime>,
580 untransformed_self_ty: ty::t,
581 explicit_self: ast::explicit_self,
582 decl: &ast::fn_decl) -> (Option<ty::t>, ty::BareFnTy)
584 let self_info = SelfInfo {
585 untransformed_self_ty: untransformed_self_ty,
586 explicit_self: explicit_self
588 let (a, b) = ty_of_method_or_bare_fn(
589 this, rscope, purity, AbiSet::Rust(), lifetimes, Some(&self_info), decl);
593 pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Clone + 'static>(
598 lifetimes: &OptVec<ast::Lifetime>,
599 decl: &ast::fn_decl) -> ty::BareFnTy
601 let (_, b) = ty_of_method_or_bare_fn(
602 this, rscope, purity, abi, lifetimes, None, decl);
606 fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Clone + 'static>(
611 lifetimes: &OptVec<ast::Lifetime>,
612 opt_self_info: Option<&SelfInfo>,
613 decl: &ast::fn_decl) -> (Option<Option<ty::t>>, ty::BareFnTy)
615 debug!("ty_of_bare_fn");
617 // new region names that appear inside of the fn decl are bound to
618 // that function type
619 let bound_lifetime_names = bound_lifetimes(this, lifetimes);
621 in_binding_rscope(rscope,
622 RegionParamNames(bound_lifetime_names.clone()));
624 let opt_transformed_self_ty = do opt_self_info.map_move |self_info| {
625 transform_self_ty(this, &rb, self_info)
628 let input_tys = decl.inputs.map(|a| ty_of_arg(this, &rb, a, None));
630 let output_ty = match decl.output.node {
631 ast::ty_infer => this.ty_infer(decl.output.span),
632 _ => ast_ty_to_ty(this, &rb, &decl.output)
635 return (opt_transformed_self_ty,
639 sig: ty::FnSig {bound_lifetime_names: bound_lifetime_names,
644 fn transform_self_ty<AC:AstConv,RS:region_scope + Clone + 'static>(
647 self_info: &SelfInfo) -> Option<ty::t>
649 match self_info.explicit_self.node {
650 ast::sty_static => None,
652 Some(self_info.untransformed_self_ty)
654 ast::sty_region(ref lifetime, mutability) => {
656 ast_region_to_region(this, rscope,
657 self_info.explicit_self.span,
659 Some(ty::mk_rptr(this.tcx(), region,
660 ty::mt {ty: self_info.untransformed_self_ty,
663 ast::sty_box(mutability) => {
664 Some(ty::mk_box(this.tcx(),
665 ty::mt {ty: self_info.untransformed_self_ty,
669 Some(ty::mk_uniq(this.tcx(),
670 ty::mt {ty: self_info.untransformed_self_ty,
677 pub fn ty_of_closure<AC:AstConv,RS:region_scope + Clone + 'static>(
682 onceness: ast::Onceness,
683 bounds: ty::BuiltinBounds,
684 opt_lifetime: &Option<ast::Lifetime>,
686 expected_sig: Option<ty::FnSig>,
687 lifetimes: &OptVec<ast::Lifetime>,
691 // The caller should not both provide explicit bound lifetime
692 // names and expected types. Either we infer the bound lifetime
693 // names or they are provided, but not both.
694 assert!(lifetimes.is_empty() || expected_sig.is_none());
696 debug!("ty_of_fn_decl");
699 // resolve the function bound region in the original region
700 // scope `rscope`, not the scope of the function parameters
701 let bound_region = match opt_lifetime {
703 ast_region_to_region(this, rscope, span, opt_lifetime)
707 ast::OwnedSigil | ast::ManagedSigil => {
708 // @fn(), ~fn() default to static as the bound
712 ast::BorrowedSigil => {
713 // &fn() defaults as normal for an omitted lifetime:
714 ast_region_to_region(this, rscope, span, opt_lifetime)
720 // new region names that appear inside of the fn decl are bound to
721 // that function type
722 let bound_lifetime_names = bound_lifetimes(this, lifetimes);
724 in_binding_rscope(rscope,
725 RegionParamNames(bound_lifetime_names.clone()));
727 let input_tys = do decl.inputs.iter().enumerate().transform |(i, a)| {
728 let expected_arg_ty = do expected_sig.chain_ref |e| {
729 // no guarantee that the correct number of expected args
731 if i < e.inputs.len() {Some(e.inputs[i])} else {None}
733 ty_of_arg(this, &rb, a, expected_arg_ty)
736 let expected_ret_ty = expected_sig.map(|e| e.output);
737 let output_ty = match decl.output.node {
738 ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.unwrap(),
739 ast::ty_infer => this.ty_infer(decl.output.span),
740 _ => ast_ty_to_ty(this, &rb, &decl.output)
747 region: bound_region,
749 sig: ty::FnSig {bound_lifetime_names: bound_lifetime_names,
755 fn conv_builtin_bounds(tcx: ty::ctxt, ast_bounds: &Option<OptVec<ast::TyParamBound>>,
756 store: ty::TraitStore)
757 -> ty::BuiltinBounds {
758 //! Converts a list of bounds from the AST into a `BuiltinBounds`
759 //! struct. Reports an error if any of the bounds that appear
760 //! in the AST refer to general traits and not the built-in traits
761 //! like `Send`. Used to translate the bounds that
762 //! appear in closure and trait types, where only builtin bounds are
764 //! If no bounds were specified, we choose a "default" bound based on
765 //! the allocation type of the fn/trait, as per issue #7264. The user can
766 //! override this with an empty bounds list, e.g. "~fn:()" or "~Trait:".
768 match (ast_bounds, store) {
769 (&Some(ref bound_vec), _) => {
770 let mut builtin_bounds = ty::EmptyBuiltinBounds();
771 for ast_bound in bound_vec.iter() {
773 ast::TraitTyParamBound(ref b) => {
774 match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
775 ast::def_trait(trait_did) => {
776 if try_add_builtin_trait(tcx,
778 &mut builtin_bounds) {
786 fmt!("only the builtin traits can be used \
787 as closure or object bounds"));
789 ast::RegionTyParamBound => {
790 builtin_bounds.add(ty::BoundStatic);
796 // ~Trait is sugar for ~Trait:Send.
797 (&None, ty::UniqTraitStore) => {
798 let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundSend); set
800 // @Trait is sugar for @Trait:'static.
801 // &'static Trait is sugar for &'static Trait:'static.
802 (&None, ty::BoxTraitStore) |
803 (&None, ty::RegionTraitStore(ty::re_static)) => {
804 let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundStatic); set
806 // &'r Trait is sugar for &'r Trait:<no-bounds>.
807 (&None, ty::RegionTraitStore(*)) => ty::EmptyBuiltinBounds(),
811 pub fn try_add_builtin_trait(tcx: ty::ctxt,
812 trait_def_id: ast::def_id,
813 builtin_bounds: &mut ty::BuiltinBounds) -> bool {
814 //! Checks whether `trait_ref` refers to one of the builtin
815 //! traits, like `Send`, and adds the corresponding
816 //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref`
817 //! is a builtin trait.
819 let li = &tcx.lang_items;
820 if Some(trait_def_id) == li.send_trait() {
821 builtin_bounds.add(ty::BoundSend);
823 } else if Some(trait_def_id) == li.freeze_trait() {
824 builtin_bounds.add(ty::BoundFreeze);
826 } else if Some(trait_def_id) == li.sized_trait() {
827 builtin_bounds.add(ty::BoundSized);