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, prohibit_type_params, prohibit_projection}
;
52 use middle
::const_val
::ConstVal
;
53 use rustc_const_eval
::eval_const_expr_partial
;
54 use rustc_const_eval
::EvalHint
::UncheckedExprHint
;
55 use hir
::def
::{self, Def}
;
56 use hir
::def_id
::DefId
;
57 use middle
::resolve_lifetime
as rl
;
58 use rustc
::ty
::subst
::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace}
;
60 use rustc
::ty
::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}
;
61 use rustc
::ty
::wf
::object_region_bounds
;
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
;
69 use rustc_const_math
::ConstInt
;
71 use syntax
::{abi, ast}
;
72 use syntax
::codemap
::{Span, Pos}
;
73 use syntax
::errors
::DiagnosticBuilder
;
74 use syntax
::feature_gate
::{GateIssue, emit_feature_err}
;
75 use syntax
::parse
::token
;
77 use rustc
::hir
::print
as pprust
;
79 use rustc_back
::slice
;
81 pub trait AstConv
<'tcx
> {
82 fn tcx
<'a
>(&'a
self) -> &'a TyCtxt
<'tcx
>;
84 /// Identify the type scheme for an item with a type, like a type
85 /// alias, fn, or struct. This allows you to figure out the set of
86 /// type parameters defined on the item.
87 fn get_item_type_scheme(&self, span
: Span
, id
: DefId
)
88 -> Result
<ty
::TypeScheme
<'tcx
>, ErrorReported
>;
90 /// Returns the `TraitDef` for a given trait. This allows you to
91 /// figure out the set of type parameters defined on the trait.
92 fn get_trait_def(&self, span
: Span
, id
: DefId
)
93 -> Result
<&'tcx ty
::TraitDef
<'tcx
>, ErrorReported
>;
95 /// Ensure that the super-predicates for the trait with the given
96 /// id are available and also for the transitive set of
98 fn ensure_super_predicates(&self, span
: Span
, id
: DefId
)
99 -> Result
<(), ErrorReported
>;
101 /// Returns the set of bounds in scope for the type parameter with
103 fn get_type_parameter_bounds(&self, span
: Span
, def_id
: ast
::NodeId
)
104 -> Result
<Vec
<ty
::PolyTraitRef
<'tcx
>>, ErrorReported
>;
106 /// Returns true if the trait with id `trait_def_id` defines an
107 /// associated type with the name `name`.
108 fn trait_defines_associated_type_named(&self, trait_def_id
: DefId
, name
: ast
::Name
)
111 /// Return an (optional) substitution to convert bound type parameters that
112 /// are in scope into free ones. This function should only return Some
113 /// within a fn body.
114 /// See ParameterEnvironment::free_substs for more information.
115 fn get_free_substs(&self) -> Option
<&Substs
<'tcx
>> {
119 /// What type should we use when a type is omitted?
121 param_and_substs
: Option
<ty
::TypeParameterDef
<'tcx
>>,
122 substs
: Option
<&mut Substs
<'tcx
>>,
123 space
: Option
<ParamSpace
>,
124 span
: Span
) -> Ty
<'tcx
>;
126 /// Projecting an associated type from a (potentially)
127 /// higher-ranked trait reference is more complicated, because of
128 /// the possibility of late-bound regions appearing in the
129 /// associated type binding. This is not legal in function
130 /// signatures for that reason. In a function body, we can always
131 /// handle it because we can use inference variables to remove the
132 /// late-bound regions.
133 fn projected_ty_from_poly_trait_ref(&self,
135 poly_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
136 item_name
: ast
::Name
)
139 if let Some(trait_ref
) = self.tcx().no_late_bound_regions(&poly_trait_ref
) {
140 self.projected_ty(span
, trait_ref
, item_name
)
142 // no late-bound regions, we can just ignore the binder
143 span_err
!(self.tcx().sess
, span
, E0212
,
144 "cannot extract an associated type from a higher-ranked trait bound \
150 /// Project an associated type from a non-higher-ranked trait reference.
151 /// This is fairly straightforward and can be accommodated in any context.
152 fn projected_ty(&self,
154 _trait_ref
: ty
::TraitRef
<'tcx
>,
155 _item_name
: ast
::Name
)
159 pub fn ast_region_to_region(tcx
: &TyCtxt
, lifetime
: &hir
::Lifetime
)
161 let r
= match tcx
.named_region_map
.get(&lifetime
.id
) {
163 // should have been recorded by the `resolve_lifetime` pass
164 span_bug
!(lifetime
.span
, "unresolved lifetime");
167 Some(&rl
::DefStaticRegion
) => {
171 Some(&rl
::DefLateBoundRegion(debruijn
, id
)) => {
172 ty
::ReLateBound(debruijn
, ty
::BrNamed(tcx
.map
.local_def_id(id
), lifetime
.name
))
175 Some(&rl
::DefEarlyBoundRegion(space
, index
, _
)) => {
176 ty
::ReEarlyBound(ty
::EarlyBoundRegion
{
183 Some(&rl
::DefFreeRegion(scope
, id
)) => {
184 ty
::ReFree(ty
::FreeRegion
{
185 scope
: scope
.to_code_extent(&tcx
.region_maps
),
186 bound_region
: ty
::BrNamed(tcx
.map
.local_def_id(id
),
192 debug
!("ast_region_to_region(lifetime={:?} id={}) yields {:?}",
200 fn report_elision_failure(
201 db
: &mut DiagnosticBuilder
,
203 params
: Vec
<ElisionFailureInfo
>)
205 let mut m
= String
::new();
206 let len
= params
.len();
207 let mut any_lifetimes
= false;
209 for (i
, info
) in params
.into_iter().enumerate() {
210 let ElisionFailureInfo
{
211 name
, lifetime_count
: n
, have_bound_regions
214 any_lifetimes
= any_lifetimes
|| (n
> 0);
216 let help_name
= if name
.is_empty() {
217 format
!("argument {}", i
+ 1)
219 format
!("`{}`", name
)
222 m
.push_str(&(if n
== 1 {
225 format
!("one of {}'s {} elided {}lifetimes", help_name
, n
,
226 if have_bound_regions { "free " }
else { "" }
)
229 if len
== 2 && i
== 0 {
231 } else if i
+ 2 == len
{
233 } else if i
+ 1 != len
{
239 fileline_help
!(db
, default_span
,
240 "this function's return type contains a borrowed value, but \
241 there is no value for it to be borrowed from");
242 fileline_help
!(db
, default_span
,
243 "consider giving it a 'static lifetime");
244 } else if !any_lifetimes
{
245 fileline_help
!(db
, default_span
,
246 "this function's return type contains a borrowed value with \
247 an elided lifetime, but the lifetime cannot be derived from \
249 fileline_help
!(db
, default_span
,
250 "consider giving it an explicit bounded or 'static \
253 fileline_help
!(db
, default_span
,
254 "this function's return type contains a borrowed value, but \
255 the signature does not say which {} it is borrowed from",
258 fileline_help
!(db
, default_span
,
259 "this function's return type contains a borrowed value, but \
260 the signature does not say whether it is borrowed from {}",
265 pub fn opt_ast_region_to_region
<'tcx
>(
266 this
: &AstConv
<'tcx
>,
267 rscope
: &RegionScope
,
269 opt_lifetime
: &Option
<hir
::Lifetime
>) -> ty
::Region
271 let r
= match *opt_lifetime
{
272 Some(ref lifetime
) => {
273 ast_region_to_region(this
.tcx(), lifetime
)
276 None
=> match rscope
.anon_regions(default_span
, 1) {
279 let mut err
= struct_span_err
!(this
.tcx().sess
, default_span
, E0106
,
280 "missing lifetime specifier");
281 if let Some(params
) = params
{
282 report_elision_failure(&mut err
, default_span
, params
);
290 debug
!("opt_ast_region_to_region(opt_lifetime={:?}) yields {:?}",
297 /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
298 /// returns an appropriate set of substitutions for this particular reference to `I`.
299 pub fn ast_path_substs_for_ty
<'tcx
>(
300 this
: &AstConv
<'tcx
>,
301 rscope
: &RegionScope
,
303 param_mode
: PathParamMode
,
304 decl_generics
: &ty
::Generics
<'tcx
>,
305 item_segment
: &hir
::PathSegment
)
308 let tcx
= this
.tcx();
310 // ast_path_substs() is only called to convert paths that are
311 // known to refer to traits, types, or structs. In these cases,
312 // all type parameters defined for the item being referenced will
313 // be in the TypeSpace or SelfSpace.
315 // Note: in the case of traits, the self parameter is also
316 // defined, but we don't currently create a `type_param_def` for
317 // `Self` because it is implicit.
318 assert
!(decl_generics
.regions
.all(|d
| d
.space
== TypeSpace
));
319 assert
!(decl_generics
.types
.all(|d
| d
.space
!= FnSpace
));
321 let (regions
, types
, assoc_bindings
) = match item_segment
.parameters
{
322 hir
::AngleBracketedParameters(ref data
) => {
323 convert_angle_bracketed_parameters(this
, rscope
, span
, decl_generics
, data
)
325 hir
::ParenthesizedParameters(..) => {
326 span_err
!(tcx
.sess
, span
, E0214
,
327 "parenthesized parameters may only be used with a trait");
328 let ty_param_defs
= decl_generics
.types
.get_slice(TypeSpace
);
330 ty_param_defs
.iter().map(|_
| tcx
.types
.err
).collect(),
335 prohibit_projections(this
.tcx(), &assoc_bindings
);
337 create_substs_for_ast_path(this
,
346 #[derive(PartialEq, Eq)]
347 pub enum PathParamMode
{
348 // Any path in a type context.
350 // The `module::Type` in `module::Type::method` in an expression.
354 fn create_region_substs
<'tcx
>(
355 this
: &AstConv
<'tcx
>,
356 rscope
: &RegionScope
,
358 decl_generics
: &ty
::Generics
<'tcx
>,
359 regions_provided
: Vec
<ty
::Region
>)
362 let tcx
= this
.tcx();
364 // If the type is parameterized by this region, then replace this
365 // region with the current anon region binding (in other words,
366 // whatever & would get replaced with).
367 let expected_num_region_params
= decl_generics
.regions
.len(TypeSpace
);
368 let supplied_num_region_params
= regions_provided
.len();
369 let regions
= if expected_num_region_params
== supplied_num_region_params
{
373 rscope
.anon_regions(span
, expected_num_region_params
);
375 if supplied_num_region_params
!= 0 || anon_regions
.is_err() {
376 report_lifetime_number_error(tcx
, span
,
377 supplied_num_region_params
,
378 expected_num_region_params
);
382 Ok(anon_regions
) => anon_regions
,
383 Err(_
) => (0..expected_num_region_params
).map(|_
| ty
::ReStatic
).collect()
386 Substs
::new_type(vec
![], regions
)
389 /// Given the type/region arguments provided to some path (along with
390 /// an implicit Self, if this is a trait reference) returns the complete
391 /// set of substitutions. This may involve applying defaulted type parameters.
393 /// Note that the type listing given here is *exactly* what the user provided.
395 /// The `region_substs` should be the result of `create_region_substs`
396 /// -- that is, a substitution with no types but the correct number of
398 fn create_substs_for_ast_path
<'tcx
>(
399 this
: &AstConv
<'tcx
>,
401 param_mode
: PathParamMode
,
402 decl_generics
: &ty
::Generics
<'tcx
>,
403 self_ty
: Option
<Ty
<'tcx
>>,
404 types_provided
: Vec
<Ty
<'tcx
>>,
405 region_substs
: Substs
<'tcx
>)
408 let tcx
= this
.tcx();
410 debug
!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \
411 types_provided={:?}, region_substs={:?})",
412 decl_generics
, self_ty
, types_provided
,
415 assert_eq
!(region_substs
.regions
.len(TypeSpace
), decl_generics
.regions
.len(TypeSpace
));
416 assert
!(region_substs
.types
.is_empty());
418 // Convert the type parameters supplied by the user.
419 let ty_param_defs
= decl_generics
.types
.get_slice(TypeSpace
);
420 let formal_ty_param_count
= ty_param_defs
.len();
421 let required_ty_param_count
= ty_param_defs
.iter()
422 .take_while(|x
| x
.default.is_none())
425 let mut type_substs
= get_type_substs_for_defs(this
,
430 region_substs
.clone(),
433 let supplied_ty_param_count
= type_substs
.len();
434 check_type_argument_count(this
.tcx(), span
, supplied_ty_param_count
,
435 required_ty_param_count
, formal_ty_param_count
);
437 if supplied_ty_param_count
< required_ty_param_count
{
438 while type_substs
.len() < required_ty_param_count
{
439 type_substs
.push(tcx
.types
.err
);
441 } else if supplied_ty_param_count
> formal_ty_param_count
{
442 type_substs
.truncate(formal_ty_param_count
);
444 assert
!(type_substs
.len() >= required_ty_param_count
&&
445 type_substs
.len() <= formal_ty_param_count
);
447 let mut substs
= region_substs
;
448 substs
.types
.extend(TypeSpace
, type_substs
.into_iter());
452 // If no self-type is provided, it's still possible that
453 // one was declared, because this could be an object type.
456 // If a self-type is provided, one should have been
457 // "declared" (in other words, this should be a
459 assert
!(decl_generics
.types
.get_self().is_some());
460 substs
.types
.push(SelfSpace
, ty
);
464 let actual_supplied_ty_param_count
= substs
.types
.len(TypeSpace
);
465 for param
in &ty_param_defs
[actual_supplied_ty_param_count
..] {
466 if let Some(default) = param
.default {
467 // If we are converting an object type, then the
468 // `Self` parameter is unknown. However, some of the
469 // other type parameters may reference `Self` in their
470 // defaults. This will lead to an ICE if we are not
472 if self_ty
.is_none() && default.has_self_ty() {
473 span_err
!(tcx
.sess
, span
, E0393
,
474 "the type parameter `{}` must be explicitly specified \
475 in an object type because its default value `{}` references \
479 substs
.types
.push(TypeSpace
, tcx
.types
.err
);
481 // This is a default type parameter.
482 let default = default.subst_spanned(tcx
,
485 substs
.types
.push(TypeSpace
, default);
488 span_bug
!(span
, "extra parameter without default");
492 debug
!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
493 decl_generics
, self_ty
, substs
);
498 /// Returns types_provided if it is not empty, otherwise populating the
499 /// type parameters with inference variables as appropriate.
500 fn get_type_substs_for_defs
<'tcx
>(this
: &AstConv
<'tcx
>,
502 types_provided
: Vec
<Ty
<'tcx
>>,
503 param_mode
: PathParamMode
,
504 ty_param_defs
: &[ty
::TypeParameterDef
<'tcx
>],
505 mut substs
: Substs
<'tcx
>,
506 self_ty
: Option
<Ty
<'tcx
>>)
509 fn default_type_parameter
<'tcx
>(p
: &ty
::TypeParameterDef
<'tcx
>, self_ty
: Option
<Ty
<'tcx
>>)
510 -> Option
<ty
::TypeParameterDef
<'tcx
>>
512 if let Some(ref default) = p
.default {
513 if self_ty
.is_none() && default.has_self_ty() {
514 // There is no suitable inference default for a type parameter
515 // that references self with no self-type provided.
523 if param_mode
== PathParamMode
::Optional
&& types_provided
.is_empty() {
526 .map(|p
| this
.ty_infer(default_type_parameter(p
, self_ty
), Some(&mut substs
),
527 Some(TypeSpace
), span
))
534 struct ConvertedBinding
<'tcx
> {
535 item_name
: ast
::Name
,
540 fn convert_angle_bracketed_parameters
<'tcx
>(this
: &AstConv
<'tcx
>,
541 rscope
: &RegionScope
,
543 decl_generics
: &ty
::Generics
<'tcx
>,
544 data
: &hir
::AngleBracketedParameterData
)
547 Vec
<ConvertedBinding
<'tcx
>>)
549 let regions
: Vec
<_
> =
550 data
.lifetimes
.iter()
551 .map(|l
| ast_region_to_region(this
.tcx(), l
))
555 create_region_substs(this
, rscope
, span
, decl_generics
, regions
);
560 .map(|(i
,t
)| ast_ty_arg_to_ty(this
, rscope
, decl_generics
,
561 i
, ®ion_substs
, t
))
564 let assoc_bindings
: Vec
<_
> =
566 .map(|b
| ConvertedBinding
{ item_name
: b
.name
,
567 ty
: ast_ty_to_ty(this
, rscope
, &b
.ty
),
571 (region_substs
, types
, assoc_bindings
)
574 /// Returns the appropriate lifetime to use for any output lifetimes
575 /// (if one exists) and a vector of the (pattern, number of lifetimes)
576 /// corresponding to each input type/pattern.
577 fn find_implied_output_region
<'tcx
>(tcx
: &TyCtxt
<'tcx
>,
578 input_tys
: &[Ty
<'tcx
>],
579 input_pats
: Vec
<String
>) -> ElidedLifetime
581 let mut lifetimes_for_params
= Vec
::new();
582 let mut possible_implied_output_region
= None
;
584 for (input_type
, input_pat
) in input_tys
.iter().zip(input_pats
) {
585 let mut regions
= FnvHashSet();
586 let have_bound_regions
= tcx
.collect_regions(input_type
, &mut regions
);
588 debug
!("find_implied_output_regions: collected {:?} from {:?} \
589 have_bound_regions={:?}", ®ions
, input_type
, have_bound_regions
);
591 if regions
.len() == 1 {
592 // there's a chance that the unique lifetime of this
593 // iteration will be the appropriate lifetime for output
594 // parameters, so lets store it.
595 possible_implied_output_region
= regions
.iter().cloned().next();
598 lifetimes_for_params
.push(ElisionFailureInfo
{
600 lifetime_count
: regions
.len(),
601 have_bound_regions
: have_bound_regions
605 if lifetimes_for_params
.iter().map(|e
| e
.lifetime_count
).sum
::<usize>() == 1 {
606 Ok(possible_implied_output_region
.unwrap())
608 Err(Some(lifetimes_for_params
))
612 fn convert_ty_with_lifetime_elision
<'tcx
>(this
: &AstConv
<'tcx
>,
613 elided_lifetime
: ElidedLifetime
,
617 match elided_lifetime
{
618 Ok(implied_output_region
) => {
619 let rb
= ElidableRscope
::new(implied_output_region
);
620 ast_ty_to_ty(this
, &rb
, ty
)
622 Err(param_lifetimes
) => {
623 // All regions must be explicitly specified in the output
624 // if the lifetime elision rules do not apply. This saves
625 // the user from potentially-confusing errors.
626 let rb
= UnelidableRscope
::new(param_lifetimes
);
627 ast_ty_to_ty(this
, &rb
, ty
)
632 fn convert_parenthesized_parameters
<'tcx
>(this
: &AstConv
<'tcx
>,
633 rscope
: &RegionScope
,
635 decl_generics
: &ty
::Generics
<'tcx
>,
636 data
: &hir
::ParenthesizedParameterData
)
639 Vec
<ConvertedBinding
<'tcx
>>)
642 create_region_substs(this
, rscope
, span
, decl_generics
, Vec
::new());
644 let binding_rscope
= BindingRscope
::new();
647 .map(|a_t
| ast_ty_arg_to_ty(this
, &binding_rscope
, decl_generics
,
648 0, ®ion_substs
, a_t
))
649 .collect
::<Vec
<Ty
<'tcx
>>>();
651 let input_params
= vec
![String
::new(); inputs
.len()];
652 let implied_output_region
= find_implied_output_region(this
.tcx(), &inputs
, input_params
);
654 let input_ty
= this
.tcx().mk_tup(inputs
);
656 let (output
, output_span
) = match data
.output
{
657 Some(ref output_ty
) => {
658 (convert_ty_with_lifetime_elision(this
,
659 implied_output_region
,
664 (this
.tcx().mk_nil(), data
.span
)
668 let output_binding
= ConvertedBinding
{
669 item_name
: token
::intern(FN_OUTPUT_NAME
),
674 (region_substs
, vec
![input_ty
], vec
![output_binding
])
677 pub fn instantiate_poly_trait_ref
<'tcx
>(
678 this
: &AstConv
<'tcx
>,
679 rscope
: &RegionScope
,
680 ast_trait_ref
: &hir
::PolyTraitRef
,
681 self_ty
: Option
<Ty
<'tcx
>>,
682 poly_projections
: &mut Vec
<ty
::PolyProjectionPredicate
<'tcx
>>)
683 -> ty
::PolyTraitRef
<'tcx
>
685 let trait_ref
= &ast_trait_ref
.trait_ref
;
686 let trait_def_id
= trait_def_id(this
, trait_ref
);
687 ast_path_to_poly_trait_ref(this
,
690 PathParamMode
::Explicit
,
693 trait_ref
.path
.segments
.last().unwrap(),
697 /// Instantiates the path for the given trait reference, assuming that it's
698 /// bound to a valid trait type. Returns the def_id for the defining trait.
699 /// Fails if the type is a type other than a trait type.
701 /// If the `projections` argument is `None`, then assoc type bindings like `Foo<T=X>`
702 /// are disallowed. Otherwise, they are pushed onto the vector given.
703 pub fn instantiate_mono_trait_ref
<'tcx
>(
704 this
: &AstConv
<'tcx
>,
705 rscope
: &RegionScope
,
706 trait_ref
: &hir
::TraitRef
,
707 self_ty
: Option
<Ty
<'tcx
>>)
708 -> ty
::TraitRef
<'tcx
>
710 let trait_def_id
= trait_def_id(this
, trait_ref
);
711 ast_path_to_mono_trait_ref(this
,
714 PathParamMode
::Explicit
,
717 trait_ref
.path
.segments
.last().unwrap())
720 fn trait_def_id
<'tcx
>(this
: &AstConv
<'tcx
>, trait_ref
: &hir
::TraitRef
) -> DefId
{
721 let path
= &trait_ref
.path
;
722 match ::lookup_full_def(this
.tcx(), path
.span
, trait_ref
.ref_id
) {
723 Def
::Trait(trait_def_id
) => trait_def_id
,
725 this
.tcx().sess
.fatal("cannot continue compilation due to previous error");
728 span_fatal
!(this
.tcx().sess
, path
.span
, E0245
, "`{}` is not a trait",
734 fn object_path_to_poly_trait_ref
<'a
,'tcx
>(
735 this
: &AstConv
<'tcx
>,
736 rscope
: &RegionScope
,
738 param_mode
: PathParamMode
,
740 trait_segment
: &hir
::PathSegment
,
741 mut projections
: &mut Vec
<ty
::PolyProjectionPredicate
<'tcx
>>)
742 -> ty
::PolyTraitRef
<'tcx
>
744 ast_path_to_poly_trait_ref(this
,
754 fn ast_path_to_poly_trait_ref
<'a
,'tcx
>(
755 this
: &AstConv
<'tcx
>,
756 rscope
: &RegionScope
,
758 param_mode
: PathParamMode
,
760 self_ty
: Option
<Ty
<'tcx
>>,
761 trait_segment
: &hir
::PathSegment
,
762 poly_projections
: &mut Vec
<ty
::PolyProjectionPredicate
<'tcx
>>)
763 -> ty
::PolyTraitRef
<'tcx
>
765 debug
!("ast_path_to_poly_trait_ref(trait_segment={:?})", trait_segment
);
766 // The trait reference introduces a binding level here, so
767 // we need to shift the `rscope`. It'd be nice if we could
768 // do away with this rscope stuff and work this knowledge
769 // into resolve_lifetimes, as we do with non-omitted
770 // lifetimes. Oh well, not there yet.
771 let shifted_rscope
= &ShiftedRscope
::new(rscope
);
773 let (substs
, assoc_bindings
) =
774 create_substs_for_ast_trait_ref(this
,
781 let poly_trait_ref
= ty
::Binder(ty
::TraitRef
::new(trait_def_id
, substs
));
784 let converted_bindings
=
787 .filter_map(|binding
| {
788 // specify type to assert that error was already reported in Err case:
789 let predicate
: Result
<_
, ErrorReported
> =
790 ast_type_binding_to_poly_projection_predicate(this
,
791 poly_trait_ref
.clone(),
794 predicate
.ok() // ok to ignore Err() because ErrorReported (see above)
796 poly_projections
.extend(converted_bindings
);
799 debug
!("ast_path_to_poly_trait_ref(trait_segment={:?}, projections={:?}) -> {:?}",
800 trait_segment
, poly_projections
, poly_trait_ref
);
804 fn ast_path_to_mono_trait_ref
<'a
,'tcx
>(this
: &AstConv
<'tcx
>,
805 rscope
: &RegionScope
,
807 param_mode
: PathParamMode
,
809 self_ty
: Option
<Ty
<'tcx
>>,
810 trait_segment
: &hir
::PathSegment
)
811 -> ty
::TraitRef
<'tcx
>
813 let (substs
, assoc_bindings
) =
814 create_substs_for_ast_trait_ref(this
,
821 prohibit_projections(this
.tcx(), &assoc_bindings
);
822 ty
::TraitRef
::new(trait_def_id
, substs
)
825 fn create_substs_for_ast_trait_ref
<'a
,'tcx
>(this
: &AstConv
<'tcx
>,
826 rscope
: &RegionScope
,
828 param_mode
: PathParamMode
,
830 self_ty
: Option
<Ty
<'tcx
>>,
831 trait_segment
: &hir
::PathSegment
)
832 -> (&'tcx Substs
<'tcx
>, Vec
<ConvertedBinding
<'tcx
>>)
834 debug
!("create_substs_for_ast_trait_ref(trait_segment={:?})",
837 let trait_def
= match this
.get_trait_def(span
, trait_def_id
) {
838 Ok(trait_def
) => trait_def
,
839 Err(ErrorReported
) => {
840 // No convenient way to recover from a cycle here. Just bail. Sorry!
841 this
.tcx().sess
.abort_if_errors();
842 bug
!("ErrorReported returned, but no errors reports?")
846 let (regions
, types
, assoc_bindings
) = match trait_segment
.parameters
{
847 hir
::AngleBracketedParameters(ref data
) => {
848 // For now, require that parenthetical notation be used
849 // only with `Fn()` etc.
850 if !this
.tcx().sess
.features
.borrow().unboxed_closures
&& trait_def
.paren_sugar
{
851 emit_feature_err(&this
.tcx().sess
.parse_sess
.span_diagnostic
,
852 "unboxed_closures", span
, GateIssue
::Language
,
854 the precise format of `Fn`-family traits' type parameters is \
855 subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead");
858 convert_angle_bracketed_parameters(this
, rscope
, span
, &trait_def
.generics
, data
)
860 hir
::ParenthesizedParameters(ref data
) => {
861 // For now, require that parenthetical notation be used
862 // only with `Fn()` etc.
863 if !this
.tcx().sess
.features
.borrow().unboxed_closures
&& !trait_def
.paren_sugar
{
864 emit_feature_err(&this
.tcx().sess
.parse_sess
.span_diagnostic
,
865 "unboxed_closures", span
, GateIssue
::Language
,
867 parenthetical notation is only stable when used with `Fn`-family traits");
870 convert_parenthesized_parameters(this
, rscope
, span
, &trait_def
.generics
, data
)
874 let substs
= create_substs_for_ast_path(this
,
882 (this
.tcx().mk_substs(substs
), assoc_bindings
)
885 fn ast_type_binding_to_poly_projection_predicate
<'tcx
>(
886 this
: &AstConv
<'tcx
>,
887 mut trait_ref
: ty
::PolyTraitRef
<'tcx
>,
888 self_ty
: Option
<Ty
<'tcx
>>,
889 binding
: &ConvertedBinding
<'tcx
>)
890 -> Result
<ty
::PolyProjectionPredicate
<'tcx
>, ErrorReported
>
892 let tcx
= this
.tcx();
894 // Given something like `U : SomeTrait<T=X>`, we want to produce a
895 // predicate like `<U as SomeTrait>::T = X`. This is somewhat
896 // subtle in the event that `T` is defined in a supertrait of
897 // `SomeTrait`, because in that case we need to upcast.
899 // That is, consider this case:
902 // trait SubTrait : SuperTrait<int> { }
903 // trait SuperTrait<A> { type T; }
905 // ... B : SubTrait<T=foo> ...
908 // We want to produce `<B as SuperTrait<int>>::T == foo`.
910 // Simple case: X is defined in the current trait.
911 if this
.trait_defines_associated_type_named(trait_ref
.def_id(), binding
.item_name
) {
912 return Ok(ty
::Binder(ty
::ProjectionPredicate
{ // <-------------------+
913 projection_ty
: ty
::ProjectionTy
{ // |
914 trait_ref
: trait_ref
.skip_binder().clone(), // Binder moved here --+
915 item_name
: binding
.item_name
,
921 // Otherwise, we have to walk through the supertraits to find
922 // those that do. This is complicated by the fact that, for an
923 // object type, the `Self` type is not present in the
924 // substitutions (after all, it's being constructed right now),
925 // but the `supertraits` iterator really wants one. To handle
926 // this, we currently insert a dummy type and then remove it
929 let dummy_self_ty
= tcx
.mk_infer(ty
::FreshTy(0));
930 if self_ty
.is_none() { // if converting for an object type
931 let mut dummy_substs
= trait_ref
.skip_binder().substs
.clone(); // binder moved here -+
932 assert
!(dummy_substs
.self_ty().is_none()); // |
933 dummy_substs
.types
.push(SelfSpace
, dummy_self_ty
); // |
934 trait_ref
= ty
::Binder(ty
::TraitRef
::new(trait_ref
.def_id(), // <------------+
935 tcx
.mk_substs(dummy_substs
)));
938 this
.ensure_super_predicates(binding
.span
, trait_ref
.def_id())?
;
940 let mut candidates
: Vec
<ty
::PolyTraitRef
> =
941 traits
::supertraits(tcx
, trait_ref
.clone())
942 .filter(|r
| this
.trait_defines_associated_type_named(r
.def_id(), binding
.item_name
))
945 // If converting for an object type, then remove the dummy-ty from `Self` now.
947 if self_ty
.is_none() {
948 for candidate
in &mut candidates
{
949 let mut dummy_substs
= candidate
.0.substs
.clone();
950 assert
!(dummy_substs
.self_ty() == Some(dummy_self_ty
));
951 dummy_substs
.types
.pop(SelfSpace
);
952 *candidate
= ty
::Binder(ty
::TraitRef
::new(candidate
.def_id(),
953 tcx
.mk_substs(dummy_substs
)));
957 let candidate
= one_bound_for_assoc_type(tcx
,
959 &trait_ref
.to_string(),
960 &binding
.item_name
.as_str(),
963 Ok(ty
::Binder(ty
::ProjectionPredicate
{ // <-------------------------+
964 projection_ty
: ty
::ProjectionTy
{ // |
965 trait_ref
: candidate
.skip_binder().clone(), // binder is moved up here --+
966 item_name
: binding
.item_name
,
972 fn ast_path_to_ty
<'tcx
>(
973 this
: &AstConv
<'tcx
>,
974 rscope
: &RegionScope
,
976 param_mode
: PathParamMode
,
978 item_segment
: &hir
::PathSegment
)
981 let tcx
= this
.tcx();
982 let (generics
, decl_ty
) = match this
.get_item_type_scheme(span
, did
) {
983 Ok(ty
::TypeScheme { generics, ty: decl_ty }
) => {
986 Err(ErrorReported
) => {
987 return tcx
.types
.err
;
991 let substs
= ast_path_substs_for_ty(this
,
998 // FIXME(#12938): This is a hack until we have full support for DST.
999 if Some(did
) == this
.tcx().lang_items
.owned_box() {
1000 assert_eq
!(substs
.types
.len(TypeSpace
), 1);
1001 return this
.tcx().mk_box(*substs
.types
.get(TypeSpace
, 0));
1004 decl_ty
.subst(this
.tcx(), &substs
)
1007 type TraitAndProjections
<'tcx
> = (ty
::PolyTraitRef
<'tcx
>, Vec
<ty
::PolyProjectionPredicate
<'tcx
>>);
1009 fn ast_ty_to_trait_ref
<'tcx
>(this
: &AstConv
<'tcx
>,
1010 rscope
: &RegionScope
,
1012 bounds
: &[hir
::TyParamBound
])
1013 -> Result
<TraitAndProjections
<'tcx
>, ErrorReported
>
1016 * In a type like `Foo + Send`, we want to wait to collect the
1017 * full set of bounds before we make the object type, because we
1018 * need them to infer a region bound. (For example, if we tried
1019 * made a type from just `Foo`, then it wouldn't be enough to
1020 * infer a 'static bound, and hence the user would get an error.)
1021 * So this function is used when we're dealing with a sum type to
1022 * convert the LHS. It only accepts a type that refers to a trait
1023 * name, and reports an error otherwise.
1027 hir
::TyPath(None
, ref path
) => {
1028 let def
= match this
.tcx().def_map
.borrow().get(&ty
.id
) {
1029 Some(&def
::PathResolution { base_def, depth: 0, .. }
) => Some(base_def
),
1033 Some(Def
::Trait(trait_def_id
)) => {
1034 let mut projection_bounds
= Vec
::new();
1035 let trait_ref
= object_path_to_poly_trait_ref(this
,
1038 PathParamMode
::Explicit
,
1040 path
.segments
.last().unwrap(),
1041 &mut projection_bounds
);
1042 Ok((trait_ref
, projection_bounds
))
1045 span_err
!(this
.tcx().sess
, ty
.span
, E0172
, "expected a reference to a trait");
1051 let mut err
= struct_span_err
!(this
.tcx().sess
, ty
.span
, E0178
,
1052 "expected a path on the left-hand side of `+`, not `{}`",
1053 pprust
::ty_to_string(ty
));
1054 let hi
= bounds
.iter().map(|x
| match *x
{
1055 hir
::TraitTyParamBound(ref tr
, _
) => tr
.span
.hi
,
1056 hir
::RegionTyParamBound(ref r
) => r
.span
.hi
,
1057 }).max_by_key(|x
| x
.to_usize());
1058 let full_span
= hi
.map(|hi
| Span
{
1061 expn_id
: ty
.span
.expn_id
,
1063 match (&ty
.node
, full_span
) {
1064 (&hir
::TyRptr(None
, ref mut_ty
), Some(full_span
)) => {
1065 let mutbl_str
= if mut_ty
.mutbl
== hir
::MutMutable { "mut " }
else { "" }
;
1066 err
.span_suggestion(full_span
, "try adding parentheses (per RFC 438):",
1067 format
!("&{}({} +{})",
1069 pprust
::ty_to_string(&mut_ty
.ty
),
1070 pprust
::bounds_to_string(bounds
)));
1072 (&hir
::TyRptr(Some(ref lt
), ref mut_ty
), Some(full_span
)) => {
1073 let mutbl_str
= if mut_ty
.mutbl
== hir
::MutMutable { "mut " }
else { "" }
;
1074 err
.span_suggestion(full_span
, "try adding parentheses (per RFC 438):",
1075 format
!("&{} {}({} +{})",
1076 pprust
::lifetime_to_string(lt
),
1078 pprust
::ty_to_string(&mut_ty
.ty
),
1079 pprust
::bounds_to_string(bounds
)));
1083 fileline_help
!(&mut err
, ty
.span
,
1084 "perhaps you forgot parentheses? (per RFC 438)");
1093 fn trait_ref_to_object_type
<'tcx
>(this
: &AstConv
<'tcx
>,
1094 rscope
: &RegionScope
,
1096 trait_ref
: ty
::PolyTraitRef
<'tcx
>,
1097 projection_bounds
: Vec
<ty
::PolyProjectionPredicate
<'tcx
>>,
1098 bounds
: &[hir
::TyParamBound
])
1101 let existential_bounds
= conv_existential_bounds(this
,
1108 let result
= make_object_type(this
, span
, trait_ref
, existential_bounds
);
1109 debug
!("trait_ref_to_object_type: result={:?}",
1115 fn make_object_type
<'tcx
>(this
: &AstConv
<'tcx
>,
1117 principal
: ty
::PolyTraitRef
<'tcx
>,
1118 bounds
: ty
::ExistentialBounds
<'tcx
>)
1120 let tcx
= this
.tcx();
1121 let object
= ty
::TraitTy
{
1122 principal
: principal
,
1125 let object_trait_ref
=
1126 object
.principal_trait_ref_with_self_ty(tcx
, tcx
.types
.err
);
1128 // ensure the super predicates and stop if we encountered an error
1129 if this
.ensure_super_predicates(span
, principal
.def_id()).is_err() {
1130 return tcx
.types
.err
;
1133 // check that there are no gross object safety violations,
1134 // most importantly, that the supertraits don't contain Self,
1136 let object_safety_violations
=
1137 traits
::astconv_object_safety_violations(tcx
, principal
.def_id());
1138 if !object_safety_violations
.is_empty() {
1139 traits
::report_object_safety_error(
1140 tcx
, span
, principal
.def_id(), object_safety_violations
)
1142 return tcx
.types
.err
;
1145 let mut associated_types
: FnvHashSet
<(DefId
, ast
::Name
)> =
1146 traits
::supertraits(tcx
, object_trait_ref
)
1148 let trait_def
= tcx
.lookup_trait_def(tr
.def_id());
1149 trait_def
.associated_type_names
1152 .map(move |associated_type_name
| (tr
.def_id(), associated_type_name
))
1156 for projection_bound
in &object
.bounds
.projection_bounds
{
1157 let pair
= (projection_bound
.0.projection_ty
.trait_ref
.def_id
,
1158 projection_bound
.0.projection_ty
.item_name
);
1159 associated_types
.remove(&pair
);
1162 for (trait_def_id
, name
) in associated_types
{
1163 span_err
!(tcx
.sess
, span
, E0191
,
1164 "the value of the associated type `{}` (from the trait `{}`) must be specified",
1166 tcx
.item_path_str(trait_def_id
));
1169 tcx
.mk_trait(object
.principal
, object
.bounds
)
1172 fn report_ambiguous_associated_type(tcx
: &TyCtxt
,
1177 span_err
!(tcx
.sess
, span
, E0223
,
1178 "ambiguous associated type; specify the type using the syntax \
1180 type_str
, trait_str
, name
);
1183 // Search for a bound on a type parameter which includes the associated item
1184 // given by assoc_name. ty_param_node_id is the node id for the type parameter
1185 // (which might be `Self`, but only if it is the `Self` of a trait, not an
1186 // impl). This function will fail if there are no suitable bounds or there is
1188 fn find_bound_for_assoc_item
<'tcx
>(this
: &AstConv
<'tcx
>,
1189 ty_param_node_id
: ast
::NodeId
,
1190 ty_param_name
: ast
::Name
,
1191 assoc_name
: ast
::Name
,
1193 -> Result
<ty
::PolyTraitRef
<'tcx
>, ErrorReported
>
1195 let tcx
= this
.tcx();
1197 let bounds
= match this
.get_type_parameter_bounds(span
, ty_param_node_id
) {
1199 Err(ErrorReported
) => {
1200 return Err(ErrorReported
);
1204 // Ensure the super predicates and stop if we encountered an error.
1205 if bounds
.iter().any(|b
| this
.ensure_super_predicates(span
, b
.def_id()).is_err()) {
1206 return Err(ErrorReported
);
1209 // Check that there is exactly one way to find an associated type with the
1211 let suitable_bounds
: Vec
<_
> =
1212 traits
::transitive_bounds(tcx
, &bounds
)
1213 .filter(|b
| this
.trait_defines_associated_type_named(b
.def_id(), assoc_name
))
1216 one_bound_for_assoc_type(tcx
,
1218 &ty_param_name
.as_str(),
1219 &assoc_name
.as_str(),
1224 // Checks that bounds contains exactly one element and reports appropriate
1225 // errors otherwise.
1226 fn one_bound_for_assoc_type
<'tcx
>(tcx
: &TyCtxt
<'tcx
>,
1227 bounds
: Vec
<ty
::PolyTraitRef
<'tcx
>>,
1228 ty_param_name
: &str,
1231 -> Result
<ty
::PolyTraitRef
<'tcx
>, ErrorReported
>
1233 if bounds
.is_empty() {
1234 span_err
!(tcx
.sess
, span
, E0220
,
1235 "associated type `{}` not found for `{}`",
1238 return Err(ErrorReported
);
1241 if bounds
.len() > 1 {
1242 let mut err
= struct_span_err
!(tcx
.sess
, span
, E0221
,
1243 "ambiguous associated type `{}` in bounds of `{}`",
1247 for bound
in &bounds
{
1248 span_note
!(&mut err
, span
,
1249 "associated type `{}` could derive from `{}`",
1256 Ok(bounds
[0].clone())
1259 // Create a type from a path to an associated type.
1260 // For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
1261 // and item_segment is the path segment for D. We return a type and a def for
1263 // Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
1264 // parameter or Self.
1265 fn associated_path_def_to_ty
<'tcx
>(this
: &AstConv
<'tcx
>,
1269 item_segment
: &hir
::PathSegment
)
1272 let tcx
= this
.tcx();
1273 let assoc_name
= item_segment
.identifier
.name
;
1275 debug
!("associated_path_def_to_ty: {:?}::{}", ty
, assoc_name
);
1277 prohibit_type_params(tcx
, slice
::ref_slice(item_segment
));
1279 // Find the type of the associated item, and the trait where the associated
1280 // item is declared.
1281 let bound
= match (&ty
.sty
, ty_path_def
) {
1282 (_
, Def
::SelfTy(Some(trait_did
), Some((impl_id
, _
)))) => {
1283 // `Self` in an impl of a trait - we have a concrete self type and a
1285 let trait_ref
= tcx
.impl_trait_ref(tcx
.map
.local_def_id(impl_id
)).unwrap();
1286 let trait_ref
= if let Some(free_substs
) = this
.get_free_substs() {
1287 trait_ref
.subst(tcx
, free_substs
)
1292 if this
.ensure_super_predicates(span
, trait_did
).is_err() {
1293 return (tcx
.types
.err
, ty_path_def
);
1296 let candidates
: Vec
<ty
::PolyTraitRef
> =
1297 traits
::supertraits(tcx
, ty
::Binder(trait_ref
))
1298 .filter(|r
| this
.trait_defines_associated_type_named(r
.def_id(),
1302 match one_bound_for_assoc_type(tcx
,
1305 &assoc_name
.as_str(),
1308 Err(ErrorReported
) => return (tcx
.types
.err
, ty_path_def
),
1311 (&ty
::TyParam(_
), Def
::SelfTy(Some(trait_did
), None
)) => {
1312 let trait_node_id
= tcx
.map
.as_local_node_id(trait_did
).unwrap();
1313 match find_bound_for_assoc_item(this
,
1315 token
::special_idents
::type_self
.name
,
1319 Err(ErrorReported
) => return (tcx
.types
.err
, ty_path_def
),
1322 (&ty
::TyParam(_
), Def
::TyParam(_
, _
, param_did
, param_name
)) => {
1323 let param_node_id
= tcx
.map
.as_local_node_id(param_did
).unwrap();
1324 match find_bound_for_assoc_item(this
,
1330 Err(ErrorReported
) => return (tcx
.types
.err
, ty_path_def
),
1334 report_ambiguous_associated_type(tcx
,
1338 &assoc_name
.as_str());
1339 return (tcx
.types
.err
, ty_path_def
);
1343 let trait_did
= bound
.0.def_id
;
1344 let ty
= this
.projected_ty_from_poly_trait_ref(span
, bound
, assoc_name
);
1346 let item_did
= if let Some(trait_id
) = tcx
.map
.as_local_node_id(trait_did
) {
1347 // `ty::trait_items` used below requires information generated
1348 // by type collection, which may be in progress at this point.
1349 match tcx
.map
.expect_item(trait_id
).node
{
1350 hir
::ItemTrait(_
, _
, _
, ref trait_items
) => {
1351 let item
= trait_items
.iter()
1352 .find(|i
| i
.name
== assoc_name
)
1353 .expect("missing associated type");
1354 tcx
.map
.local_def_id(item
.id
)
1359 let trait_items
= tcx
.trait_items(trait_did
);
1360 let item
= trait_items
.iter().find(|i
| i
.name() == assoc_name
);
1361 item
.expect("missing associated type").def_id()
1364 (ty
, Def
::AssociatedTy(trait_did
, item_did
))
1367 fn qpath_to_ty
<'tcx
>(this
: &AstConv
<'tcx
>,
1368 rscope
: &RegionScope
,
1370 param_mode
: PathParamMode
,
1371 opt_self_ty
: Option
<Ty
<'tcx
>>,
1372 trait_def_id
: DefId
,
1373 trait_segment
: &hir
::PathSegment
,
1374 item_segment
: &hir
::PathSegment
)
1377 let tcx
= this
.tcx();
1379 prohibit_type_params(tcx
, slice
::ref_slice(item_segment
));
1381 let self_ty
= if let Some(ty
) = opt_self_ty
{
1384 let path_str
= tcx
.item_path_str(trait_def_id
);
1385 report_ambiguous_associated_type(tcx
,
1389 &item_segment
.identifier
.name
.as_str());
1390 return tcx
.types
.err
;
1393 debug
!("qpath_to_ty: self_type={:?}", self_ty
);
1395 let trait_ref
= ast_path_to_mono_trait_ref(this
,
1403 debug
!("qpath_to_ty: trait_ref={:?}", trait_ref
);
1405 this
.projected_ty(span
, trait_ref
, item_segment
.identifier
.name
)
1408 /// Convert a type supplied as value for a type argument from AST into our
1409 /// our internal representation. This is the same as `ast_ty_to_ty` but that
1410 /// it applies the object lifetime default.
1414 /// * `this`, `rscope`: the surrounding context
1415 /// * `decl_generics`: the generics of the struct/enum/trait declaration being
1417 /// * `index`: the index of the type parameter being instantiated from the list
1418 /// (we assume it is in the `TypeSpace`)
1419 /// * `region_substs`: a partial substitution consisting of
1420 /// only the region type parameters being supplied to this type.
1421 /// * `ast_ty`: the ast representation of the type being supplied
1422 pub fn ast_ty_arg_to_ty
<'tcx
>(this
: &AstConv
<'tcx
>,
1423 rscope
: &RegionScope
,
1424 decl_generics
: &ty
::Generics
<'tcx
>,
1426 region_substs
: &Substs
<'tcx
>,
1430 let tcx
= this
.tcx();
1432 if let Some(def
) = decl_generics
.types
.opt_get(TypeSpace
, index
) {
1433 let object_lifetime_default
= def
.object_lifetime_default
.subst(tcx
, region_substs
);
1434 let rscope1
= &ObjectLifetimeDefaultRscope
::new(rscope
, object_lifetime_default
);
1435 ast_ty_to_ty(this
, rscope1
, ast_ty
)
1437 ast_ty_to_ty(this
, rscope
, ast_ty
)
1441 // Check the base def in a PathResolution and convert it to a Ty. If there are
1442 // associated types in the PathResolution, these will need to be separately
1444 fn base_def_to_ty
<'tcx
>(this
: &AstConv
<'tcx
>,
1445 rscope
: &RegionScope
,
1447 param_mode
: PathParamMode
,
1449 opt_self_ty
: Option
<Ty
<'tcx
>>,
1450 base_segments
: &[hir
::PathSegment
])
1452 let tcx
= this
.tcx();
1455 Def
::Trait(trait_def_id
) => {
1456 // N.B. this case overlaps somewhat with
1457 // TyObjectSum, see that fn for details
1458 let mut projection_bounds
= Vec
::new();
1460 let trait_ref
= object_path_to_poly_trait_ref(this
,
1465 base_segments
.last().unwrap(),
1466 &mut projection_bounds
);
1468 prohibit_type_params(tcx
, base_segments
.split_last().unwrap().1);
1469 trait_ref_to_object_type(this
,
1476 Def
::Enum(did
) | Def
::TyAlias(did
) | Def
::Struct(did
) => {
1477 prohibit_type_params(tcx
, base_segments
.split_last().unwrap().1);
1478 ast_path_to_ty(this
,
1483 base_segments
.last().unwrap())
1485 Def
::TyParam(space
, index
, _
, name
) => {
1486 prohibit_type_params(tcx
, base_segments
);
1487 tcx
.mk_param(space
, index
, name
)
1489 Def
::SelfTy(_
, Some((_
, self_ty_id
))) => {
1490 // Self in impl (we know the concrete type).
1491 prohibit_type_params(tcx
, base_segments
);
1492 if let Some(&ty
) = tcx
.ast_ty_to_ty_cache
.borrow().get(&self_ty_id
) {
1493 if let Some(free_substs
) = this
.get_free_substs() {
1494 ty
.subst(tcx
, free_substs
)
1499 span_bug
!(span
, "self type has not been fully resolved")
1502 Def
::SelfTy(Some(_
), None
) => {
1504 prohibit_type_params(tcx
, base_segments
);
1507 Def
::AssociatedTy(trait_did
, _
) => {
1508 prohibit_type_params(tcx
, &base_segments
[..base_segments
.len()-2]);
1515 &base_segments
[base_segments
.len()-2],
1516 base_segments
.last().unwrap())
1519 // Used as sentinel by callers to indicate the `<T>::A::B::C` form.
1520 // FIXME(#22519) This part of the resolution logic should be
1521 // avoided entirely for that form, once we stop needed a Def
1522 // for `associated_path_def_to_ty`.
1523 // Fixing this will also let use resolve <Self>::Foo the same way we
1524 // resolve Self::Foo, at the moment we can't resolve the former because
1525 // we don't have the trait information around, which is just sad.
1527 assert
!(base_segments
.is_empty());
1529 opt_self_ty
.expect("missing T in <T>::a::b::c")
1531 Def
::PrimTy(prim_ty
) => {
1532 prim_ty_to_ty(tcx
, base_segments
, prim_ty
)
1535 return this
.tcx().types
.err
;
1538 span_err
!(tcx
.sess
, span
, E0248
,
1539 "found value `{}` used as a type",
1540 tcx
.item_path_str(def
.def_id()));
1541 return this
.tcx().types
.err
;
1546 // Note that both base_segments and assoc_segments may be empty, although not at
1548 pub fn finish_resolving_def_to_ty
<'tcx
>(this
: &AstConv
<'tcx
>,
1549 rscope
: &RegionScope
,
1551 param_mode
: PathParamMode
,
1553 opt_self_ty
: Option
<Ty
<'tcx
>>,
1554 base_segments
: &[hir
::PathSegment
],
1555 assoc_segments
: &[hir
::PathSegment
])
1557 let mut ty
= base_def_to_ty(this
,
1565 // If any associated type segments remain, attempt to resolve them.
1566 for segment
in assoc_segments
{
1567 if ty
.sty
== ty
::TyError
{
1570 // This is pretty bad (it will fail except for T::A and Self::A).
1571 let (a_ty
, a_def
) = associated_path_def_to_ty(this
,
1582 /// Parses the programmer's textual representation of a type into our
1583 /// internal notion of a type.
1584 pub fn ast_ty_to_ty
<'tcx
>(this
: &AstConv
<'tcx
>,
1585 rscope
: &RegionScope
,
1589 debug
!("ast_ty_to_ty(id={:?}, ast_ty={:?})",
1592 let tcx
= this
.tcx();
1594 if let Some(&ty
) = tcx
.ast_ty_to_ty_cache
.borrow().get(&ast_ty
.id
) {
1595 debug
!("ast_ty_to_ty: id={:?} ty={:?} (cached)", ast_ty
.id
, ty
);
1599 let typ
= match ast_ty
.node
{
1600 hir
::TyVec(ref ty
) => {
1601 tcx
.mk_slice(ast_ty_to_ty(this
, rscope
, &ty
))
1603 hir
::TyObjectSum(ref ty
, ref bounds
) => {
1604 match ast_ty_to_trait_ref(this
, rscope
, &ty
, bounds
) {
1605 Ok((trait_ref
, projection_bounds
)) => {
1606 trait_ref_to_object_type(this
,
1613 Err(ErrorReported
) => {
1614 this
.tcx().types
.err
1618 hir
::TyPtr(ref mt
) => {
1619 tcx
.mk_ptr(ty
::TypeAndMut
{
1620 ty
: ast_ty_to_ty(this
, rscope
, &mt
.ty
),
1624 hir
::TyRptr(ref region
, ref mt
) => {
1625 let r
= opt_ast_region_to_region(this
, rscope
, ast_ty
.span
, region
);
1626 debug
!("TyRef r={:?}", r
);
1628 &ObjectLifetimeDefaultRscope
::new(
1630 ty
::ObjectLifetimeDefault
::Specific(r
));
1631 let t
= ast_ty_to_ty(this
, rscope1
, &mt
.ty
);
1632 tcx
.mk_ref(tcx
.mk_region(r
), ty
::TypeAndMut {ty: t, mutbl: mt.mutbl}
)
1634 hir
::TyTup(ref fields
) => {
1635 let flds
= fields
.iter()
1636 .map(|t
| ast_ty_to_ty(this
, rscope
, &t
))
1640 hir
::TyBareFn(ref bf
) => {
1641 require_c_abi_if_variadic(tcx
, &bf
.decl
, bf
.abi
, ast_ty
.span
);
1642 tcx
.mk_fn_ptr(ty_of_bare_fn(this
, bf
.unsafety
, bf
.abi
, &bf
.decl
))
1644 hir
::TyPolyTraitRef(ref bounds
) => {
1645 conv_ty_poly_trait_ref(this
, rscope
, ast_ty
.span
, bounds
)
1647 hir
::TyPath(ref maybe_qself
, ref path
) => {
1648 let path_res
= if let Some(&d
) = tcx
.def_map
.borrow().get(&ast_ty
.id
) {
1650 } else if let Some(hir
::QSelf { position: 0, .. }
) = *maybe_qself
{
1651 // Create some fake resolution that can't possibly be a type.
1652 def
::PathResolution
{
1653 base_def
: Def
::Mod(tcx
.map
.local_def_id(ast
::CRATE_NODE_ID
)),
1654 depth
: path
.segments
.len()
1657 span_bug
!(ast_ty
.span
, "unbound path {:?}", ast_ty
)
1659 let def
= path_res
.base_def
;
1660 let base_ty_end
= path
.segments
.len() - path_res
.depth
;
1661 let opt_self_ty
= maybe_qself
.as_ref().map(|qself
| {
1662 ast_ty_to_ty(this
, rscope
, &qself
.ty
)
1664 let ty
= finish_resolving_def_to_ty(this
,
1667 PathParamMode
::Explicit
,
1670 &path
.segments
[..base_ty_end
],
1671 &path
.segments
[base_ty_end
..]);
1673 if path_res
.depth
!= 0 && ty
.sty
!= ty
::TyError
{
1674 // Write back the new resolution.
1675 tcx
.def_map
.borrow_mut().insert(ast_ty
.id
, def
::PathResolution
{
1683 hir
::TyFixedLengthVec(ref ty
, ref e
) => {
1684 let hint
= UncheckedExprHint(tcx
.types
.usize);
1685 match eval_const_expr_partial(tcx
, &e
, hint
, None
) {
1686 Ok(ConstVal
::Integral(ConstInt
::Usize(i
))) => {
1687 let i
= i
.as_u64(tcx
.sess
.target
.uint_type
);
1688 assert_eq
!(i
as usize as u64, i
);
1689 tcx
.mk_array(ast_ty_to_ty(this
, rscope
, &ty
), i
as usize)
1692 span_err
!(tcx
.sess
, ast_ty
.span
, E0249
,
1693 "expected usize value for array length, got {}", val
.description());
1694 this
.tcx().types
.err
1697 let mut err
= struct_span_err
!(tcx
.sess
, r
.span
, E0250
,
1698 "array length constant evaluation error: {}",
1700 if !ast_ty
.span
.contains(r
.span
) {
1701 span_note
!(&mut err
, ast_ty
.span
, "for array length here")
1704 this
.tcx().types
.err
1708 hir
::TyTypeof(ref _e
) => {
1709 span_err
!(tcx
.sess
, ast_ty
.span
, E0516
,
1710 "`typeof` is a reserved keyword but unimplemented");
1714 // TyInfer also appears as the type of arguments or return
1715 // values in a ExprClosure, or as
1716 // the type of local variables. Both of these cases are
1717 // handled specially and will not descend into this routine.
1718 this
.ty_infer(None
, None
, None
, ast_ty
.span
)
1722 debug
!("ast_ty_to_ty: id={:?} ty={:?}", ast_ty
.id
, typ
);
1723 tcx
.ast_ty_to_ty_cache
.borrow_mut().insert(ast_ty
.id
, typ
);
1727 pub fn ty_of_arg
<'tcx
>(this
: &AstConv
<'tcx
>,
1728 rscope
: &RegionScope
,
1730 expected_ty
: Option
<Ty
<'tcx
>>)
1734 hir
::TyInfer
if expected_ty
.is_some() => expected_ty
.unwrap(),
1735 hir
::TyInfer
=> this
.ty_infer(None
, None
, None
, a
.ty
.span
),
1736 _
=> ast_ty_to_ty(this
, rscope
, &a
.ty
),
1740 struct SelfInfo
<'a
, 'tcx
> {
1741 untransformed_self_ty
: Ty
<'tcx
>,
1742 explicit_self
: &'a hir
::ExplicitSelf
,
1745 pub fn ty_of_method
<'tcx
>(this
: &AstConv
<'tcx
>,
1746 sig
: &hir
::MethodSig
,
1747 untransformed_self_ty
: Ty
<'tcx
>)
1748 -> (ty
::BareFnTy
<'tcx
>, ty
::ExplicitSelfCategory
) {
1749 let self_info
= Some(SelfInfo
{
1750 untransformed_self_ty
: untransformed_self_ty
,
1751 explicit_self
: &sig
.explicit_self
,
1753 let (bare_fn_ty
, optional_explicit_self_category
) =
1754 ty_of_method_or_bare_fn(this
,
1759 (bare_fn_ty
, optional_explicit_self_category
.unwrap())
1762 pub fn ty_of_bare_fn
<'tcx
>(this
: &AstConv
<'tcx
>, unsafety
: hir
::Unsafety
, abi
: abi
::Abi
,
1763 decl
: &hir
::FnDecl
) -> ty
::BareFnTy
<'tcx
> {
1764 let (bare_fn_ty
, _
) = ty_of_method_or_bare_fn(this
, unsafety
, abi
, None
, decl
);
1768 fn ty_of_method_or_bare_fn
<'a
, 'tcx
>(this
: &AstConv
<'tcx
>,
1769 unsafety
: hir
::Unsafety
,
1771 opt_self_info
: Option
<SelfInfo
<'a
, 'tcx
>>,
1773 -> (ty
::BareFnTy
<'tcx
>, Option
<ty
::ExplicitSelfCategory
>)
1775 debug
!("ty_of_method_or_bare_fn");
1777 // New region names that appear inside of the arguments of the function
1778 // declaration are bound to that function type.
1779 let rb
= rscope
::BindingRscope
::new();
1781 // `implied_output_region` is the region that will be assumed for any
1782 // region parameters in the return type. In accordance with the rules for
1783 // lifetime elision, we can determine it in two ways. First (determined
1784 // here), if self is by-reference, then the implied output region is the
1785 // region of the self parameter.
1786 let (self_ty
, explicit_self_category
) = match opt_self_info
{
1787 None
=> (None
, None
),
1788 Some(self_info
) => determine_self_type(this
, &rb
, self_info
)
1791 // HACK(eddyb) replace the fake self type in the AST with the actual type.
1792 let arg_params
= if self_ty
.is_some() {
1797 let arg_tys
: Vec
<Ty
> =
1798 arg_params
.iter().map(|a
| ty_of_arg(this
, &rb
, a
, None
)).collect();
1799 let arg_pats
: Vec
<String
> =
1800 arg_params
.iter().map(|a
| pprust
::pat_to_string(&a
.pat
)).collect();
1802 // Second, if there was exactly one lifetime (either a substitution or a
1803 // reference) in the arguments, then any anonymous regions in the output
1804 // have that lifetime.
1805 let implied_output_region
= match explicit_self_category
{
1806 Some(ty
::ExplicitSelfCategory
::ByReference(region
, _
)) => Ok(region
),
1807 _
=> find_implied_output_region(this
.tcx(), &arg_tys
, arg_pats
)
1810 let output_ty
= match decl
.output
{
1811 hir
::Return(ref output
) =>
1812 ty
::FnConverging(convert_ty_with_lifetime_elision(this
,
1813 implied_output_region
,
1815 hir
::DefaultReturn(..) => ty
::FnConverging(this
.tcx().mk_nil()),
1816 hir
::NoReturn(..) => ty
::FnDiverging
1822 sig
: ty
::Binder(ty
::FnSig
{
1823 inputs
: self_ty
.into_iter().chain(arg_tys
).collect(),
1825 variadic
: decl
.variadic
1827 }, explicit_self_category
)
1830 fn determine_self_type
<'a
, 'tcx
>(this
: &AstConv
<'tcx
>,
1831 rscope
: &RegionScope
,
1832 self_info
: SelfInfo
<'a
, 'tcx
>)
1833 -> (Option
<Ty
<'tcx
>>, Option
<ty
::ExplicitSelfCategory
>)
1835 let self_ty
= self_info
.untransformed_self_ty
;
1836 return match self_info
.explicit_self
.node
{
1837 hir
::SelfStatic
=> (None
, Some(ty
::ExplicitSelfCategory
::Static
)),
1838 hir
::SelfValue(_
) => {
1839 (Some(self_ty
), Some(ty
::ExplicitSelfCategory
::ByValue
))
1841 hir
::SelfRegion(ref lifetime
, mutability
, _
) => {
1843 opt_ast_region_to_region(this
,
1845 self_info
.explicit_self
.span
,
1847 (Some(this
.tcx().mk_ref(
1848 this
.tcx().mk_region(region
),
1853 Some(ty
::ExplicitSelfCategory
::ByReference(region
, mutability
)))
1855 hir
::SelfExplicit(ref ast_type
, _
) => {
1856 let explicit_type
= ast_ty_to_ty(this
, rscope
, &ast_type
);
1858 // We wish to (for now) categorize an explicit self
1859 // declaration like `self: SomeType` into either `self`,
1860 // `&self`, `&mut self`, or `Box<self>`. We do this here
1861 // by some simple pattern matching. A more precise check
1862 // is done later in `check_method_self_type()`.
1867 // impl Foo for &T {
1868 // // Legal declarations:
1869 // fn method1(self: &&T); // ExplicitSelfCategory::ByReference
1870 // fn method2(self: &T); // ExplicitSelfCategory::ByValue
1871 // fn method3(self: Box<&T>); // ExplicitSelfCategory::ByBox
1873 // // Invalid cases will be caught later by `check_method_self_type`:
1874 // fn method_err1(self: &mut T); // ExplicitSelfCategory::ByReference
1878 // To do the check we just count the number of "modifiers"
1879 // on each type and compare them. If they are the same or
1880 // the impl has more, we call it "by value". Otherwise, we
1881 // look at the outermost modifier on the method decl and
1882 // call it by-ref, by-box as appropriate. For method1, for
1883 // example, the impl type has one modifier, but the method
1884 // type has two, so we end up with
1885 // ExplicitSelfCategory::ByReference.
1887 let impl_modifiers
= count_modifiers(self_info
.untransformed_self_ty
);
1888 let method_modifiers
= count_modifiers(explicit_type
);
1890 debug
!("determine_explicit_self_category(self_info.untransformed_self_ty={:?} \
1891 explicit_type={:?} \
1893 self_info
.untransformed_self_ty
,
1898 let category
= if impl_modifiers
>= method_modifiers
{
1899 ty
::ExplicitSelfCategory
::ByValue
1901 match explicit_type
.sty
{
1902 ty
::TyRef(r
, mt
) => ty
::ExplicitSelfCategory
::ByReference(*r
, mt
.mutbl
),
1903 ty
::TyBox(_
) => ty
::ExplicitSelfCategory
::ByBox
,
1904 _
=> ty
::ExplicitSelfCategory
::ByValue
,
1908 (Some(explicit_type
), Some(category
))
1912 fn count_modifiers(ty
: Ty
) -> usize {
1914 ty
::TyRef(_
, mt
) => count_modifiers(mt
.ty
) + 1,
1915 ty
::TyBox(t
) => count_modifiers(t
) + 1,
1921 pub fn ty_of_closure
<'tcx
>(
1922 this
: &AstConv
<'tcx
>,
1923 unsafety
: hir
::Unsafety
,
1926 expected_sig
: Option
<ty
::FnSig
<'tcx
>>)
1927 -> ty
::ClosureTy
<'tcx
>
1929 debug
!("ty_of_closure(expected_sig={:?})",
1932 // new region names that appear inside of the fn decl are bound to
1933 // that function type
1934 let rb
= rscope
::BindingRscope
::new();
1936 let input_tys
: Vec
<_
> = decl
.inputs
.iter().enumerate().map(|(i
, a
)| {
1937 let expected_arg_ty
= expected_sig
.as_ref().and_then(|e
| {
1938 // no guarantee that the correct number of expected args
1940 if i
< e
.inputs
.len() {
1946 ty_of_arg(this
, &rb
, a
, expected_arg_ty
)
1949 let expected_ret_ty
= expected_sig
.map(|e
| e
.output
);
1951 let is_infer
= match decl
.output
{
1952 hir
::Return(ref output
) if output
.node
== hir
::TyInfer
=> true,
1953 hir
::DefaultReturn(..) => true,
1957 let output_ty
= match decl
.output
{
1958 _
if is_infer
&& expected_ret_ty
.is_some() =>
1959 expected_ret_ty
.unwrap(),
1961 ty
::FnConverging(this
.ty_infer(None
, None
, None
, decl
.output
.span())),
1962 hir
::Return(ref output
) =>
1963 ty
::FnConverging(ast_ty_to_ty(this
, &rb
, &output
)),
1964 hir
::DefaultReturn(..) => bug
!(),
1965 hir
::NoReturn(..) => ty
::FnDiverging
1968 debug
!("ty_of_closure: input_tys={:?}", input_tys
);
1969 debug
!("ty_of_closure: output_ty={:?}", output_ty
);
1974 sig
: ty
::Binder(ty
::FnSig
{inputs
: input_tys
,
1976 variadic
: decl
.variadic
}),
1980 /// Given an existential type like `Foo+'a+Bar`, this routine converts the `'a` and `Bar` intos an
1981 /// `ExistentialBounds` struct. The `main_trait_refs` argument specifies the `Foo` -- it is absent
1982 /// for closures. Eventually this should all be normalized, I think, so that there is no "main
1983 /// trait ref" and instead we just have a flat list of bounds as the existential type.
1984 fn conv_existential_bounds
<'tcx
>(
1985 this
: &AstConv
<'tcx
>,
1986 rscope
: &RegionScope
,
1988 principal_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
1989 projection_bounds
: Vec
<ty
::PolyProjectionPredicate
<'tcx
>>,
1990 ast_bounds
: &[hir
::TyParamBound
])
1991 -> ty
::ExistentialBounds
<'tcx
>
1993 let partitioned_bounds
=
1994 partition_bounds(this
.tcx(), span
, ast_bounds
);
1996 conv_existential_bounds_from_partitioned_bounds(
1997 this
, rscope
, span
, principal_trait_ref
, projection_bounds
, partitioned_bounds
)
2000 fn conv_ty_poly_trait_ref
<'tcx
>(
2001 this
: &AstConv
<'tcx
>,
2002 rscope
: &RegionScope
,
2004 ast_bounds
: &[hir
::TyParamBound
])
2007 let mut partitioned_bounds
= partition_bounds(this
.tcx(), span
, &ast_bounds
[..]);
2009 let mut projection_bounds
= Vec
::new();
2010 let main_trait_bound
= if !partitioned_bounds
.trait_bounds
.is_empty() {
2011 let trait_bound
= partitioned_bounds
.trait_bounds
.remove(0);
2012 instantiate_poly_trait_ref(this
,
2016 &mut projection_bounds
)
2018 span_err
!(this
.tcx().sess
, span
, E0224
,
2019 "at least one non-builtin trait is required for an object type");
2020 return this
.tcx().types
.err
;
2024 conv_existential_bounds_from_partitioned_bounds(this
,
2027 main_trait_bound
.clone(),
2029 partitioned_bounds
);
2031 make_object_type(this
, span
, main_trait_bound
, bounds
)
2034 pub fn conv_existential_bounds_from_partitioned_bounds
<'tcx
>(
2035 this
: &AstConv
<'tcx
>,
2036 rscope
: &RegionScope
,
2038 principal_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
2039 projection_bounds
: Vec
<ty
::PolyProjectionPredicate
<'tcx
>>, // Empty for boxed closures
2040 partitioned_bounds
: PartitionedBounds
)
2041 -> ty
::ExistentialBounds
<'tcx
>
2043 let PartitionedBounds
{ builtin_bounds
,
2048 if !trait_bounds
.is_empty() {
2049 let b
= &trait_bounds
[0];
2050 span_err
!(this
.tcx().sess
, b
.trait_ref
.path
.span
, E0225
,
2051 "only the builtin traits can be used as closure or object bounds");
2055 compute_object_lifetime_bound(this
,
2058 principal_trait_ref
,
2061 let region_bound
= match region_bound
{
2064 match rscope
.object_lifetime_default(span
) {
2067 span_err
!(this
.tcx().sess
, span
, E0228
,
2068 "the lifetime bound for this object type cannot be deduced \
2069 from context; please supply an explicit bound");
2076 debug
!("region_bound: {:?}", region_bound
);
2078 ty
::ExistentialBounds
::new(region_bound
, builtin_bounds
, projection_bounds
)
2081 /// Given the bounds on an object, determines what single region bound
2082 /// (if any) we can use to summarize this type. The basic idea is that we will use the bound the
2083 /// user provided, if they provided one, and otherwise search the supertypes of trait bounds for
2084 /// region bounds. It may be that we can derive no bound at all, in which case we return `None`.
2085 fn compute_object_lifetime_bound
<'tcx
>(
2086 this
: &AstConv
<'tcx
>,
2088 explicit_region_bounds
: &[&hir
::Lifetime
],
2089 principal_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
2090 builtin_bounds
: ty
::BuiltinBounds
)
2091 -> Option
<ty
::Region
> // if None, use the default
2093 let tcx
= this
.tcx();
2095 debug
!("compute_opt_region_bound(explicit_region_bounds={:?}, \
2096 principal_trait_ref={:?}, builtin_bounds={:?})",
2097 explicit_region_bounds
,
2098 principal_trait_ref
,
2101 if explicit_region_bounds
.len() > 1 {
2102 span_err
!(tcx
.sess
, explicit_region_bounds
[1].span
, E0226
,
2103 "only a single explicit lifetime bound is permitted");
2106 if !explicit_region_bounds
.is_empty() {
2107 // Explicitly specified region bound. Use that.
2108 let r
= explicit_region_bounds
[0];
2109 return Some(ast_region_to_region(tcx
, r
));
2112 if let Err(ErrorReported
) = this
.ensure_super_predicates(span
,principal_trait_ref
.def_id()) {
2113 return Some(ty
::ReStatic
);
2116 // No explicit region bound specified. Therefore, examine trait
2117 // bounds and see if we can derive region bounds from those.
2118 let derived_region_bounds
=
2119 object_region_bounds(tcx
, &principal_trait_ref
, builtin_bounds
);
2121 // If there are no derived region bounds, then report back that we
2122 // can find no region bound. The caller will use the default.
2123 if derived_region_bounds
.is_empty() {
2127 // If any of the derived region bounds are 'static, that is always
2129 if derived_region_bounds
.iter().any(|r
| ty
::ReStatic
== *r
) {
2130 return Some(ty
::ReStatic
);
2133 // Determine whether there is exactly one unique region in the set
2134 // of derived region bounds. If so, use that. Otherwise, report an
2136 let r
= derived_region_bounds
[0];
2137 if derived_region_bounds
[1..].iter().any(|r1
| r
!= *r1
) {
2138 span_err
!(tcx
.sess
, span
, E0227
,
2139 "ambiguous lifetime bound, explicit lifetime bound required");
2144 pub struct PartitionedBounds
<'a
> {
2145 pub builtin_bounds
: ty
::BuiltinBounds
,
2146 pub trait_bounds
: Vec
<&'a hir
::PolyTraitRef
>,
2147 pub region_bounds
: Vec
<&'a hir
::Lifetime
>,
2150 /// Divides a list of bounds from the AST into three groups: builtin bounds (Copy, Sized etc),
2151 /// general trait bounds, and region bounds.
2152 pub fn partition_bounds
<'a
>(tcx
: &TyCtxt
,
2154 ast_bounds
: &'a
[hir
::TyParamBound
])
2155 -> PartitionedBounds
<'a
>
2157 let mut builtin_bounds
= ty
::BuiltinBounds
::empty();
2158 let mut region_bounds
= Vec
::new();
2159 let mut trait_bounds
= Vec
::new();
2160 for ast_bound
in ast_bounds
{
2162 hir
::TraitTyParamBound(ref b
, hir
::TraitBoundModifier
::None
) => {
2163 match ::lookup_full_def(tcx
, b
.trait_ref
.path
.span
, b
.trait_ref
.ref_id
) {
2164 Def
::Trait(trait_did
) => {
2165 if tcx
.try_add_builtin_trait(trait_did
,
2166 &mut builtin_bounds
) {
2167 let segments
= &b
.trait_ref
.path
.segments
;
2168 let parameters
= &segments
[segments
.len() - 1].parameters
;
2169 if !parameters
.types().is_empty() {
2170 check_type_argument_count(tcx
, b
.trait_ref
.path
.span
,
2171 parameters
.types().len(), 0, 0);
2173 if !parameters
.lifetimes().is_empty() {
2174 report_lifetime_number_error(tcx
, b
.trait_ref
.path
.span
,
2175 parameters
.lifetimes().len(), 0);
2177 continue; // success
2181 // Not a trait? that's an error, but it'll get
2185 trait_bounds
.push(b
);
2187 hir
::TraitTyParamBound(_
, hir
::TraitBoundModifier
::Maybe
) => {}
2188 hir
::RegionTyParamBound(ref l
) => {
2189 region_bounds
.push(l
);
2195 builtin_bounds
: builtin_bounds
,
2196 trait_bounds
: trait_bounds
,
2197 region_bounds
: region_bounds
,
2201 fn prohibit_projections
<'tcx
>(tcx
: &TyCtxt
<'tcx
>,
2202 bindings
: &[ConvertedBinding
<'tcx
>])
2204 for binding
in bindings
.iter().take(1) {
2205 prohibit_projection(tcx
, binding
.span
);
2209 fn check_type_argument_count(tcx
: &TyCtxt
, span
: Span
, supplied
: usize,
2210 required
: usize, accepted
: usize) {
2211 if supplied
< required
{
2212 let expected
= if required
< accepted
{
2217 span_err
!(tcx
.sess
, span
, E0243
,
2218 "wrong number of type arguments: {} {}, found {}",
2219 expected
, required
, supplied
);
2220 } else if supplied
> accepted
{
2221 let expected
= if required
< accepted
{
2226 span_err
!(tcx
.sess
, span
, E0244
,
2227 "wrong number of type arguments: {} {}, found {}",
2234 fn report_lifetime_number_error(tcx
: &TyCtxt
, span
: Span
, number
: usize, expected
: usize) {
2235 span_err
!(tcx
.sess
, span
, E0107
,
2236 "wrong number of lifetime parameters: expected {}, found {}",
2240 // A helper struct for conveniently grouping a set of bounds which we pass to
2241 // and return from functions in multiple places.
2242 #[derive(PartialEq, Eq, Clone, Debug)]
2243 pub struct Bounds
<'tcx
> {
2244 pub region_bounds
: Vec
<ty
::Region
>,
2245 pub builtin_bounds
: ty
::BuiltinBounds
,
2246 pub trait_bounds
: Vec
<ty
::PolyTraitRef
<'tcx
>>,
2247 pub projection_bounds
: Vec
<ty
::PolyProjectionPredicate
<'tcx
>>,
2250 impl<'tcx
> Bounds
<'tcx
> {
2251 pub fn predicates(&self,
2254 -> Vec
<ty
::Predicate
<'tcx
>>
2256 let mut vec
= Vec
::new();
2258 for builtin_bound
in &self.builtin_bounds
{
2259 match traits
::trait_ref_for_builtin_bound(tcx
, builtin_bound
, param_ty
) {
2260 Ok(trait_ref
) => { vec.push(trait_ref.to_predicate()); }
2261 Err(ErrorReported
) => { }
2265 for ®ion_bound
in &self.region_bounds
{
2266 // account for the binder being introduced below; no need to shift `param_ty`
2267 // because, at present at least, it can only refer to early-bound regions
2268 let region_bound
= ty
::fold
::shift_region(region_bound
, 1);
2269 vec
.push(ty
::Binder(ty
::OutlivesPredicate(param_ty
, region_bound
)).to_predicate());
2272 for bound_trait_ref
in &self.trait_bounds
{
2273 vec
.push(bound_trait_ref
.to_predicate());
2276 for projection
in &self.projection_bounds
{
2277 vec
.push(projection
.to_predicate());