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.
11 //! Conversion from AST representation of types to the ty.rs
12 //! representation. The main routine here is `ast_ty_to_ty()`: each use
13 //! is parameterized by an instance of `AstConv` and a `RegionScope`.
15 //! The parameterization of `ast_ty_to_ty()` is because it behaves
16 //! somewhat differently during the collect and check phases,
17 //! particularly with respect to looking up the types of top-level
18 //! items. In the collect phase, the crate context is used as the
19 //! `AstConv` instance; in this phase, the `get_item_type_scheme()`
20 //! function triggers a recursive call to `type_scheme_of_item()`
21 //! (note that `ast_ty_to_ty()` will detect recursive types and report
22 //! an error). In the check phase, when the FnCtxt is used as the
23 //! `AstConv`, `get_item_type_scheme()` just looks up the item type in
24 //! `tcx.tcache` (using `ty::lookup_item_type`).
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:
43 //! type foo<'a> = ...;
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.
51 use middle
::astconv_util
::{prim_ty_to_ty, check_path_args, NO_TPS, NO_REGIONS}
;
52 use middle
::const_eval
::{self, ConstVal}
;
53 use middle
::const_eval
::EvalHint
::UncheckedExprHint
;
55 use middle
::implicator
::object_region_bounds
;
56 use middle
::resolve_lifetime
as rl
;
57 use middle
::privacy
::{AllPublic, LastMod}
;
58 use middle
::subst
::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace}
;
60 use middle
::ty
::{self, RegionEscape, Ty, ToPredicate, HasTypeFlags}
;
62 use require_c_abi_if_variadic
;
63 use rscope
::{self, UnelidableRscope
, RegionScope
, ElidableRscope
,
64 ObjectLifetimeDefaultRscope
, ShiftedRscope
, BindingRscope
,
65 ElisionFailureInfo
, ElidedLifetime
};
66 use util
::common
::{ErrorReported, FN_OUTPUT_NAME}
;
67 use util
::nodemap
::FnvHashSet
;
70 use syntax
::{abi, ast, ast_util}
;
71 use syntax
::codemap
::{Span, Pos}
;
72 use syntax
::feature_gate
::emit_feature_err
;
73 use syntax
::parse
::token
;
74 use syntax
::print
::pprust
;
76 pub trait AstConv
<'tcx
> {
77 fn tcx
<'a
>(&'a
self) -> &'a ty
::ctxt
<'tcx
>;
79 /// Identify the type scheme for an item with a type, like a type
80 /// alias, fn, or struct. This allows you to figure out the set of
81 /// type parameters defined on the item.
82 fn get_item_type_scheme(&self, span
: Span
, id
: ast
::DefId
)
83 -> Result
<ty
::TypeScheme
<'tcx
>, ErrorReported
>;
85 /// Returns the `TraitDef` for a given trait. This allows you to
86 /// figure out the set of type parameters defined on the trait.
87 fn get_trait_def(&self, span
: Span
, id
: ast
::DefId
)
88 -> Result
<&'tcx ty
::TraitDef
<'tcx
>, ErrorReported
>;
90 /// Ensure that the super-predicates for the trait with the given
91 /// id are available and also for the transitive set of
93 fn ensure_super_predicates(&self, span
: Span
, id
: ast
::DefId
)
94 -> Result
<(), ErrorReported
>;
96 /// Returns the set of bounds in scope for the type parameter with
98 fn get_type_parameter_bounds(&self, span
: Span
, def_id
: ast
::NodeId
)
99 -> Result
<Vec
<ty
::PolyTraitRef
<'tcx
>>, ErrorReported
>;
101 /// Returns true if the trait with id `trait_def_id` defines an
102 /// associated type with the name `name`.
103 fn trait_defines_associated_type_named(&self, trait_def_id
: ast
::DefId
, name
: ast
::Name
)
106 /// Return an (optional) substitution to convert bound type parameters that
107 /// are in scope into free ones. This function should only return Some
108 /// within a fn body.
109 /// See ParameterEnvironment::free_substs for more information.
110 fn get_free_substs(&self) -> Option
<&Substs
<'tcx
>> {
114 /// What type should we use when a type is omitted?
116 param_and_substs
: Option
<ty
::TypeParameterDef
<'tcx
>>,
117 substs
: Option
<&mut Substs
<'tcx
>>,
118 space
: Option
<ParamSpace
>,
119 span
: Span
) -> Ty
<'tcx
>;
121 /// Projecting an associated type from a (potentially)
122 /// higher-ranked trait reference is more complicated, because of
123 /// the possibility of late-bound regions appearing in the
124 /// associated type binding. This is not legal in function
125 /// signatures for that reason. In a function body, we can always
126 /// handle it because we can use inference variables to remove the
127 /// late-bound regions.
128 fn projected_ty_from_poly_trait_ref(&self,
130 poly_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
131 item_name
: ast
::Name
)
134 if let Some(trait_ref
) = self.tcx().no_late_bound_regions(&poly_trait_ref
) {
135 self.projected_ty(span
, trait_ref
, item_name
)
137 // no late-bound regions, we can just ignore the binder
138 span_err
!(self.tcx().sess
, span
, E0212
,
139 "cannot extract an associated type from a higher-ranked trait bound \
145 /// Project an associated type from a non-higher-ranked trait reference.
146 /// This is fairly straightforward and can be accommodated in any context.
147 fn projected_ty(&self,
149 _trait_ref
: ty
::TraitRef
<'tcx
>,
150 _item_name
: ast
::Name
)
154 pub fn ast_region_to_region(tcx
: &ty
::ctxt
, lifetime
: &ast
::Lifetime
)
156 let r
= match tcx
.named_region_map
.get(&lifetime
.id
) {
158 // should have been recorded by the `resolve_lifetime` pass
159 tcx
.sess
.span_bug(lifetime
.span
, "unresolved lifetime");
162 Some(&rl
::DefStaticRegion
) => {
166 Some(&rl
::DefLateBoundRegion(debruijn
, id
)) => {
167 ty
::ReLateBound(debruijn
, ty
::BrNamed(ast_util
::local_def(id
), lifetime
.name
))
170 Some(&rl
::DefEarlyBoundRegion(space
, index
, id
)) => {
171 ty
::ReEarlyBound(ty
::EarlyBoundRegion
{
179 Some(&rl
::DefFreeRegion(scope
, id
)) => {
180 ty
::ReFree(ty
::FreeRegion
{
182 bound_region
: ty
::BrNamed(ast_util
::local_def(id
),
188 debug
!("ast_region_to_region(lifetime={:?} id={}) yields {:?}",
196 fn report_elision_failure(
199 params
: Vec
<ElisionFailureInfo
>)
201 let mut m
= String
::new();
202 let len
= params
.len();
203 for (i
, info
) in params
.into_iter().enumerate() {
204 let ElisionFailureInfo
{
205 name
, lifetime_count
: n
, have_bound_regions
208 let help_name
= if name
.is_empty() {
209 format
!("argument {}", i
+ 1)
211 format
!("`{}`", name
)
214 m
.push_str(&(if n
== 1 {
217 format
!("one of {}'s {} elided {}lifetimes", help_name
, n
,
218 if have_bound_regions { "free " }
else { "" }
)
221 if len
== 2 && i
== 0 {
223 } else if i
+ 2 == len
{
225 } else if i
+ 1 != len
{
230 fileline_help
!(tcx
.sess
, default_span
,
231 "this function's return type contains a borrowed value, but \
232 the signature does not say which {} it is borrowed from",
235 fileline_help
!(tcx
.sess
, default_span
,
236 "this function's return type contains a borrowed value, but \
237 there is no value for it to be borrowed from");
238 fileline_help
!(tcx
.sess
, default_span
,
239 "consider giving it a 'static lifetime");
241 fileline_help
!(tcx
.sess
, default_span
,
242 "this function's return type contains a borrowed value, but \
243 the signature does not say whether it is borrowed from {}",
248 pub fn opt_ast_region_to_region
<'tcx
>(
249 this
: &AstConv
<'tcx
>,
250 rscope
: &RegionScope
,
252 opt_lifetime
: &Option
<ast
::Lifetime
>) -> ty
::Region
254 let r
= match *opt_lifetime
{
255 Some(ref lifetime
) => {
256 ast_region_to_region(this
.tcx(), lifetime
)
259 None
=> match rscope
.anon_regions(default_span
, 1) {
262 span_err
!(this
.tcx().sess
, default_span
, E0106
,
263 "missing lifetime specifier");
264 if let Some(params
) = params
{
265 report_elision_failure(this
.tcx(), default_span
, params
);
272 debug
!("opt_ast_region_to_region(opt_lifetime={:?}) yields {:?}",
279 /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
280 /// returns an appropriate set of substitutions for this particular reference to `I`.
281 pub fn ast_path_substs_for_ty
<'tcx
>(
282 this
: &AstConv
<'tcx
>,
283 rscope
: &RegionScope
,
285 param_mode
: PathParamMode
,
286 decl_generics
: &ty
::Generics
<'tcx
>,
287 item_segment
: &ast
::PathSegment
)
290 let tcx
= this
.tcx();
292 // ast_path_substs() is only called to convert paths that are
293 // known to refer to traits, types, or structs. In these cases,
294 // all type parameters defined for the item being referenced will
295 // be in the TypeSpace or SelfSpace.
297 // Note: in the case of traits, the self parameter is also
298 // defined, but we don't currently create a `type_param_def` for
299 // `Self` because it is implicit.
300 assert
!(decl_generics
.regions
.all(|d
| d
.space
== TypeSpace
));
301 assert
!(decl_generics
.types
.all(|d
| d
.space
!= FnSpace
));
303 let (regions
, types
, assoc_bindings
) = match item_segment
.parameters
{
304 ast
::AngleBracketedParameters(ref data
) => {
305 convert_angle_bracketed_parameters(this
, rscope
, span
, decl_generics
, data
)
307 ast
::ParenthesizedParameters(..) => {
308 span_err
!(tcx
.sess
, span
, E0214
,
309 "parenthesized parameters may only be used with a trait");
310 let ty_param_defs
= decl_generics
.types
.get_slice(TypeSpace
);
312 ty_param_defs
.iter().map(|_
| tcx
.types
.err
).collect(),
317 prohibit_projections(this
.tcx(), &assoc_bindings
);
319 create_substs_for_ast_path(this
,
328 #[derive(PartialEq, Eq)]
329 pub enum PathParamMode
{
330 // Any path in a type context.
332 // The `module::Type` in `module::Type::method` in an expression.
336 fn create_region_substs
<'tcx
>(
337 this
: &AstConv
<'tcx
>,
338 rscope
: &RegionScope
,
340 decl_generics
: &ty
::Generics
<'tcx
>,
341 regions_provided
: Vec
<ty
::Region
>)
344 let tcx
= this
.tcx();
346 // If the type is parameterized by the this region, then replace this
347 // region with the current anon region binding (in other words,
348 // whatever & would get replaced with).
349 let expected_num_region_params
= decl_generics
.regions
.len(TypeSpace
);
350 let supplied_num_region_params
= regions_provided
.len();
351 let regions
= if expected_num_region_params
== supplied_num_region_params
{
355 rscope
.anon_regions(span
, expected_num_region_params
);
357 if supplied_num_region_params
!= 0 || anon_regions
.is_err() {
358 report_lifetime_number_error(tcx
, span
,
359 supplied_num_region_params
,
360 expected_num_region_params
);
364 Ok(anon_regions
) => anon_regions
,
365 Err(_
) => (0..expected_num_region_params
).map(|_
| ty
::ReStatic
).collect()
368 Substs
::new_type(vec
![], regions
)
371 /// Given the type/region arguments provided to some path (along with
372 /// an implicit Self, if this is a trait reference) returns the complete
373 /// set of substitutions. This may involve applying defaulted type parameters.
375 /// Note that the type listing given here is *exactly* what the user provided.
377 /// The `region_substs` should be the result of `create_region_substs`
378 /// -- that is, a substitution with no types but the correct number of
380 fn create_substs_for_ast_path
<'tcx
>(
381 this
: &AstConv
<'tcx
>,
383 param_mode
: PathParamMode
,
384 decl_generics
: &ty
::Generics
<'tcx
>,
385 self_ty
: Option
<Ty
<'tcx
>>,
386 types_provided
: Vec
<Ty
<'tcx
>>,
387 region_substs
: Substs
<'tcx
>)
390 let tcx
= this
.tcx();
392 debug
!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \
393 types_provided={:?}, region_substs={:?}",
394 decl_generics
, self_ty
, types_provided
,
397 assert_eq
!(region_substs
.regions().len(TypeSpace
), decl_generics
.regions
.len(TypeSpace
));
398 assert
!(region_substs
.types
.is_empty());
400 // Convert the type parameters supplied by the user.
401 let ty_param_defs
= decl_generics
.types
.get_slice(TypeSpace
);
402 let formal_ty_param_count
= ty_param_defs
.len();
403 let required_ty_param_count
= ty_param_defs
.iter()
404 .take_while(|x
| x
.default.is_none())
407 // Fill with `ty_infer` if no params were specified, as long as
408 // they were optional (e.g. paths inside expressions).
409 let mut type_substs
= if param_mode
== PathParamMode
::Optional
&&
410 types_provided
.is_empty() {
411 let mut substs
= region_substs
.clone();
414 .map(|p
| this
.ty_infer(Some(p
.clone()), Some(&mut substs
), Some(TypeSpace
), span
))
420 let supplied_ty_param_count
= type_substs
.len();
421 check_type_argument_count(this
.tcx(), span
, supplied_ty_param_count
,
422 required_ty_param_count
, formal_ty_param_count
);
424 if supplied_ty_param_count
< required_ty_param_count
{
425 while type_substs
.len() < required_ty_param_count
{
426 type_substs
.push(tcx
.types
.err
);
428 } else if supplied_ty_param_count
> formal_ty_param_count
{
429 type_substs
.truncate(formal_ty_param_count
);
431 assert
!(type_substs
.len() >= required_ty_param_count
&&
432 type_substs
.len() <= formal_ty_param_count
);
434 let mut substs
= region_substs
;
435 substs
.types
.extend(TypeSpace
, type_substs
.into_iter());
439 // If no self-type is provided, it's still possible that
440 // one was declared, because this could be an object type.
443 // If a self-type is provided, one should have been
444 // "declared" (in other words, this should be a
446 assert
!(decl_generics
.types
.get_self().is_some());
447 substs
.types
.push(SelfSpace
, ty
);
451 let actual_supplied_ty_param_count
= substs
.types
.len(TypeSpace
);
452 for param
in &ty_param_defs
[actual_supplied_ty_param_count
..] {
453 if let Some(default) = param
.default {
454 // If we are converting an object type, then the
455 // `Self` parameter is unknown. However, some of the
456 // other type parameters may reference `Self` in their
457 // defaults. This will lead to an ICE if we are not
459 if self_ty
.is_none() && default.has_self_ty() {
460 span_err
!(tcx
.sess
, span
, E0393
,
461 "the type parameter `{}` must be explicitly specified \
462 in an object type because its default value `{}` references \
466 substs
.types
.push(TypeSpace
, tcx
.types
.err
);
468 // This is a default type parameter.
469 let default = default.subst_spanned(tcx
,
472 substs
.types
.push(TypeSpace
, default);
475 tcx
.sess
.span_bug(span
, "extra parameter without default");
482 struct ConvertedBinding
<'tcx
> {
483 item_name
: ast
::Name
,
488 fn convert_angle_bracketed_parameters
<'tcx
>(this
: &AstConv
<'tcx
>,
489 rscope
: &RegionScope
,
491 decl_generics
: &ty
::Generics
<'tcx
>,
492 data
: &ast
::AngleBracketedParameterData
)
495 Vec
<ConvertedBinding
<'tcx
>>)
497 let regions
: Vec
<_
> =
498 data
.lifetimes
.iter()
499 .map(|l
| ast_region_to_region(this
.tcx(), l
))
503 create_region_substs(this
, rscope
, span
, decl_generics
, regions
);
508 .map(|(i
,t
)| ast_ty_arg_to_ty(this
, rscope
, decl_generics
,
509 i
, ®ion_substs
, t
))
512 let assoc_bindings
: Vec
<_
> =
514 .map(|b
| ConvertedBinding
{ item_name
: b
.ident
.name
,
515 ty
: ast_ty_to_ty(this
, rscope
, &*b
.ty
),
519 (region_substs
, types
, assoc_bindings
)
522 /// Returns the appropriate lifetime to use for any output lifetimes
523 /// (if one exists) and a vector of the (pattern, number of lifetimes)
524 /// corresponding to each input type/pattern.
525 fn find_implied_output_region
<'tcx
>(tcx
: &ty
::ctxt
<'tcx
>,
526 input_tys
: &[Ty
<'tcx
>],
527 input_pats
: Vec
<String
>) -> ElidedLifetime
529 let mut lifetimes_for_params
= Vec
::new();
530 let mut possible_implied_output_region
= None
;
532 for (input_type
, input_pat
) in input_tys
.iter().zip(input_pats
) {
533 let mut regions
= FnvHashSet();
534 let have_bound_regions
= ty_fold
::collect_regions(tcx
,
538 debug
!("find_implied_output_regions: collected {:?} from {:?} \
539 have_bound_regions={:?}", ®ions
, input_type
, have_bound_regions
);
541 if regions
.len() == 1 {
542 // there's a chance that the unique lifetime of this
543 // iteration will be the appropriate lifetime for output
544 // parameters, so lets store it.
545 possible_implied_output_region
= regions
.iter().cloned().next();
548 lifetimes_for_params
.push(ElisionFailureInfo
{
550 lifetime_count
: regions
.len(),
551 have_bound_regions
: have_bound_regions
555 if lifetimes_for_params
.iter().map(|e
| e
.lifetime_count
).sum
::<usize>() == 1 {
556 Ok(possible_implied_output_region
.unwrap())
558 Err(Some(lifetimes_for_params
))
562 fn convert_ty_with_lifetime_elision
<'tcx
>(this
: &AstConv
<'tcx
>,
563 elided_lifetime
: ElidedLifetime
,
567 match elided_lifetime
{
568 Ok(implied_output_region
) => {
569 let rb
= ElidableRscope
::new(implied_output_region
);
570 ast_ty_to_ty(this
, &rb
, ty
)
572 Err(param_lifetimes
) => {
573 // All regions must be explicitly specified in the output
574 // if the lifetime elision rules do not apply. This saves
575 // the user from potentially-confusing errors.
576 let rb
= UnelidableRscope
::new(param_lifetimes
);
577 ast_ty_to_ty(this
, &rb
, ty
)
582 fn convert_parenthesized_parameters
<'tcx
>(this
: &AstConv
<'tcx
>,
583 rscope
: &RegionScope
,
585 decl_generics
: &ty
::Generics
<'tcx
>,
586 data
: &ast
::ParenthesizedParameterData
)
589 Vec
<ConvertedBinding
<'tcx
>>)
592 create_region_substs(this
, rscope
, span
, decl_generics
, Vec
::new());
594 let binding_rscope
= BindingRscope
::new();
597 .map(|a_t
| ast_ty_arg_to_ty(this
, &binding_rscope
, decl_generics
,
598 0, ®ion_substs
, a_t
))
599 .collect
::<Vec
<Ty
<'tcx
>>>();
601 let input_params
= vec
![String
::new(); inputs
.len()];
602 let implied_output_region
= find_implied_output_region(this
.tcx(), &inputs
, input_params
);
604 let input_ty
= this
.tcx().mk_tup(inputs
);
606 let (output
, output_span
) = match data
.output
{
607 Some(ref output_ty
) => {
608 (convert_ty_with_lifetime_elision(this
,
609 implied_output_region
,
614 (this
.tcx().mk_nil(), data
.span
)
618 let output_binding
= ConvertedBinding
{
619 item_name
: token
::intern(FN_OUTPUT_NAME
),
624 (region_substs
, vec
![input_ty
], vec
![output_binding
])
627 pub fn instantiate_poly_trait_ref
<'tcx
>(
628 this
: &AstConv
<'tcx
>,
629 rscope
: &RegionScope
,
630 ast_trait_ref
: &ast
::PolyTraitRef
,
631 self_ty
: Option
<Ty
<'tcx
>>,
632 poly_projections
: &mut Vec
<ty
::PolyProjectionPredicate
<'tcx
>>)
633 -> ty
::PolyTraitRef
<'tcx
>
635 let trait_ref
= &ast_trait_ref
.trait_ref
;
636 let trait_def_id
= trait_def_id(this
, trait_ref
);
637 ast_path_to_poly_trait_ref(this
,
640 PathParamMode
::Explicit
,
643 trait_ref
.path
.segments
.last().unwrap(),
647 /// Instantiates the path for the given trait reference, assuming that it's
648 /// bound to a valid trait type. Returns the def_id for the defining trait.
649 /// Fails if the type is a type other than a trait type.
651 /// If the `projections` argument is `None`, then assoc type bindings like `Foo<T=X>`
652 /// are disallowed. Otherwise, they are pushed onto the vector given.
653 pub fn instantiate_mono_trait_ref
<'tcx
>(
654 this
: &AstConv
<'tcx
>,
655 rscope
: &RegionScope
,
656 trait_ref
: &ast
::TraitRef
,
657 self_ty
: Option
<Ty
<'tcx
>>)
658 -> ty
::TraitRef
<'tcx
>
660 let trait_def_id
= trait_def_id(this
, trait_ref
);
661 ast_path_to_mono_trait_ref(this
,
664 PathParamMode
::Explicit
,
667 trait_ref
.path
.segments
.last().unwrap())
670 fn trait_def_id
<'tcx
>(this
: &AstConv
<'tcx
>, trait_ref
: &ast
::TraitRef
) -> ast
::DefId
{
671 let path
= &trait_ref
.path
;
672 match ::lookup_full_def(this
.tcx(), path
.span
, trait_ref
.ref_id
) {
673 def
::DefTrait(trait_def_id
) => trait_def_id
,
675 span_fatal
!(this
.tcx().sess
, path
.span
, E0245
, "`{}` is not a trait",
681 fn object_path_to_poly_trait_ref
<'a
,'tcx
>(
682 this
: &AstConv
<'tcx
>,
683 rscope
: &RegionScope
,
685 param_mode
: PathParamMode
,
686 trait_def_id
: ast
::DefId
,
687 trait_segment
: &ast
::PathSegment
,
688 mut projections
: &mut Vec
<ty
::PolyProjectionPredicate
<'tcx
>>)
689 -> ty
::PolyTraitRef
<'tcx
>
691 ast_path_to_poly_trait_ref(this
,
701 fn ast_path_to_poly_trait_ref
<'a
,'tcx
>(
702 this
: &AstConv
<'tcx
>,
703 rscope
: &RegionScope
,
705 param_mode
: PathParamMode
,
706 trait_def_id
: ast
::DefId
,
707 self_ty
: Option
<Ty
<'tcx
>>,
708 trait_segment
: &ast
::PathSegment
,
709 poly_projections
: &mut Vec
<ty
::PolyProjectionPredicate
<'tcx
>>)
710 -> ty
::PolyTraitRef
<'tcx
>
712 // The trait reference introduces a binding level here, so
713 // we need to shift the `rscope`. It'd be nice if we could
714 // do away with this rscope stuff and work this knowledge
715 // into resolve_lifetimes, as we do with non-omitted
716 // lifetimes. Oh well, not there yet.
717 let shifted_rscope
= &ShiftedRscope
::new(rscope
);
719 let (substs
, assoc_bindings
) =
720 create_substs_for_ast_trait_ref(this
,
727 let poly_trait_ref
= ty
::Binder(ty
::TraitRef
::new(trait_def_id
, substs
));
730 let converted_bindings
=
733 .filter_map(|binding
| {
734 // specify type to assert that error was already reported in Err case:
735 let predicate
: Result
<_
, ErrorReported
> =
736 ast_type_binding_to_poly_projection_predicate(this
,
737 poly_trait_ref
.clone(),
740 predicate
.ok() // ok to ignore Err() because ErrorReported (see above)
742 poly_projections
.extend(converted_bindings
);
748 fn ast_path_to_mono_trait_ref
<'a
,'tcx
>(this
: &AstConv
<'tcx
>,
749 rscope
: &RegionScope
,
751 param_mode
: PathParamMode
,
752 trait_def_id
: ast
::DefId
,
753 self_ty
: Option
<Ty
<'tcx
>>,
754 trait_segment
: &ast
::PathSegment
)
755 -> ty
::TraitRef
<'tcx
>
757 let (substs
, assoc_bindings
) =
758 create_substs_for_ast_trait_ref(this
,
765 prohibit_projections(this
.tcx(), &assoc_bindings
);
766 ty
::TraitRef
::new(trait_def_id
, substs
)
769 fn create_substs_for_ast_trait_ref
<'a
,'tcx
>(this
: &AstConv
<'tcx
>,
770 rscope
: &RegionScope
,
772 param_mode
: PathParamMode
,
773 trait_def_id
: ast
::DefId
,
774 self_ty
: Option
<Ty
<'tcx
>>,
775 trait_segment
: &ast
::PathSegment
)
776 -> (&'tcx Substs
<'tcx
>, Vec
<ConvertedBinding
<'tcx
>>)
778 debug
!("create_substs_for_ast_trait_ref(trait_segment={:?})",
781 let trait_def
= match this
.get_trait_def(span
, trait_def_id
) {
782 Ok(trait_def
) => trait_def
,
783 Err(ErrorReported
) => {
784 // No convenient way to recover from a cycle here. Just bail. Sorry!
785 this
.tcx().sess
.abort_if_errors();
786 this
.tcx().sess
.bug("ErrorReported returned, but no errors reports?")
790 let (regions
, types
, assoc_bindings
) = match trait_segment
.parameters
{
791 ast
::AngleBracketedParameters(ref data
) => {
792 // For now, require that parenthetical notation be used
793 // only with `Fn()` etc.
794 if !this
.tcx().sess
.features
.borrow().unboxed_closures
&& trait_def
.paren_sugar
{
795 emit_feature_err(&this
.tcx().sess
.parse_sess
.span_diagnostic
,
796 "unboxed_closures", span
,
798 the precise format of `Fn`-family traits' type parameters is \
799 subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead");
802 convert_angle_bracketed_parameters(this
, rscope
, span
, &trait_def
.generics
, data
)
804 ast
::ParenthesizedParameters(ref data
) => {
805 // For now, require that parenthetical notation be used
806 // only with `Fn()` etc.
807 if !this
.tcx().sess
.features
.borrow().unboxed_closures
&& !trait_def
.paren_sugar
{
808 emit_feature_err(&this
.tcx().sess
.parse_sess
.span_diagnostic
,
809 "unboxed_closures", span
,
811 parenthetical notation is only stable when used with `Fn`-family traits");
814 convert_parenthesized_parameters(this
, rscope
, span
, &trait_def
.generics
, data
)
818 let substs
= create_substs_for_ast_path(this
,
826 (this
.tcx().mk_substs(substs
), assoc_bindings
)
829 fn ast_type_binding_to_poly_projection_predicate
<'tcx
>(
830 this
: &AstConv
<'tcx
>,
831 mut trait_ref
: ty
::PolyTraitRef
<'tcx
>,
832 self_ty
: Option
<Ty
<'tcx
>>,
833 binding
: &ConvertedBinding
<'tcx
>)
834 -> Result
<ty
::PolyProjectionPredicate
<'tcx
>, ErrorReported
>
836 let tcx
= this
.tcx();
838 // Given something like `U : SomeTrait<T=X>`, we want to produce a
839 // predicate like `<U as SomeTrait>::T = X`. This is somewhat
840 // subtle in the event that `T` is defined in a supertrait of
841 // `SomeTrait`, because in that case we need to upcast.
843 // That is, consider this case:
846 // trait SubTrait : SuperTrait<int> { }
847 // trait SuperTrait<A> { type T; }
849 // ... B : SubTrait<T=foo> ...
852 // We want to produce `<B as SuperTrait<int>>::T == foo`.
854 // Simple case: X is defined in the current trait.
855 if this
.trait_defines_associated_type_named(trait_ref
.def_id(), binding
.item_name
) {
856 return Ok(ty
::Binder(ty
::ProjectionPredicate
{ // <-------------------+
857 projection_ty
: ty
::ProjectionTy
{ // |
858 trait_ref
: trait_ref
.skip_binder().clone(), // Binder moved here --+
859 item_name
: binding
.item_name
,
865 // Otherwise, we have to walk through the supertraits to find
866 // those that do. This is complicated by the fact that, for an
867 // object type, the `Self` type is not present in the
868 // substitutions (after all, it's being constructed right now),
869 // but the `supertraits` iterator really wants one. To handle
870 // this, we currently insert a dummy type and then remove it
873 let dummy_self_ty
= tcx
.mk_infer(ty
::FreshTy(0));
874 if self_ty
.is_none() { // if converting for an object type
875 let mut dummy_substs
= trait_ref
.skip_binder().substs
.clone(); // binder moved here -+
876 assert
!(dummy_substs
.self_ty().is_none()); // |
877 dummy_substs
.types
.push(SelfSpace
, dummy_self_ty
); // |
878 trait_ref
= ty
::Binder(ty
::TraitRef
::new(trait_ref
.def_id(), // <------------+
879 tcx
.mk_substs(dummy_substs
)));
882 try
!(this
.ensure_super_predicates(binding
.span
, trait_ref
.def_id()));
884 let mut candidates
: Vec
<ty
::PolyTraitRef
> =
885 traits
::supertraits(tcx
, trait_ref
.clone())
886 .filter(|r
| this
.trait_defines_associated_type_named(r
.def_id(), binding
.item_name
))
889 // If converting for an object type, then remove the dummy-ty from `Self` now.
891 if self_ty
.is_none() {
892 for candidate
in &mut candidates
{
893 let mut dummy_substs
= candidate
.0.substs
.clone();
894 assert
!(dummy_substs
.self_ty() == Some(dummy_self_ty
));
895 dummy_substs
.types
.pop(SelfSpace
);
896 *candidate
= ty
::Binder(ty
::TraitRef
::new(candidate
.def_id(),
897 tcx
.mk_substs(dummy_substs
)));
901 let candidate
= try
!(one_bound_for_assoc_type(tcx
,
903 &trait_ref
.to_string(),
904 &binding
.item_name
.as_str(),
907 Ok(ty
::Binder(ty
::ProjectionPredicate
{ // <-------------------------+
908 projection_ty
: ty
::ProjectionTy
{ // |
909 trait_ref
: candidate
.skip_binder().clone(), // binder is moved up here --+
910 item_name
: binding
.item_name
,
916 fn ast_path_to_ty
<'tcx
>(
917 this
: &AstConv
<'tcx
>,
918 rscope
: &RegionScope
,
920 param_mode
: PathParamMode
,
922 item_segment
: &ast
::PathSegment
)
925 let tcx
= this
.tcx();
926 let (generics
, decl_ty
) = match this
.get_item_type_scheme(span
, did
) {
927 Ok(ty
::TypeScheme { generics, ty: decl_ty }
) => {
930 Err(ErrorReported
) => {
931 return tcx
.types
.err
;
935 let substs
= ast_path_substs_for_ty(this
,
942 // FIXME(#12938): This is a hack until we have full support for DST.
943 if Some(did
) == this
.tcx().lang_items
.owned_box() {
944 assert_eq
!(substs
.types
.len(TypeSpace
), 1);
945 return this
.tcx().mk_box(*substs
.types
.get(TypeSpace
, 0));
948 decl_ty
.subst(this
.tcx(), &substs
)
951 type TraitAndProjections
<'tcx
> = (ty
::PolyTraitRef
<'tcx
>, Vec
<ty
::PolyProjectionPredicate
<'tcx
>>);
953 fn ast_ty_to_trait_ref
<'tcx
>(this
: &AstConv
<'tcx
>,
954 rscope
: &RegionScope
,
956 bounds
: &[ast
::TyParamBound
])
957 -> Result
<TraitAndProjections
<'tcx
>, ErrorReported
>
960 * In a type like `Foo + Send`, we want to wait to collect the
961 * full set of bounds before we make the object type, because we
962 * need them to infer a region bound. (For example, if we tried
963 * made a type from just `Foo`, then it wouldn't be enough to
964 * infer a 'static bound, and hence the user would get an error.)
965 * So this function is used when we're dealing with a sum type to
966 * convert the LHS. It only accepts a type that refers to a trait
967 * name, and reports an error otherwise.
971 ast
::TyPath(None
, ref path
) => {
972 let def
= match this
.tcx().def_map
.borrow().get(&ty
.id
) {
973 Some(&def
::PathResolution { base_def, depth: 0, .. }
) => Some(base_def
),
977 Some(def
::DefTrait(trait_def_id
)) => {
978 let mut projection_bounds
= Vec
::new();
979 let trait_ref
= object_path_to_poly_trait_ref(this
,
982 PathParamMode
::Explicit
,
984 path
.segments
.last().unwrap(),
985 &mut projection_bounds
);
986 Ok((trait_ref
, projection_bounds
))
989 span_err
!(this
.tcx().sess
, ty
.span
, E0172
, "expected a reference to a trait");
995 span_err
!(this
.tcx().sess
, ty
.span
, E0178
,
996 "expected a path on the left-hand side of `+`, not `{}`",
997 pprust
::ty_to_string(ty
));
998 let hi
= bounds
.iter().map(|x
| match *x
{
999 ast
::TraitTyParamBound(ref tr
, _
) => tr
.span
.hi
,
1000 ast
::RegionTyParamBound(ref r
) => r
.span
.hi
,
1001 }).max_by(|x
| x
.to_usize());
1002 let full_span
= hi
.map(|hi
| Span
{
1005 expn_id
: ty
.span
.expn_id
,
1007 match (&ty
.node
, full_span
) {
1008 (&ast
::TyRptr(None
, ref mut_ty
), Some(full_span
)) => {
1009 let mutbl_str
= if mut_ty
.mutbl
== ast
::MutMutable { "mut " }
else { "" }
;
1011 .span_suggestion(full_span
, "try adding parentheses (per RFC 438):",
1012 format
!("&{}({} +{})",
1014 pprust
::ty_to_string(&*mut_ty
.ty
),
1015 pprust
::bounds_to_string(bounds
)));
1017 (&ast
::TyRptr(Some(ref lt
), ref mut_ty
), Some(full_span
)) => {
1018 let mutbl_str
= if mut_ty
.mutbl
== ast
::MutMutable { "mut " }
else { "" }
;
1020 .span_suggestion(full_span
, "try adding parentheses (per RFC 438):",
1021 format
!("&{} {}({} +{})",
1022 pprust
::lifetime_to_string(lt
),
1024 pprust
::ty_to_string(&*mut_ty
.ty
),
1025 pprust
::bounds_to_string(bounds
)));
1029 fileline_help
!(this
.tcx().sess
, ty
.span
,
1030 "perhaps you forgot parentheses? (per RFC 438)");
1038 fn trait_ref_to_object_type
<'tcx
>(this
: &AstConv
<'tcx
>,
1039 rscope
: &RegionScope
,
1041 trait_ref
: ty
::PolyTraitRef
<'tcx
>,
1042 projection_bounds
: Vec
<ty
::PolyProjectionPredicate
<'tcx
>>,
1043 bounds
: &[ast
::TyParamBound
])
1046 let existential_bounds
= conv_existential_bounds(this
,
1053 let result
= make_object_type(this
, span
, trait_ref
, existential_bounds
);
1054 debug
!("trait_ref_to_object_type: result={:?}",
1060 fn make_object_type
<'tcx
>(this
: &AstConv
<'tcx
>,
1062 principal
: ty
::PolyTraitRef
<'tcx
>,
1063 bounds
: ty
::ExistentialBounds
<'tcx
>)
1065 let tcx
= this
.tcx();
1066 let object
= ty
::TraitTy
{
1067 principal
: principal
,
1070 let object_trait_ref
=
1071 object
.principal_trait_ref_with_self_ty(tcx
, tcx
.types
.err
);
1073 // ensure the super predicates and stop if we encountered an error
1074 if this
.ensure_super_predicates(span
, object
.principal_def_id()).is_err() {
1075 return tcx
.types
.err
;
1078 let mut associated_types
: FnvHashSet
<(ast
::DefId
, ast
::Name
)> =
1079 traits
::supertraits(tcx
, object_trait_ref
)
1081 let trait_def
= tcx
.lookup_trait_def(tr
.def_id());
1082 trait_def
.associated_type_names
1085 .map(move |associated_type_name
| (tr
.def_id(), associated_type_name
))
1089 for projection_bound
in &object
.bounds
.projection_bounds
{
1090 let pair
= (projection_bound
.0.projection_ty
.trait_ref
.def_id
,
1091 projection_bound
.0.projection_ty
.item_name
);
1092 associated_types
.remove(&pair
);
1095 for (trait_def_id
, name
) in associated_types
{
1096 span_err
!(tcx
.sess
, span
, E0191
,
1097 "the value of the associated type `{}` (from the trait `{}`) must be specified",
1099 tcx
.item_path_str(trait_def_id
));
1102 tcx
.mk_trait(object
.principal
, object
.bounds
)
1105 fn report_ambiguous_associated_type(tcx
: &ty
::ctxt
,
1110 span_err
!(tcx
.sess
, span
, E0223
,
1111 "ambiguous associated type; specify the type using the syntax \
1113 type_str
, trait_str
, name
);
1116 // Search for a bound on a type parameter which includes the associated item
1117 // given by assoc_name. ty_param_node_id is the node id for the type parameter
1118 // (which might be `Self`, but only if it is the `Self` of a trait, not an
1119 // impl). This function will fail if there are no suitable bounds or there is
1121 fn find_bound_for_assoc_item
<'tcx
>(this
: &AstConv
<'tcx
>,
1122 ty_param_node_id
: ast
::NodeId
,
1123 ty_param_name
: ast
::Name
,
1124 assoc_name
: ast
::Name
,
1126 -> Result
<ty
::PolyTraitRef
<'tcx
>, ErrorReported
>
1128 let tcx
= this
.tcx();
1130 let bounds
= match this
.get_type_parameter_bounds(span
, ty_param_node_id
) {
1132 Err(ErrorReported
) => {
1133 return Err(ErrorReported
);
1137 // Ensure the super predicates and stop if we encountered an error.
1138 if bounds
.iter().any(|b
| this
.ensure_super_predicates(span
, b
.def_id()).is_err()) {
1139 return Err(ErrorReported
);
1142 // Check that there is exactly one way to find an associated type with the
1144 let suitable_bounds
: Vec
<_
> =
1145 traits
::transitive_bounds(tcx
, &bounds
)
1146 .filter(|b
| this
.trait_defines_associated_type_named(b
.def_id(), assoc_name
))
1149 one_bound_for_assoc_type(tcx
,
1151 &ty_param_name
.as_str(),
1152 &assoc_name
.as_str(),
1157 // Checks that bounds contains exactly one element and reports appropriate
1158 // errors otherwise.
1159 fn one_bound_for_assoc_type
<'tcx
>(tcx
: &ty
::ctxt
<'tcx
>,
1160 bounds
: Vec
<ty
::PolyTraitRef
<'tcx
>>,
1161 ty_param_name
: &str,
1164 -> Result
<ty
::PolyTraitRef
<'tcx
>, ErrorReported
>
1166 if bounds
.is_empty() {
1167 span_err
!(tcx
.sess
, span
, E0220
,
1168 "associated type `{}` not found for `{}`",
1171 return Err(ErrorReported
);
1174 if bounds
.len() > 1 {
1175 span_err
!(tcx
.sess
, span
, E0221
,
1176 "ambiguous associated type `{}` in bounds of `{}`",
1180 for bound
in &bounds
{
1181 span_note
!(tcx
.sess
, span
,
1182 "associated type `{}` could derive from `{}`",
1188 Ok(bounds
[0].clone())
1191 // Create a type from a a path to an associated type.
1192 // For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
1193 // and item_segment is the path segment for D. We return a type and a def for
1195 // Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
1196 // parameter or Self.
1197 fn associated_path_def_to_ty
<'tcx
>(this
: &AstConv
<'tcx
>,
1200 ty_path_def
: def
::Def
,
1201 item_segment
: &ast
::PathSegment
)
1202 -> (Ty
<'tcx
>, def
::Def
)
1204 let tcx
= this
.tcx();
1205 let assoc_name
= item_segment
.identifier
.name
;
1207 debug
!("associated_path_def_to_ty: {:?}::{}", ty
, assoc_name
);
1209 check_path_args(tcx
, slice
::ref_slice(item_segment
), NO_TPS
| NO_REGIONS
);
1211 // Find the type of the associated item, and the trait where the associated
1212 // item is declared.
1213 let bound
= match (&ty
.sty
, ty_path_def
) {
1214 (_
, def
::DefSelfTy(Some(trait_did
), Some((impl_id
, _
)))) => {
1215 // `Self` in an impl of a trait - we have a concrete self type and a
1217 let trait_ref
= tcx
.impl_trait_ref(ast_util
::local_def(impl_id
)).unwrap();
1218 let trait_ref
= if let Some(free_substs
) = this
.get_free_substs() {
1219 trait_ref
.subst(tcx
, free_substs
)
1224 if this
.ensure_super_predicates(span
, trait_did
).is_err() {
1225 return (tcx
.types
.err
, ty_path_def
);
1228 let candidates
: Vec
<ty
::PolyTraitRef
> =
1229 traits
::supertraits(tcx
, ty
::Binder(trait_ref
))
1230 .filter(|r
| this
.trait_defines_associated_type_named(r
.def_id(),
1234 match one_bound_for_assoc_type(tcx
,
1237 &assoc_name
.as_str(),
1240 Err(ErrorReported
) => return (tcx
.types
.err
, ty_path_def
),
1243 (&ty
::TyParam(_
), def
::DefSelfTy(Some(trait_did
), None
)) => {
1244 assert_eq
!(trait_did
.krate
, ast
::LOCAL_CRATE
);
1245 match find_bound_for_assoc_item(this
,
1247 token
::special_idents
::type_self
.name
,
1251 Err(ErrorReported
) => return (tcx
.types
.err
, ty_path_def
),
1254 (&ty
::TyParam(_
), def
::DefTyParam(_
, _
, param_did
, param_name
)) => {
1255 assert_eq
!(param_did
.krate
, ast
::LOCAL_CRATE
);
1256 match find_bound_for_assoc_item(this
,
1262 Err(ErrorReported
) => return (tcx
.types
.err
, ty_path_def
),
1266 report_ambiguous_associated_type(tcx
,
1270 &assoc_name
.as_str());
1271 return (tcx
.types
.err
, ty_path_def
);
1275 let trait_did
= bound
.0.def_id
;
1276 let ty
= this
.projected_ty_from_poly_trait_ref(span
, bound
, assoc_name
);
1278 let item_did
= if trait_did
.krate
== ast
::LOCAL_CRATE
{
1279 // `ty::trait_items` used below requires information generated
1280 // by type collection, which may be in progress at this point.
1281 match tcx
.map
.expect_item(trait_did
.node
).node
{
1282 ast
::ItemTrait(_
, _
, _
, ref trait_items
) => {
1283 let item
= trait_items
.iter()
1284 .find(|i
| i
.ident
.name
== assoc_name
)
1285 .expect("missing associated type");
1286 ast_util
::local_def(item
.id
)
1291 let trait_items
= tcx
.trait_items(trait_did
);
1292 let item
= trait_items
.iter().find(|i
| i
.name() == assoc_name
);
1293 item
.expect("missing associated type").def_id()
1296 (ty
, def
::DefAssociatedTy(trait_did
, item_did
))
1299 fn qpath_to_ty
<'tcx
>(this
: &AstConv
<'tcx
>,
1300 rscope
: &RegionScope
,
1302 param_mode
: PathParamMode
,
1303 opt_self_ty
: Option
<Ty
<'tcx
>>,
1304 trait_def_id
: ast
::DefId
,
1305 trait_segment
: &ast
::PathSegment
,
1306 item_segment
: &ast
::PathSegment
)
1309 let tcx
= this
.tcx();
1311 check_path_args(tcx
, slice
::ref_slice(item_segment
), NO_TPS
| NO_REGIONS
);
1313 let self_ty
= if let Some(ty
) = opt_self_ty
{
1316 let path_str
= tcx
.item_path_str(trait_def_id
);
1317 report_ambiguous_associated_type(tcx
,
1321 &item_segment
.identifier
.name
.as_str());
1322 return tcx
.types
.err
;
1325 debug
!("qpath_to_ty: self_type={:?}", self_ty
);
1327 let trait_ref
= ast_path_to_mono_trait_ref(this
,
1335 debug
!("qpath_to_ty: trait_ref={:?}", trait_ref
);
1337 this
.projected_ty(span
, trait_ref
, item_segment
.identifier
.name
)
1340 /// Convert a type supplied as value for a type argument from AST into our
1341 /// our internal representation. This is the same as `ast_ty_to_ty` but that
1342 /// it applies the object lifetime default.
1346 /// * `this`, `rscope`: the surrounding context
1347 /// * `decl_generics`: the generics of the struct/enum/trait declaration being
1349 /// * `index`: the index of the type parameter being instantiated from the list
1350 /// (we assume it is in the `TypeSpace`)
1351 /// * `region_substs`: a partial substitution consisting of
1352 /// only the region type parameters being supplied to this type.
1353 /// * `ast_ty`: the ast representation of the type being supplied
1354 pub fn ast_ty_arg_to_ty
<'tcx
>(this
: &AstConv
<'tcx
>,
1355 rscope
: &RegionScope
,
1356 decl_generics
: &ty
::Generics
<'tcx
>,
1358 region_substs
: &Substs
<'tcx
>,
1362 let tcx
= this
.tcx();
1364 if let Some(def
) = decl_generics
.types
.opt_get(TypeSpace
, index
) {
1365 let object_lifetime_default
= def
.object_lifetime_default
.subst(tcx
, region_substs
);
1366 let rscope1
= &ObjectLifetimeDefaultRscope
::new(rscope
, object_lifetime_default
);
1367 ast_ty_to_ty(this
, rscope1
, ast_ty
)
1369 ast_ty_to_ty(this
, rscope
, ast_ty
)
1373 // Check the base def in a PathResolution and convert it to a Ty. If there are
1374 // associated types in the PathResolution, these will need to be separately
1376 fn base_def_to_ty
<'tcx
>(this
: &AstConv
<'tcx
>,
1377 rscope
: &RegionScope
,
1379 param_mode
: PathParamMode
,
1381 opt_self_ty
: Option
<Ty
<'tcx
>>,
1382 base_segments
: &[ast
::PathSegment
])
1384 let tcx
= this
.tcx();
1387 def
::DefTrait(trait_def_id
) => {
1388 // N.B. this case overlaps somewhat with
1389 // TyObjectSum, see that fn for details
1390 let mut projection_bounds
= Vec
::new();
1392 let trait_ref
= object_path_to_poly_trait_ref(this
,
1397 base_segments
.last().unwrap(),
1398 &mut projection_bounds
);
1400 check_path_args(tcx
, base_segments
.split_last().unwrap().1, NO_TPS
| NO_REGIONS
);
1401 trait_ref_to_object_type(this
,
1408 def
::DefTy(did
, _
) | def
::DefStruct(did
) => {
1409 check_path_args(tcx
, base_segments
.split_last().unwrap().1, NO_TPS
| NO_REGIONS
);
1410 ast_path_to_ty(this
,
1415 base_segments
.last().unwrap())
1417 def
::DefTyParam(space
, index
, _
, name
) => {
1418 check_path_args(tcx
, base_segments
, NO_TPS
| NO_REGIONS
);
1419 tcx
.mk_param(space
, index
, name
)
1421 def
::DefSelfTy(_
, Some((_
, self_ty_id
))) => {
1422 // Self in impl (we know the concrete type).
1423 check_path_args(tcx
, base_segments
, NO_TPS
| NO_REGIONS
);
1424 if let Some(&ty
) = tcx
.ast_ty_to_ty_cache
.borrow().get(&self_ty_id
) {
1425 if let Some(free_substs
) = this
.get_free_substs() {
1426 ty
.subst(tcx
, free_substs
)
1431 tcx
.sess
.span_bug(span
, "self type has not been fully resolved")
1434 def
::DefSelfTy(Some(_
), None
) => {
1436 check_path_args(tcx
, base_segments
, NO_TPS
| NO_REGIONS
);
1439 def
::DefAssociatedTy(trait_did
, _
) => {
1440 check_path_args(tcx
, &base_segments
[..base_segments
.len()-2], NO_TPS
| NO_REGIONS
);
1447 &base_segments
[base_segments
.len()-2],
1448 base_segments
.last().unwrap())
1450 def
::DefMod(id
) => {
1451 // Used as sentinel by callers to indicate the `<T>::A::B::C` form.
1452 // FIXME(#22519) This part of the resolution logic should be
1453 // avoided entirely for that form, once we stop needed a Def
1454 // for `associated_path_def_to_ty`.
1455 // Fixing this will also let use resolve <Self>::Foo the same way we
1456 // resolve Self::Foo, at the moment we can't resolve the former because
1457 // we don't have the trait information around, which is just sad.
1459 if !base_segments
.is_empty() {
1463 "found module name used as a type: {}",
1464 tcx
.map
.node_to_string(id
.node
));
1465 return this
.tcx().types
.err
;
1468 opt_self_ty
.expect("missing T in <T>::a::b::c")
1470 def
::DefPrimTy(prim_ty
) => {
1471 prim_ty_to_ty(tcx
, base_segments
, prim_ty
)
1474 let node
= def
.def_id().node
;
1475 span_err
!(tcx
.sess
, span
, E0248
,
1476 "found value `{}` used as a type",
1477 tcx
.map
.path_to_string(node
));
1478 return this
.tcx().types
.err
;
1483 // Note that both base_segments and assoc_segments may be empty, although not at
1485 pub fn finish_resolving_def_to_ty
<'tcx
>(this
: &AstConv
<'tcx
>,
1486 rscope
: &RegionScope
,
1488 param_mode
: PathParamMode
,
1490 opt_self_ty
: Option
<Ty
<'tcx
>>,
1491 base_segments
: &[ast
::PathSegment
],
1492 assoc_segments
: &[ast
::PathSegment
])
1494 let mut ty
= base_def_to_ty(this
,
1502 // If any associated type segments remain, attempt to resolve them.
1503 for segment
in assoc_segments
{
1504 if ty
.sty
== ty
::TyError
{
1507 // This is pretty bad (it will fail except for T::A and Self::A).
1508 let (a_ty
, a_def
) = associated_path_def_to_ty(this
,
1519 /// Parses the programmer's textual representation of a type into our
1520 /// internal notion of a type.
1521 pub fn ast_ty_to_ty
<'tcx
>(this
: &AstConv
<'tcx
>,
1522 rscope
: &RegionScope
,
1526 debug
!("ast_ty_to_ty(ast_ty={:?})",
1529 let tcx
= this
.tcx();
1531 if let Some(&ty
) = tcx
.ast_ty_to_ty_cache
.borrow().get(&ast_ty
.id
) {
1535 let typ
= match ast_ty
.node
{
1536 ast
::TyVec(ref ty
) => {
1537 tcx
.mk_slice(ast_ty_to_ty(this
, rscope
, &**ty
))
1539 ast
::TyObjectSum(ref ty
, ref bounds
) => {
1540 match ast_ty_to_trait_ref(this
, rscope
, &**ty
, bounds
) {
1541 Ok((trait_ref
, projection_bounds
)) => {
1542 trait_ref_to_object_type(this
,
1549 Err(ErrorReported
) => {
1550 this
.tcx().types
.err
1554 ast
::TyPtr(ref mt
) => {
1555 tcx
.mk_ptr(ty
::TypeAndMut
{
1556 ty
: ast_ty_to_ty(this
, rscope
, &*mt
.ty
),
1560 ast
::TyRptr(ref region
, ref mt
) => {
1561 let r
= opt_ast_region_to_region(this
, rscope
, ast_ty
.span
, region
);
1562 debug
!("TyRef r={:?}", r
);
1564 &ObjectLifetimeDefaultRscope
::new(
1566 ty
::ObjectLifetimeDefault
::Specific(r
));
1567 let t
= ast_ty_to_ty(this
, rscope1
, &*mt
.ty
);
1568 tcx
.mk_ref(tcx
.mk_region(r
), ty
::TypeAndMut {ty: t, mutbl: mt.mutbl}
)
1570 ast
::TyTup(ref fields
) => {
1571 let flds
= fields
.iter()
1572 .map(|t
| ast_ty_to_ty(this
, rscope
, &**t
))
1576 ast
::TyParen(ref typ
) => ast_ty_to_ty(this
, rscope
, &**typ
),
1577 ast
::TyBareFn(ref bf
) => {
1578 require_c_abi_if_variadic(tcx
, &bf
.decl
, bf
.abi
, ast_ty
.span
);
1579 let bare_fn
= ty_of_bare_fn(this
, bf
.unsafety
, bf
.abi
, &*bf
.decl
);
1580 tcx
.mk_fn(None
, tcx
.mk_bare_fn(bare_fn
))
1582 ast
::TyPolyTraitRef(ref bounds
) => {
1583 conv_ty_poly_trait_ref(this
, rscope
, ast_ty
.span
, bounds
)
1585 ast
::TyPath(ref maybe_qself
, ref path
) => {
1586 let path_res
= if let Some(&d
) = tcx
.def_map
.borrow().get(&ast_ty
.id
) {
1588 } else if let Some(ast
::QSelf { position: 0, .. }
) = *maybe_qself
{
1589 // Create some fake resolution that can't possibly be a type.
1590 def
::PathResolution
{
1591 base_def
: def
::DefMod(ast_util
::local_def(ast
::CRATE_NODE_ID
)),
1592 last_private
: LastMod(AllPublic
),
1593 depth
: path
.segments
.len()
1596 tcx
.sess
.span_bug(ast_ty
.span
, &format
!("unbound path {:?}", ast_ty
))
1598 let def
= path_res
.base_def
;
1599 let base_ty_end
= path
.segments
.len() - path_res
.depth
;
1600 let opt_self_ty
= maybe_qself
.as_ref().map(|qself
| {
1601 ast_ty_to_ty(this
, rscope
, &qself
.ty
)
1603 let ty
= finish_resolving_def_to_ty(this
,
1606 PathParamMode
::Explicit
,
1609 &path
.segments
[..base_ty_end
],
1610 &path
.segments
[base_ty_end
..]);
1612 if path_res
.depth
!= 0 && ty
.sty
!= ty
::TyError
{
1613 // Write back the new resolution.
1614 tcx
.def_map
.borrow_mut().insert(ast_ty
.id
, def
::PathResolution
{
1616 last_private
: path_res
.last_private
,
1623 ast
::TyFixedLengthVec(ref ty
, ref e
) => {
1624 let hint
= UncheckedExprHint(tcx
.types
.usize);
1625 match const_eval
::eval_const_expr_partial(tcx
, &e
, hint
) {
1629 tcx
.mk_array(ast_ty_to_ty(this
, rscope
, &**ty
),
1631 ConstVal
::Uint(i
) =>
1632 tcx
.mk_array(ast_ty_to_ty(this
, rscope
, &**ty
),
1635 span_err
!(tcx
.sess
, ast_ty
.span
, E0249
,
1636 "expected constant integer expression \
1638 this
.tcx().types
.err
1644 ast_ty
.span
.lo
<= r
.span
.lo
&& r
.span
.hi
<= ast_ty
.span
.hi
;
1645 span_err
!(tcx
.sess
, r
.span
, E0250
,
1646 "array length constant evaluation error: {}",
1649 span_note
!(tcx
.sess
, ast_ty
.span
, "for array length here")
1651 this
.tcx().types
.err
1655 ast
::TyTypeof(ref _e
) => {
1656 tcx
.sess
.span_bug(ast_ty
.span
, "typeof is reserved but unimplemented");
1659 // TyInfer also appears as the type of arguments or return
1660 // values in a ExprClosure, or as
1661 // the type of local variables. Both of these cases are
1662 // handled specially and will not descend into this routine.
1663 this
.ty_infer(None
, None
, None
, ast_ty
.span
)
1667 tcx
.ast_ty_to_ty_cache
.borrow_mut().insert(ast_ty
.id
, typ
);
1671 pub fn ty_of_arg
<'tcx
>(this
: &AstConv
<'tcx
>,
1672 rscope
: &RegionScope
,
1674 expected_ty
: Option
<Ty
<'tcx
>>)
1678 ast
::TyInfer
if expected_ty
.is_some() => expected_ty
.unwrap(),
1679 ast
::TyInfer
=> this
.ty_infer(None
, None
, None
, a
.ty
.span
),
1680 _
=> ast_ty_to_ty(this
, rscope
, &*a
.ty
),
1684 struct SelfInfo
<'a
, 'tcx
> {
1685 untransformed_self_ty
: Ty
<'tcx
>,
1686 explicit_self
: &'a ast
::ExplicitSelf
,
1689 pub fn ty_of_method
<'tcx
>(this
: &AstConv
<'tcx
>,
1690 sig
: &ast
::MethodSig
,
1691 untransformed_self_ty
: Ty
<'tcx
>)
1692 -> (ty
::BareFnTy
<'tcx
>, ty
::ExplicitSelfCategory
) {
1693 let self_info
= Some(SelfInfo
{
1694 untransformed_self_ty
: untransformed_self_ty
,
1695 explicit_self
: &sig
.explicit_self
,
1697 let (bare_fn_ty
, optional_explicit_self_category
) =
1698 ty_of_method_or_bare_fn(this
,
1703 (bare_fn_ty
, optional_explicit_self_category
.unwrap())
1706 pub fn ty_of_bare_fn
<'tcx
>(this
: &AstConv
<'tcx
>, unsafety
: ast
::Unsafety
, abi
: abi
::Abi
,
1707 decl
: &ast
::FnDecl
) -> ty
::BareFnTy
<'tcx
> {
1708 let (bare_fn_ty
, _
) = ty_of_method_or_bare_fn(this
, unsafety
, abi
, None
, decl
);
1712 fn ty_of_method_or_bare_fn
<'a
, 'tcx
>(this
: &AstConv
<'tcx
>,
1713 unsafety
: ast
::Unsafety
,
1715 opt_self_info
: Option
<SelfInfo
<'a
, 'tcx
>>,
1717 -> (ty
::BareFnTy
<'tcx
>, Option
<ty
::ExplicitSelfCategory
>)
1719 debug
!("ty_of_method_or_bare_fn");
1721 // New region names that appear inside of the arguments of the function
1722 // declaration are bound to that function type.
1723 let rb
= rscope
::BindingRscope
::new();
1725 // `implied_output_region` is the region that will be assumed for any
1726 // region parameters in the return type. In accordance with the rules for
1727 // lifetime elision, we can determine it in two ways. First (determined
1728 // here), if self is by-reference, then the implied output region is the
1729 // region of the self parameter.
1730 let mut explicit_self_category_result
= None
;
1731 let (self_ty
, implied_output_region
) = match opt_self_info
{
1732 None
=> (None
, None
),
1733 Some(self_info
) => {
1734 // This type comes from an impl or trait; no late-bound
1735 // regions should be present.
1736 assert
!(!self_info
.untransformed_self_ty
.has_escaping_regions());
1738 // Figure out and record the explicit self category.
1739 let explicit_self_category
=
1740 determine_explicit_self_category(this
, &rb
, &self_info
);
1741 explicit_self_category_result
= Some(explicit_self_category
);
1742 match explicit_self_category
{
1743 ty
::StaticExplicitSelfCategory
=> {
1746 ty
::ByValueExplicitSelfCategory
=> {
1747 (Some(self_info
.untransformed_self_ty
), None
)
1749 ty
::ByReferenceExplicitSelfCategory(region
, mutability
) => {
1750 (Some(this
.tcx().mk_ref(
1751 this
.tcx().mk_region(region
),
1753 ty
: self_info
.untransformed_self_ty
,
1758 ty
::ByBoxExplicitSelfCategory
=> {
1759 (Some(this
.tcx().mk_box(self_info
.untransformed_self_ty
)), None
)
1765 // HACK(eddyb) replace the fake self type in the AST with the actual type.
1766 let input_params
= if self_ty
.is_some() {
1771 let input_tys
= input_params
.iter().map(|a
| ty_of_arg(this
, &rb
, a
, None
));
1772 let input_pats
: Vec
<String
> = input_params
.iter()
1773 .map(|a
| pprust
::pat_to_string(&*a
.pat
))
1775 let self_and_input_tys
: Vec
<Ty
> =
1776 self_ty
.into_iter().chain(input_tys
).collect();
1779 // Second, if there was exactly one lifetime (either a substitution or a
1780 // reference) in the arguments, then any anonymous regions in the output
1781 // have that lifetime.
1782 let implied_output_region
= match implied_output_region
{
1785 let input_tys
= if self_ty
.is_some() {
1786 // Skip the first argument if `self` is present.
1787 &self_and_input_tys
[1..]
1789 &self_and_input_tys
[..]
1792 find_implied_output_region(this
.tcx(), input_tys
, input_pats
)
1796 let output_ty
= match decl
.output
{
1797 ast
::Return(ref output
) if output
.node
== ast
::TyInfer
=>
1798 ty
::FnConverging(this
.ty_infer(None
, None
, None
, output
.span
)),
1799 ast
::Return(ref output
) =>
1800 ty
::FnConverging(convert_ty_with_lifetime_elision(this
,
1801 implied_output_region
,
1803 ast
::DefaultReturn(..) => ty
::FnConverging(this
.tcx().mk_nil()),
1804 ast
::NoReturn(..) => ty
::FnDiverging
1810 sig
: ty
::Binder(ty
::FnSig
{
1811 inputs
: self_and_input_tys
,
1813 variadic
: decl
.variadic
1815 }, explicit_self_category_result
)
1818 fn determine_explicit_self_category
<'a
, 'tcx
>(this
: &AstConv
<'tcx
>,
1819 rscope
: &RegionScope
,
1820 self_info
: &SelfInfo
<'a
, 'tcx
>)
1821 -> ty
::ExplicitSelfCategory
1823 return match self_info
.explicit_self
.node
{
1824 ast
::SelfStatic
=> ty
::StaticExplicitSelfCategory
,
1825 ast
::SelfValue(_
) => ty
::ByValueExplicitSelfCategory
,
1826 ast
::SelfRegion(ref lifetime
, mutability
, _
) => {
1828 opt_ast_region_to_region(this
,
1830 self_info
.explicit_self
.span
,
1832 ty
::ByReferenceExplicitSelfCategory(region
, mutability
)
1834 ast
::SelfExplicit(ref ast_type
, _
) => {
1835 let explicit_type
= ast_ty_to_ty(this
, rscope
, &**ast_type
);
1837 // We wish to (for now) categorize an explicit self
1838 // declaration like `self: SomeType` into either `self`,
1839 // `&self`, `&mut self`, or `Box<self>`. We do this here
1840 // by some simple pattern matching. A more precise check
1841 // is done later in `check_method_self_type()`.
1846 // impl Foo for &T {
1847 // // Legal declarations:
1848 // fn method1(self: &&T); // ByReferenceExplicitSelfCategory
1849 // fn method2(self: &T); // ByValueExplicitSelfCategory
1850 // fn method3(self: Box<&T>); // ByBoxExplicitSelfCategory
1852 // // Invalid cases will be caught later by `check_method_self_type`:
1853 // fn method_err1(self: &mut T); // ByReferenceExplicitSelfCategory
1857 // To do the check we just count the number of "modifiers"
1858 // on each type and compare them. If they are the same or
1859 // the impl has more, we call it "by value". Otherwise, we
1860 // look at the outermost modifier on the method decl and
1861 // call it by-ref, by-box as appropriate. For method1, for
1862 // example, the impl type has one modifier, but the method
1863 // type has two, so we end up with
1864 // ByReferenceExplicitSelfCategory.
1866 let impl_modifiers
= count_modifiers(self_info
.untransformed_self_ty
);
1867 let method_modifiers
= count_modifiers(explicit_type
);
1869 debug
!("determine_explicit_self_category(self_info.untransformed_self_ty={:?} \
1870 explicit_type={:?} \
1872 self_info
.untransformed_self_ty
,
1877 if impl_modifiers
>= method_modifiers
{
1878 ty
::ByValueExplicitSelfCategory
1880 match explicit_type
.sty
{
1881 ty
::TyRef(r
, mt
) => ty
::ByReferenceExplicitSelfCategory(*r
, mt
.mutbl
),
1882 ty
::TyBox(_
) => ty
::ByBoxExplicitSelfCategory
,
1883 _
=> ty
::ByValueExplicitSelfCategory
,
1889 fn count_modifiers(ty
: Ty
) -> usize {
1891 ty
::TyRef(_
, mt
) => count_modifiers(mt
.ty
) + 1,
1892 ty
::TyBox(t
) => count_modifiers(t
) + 1,
1898 pub fn ty_of_closure
<'tcx
>(
1899 this
: &AstConv
<'tcx
>,
1900 unsafety
: ast
::Unsafety
,
1903 expected_sig
: Option
<ty
::FnSig
<'tcx
>>)
1904 -> ty
::ClosureTy
<'tcx
>
1906 debug
!("ty_of_closure(expected_sig={:?})",
1909 // new region names that appear inside of the fn decl are bound to
1910 // that function type
1911 let rb
= rscope
::BindingRscope
::new();
1913 let input_tys
: Vec
<_
> = decl
.inputs
.iter().enumerate().map(|(i
, a
)| {
1914 let expected_arg_ty
= expected_sig
.as_ref().and_then(|e
| {
1915 // no guarantee that the correct number of expected args
1917 if i
< e
.inputs
.len() {
1923 ty_of_arg(this
, &rb
, a
, expected_arg_ty
)
1926 let expected_ret_ty
= expected_sig
.map(|e
| e
.output
);
1928 let is_infer
= match decl
.output
{
1929 ast
::Return(ref output
) if output
.node
== ast
::TyInfer
=> true,
1930 ast
::DefaultReturn(..) => true,
1934 let output_ty
= match decl
.output
{
1935 _
if is_infer
&& expected_ret_ty
.is_some() =>
1936 expected_ret_ty
.unwrap(),
1938 ty
::FnConverging(this
.ty_infer(None
, None
, None
, decl
.output
.span())),
1939 ast
::Return(ref output
) =>
1940 ty
::FnConverging(ast_ty_to_ty(this
, &rb
, &**output
)),
1941 ast
::DefaultReturn(..) => unreachable
!(),
1942 ast
::NoReturn(..) => ty
::FnDiverging
1945 debug
!("ty_of_closure: input_tys={:?}", input_tys
);
1946 debug
!("ty_of_closure: output_ty={:?}", output_ty
);
1951 sig
: ty
::Binder(ty
::FnSig
{inputs
: input_tys
,
1953 variadic
: decl
.variadic
}),
1957 /// Given an existential type like `Foo+'a+Bar`, this routine converts the `'a` and `Bar` intos an
1958 /// `ExistentialBounds` struct. The `main_trait_refs` argument specifies the `Foo` -- it is absent
1959 /// for closures. Eventually this should all be normalized, I think, so that there is no "main
1960 /// trait ref" and instead we just have a flat list of bounds as the existential type.
1961 fn conv_existential_bounds
<'tcx
>(
1962 this
: &AstConv
<'tcx
>,
1963 rscope
: &RegionScope
,
1965 principal_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
1966 projection_bounds
: Vec
<ty
::PolyProjectionPredicate
<'tcx
>>,
1967 ast_bounds
: &[ast
::TyParamBound
])
1968 -> ty
::ExistentialBounds
<'tcx
>
1970 let partitioned_bounds
=
1971 partition_bounds(this
.tcx(), span
, ast_bounds
);
1973 conv_existential_bounds_from_partitioned_bounds(
1974 this
, rscope
, span
, principal_trait_ref
, projection_bounds
, partitioned_bounds
)
1977 fn conv_ty_poly_trait_ref
<'tcx
>(
1978 this
: &AstConv
<'tcx
>,
1979 rscope
: &RegionScope
,
1981 ast_bounds
: &[ast
::TyParamBound
])
1984 let mut partitioned_bounds
= partition_bounds(this
.tcx(), span
, &ast_bounds
[..]);
1986 let mut projection_bounds
= Vec
::new();
1987 let main_trait_bound
= if !partitioned_bounds
.trait_bounds
.is_empty() {
1988 let trait_bound
= partitioned_bounds
.trait_bounds
.remove(0);
1989 instantiate_poly_trait_ref(this
,
1993 &mut projection_bounds
)
1995 span_err
!(this
.tcx().sess
, span
, E0224
,
1996 "at least one non-builtin trait is required for an object type");
1997 return this
.tcx().types
.err
;
2001 conv_existential_bounds_from_partitioned_bounds(this
,
2004 main_trait_bound
.clone(),
2006 partitioned_bounds
);
2008 make_object_type(this
, span
, main_trait_bound
, bounds
)
2011 pub fn conv_existential_bounds_from_partitioned_bounds
<'tcx
>(
2012 this
: &AstConv
<'tcx
>,
2013 rscope
: &RegionScope
,
2015 principal_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
2016 mut projection_bounds
: Vec
<ty
::PolyProjectionPredicate
<'tcx
>>, // Empty for boxed closures
2017 partitioned_bounds
: PartitionedBounds
)
2018 -> ty
::ExistentialBounds
<'tcx
>
2020 let PartitionedBounds
{ builtin_bounds
,
2025 if !trait_bounds
.is_empty() {
2026 let b
= &trait_bounds
[0];
2027 span_err
!(this
.tcx().sess
, b
.trait_ref
.path
.span
, E0225
,
2028 "only the builtin traits can be used as closure or object bounds");
2032 compute_object_lifetime_bound(this
,
2035 principal_trait_ref
,
2038 let region_bound
= match region_bound
{
2041 match rscope
.object_lifetime_default(span
) {
2044 span_err
!(this
.tcx().sess
, span
, E0228
,
2045 "the lifetime bound for this object type cannot be deduced \
2046 from context; please supply an explicit bound");
2053 debug
!("region_bound: {:?}", region_bound
);
2055 ty
::sort_bounds_list(&mut projection_bounds
);
2057 ty
::ExistentialBounds
{
2058 region_bound
: region_bound
,
2059 builtin_bounds
: builtin_bounds
,
2060 projection_bounds
: projection_bounds
,
2064 /// Given the bounds on an object, determines what single region bound
2065 /// (if any) we can use to summarize this type. The basic idea is that we will use the bound the
2066 /// user provided, if they provided one, and otherwise search the supertypes of trait bounds for
2067 /// region bounds. It may be that we can derive no bound at all, in which case we return `None`.
2068 fn compute_object_lifetime_bound
<'tcx
>(
2069 this
: &AstConv
<'tcx
>,
2071 explicit_region_bounds
: &[&ast
::Lifetime
],
2072 principal_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
2073 builtin_bounds
: ty
::BuiltinBounds
)
2074 -> Option
<ty
::Region
> // if None, use the default
2076 let tcx
= this
.tcx();
2078 debug
!("compute_opt_region_bound(explicit_region_bounds={:?}, \
2079 principal_trait_ref={:?}, builtin_bounds={:?})",
2080 explicit_region_bounds
,
2081 principal_trait_ref
,
2084 if explicit_region_bounds
.len() > 1 {
2085 span_err
!(tcx
.sess
, explicit_region_bounds
[1].span
, E0226
,
2086 "only a single explicit lifetime bound is permitted");
2089 if !explicit_region_bounds
.is_empty() {
2090 // Explicitly specified region bound. Use that.
2091 let r
= explicit_region_bounds
[0];
2092 return Some(ast_region_to_region(tcx
, r
));
2095 if let Err(ErrorReported
) = this
.ensure_super_predicates(span
,principal_trait_ref
.def_id()) {
2096 return Some(ty
::ReStatic
);
2099 // No explicit region bound specified. Therefore, examine trait
2100 // bounds and see if we can derive region bounds from those.
2101 let derived_region_bounds
=
2102 object_region_bounds(tcx
, &principal_trait_ref
, builtin_bounds
);
2104 // If there are no derived region bounds, then report back that we
2105 // can find no region bound. The caller will use the default.
2106 if derived_region_bounds
.is_empty() {
2110 // If any of the derived region bounds are 'static, that is always
2112 if derived_region_bounds
.iter().any(|r
| ty
::ReStatic
== *r
) {
2113 return Some(ty
::ReStatic
);
2116 // Determine whether there is exactly one unique region in the set
2117 // of derived region bounds. If so, use that. Otherwise, report an
2119 let r
= derived_region_bounds
[0];
2120 if derived_region_bounds
[1..].iter().any(|r1
| r
!= *r1
) {
2121 span_err
!(tcx
.sess
, span
, E0227
,
2122 "ambiguous lifetime bound, explicit lifetime bound required");
2127 pub struct PartitionedBounds
<'a
> {
2128 pub builtin_bounds
: ty
::BuiltinBounds
,
2129 pub trait_bounds
: Vec
<&'a ast
::PolyTraitRef
>,
2130 pub region_bounds
: Vec
<&'a ast
::Lifetime
>,
2133 /// Divides a list of bounds from the AST into three groups: builtin bounds (Copy, Sized etc),
2134 /// general trait bounds, and region bounds.
2135 pub fn partition_bounds
<'a
>(tcx
: &ty
::ctxt
,
2137 ast_bounds
: &'a
[ast
::TyParamBound
])
2138 -> PartitionedBounds
<'a
>
2140 let mut builtin_bounds
= ty
::BuiltinBounds
::empty();
2141 let mut region_bounds
= Vec
::new();
2142 let mut trait_bounds
= Vec
::new();
2143 for ast_bound
in ast_bounds
{
2145 ast
::TraitTyParamBound(ref b
, ast
::TraitBoundModifier
::None
) => {
2146 match ::lookup_full_def(tcx
, b
.trait_ref
.path
.span
, b
.trait_ref
.ref_id
) {
2147 def
::DefTrait(trait_did
) => {
2148 if tcx
.try_add_builtin_trait(trait_did
,
2149 &mut builtin_bounds
) {
2150 let segments
= &b
.trait_ref
.path
.segments
;
2151 let parameters
= &segments
[segments
.len() - 1].parameters
;
2152 if !parameters
.types().is_empty() {
2153 check_type_argument_count(tcx
, b
.trait_ref
.path
.span
,
2154 parameters
.types().len(), 0, 0);
2156 if !parameters
.lifetimes().is_empty() {
2157 report_lifetime_number_error(tcx
, b
.trait_ref
.path
.span
,
2158 parameters
.lifetimes().len(), 0);
2160 continue; // success
2164 // Not a trait? that's an error, but it'll get
2168 trait_bounds
.push(b
);
2170 ast
::TraitTyParamBound(_
, ast
::TraitBoundModifier
::Maybe
) => {}
2171 ast
::RegionTyParamBound(ref l
) => {
2172 region_bounds
.push(l
);
2178 builtin_bounds
: builtin_bounds
,
2179 trait_bounds
: trait_bounds
,
2180 region_bounds
: region_bounds
,
2184 fn prohibit_projections
<'tcx
>(tcx
: &ty
::ctxt
<'tcx
>,
2185 bindings
: &[ConvertedBinding
<'tcx
>])
2187 for binding
in bindings
.iter().take(1) {
2188 span_err
!(tcx
.sess
, binding
.span
, E0229
,
2189 "associated type bindings are not allowed here");
2193 fn check_type_argument_count(tcx
: &ty
::ctxt
, span
: Span
, supplied
: usize,
2194 required
: usize, accepted
: usize) {
2195 if supplied
< required
{
2196 let expected
= if required
< accepted
{
2201 span_err
!(tcx
.sess
, span
, E0243
,
2202 "wrong number of type arguments: {} {}, found {}",
2203 expected
, required
, supplied
);
2204 } else if supplied
> accepted
{
2205 let expected
= if required
< accepted
{
2210 span_err
!(tcx
.sess
, span
, E0244
,
2211 "wrong number of type arguments: {} {}, found {}",
2218 fn report_lifetime_number_error(tcx
: &ty
::ctxt
, span
: Span
, number
: usize, expected
: usize) {
2219 span_err
!(tcx
.sess
, span
, E0107
,
2220 "wrong number of lifetime parameters: expected {}, found {}",
2224 // A helper struct for conveniently grouping a set of bounds which we pass to
2225 // and return from functions in multiple places.
2226 #[derive(PartialEq, Eq, Clone, Debug)]
2227 pub struct Bounds
<'tcx
> {
2228 pub region_bounds
: Vec
<ty
::Region
>,
2229 pub builtin_bounds
: ty
::BuiltinBounds
,
2230 pub trait_bounds
: Vec
<ty
::PolyTraitRef
<'tcx
>>,
2231 pub projection_bounds
: Vec
<ty
::PolyProjectionPredicate
<'tcx
>>,
2234 impl<'tcx
> Bounds
<'tcx
> {
2235 pub fn predicates(&self,
2236 tcx
: &ty
::ctxt
<'tcx
>,
2238 -> Vec
<ty
::Predicate
<'tcx
>>
2240 let mut vec
= Vec
::new();
2242 for builtin_bound
in &self.builtin_bounds
{
2243 match traits
::trait_ref_for_builtin_bound(tcx
, builtin_bound
, param_ty
) {
2244 Ok(trait_ref
) => { vec.push(trait_ref.to_predicate()); }
2245 Err(ErrorReported
) => { }
2249 for ®ion_bound
in &self.region_bounds
{
2250 // account for the binder being introduced below; no need to shift `param_ty`
2251 // because, at present at least, it can only refer to early-bound regions
2252 let region_bound
= ty_fold
::shift_region(region_bound
, 1);
2253 vec
.push(ty
::Binder(ty
::OutlivesPredicate(param_ty
, region_bound
)).to_predicate());
2256 for bound_trait_ref
in &self.trait_bounds
{
2257 vec
.push(bound_trait_ref
.to_predicate());
2260 for projection
in &self.projection_bounds
{
2261 vec
.push(projection
.to_predicate());