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 rustc_const_eval
::eval_length
;
52 use hir
::{self, SelfKind}
;
53 use hir
::def
::{Def, PathResolution}
;
54 use hir
::def_id
::DefId
;
55 use hir
::print
as pprust
;
56 use middle
::resolve_lifetime
as rl
;
58 use rustc
::ty
::subst
::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace}
;
59 use rustc
::ty
::subst
::VecPerParamSpace
;
61 use rustc
::ty
::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}
;
62 use rustc
::ty
::wf
::object_region_bounds
;
63 use rustc_back
::slice
;
64 use require_c_abi_if_variadic
;
65 use rscope
::{self, UnelidableRscope
, RegionScope
, ElidableRscope
,
66 ObjectLifetimeDefaultRscope
, ShiftedRscope
, BindingRscope
,
67 ElisionFailureInfo
, ElidedLifetime
};
68 use rscope
::{AnonTypeScope, MaybeWithAnonTypes}
;
69 use util
::common
::{ErrorReported, FN_OUTPUT_NAME}
;
70 use util
::nodemap
::{NodeMap, FnvHashSet}
;
72 use std
::cell
::RefCell
;
73 use syntax
::{abi, ast}
;
74 use syntax
::feature_gate
::{GateIssue, emit_feature_err}
;
75 use syntax
::parse
::token
::{self, keywords}
;
76 use syntax_pos
::{Span, Pos}
;
77 use errors
::DiagnosticBuilder
;
79 pub trait AstConv
<'gcx
, 'tcx
> {
80 fn tcx
<'a
>(&'a
self) -> TyCtxt
<'a
, 'gcx
, 'tcx
>;
82 /// A cache used for the result of `ast_ty_to_ty_cache`
83 fn ast_ty_to_ty_cache(&self) -> &RefCell
<NodeMap
<Ty
<'tcx
>>>;
85 /// Identify the type scheme for an item with a type, like a type
86 /// alias, fn, or struct. This allows you to figure out the set of
87 /// type parameters defined on the item.
88 fn get_item_type_scheme(&self, span
: Span
, id
: DefId
)
89 -> Result
<ty
::TypeScheme
<'tcx
>, ErrorReported
>;
91 /// Returns the `TraitDef` for a given trait. This allows you to
92 /// figure out the set of type parameters defined on the trait.
93 fn get_trait_def(&self, span
: Span
, id
: DefId
)
94 -> Result
<&'tcx ty
::TraitDef
<'tcx
>, ErrorReported
>;
96 /// Ensure that the super-predicates for the trait with the given
97 /// id are available and also for the transitive set of
99 fn ensure_super_predicates(&self, span
: Span
, id
: DefId
)
100 -> Result
<(), ErrorReported
>;
102 /// Returns the set of bounds in scope for the type parameter with
104 fn get_type_parameter_bounds(&self, span
: Span
, def_id
: ast
::NodeId
)
105 -> Result
<Vec
<ty
::PolyTraitRef
<'tcx
>>, ErrorReported
>;
107 /// Returns true if the trait with id `trait_def_id` defines an
108 /// associated type with the name `name`.
109 fn trait_defines_associated_type_named(&self, trait_def_id
: DefId
, name
: ast
::Name
)
112 /// Return an (optional) substitution to convert bound type parameters that
113 /// are in scope into free ones. This function should only return Some
114 /// within a fn body.
115 /// See ParameterEnvironment::free_substs for more information.
116 fn get_free_substs(&self) -> Option
<&Substs
<'tcx
>>;
118 /// What type should we use when a type is omitted?
120 param_and_substs
: Option
<ty
::TypeParameterDef
<'tcx
>>,
121 substs
: Option
<&mut Substs
<'tcx
>>,
122 space
: Option
<ParamSpace
>,
123 span
: Span
) -> Ty
<'tcx
>;
125 /// Projecting an associated type from a (potentially)
126 /// higher-ranked trait reference is more complicated, because of
127 /// the possibility of late-bound regions appearing in the
128 /// associated type binding. This is not legal in function
129 /// signatures for that reason. In a function body, we can always
130 /// handle it because we can use inference variables to remove the
131 /// late-bound regions.
132 fn projected_ty_from_poly_trait_ref(&self,
134 poly_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
135 item_name
: ast
::Name
)
138 /// Project an associated type from a non-higher-ranked trait reference.
139 /// This is fairly straightforward and can be accommodated in any context.
140 fn projected_ty(&self,
142 _trait_ref
: ty
::TraitRef
<'tcx
>,
143 _item_name
: ast
::Name
)
146 /// Invoked when we encounter an error from some prior pass
147 /// (e.g. resolve) that is translated into a ty-error. This is
148 /// used to help suppress derived errors typeck might otherwise
150 fn set_tainted_by_errors(&self);
153 #[derive(PartialEq, Eq)]
154 pub enum PathParamMode
{
155 // Any path in a type context.
157 // The `module::Type` in `module::Type::method` in an expression.
161 struct ConvertedBinding
<'tcx
> {
162 item_name
: ast
::Name
,
167 type TraitAndProjections
<'tcx
> = (ty
::PolyTraitRef
<'tcx
>, Vec
<ty
::PolyProjectionPredicate
<'tcx
>>);
169 pub fn ast_region_to_region(tcx
: TyCtxt
, lifetime
: &hir
::Lifetime
)
171 let r
= match tcx
.named_region_map
.defs
.get(&lifetime
.id
) {
173 // should have been recorded by the `resolve_lifetime` pass
174 span_bug
!(lifetime
.span
, "unresolved lifetime");
177 Some(&rl
::DefStaticRegion
) => {
181 Some(&rl
::DefLateBoundRegion(debruijn
, id
)) => {
182 // If this region is declared on a function, it will have
183 // an entry in `late_bound`, but if it comes from
184 // `for<'a>` in some type or something, it won't
185 // necessarily have one. In that case though, we won't be
186 // changed from late to early bound, so we can just
188 let issue_32330
= tcx
.named_region_map
192 .unwrap_or(ty
::Issue32330
::WontChange
);
193 ty
::ReLateBound(debruijn
, ty
::BrNamed(tcx
.map
.local_def_id(id
),
198 Some(&rl
::DefEarlyBoundRegion(space
, index
, _
)) => {
199 ty
::ReEarlyBound(ty
::EarlyBoundRegion
{
206 Some(&rl
::DefFreeRegion(scope
, id
)) => {
207 // As in DefLateBoundRegion above, could be missing for some late-bound
208 // regions, but also for early-bound regions.
209 let issue_32330
= tcx
.named_region_map
213 .unwrap_or(ty
::Issue32330
::WontChange
);
214 ty
::ReFree(ty
::FreeRegion
{
215 scope
: scope
.to_code_extent(&tcx
.region_maps
),
216 bound_region
: ty
::BrNamed(tcx
.map
.local_def_id(id
),
221 // (*) -- not late-bound, won't change
225 debug
!("ast_region_to_region(lifetime={:?} id={}) yields {:?}",
233 fn report_elision_failure(
234 db
: &mut DiagnosticBuilder
,
235 params
: Vec
<ElisionFailureInfo
>)
237 let mut m
= String
::new();
238 let len
= params
.len();
240 let elided_params
: Vec
<_
> = params
.into_iter()
241 .filter(|info
| info
.lifetime_count
> 0)
244 let elided_len
= elided_params
.len();
246 for (i
, info
) in elided_params
.into_iter().enumerate() {
247 let ElisionFailureInfo
{
248 name
, lifetime_count
: n
, have_bound_regions
251 let help_name
= if name
.is_empty() {
252 format
!("argument {}", i
+ 1)
254 format
!("`{}`", name
)
257 m
.push_str(&(if n
== 1 {
260 format
!("one of {}'s {} elided {}lifetimes", help_name
, n
,
261 if have_bound_regions { "free " }
else { "" }
)
264 if elided_len
== 2 && i
== 0 {
266 } else if i
+ 2 == elided_len
{
268 } else if i
!= elided_len
- 1 {
276 "this function's return type contains a borrowed value, but \
277 there is no value for it to be borrowed from");
279 "consider giving it a 'static lifetime");
280 } else if elided_len
== 0 {
282 "this function's return type contains a borrowed value with \
283 an elided lifetime, but the lifetime cannot be derived from \
286 "consider giving it an explicit bounded or 'static \
288 } else if elided_len
== 1 {
290 "this function's return type contains a borrowed value, but \
291 the signature does not say which {} it is borrowed from",
295 "this function's return type contains a borrowed value, but \
296 the signature does not say whether it is borrowed from {}",
301 impl<'o
, 'gcx
: 'tcx
, 'tcx
> AstConv
<'gcx
, 'tcx
>+'o
{
302 pub fn opt_ast_region_to_region(&self,
303 rscope
: &RegionScope
,
305 opt_lifetime
: &Option
<hir
::Lifetime
>) -> ty
::Region
307 let r
= match *opt_lifetime
{
308 Some(ref lifetime
) => {
309 ast_region_to_region(self.tcx(), lifetime
)
312 None
=> match rscope
.anon_regions(default_span
, 1) {
315 let ampersand_span
= Span { hi: default_span.lo, ..default_span}
;
317 let mut err
= struct_span_err
!(self.tcx().sess
, ampersand_span
, E0106
,
318 "missing lifetime specifier");
319 err
.span_label(ampersand_span
, &format
!("expected lifetime parameter"));
321 if let Some(params
) = params
{
322 report_elision_failure(&mut err
, params
);
330 debug
!("opt_ast_region_to_region(opt_lifetime={:?}) yields {:?}",
337 /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
338 /// returns an appropriate set of substitutions for this particular reference to `I`.
339 pub fn ast_path_substs_for_ty(&self,
340 rscope
: &RegionScope
,
342 param_mode
: PathParamMode
,
343 decl_generics
: &ty
::Generics
<'tcx
>,
344 item_segment
: &hir
::PathSegment
)
347 let tcx
= self.tcx();
349 // ast_path_substs() is only called to convert paths that are
350 // known to refer to traits, types, or structs. In these cases,
351 // all type parameters defined for the item being referenced will
352 // be in the TypeSpace or SelfSpace.
354 // Note: in the case of traits, the self parameter is also
355 // defined, but we don't currently create a `type_param_def` for
356 // `Self` because it is implicit.
357 assert
!(decl_generics
.regions
.all(|d
| d
.space
== TypeSpace
));
358 assert
!(decl_generics
.types
.all(|d
| d
.space
!= FnSpace
));
360 let (regions
, types
, assoc_bindings
) = match item_segment
.parameters
{
361 hir
::AngleBracketedParameters(ref data
) => {
362 self.convert_angle_bracketed_parameters(rscope
, span
, decl_generics
, data
)
364 hir
::ParenthesizedParameters(..) => {
365 struct_span_err
!(tcx
.sess
, span
, E0214
,
366 "parenthesized parameters may only be used with a trait")
367 .span_label(span
, &format
!("only traits may use parentheses"))
370 let ty_param_defs
= decl_generics
.types
.get_slice(TypeSpace
);
372 ty_param_defs
.iter().map(|_
| tcx
.types
.err
).collect(),
377 assoc_bindings
.first().map(|b
| self.tcx().prohibit_projection(b
.span
));
379 self.create_substs_for_ast_path(span
,
387 fn create_region_substs(&self,
388 rscope
: &RegionScope
,
390 decl_generics
: &ty
::Generics
<'tcx
>,
391 regions_provided
: Vec
<ty
::Region
>)
394 let tcx
= self.tcx();
396 // If the type is parameterized by this region, then replace this
397 // region with the current anon region binding (in other words,
398 // whatever & would get replaced with).
399 let expected_num_region_params
= decl_generics
.regions
.len(TypeSpace
);
400 let supplied_num_region_params
= regions_provided
.len();
401 let regions
= if expected_num_region_params
== supplied_num_region_params
{
405 rscope
.anon_regions(span
, expected_num_region_params
);
407 if supplied_num_region_params
!= 0 || anon_regions
.is_err() {
408 report_lifetime_number_error(tcx
, span
,
409 supplied_num_region_params
,
410 expected_num_region_params
);
414 Ok(anon_regions
) => anon_regions
,
415 Err(_
) => (0..expected_num_region_params
).map(|_
| ty
::ReStatic
).collect()
418 Substs
::new_type(vec
![], regions
)
421 /// Given the type/region arguments provided to some path (along with
422 /// an implicit Self, if this is a trait reference) returns the complete
423 /// set of substitutions. This may involve applying defaulted type parameters.
425 /// Note that the type listing given here is *exactly* what the user provided.
427 /// The `region_substs` should be the result of `create_region_substs`
428 /// -- that is, a substitution with no types but the correct number of
430 fn create_substs_for_ast_path(&self,
432 param_mode
: PathParamMode
,
433 decl_generics
: &ty
::Generics
<'tcx
>,
434 self_ty
: Option
<Ty
<'tcx
>>,
435 types_provided
: Vec
<Ty
<'tcx
>>,
436 region_substs
: Substs
<'tcx
>)
439 let tcx
= self.tcx();
441 debug
!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \
442 types_provided={:?}, region_substs={:?})",
443 decl_generics
, self_ty
, types_provided
,
446 assert_eq
!(region_substs
.regions
.len(TypeSpace
), decl_generics
.regions
.len(TypeSpace
));
447 assert
!(region_substs
.types
.is_empty());
449 // Convert the type parameters supplied by the user.
450 let ty_param_defs
= decl_generics
.types
.get_slice(TypeSpace
);
451 let formal_ty_param_count
= ty_param_defs
.len();
452 let required_ty_param_count
= ty_param_defs
.iter()
453 .take_while(|x
| x
.default.is_none())
456 let mut type_substs
= self.get_type_substs_for_defs(span
,
460 region_substs
.clone(),
463 let supplied_ty_param_count
= type_substs
.len();
464 check_type_argument_count(self.tcx(), span
, supplied_ty_param_count
,
465 required_ty_param_count
, formal_ty_param_count
);
467 if supplied_ty_param_count
< required_ty_param_count
{
468 while type_substs
.len() < required_ty_param_count
{
469 type_substs
.push(tcx
.types
.err
);
471 } else if supplied_ty_param_count
> formal_ty_param_count
{
472 type_substs
.truncate(formal_ty_param_count
);
474 assert
!(type_substs
.len() >= required_ty_param_count
&&
475 type_substs
.len() <= formal_ty_param_count
);
477 let mut substs
= region_substs
;
478 substs
.types
.extend(TypeSpace
, type_substs
.into_iter());
482 // If no self-type is provided, it's still possible that
483 // one was declared, because this could be an object type.
486 // If a self-type is provided, one should have been
487 // "declared" (in other words, this should be a
489 assert
!(decl_generics
.types
.get_self().is_some());
490 substs
.types
.push(SelfSpace
, ty
);
494 let actual_supplied_ty_param_count
= substs
.types
.len(TypeSpace
);
495 for param
in &ty_param_defs
[actual_supplied_ty_param_count
..] {
496 if let Some(default) = param
.default {
497 // If we are converting an object type, then the
498 // `Self` parameter is unknown. However, some of the
499 // other type parameters may reference `Self` in their
500 // defaults. This will lead to an ICE if we are not
502 if self_ty
.is_none() && default.has_self_ty() {
503 span_err
!(tcx
.sess
, span
, E0393
,
504 "the type parameter `{}` must be explicitly specified \
505 in an object type because its default value `{}` references \
509 substs
.types
.push(TypeSpace
, tcx
.types
.err
);
511 // This is a default type parameter.
512 let default = default.subst_spanned(tcx
,
515 substs
.types
.push(TypeSpace
, default);
518 span_bug
!(span
, "extra parameter without default");
522 debug
!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
523 decl_generics
, self_ty
, substs
);
528 /// Returns types_provided if it is not empty, otherwise populating the
529 /// type parameters with inference variables as appropriate.
530 fn get_type_substs_for_defs(&self,
532 types_provided
: Vec
<Ty
<'tcx
>>,
533 param_mode
: PathParamMode
,
534 ty_param_defs
: &[ty
::TypeParameterDef
<'tcx
>],
535 mut substs
: Substs
<'tcx
>,
536 self_ty
: Option
<Ty
<'tcx
>>)
539 fn default_type_parameter
<'tcx
>(p
: &ty
::TypeParameterDef
<'tcx
>, self_ty
: Option
<Ty
<'tcx
>>)
540 -> Option
<ty
::TypeParameterDef
<'tcx
>>
542 if let Some(ref default) = p
.default {
543 if self_ty
.is_none() && default.has_self_ty() {
544 // There is no suitable inference default for a type parameter
545 // that references self with no self-type provided.
553 if param_mode
== PathParamMode
::Optional
&& types_provided
.is_empty() {
556 .map(|p
| self.ty_infer(default_type_parameter(p
, self_ty
), Some(&mut substs
),
557 Some(TypeSpace
), span
))
564 fn convert_angle_bracketed_parameters(&self,
565 rscope
: &RegionScope
,
567 decl_generics
: &ty
::Generics
<'tcx
>,
568 data
: &hir
::AngleBracketedParameterData
)
571 Vec
<ConvertedBinding
<'tcx
>>)
573 let regions
: Vec
<_
> =
574 data
.lifetimes
.iter()
575 .map(|l
| ast_region_to_region(self.tcx(), l
))
579 self.create_region_substs(rscope
, span
, decl_generics
, regions
);
584 .map(|(i
,t
)| self.ast_ty_arg_to_ty(rscope
, decl_generics
,
585 i
, ®ion_substs
, t
))
588 let assoc_bindings
: Vec
<_
> =
590 .map(|b
| ConvertedBinding
{ item_name
: b
.name
,
591 ty
: self.ast_ty_to_ty(rscope
, &b
.ty
),
595 (region_substs
, types
, assoc_bindings
)
598 /// Returns the appropriate lifetime to use for any output lifetimes
599 /// (if one exists) and a vector of the (pattern, number of lifetimes)
600 /// corresponding to each input type/pattern.
601 fn find_implied_output_region(&self,
602 input_tys
: &[Ty
<'tcx
>],
603 input_pats
: Vec
<String
>) -> ElidedLifetime
605 let tcx
= self.tcx();
606 let mut lifetimes_for_params
= Vec
::new();
607 let mut possible_implied_output_region
= None
;
609 for (input_type
, input_pat
) in input_tys
.iter().zip(input_pats
) {
610 let mut regions
= FnvHashSet();
611 let have_bound_regions
= tcx
.collect_regions(input_type
, &mut regions
);
613 debug
!("find_implied_output_regions: collected {:?} from {:?} \
614 have_bound_regions={:?}", ®ions
, input_type
, have_bound_regions
);
616 if regions
.len() == 1 {
617 // there's a chance that the unique lifetime of this
618 // iteration will be the appropriate lifetime for output
619 // parameters, so lets store it.
620 possible_implied_output_region
= regions
.iter().cloned().next();
623 lifetimes_for_params
.push(ElisionFailureInfo
{
625 lifetime_count
: regions
.len(),
626 have_bound_regions
: have_bound_regions
630 if lifetimes_for_params
.iter().map(|e
| e
.lifetime_count
).sum
::<usize>() == 1 {
631 Ok(possible_implied_output_region
.unwrap())
633 Err(Some(lifetimes_for_params
))
637 fn convert_ty_with_lifetime_elision(&self,
638 elided_lifetime
: ElidedLifetime
,
640 anon_scope
: Option
<AnonTypeScope
>)
643 match elided_lifetime
{
644 Ok(implied_output_region
) => {
645 let rb
= ElidableRscope
::new(implied_output_region
);
646 self.ast_ty_to_ty(&MaybeWithAnonTypes
::new(rb
, anon_scope
), ty
)
648 Err(param_lifetimes
) => {
649 // All regions must be explicitly specified in the output
650 // if the lifetime elision rules do not apply. This saves
651 // the user from potentially-confusing errors.
652 let rb
= UnelidableRscope
::new(param_lifetimes
);
653 self.ast_ty_to_ty(&MaybeWithAnonTypes
::new(rb
, anon_scope
), ty
)
658 fn convert_parenthesized_parameters(&self,
659 rscope
: &RegionScope
,
661 decl_generics
: &ty
::Generics
<'tcx
>,
662 data
: &hir
::ParenthesizedParameterData
)
665 Vec
<ConvertedBinding
<'tcx
>>)
668 self.create_region_substs(rscope
, span
, decl_generics
, Vec
::new());
670 let anon_scope
= rscope
.anon_type_scope();
671 let binding_rscope
= MaybeWithAnonTypes
::new(BindingRscope
::new(), anon_scope
);
674 .map(|a_t
| self.ast_ty_arg_to_ty(&binding_rscope
, decl_generics
,
675 0, ®ion_substs
, a_t
))
676 .collect
::<Vec
<Ty
<'tcx
>>>();
678 let input_params
= vec
![String
::new(); inputs
.len()];
679 let implied_output_region
= self.find_implied_output_region(&inputs
, input_params
);
681 let input_ty
= self.tcx().mk_tup(inputs
);
683 let (output
, output_span
) = match data
.output
{
684 Some(ref output_ty
) => {
685 (self.convert_ty_with_lifetime_elision(implied_output_region
,
691 (self.tcx().mk_nil(), data
.span
)
695 let output_binding
= ConvertedBinding
{
696 item_name
: token
::intern(FN_OUTPUT_NAME
),
701 (region_substs
, vec
![input_ty
], vec
![output_binding
])
704 pub fn instantiate_poly_trait_ref(&self,
705 rscope
: &RegionScope
,
706 ast_trait_ref
: &hir
::PolyTraitRef
,
707 self_ty
: Option
<Ty
<'tcx
>>,
708 poly_projections
: &mut Vec
<ty
::PolyProjectionPredicate
<'tcx
>>)
709 -> ty
::PolyTraitRef
<'tcx
>
711 let trait_ref
= &ast_trait_ref
.trait_ref
;
712 let trait_def_id
= self.trait_def_id(trait_ref
);
713 self.ast_path_to_poly_trait_ref(rscope
,
715 PathParamMode
::Explicit
,
719 trait_ref
.path
.segments
.last().unwrap(),
723 /// Instantiates the path for the given trait reference, assuming that it's
724 /// bound to a valid trait type. Returns the def_id for the defining trait.
725 /// Fails if the type is a type other than a trait type.
727 /// If the `projections` argument is `None`, then assoc type bindings like `Foo<T=X>`
728 /// are disallowed. Otherwise, they are pushed onto the vector given.
729 pub fn instantiate_mono_trait_ref(&self,
730 rscope
: &RegionScope
,
731 trait_ref
: &hir
::TraitRef
,
732 self_ty
: Option
<Ty
<'tcx
>>)
733 -> ty
::TraitRef
<'tcx
>
735 let trait_def_id
= self.trait_def_id(trait_ref
);
736 self.ast_path_to_mono_trait_ref(rscope
,
738 PathParamMode
::Explicit
,
741 trait_ref
.path
.segments
.last().unwrap())
744 fn trait_def_id(&self, trait_ref
: &hir
::TraitRef
) -> DefId
{
745 let path
= &trait_ref
.path
;
746 match self.tcx().expect_def(trait_ref
.ref_id
) {
747 Def
::Trait(trait_def_id
) => trait_def_id
,
749 self.tcx().sess
.fatal("cannot continue compilation due to previous error");
752 span_fatal
!(self.tcx().sess
, path
.span
, E0245
, "`{}` is not a trait",
758 fn object_path_to_poly_trait_ref(&self,
759 rscope
: &RegionScope
,
761 param_mode
: PathParamMode
,
763 trait_path_ref_id
: ast
::NodeId
,
764 trait_segment
: &hir
::PathSegment
,
765 mut projections
: &mut Vec
<ty
::PolyProjectionPredicate
<'tcx
>>)
766 -> ty
::PolyTraitRef
<'tcx
>
768 self.ast_path_to_poly_trait_ref(rscope
,
778 fn ast_path_to_poly_trait_ref(&self,
779 rscope
: &RegionScope
,
781 param_mode
: PathParamMode
,
783 self_ty
: Option
<Ty
<'tcx
>>,
784 path_id
: ast
::NodeId
,
785 trait_segment
: &hir
::PathSegment
,
786 poly_projections
: &mut Vec
<ty
::PolyProjectionPredicate
<'tcx
>>)
787 -> ty
::PolyTraitRef
<'tcx
>
789 debug
!("ast_path_to_poly_trait_ref(trait_segment={:?})", trait_segment
);
790 // The trait reference introduces a binding level here, so
791 // we need to shift the `rscope`. It'd be nice if we could
792 // do away with this rscope stuff and work this knowledge
793 // into resolve_lifetimes, as we do with non-omitted
794 // lifetimes. Oh well, not there yet.
795 let shifted_rscope
= &ShiftedRscope
::new(rscope
);
797 let (substs
, assoc_bindings
) =
798 self.create_substs_for_ast_trait_ref(shifted_rscope
,
804 let poly_trait_ref
= ty
::Binder(ty
::TraitRef
::new(trait_def_id
, substs
));
807 let converted_bindings
=
810 .filter_map(|binding
| {
811 // specify type to assert that error was already reported in Err case:
812 let predicate
: Result
<_
, ErrorReported
> =
813 self.ast_type_binding_to_poly_projection_predicate(path_id
,
814 poly_trait_ref
.clone(),
817 predicate
.ok() // ok to ignore Err() because ErrorReported (see above)
819 poly_projections
.extend(converted_bindings
);
822 debug
!("ast_path_to_poly_trait_ref(trait_segment={:?}, projections={:?}) -> {:?}",
823 trait_segment
, poly_projections
, poly_trait_ref
);
827 fn ast_path_to_mono_trait_ref(&self,
828 rscope
: &RegionScope
,
830 param_mode
: PathParamMode
,
832 self_ty
: Option
<Ty
<'tcx
>>,
833 trait_segment
: &hir
::PathSegment
)
834 -> ty
::TraitRef
<'tcx
>
836 let (substs
, assoc_bindings
) =
837 self.create_substs_for_ast_trait_ref(rscope
,
843 assoc_bindings
.first().map(|b
| self.tcx().prohibit_projection(b
.span
));
844 ty
::TraitRef
::new(trait_def_id
, substs
)
847 fn create_substs_for_ast_trait_ref(&self,
848 rscope
: &RegionScope
,
850 param_mode
: PathParamMode
,
852 self_ty
: Option
<Ty
<'tcx
>>,
853 trait_segment
: &hir
::PathSegment
)
854 -> (&'tcx Substs
<'tcx
>, Vec
<ConvertedBinding
<'tcx
>>)
856 debug
!("create_substs_for_ast_trait_ref(trait_segment={:?})",
859 let trait_def
= match self.get_trait_def(span
, trait_def_id
) {
860 Ok(trait_def
) => trait_def
,
861 Err(ErrorReported
) => {
862 // No convenient way to recover from a cycle here. Just bail. Sorry!
863 self.tcx().sess
.abort_if_errors();
864 bug
!("ErrorReported returned, but no errors reports?")
868 let (regions
, types
, assoc_bindings
) = match trait_segment
.parameters
{
869 hir
::AngleBracketedParameters(ref data
) => {
870 // For now, require that parenthetical notation be used
871 // only with `Fn()` etc.
872 if !self.tcx().sess
.features
.borrow().unboxed_closures
&& trait_def
.paren_sugar
{
873 emit_feature_err(&self.tcx().sess
.parse_sess
.span_diagnostic
,
874 "unboxed_closures", span
, GateIssue
::Language
,
876 the precise format of `Fn`-family traits' \
877 type parameters is subject to change. \
878 Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead");
881 self.convert_angle_bracketed_parameters(rscope
, span
, &trait_def
.generics
, data
)
883 hir
::ParenthesizedParameters(ref data
) => {
884 // For now, require that parenthetical notation be used
885 // only with `Fn()` etc.
886 if !self.tcx().sess
.features
.borrow().unboxed_closures
&& !trait_def
.paren_sugar
{
887 emit_feature_err(&self.tcx().sess
.parse_sess
.span_diagnostic
,
888 "unboxed_closures", span
, GateIssue
::Language
,
890 parenthetical notation is only stable when used with `Fn`-family traits");
893 self.convert_parenthesized_parameters(rscope
, span
, &trait_def
.generics
, data
)
897 let substs
= self.create_substs_for_ast_path(span
,
904 (self.tcx().mk_substs(substs
), assoc_bindings
)
907 fn ast_type_binding_to_poly_projection_predicate(
909 path_id
: ast
::NodeId
,
910 mut trait_ref
: ty
::PolyTraitRef
<'tcx
>,
911 self_ty
: Option
<Ty
<'tcx
>>,
912 binding
: &ConvertedBinding
<'tcx
>)
913 -> Result
<ty
::PolyProjectionPredicate
<'tcx
>, ErrorReported
>
915 let tcx
= self.tcx();
917 // Given something like `U : SomeTrait<T=X>`, we want to produce a
918 // predicate like `<U as SomeTrait>::T = X`. This is somewhat
919 // subtle in the event that `T` is defined in a supertrait of
920 // `SomeTrait`, because in that case we need to upcast.
922 // That is, consider this case:
925 // trait SubTrait : SuperTrait<int> { }
926 // trait SuperTrait<A> { type T; }
928 // ... B : SubTrait<T=foo> ...
931 // We want to produce `<B as SuperTrait<int>>::T == foo`.
933 // Find any late-bound regions declared in `ty` that are not
934 // declared in the trait-ref. These are not wellformed.
938 // for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
939 // for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
940 let late_bound_in_trait_ref
= tcx
.collect_constrained_late_bound_regions(&trait_ref
);
941 let late_bound_in_ty
= tcx
.collect_referenced_late_bound_regions(&ty
::Binder(binding
.ty
));
942 debug
!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref
);
943 debug
!("late_bound_in_ty = {:?}", late_bound_in_ty
);
944 for br
in late_bound_in_ty
.difference(&late_bound_in_trait_ref
) {
945 let br_name
= match *br
{
946 ty
::BrNamed(_
, name
, _
) => name
,
950 "anonymous bound region {:?} in binding but not trait ref",
955 lint
::builtin
::HR_LIFETIME_IN_ASSOC_TYPE
,
958 format
!("binding for associated type `{}` references lifetime `{}`, \
959 which does not appear in the trait input types",
960 binding
.item_name
, br_name
));
963 // Simple case: X is defined in the current trait.
964 if self.trait_defines_associated_type_named(trait_ref
.def_id(), binding
.item_name
) {
965 return Ok(ty
::Binder(ty
::ProjectionPredicate
{ // <-------------------+
966 projection_ty
: ty
::ProjectionTy
{ // |
967 trait_ref
: trait_ref
.skip_binder().clone(), // Binder moved here --+
968 item_name
: binding
.item_name
,
974 // Otherwise, we have to walk through the supertraits to find
975 // those that do. This is complicated by the fact that, for an
976 // object type, the `Self` type is not present in the
977 // substitutions (after all, it's being constructed right now),
978 // but the `supertraits` iterator really wants one. To handle
979 // this, we currently insert a dummy type and then remove it
982 let dummy_self_ty
= tcx
.mk_infer(ty
::FreshTy(0));
983 if self_ty
.is_none() { // if converting for an object type
984 let mut dummy_substs
= trait_ref
.skip_binder().substs
.clone(); // binder moved here -+
985 assert
!(dummy_substs
.self_ty().is_none()); // |
986 dummy_substs
.types
.push(SelfSpace
, dummy_self_ty
); // |
987 trait_ref
= ty
::Binder(ty
::TraitRef
::new(trait_ref
.def_id(), // <------------+
988 tcx
.mk_substs(dummy_substs
)));
991 self.ensure_super_predicates(binding
.span
, trait_ref
.def_id())?
;
993 let mut candidates
: Vec
<ty
::PolyTraitRef
> =
994 traits
::supertraits(tcx
, trait_ref
.clone())
995 .filter(|r
| self.trait_defines_associated_type_named(r
.def_id(), binding
.item_name
))
998 // If converting for an object type, then remove the dummy-ty from `Self` now.
1000 if self_ty
.is_none() {
1001 for candidate
in &mut candidates
{
1002 let mut dummy_substs
= candidate
.0.substs
.clone();
1003 assert
!(dummy_substs
.self_ty() == Some(dummy_self_ty
));
1004 dummy_substs
.types
.pop(SelfSpace
);
1005 *candidate
= ty
::Binder(ty
::TraitRef
::new(candidate
.def_id(),
1006 tcx
.mk_substs(dummy_substs
)));
1010 let candidate
= self.one_bound_for_assoc_type(candidates
,
1011 &trait_ref
.to_string(),
1012 &binding
.item_name
.as_str(),
1015 Ok(ty
::Binder(ty
::ProjectionPredicate
{ // <-------------------------+
1016 projection_ty
: ty
::ProjectionTy
{ // |
1017 trait_ref
: candidate
.skip_binder().clone(), // binder is moved up here --+
1018 item_name
: binding
.item_name
,
1024 fn ast_path_to_ty(&self,
1025 rscope
: &RegionScope
,
1027 param_mode
: PathParamMode
,
1029 item_segment
: &hir
::PathSegment
)
1032 let tcx
= self.tcx();
1033 let (generics
, decl_ty
) = match self.get_item_type_scheme(span
, did
) {
1034 Ok(ty
::TypeScheme { generics, ty: decl_ty }
) => {
1037 Err(ErrorReported
) => {
1038 return tcx
.types
.err
;
1042 let substs
= self.ast_path_substs_for_ty(rscope
,
1048 // FIXME(#12938): This is a hack until we have full support for DST.
1049 if Some(did
) == self.tcx().lang_items
.owned_box() {
1050 assert_eq
!(substs
.types
.len(TypeSpace
), 1);
1051 return self.tcx().mk_box(*substs
.types
.get(TypeSpace
, 0));
1054 decl_ty
.subst(self.tcx(), &substs
)
1057 fn ast_ty_to_trait_ref(&self,
1058 rscope
: &RegionScope
,
1060 bounds
: &[hir
::TyParamBound
])
1061 -> Result
<TraitAndProjections
<'tcx
>, ErrorReported
>
1064 * In a type like `Foo + Send`, we want to wait to collect the
1065 * full set of bounds before we make the object type, because we
1066 * need them to infer a region bound. (For example, if we tried
1067 * made a type from just `Foo`, then it wouldn't be enough to
1068 * infer a 'static bound, and hence the user would get an error.)
1069 * So this function is used when we're dealing with a sum type to
1070 * convert the LHS. It only accepts a type that refers to a trait
1071 * name, and reports an error otherwise.
1075 hir
::TyPath(None
, ref path
) => {
1076 let resolution
= self.tcx().expect_resolution(ty
.id
);
1077 match resolution
.base_def
{
1078 Def
::Trait(trait_def_id
) if resolution
.depth
== 0 => {
1079 let mut projection_bounds
= Vec
::new();
1081 self.object_path_to_poly_trait_ref(rscope
,
1083 PathParamMode
::Explicit
,
1086 path
.segments
.last().unwrap(),
1087 &mut projection_bounds
);
1088 Ok((trait_ref
, projection_bounds
))
1091 struct_span_err
!(self.tcx().sess
, ty
.span
, E0172
,
1092 "expected a reference to a trait")
1093 .span_label(ty
.span
, &format
!("expected a trait"))
1100 let mut err
= struct_span_err
!(self.tcx().sess
, ty
.span
, E0178
,
1101 "expected a path on the left-hand side \
1103 pprust
::ty_to_string(ty
));
1104 err
.span_label(ty
.span
, &format
!("expected a path"));
1105 let hi
= bounds
.iter().map(|x
| match *x
{
1106 hir
::TraitTyParamBound(ref tr
, _
) => tr
.span
.hi
,
1107 hir
::RegionTyParamBound(ref r
) => r
.span
.hi
,
1108 }).max_by_key(|x
| x
.to_usize());
1109 let full_span
= hi
.map(|hi
| Span
{
1112 expn_id
: ty
.span
.expn_id
,
1114 match (&ty
.node
, full_span
) {
1115 (&hir
::TyRptr(None
, ref mut_ty
), Some(full_span
)) => {
1116 let mutbl_str
= if mut_ty
.mutbl
== hir
::MutMutable { "mut " }
else { "" }
;
1117 err
.span_suggestion(full_span
, "try adding parentheses (per RFC 438):",
1118 format
!("&{}({} +{})",
1120 pprust
::ty_to_string(&mut_ty
.ty
),
1121 pprust
::bounds_to_string(bounds
)));
1123 (&hir
::TyRptr(Some(ref lt
), ref mut_ty
), Some(full_span
)) => {
1124 let mutbl_str
= if mut_ty
.mutbl
== hir
::MutMutable { "mut " }
else { "" }
;
1125 err
.span_suggestion(full_span
, "try adding parentheses (per RFC 438):",
1126 format
!("&{} {}({} +{})",
1127 pprust
::lifetime_to_string(lt
),
1129 pprust
::ty_to_string(&mut_ty
.ty
),
1130 pprust
::bounds_to_string(bounds
)));
1135 "perhaps you forgot parentheses? (per RFC 438)");
1144 fn trait_ref_to_object_type(&self,
1145 rscope
: &RegionScope
,
1147 trait_ref
: ty
::PolyTraitRef
<'tcx
>,
1148 projection_bounds
: Vec
<ty
::PolyProjectionPredicate
<'tcx
>>,
1149 bounds
: &[hir
::TyParamBound
])
1152 let existential_bounds
= self.conv_existential_bounds(rscope
,
1158 let result
= self.make_object_type(span
, trait_ref
, existential_bounds
);
1159 debug
!("trait_ref_to_object_type: result={:?}",
1165 fn make_object_type(&self,
1167 principal
: ty
::PolyTraitRef
<'tcx
>,
1168 bounds
: ty
::ExistentialBounds
<'tcx
>)
1170 let tcx
= self.tcx();
1171 let object
= ty
::TraitTy
{
1172 principal
: principal
,
1175 let object_trait_ref
=
1176 object
.principal_trait_ref_with_self_ty(tcx
, tcx
.types
.err
);
1178 // ensure the super predicates and stop if we encountered an error
1179 if self.ensure_super_predicates(span
, principal
.def_id()).is_err() {
1180 return tcx
.types
.err
;
1183 // check that there are no gross object safety violations,
1184 // most importantly, that the supertraits don't contain Self,
1186 let object_safety_violations
=
1187 tcx
.astconv_object_safety_violations(principal
.def_id());
1188 if !object_safety_violations
.is_empty() {
1189 tcx
.report_object_safety_error(
1190 span
, principal
.def_id(), None
, object_safety_violations
)
1192 return tcx
.types
.err
;
1195 let mut associated_types
: FnvHashSet
<(DefId
, ast
::Name
)> =
1196 traits
::supertraits(tcx
, object_trait_ref
)
1198 let trait_def
= tcx
.lookup_trait_def(tr
.def_id());
1199 trait_def
.associated_type_names
1202 .map(move |associated_type_name
| (tr
.def_id(), associated_type_name
))
1206 for projection_bound
in &object
.bounds
.projection_bounds
{
1207 let pair
= (projection_bound
.0.projection_ty
.trait_ref
.def_id
,
1208 projection_bound
.0.projection_ty
.item_name
);
1209 associated_types
.remove(&pair
);
1212 for (trait_def_id
, name
) in associated_types
{
1213 struct_span_err
!(tcx
.sess
, span
, E0191
,
1214 "the value of the associated type `{}` (from the trait `{}`) must be specified",
1216 tcx
.item_path_str(trait_def_id
))
1217 .span_label(span
, &format
!(
1218 "missing associated type `{}` value", name
))
1222 tcx
.mk_trait(object
.principal
, object
.bounds
)
1225 fn report_ambiguous_associated_type(&self,
1230 struct_span_err
!(self.tcx().sess
, span
, E0223
, "ambiguous associated type")
1231 .span_label(span
, &format
!("ambiguous associated type"))
1232 .note(&format
!("specify the type using the syntax `<{} as {}>::{}`",
1233 type_str
, trait_str
, name
))
1238 // Search for a bound on a type parameter which includes the associated item
1239 // given by assoc_name. ty_param_node_id is the node id for the type parameter
1240 // (which might be `Self`, but only if it is the `Self` of a trait, not an
1241 // impl). This function will fail if there are no suitable bounds or there is
1243 fn find_bound_for_assoc_item(&self,
1244 ty_param_node_id
: ast
::NodeId
,
1245 ty_param_name
: ast
::Name
,
1246 assoc_name
: ast
::Name
,
1248 -> Result
<ty
::PolyTraitRef
<'tcx
>, ErrorReported
>
1250 let tcx
= self.tcx();
1252 let bounds
= match self.get_type_parameter_bounds(span
, ty_param_node_id
) {
1254 Err(ErrorReported
) => {
1255 return Err(ErrorReported
);
1259 // Ensure the super predicates and stop if we encountered an error.
1260 if bounds
.iter().any(|b
| self.ensure_super_predicates(span
, b
.def_id()).is_err()) {
1261 return Err(ErrorReported
);
1264 // Check that there is exactly one way to find an associated type with the
1266 let suitable_bounds
: Vec
<_
> =
1267 traits
::transitive_bounds(tcx
, &bounds
)
1268 .filter(|b
| self.trait_defines_associated_type_named(b
.def_id(), assoc_name
))
1271 self.one_bound_for_assoc_type(suitable_bounds
,
1272 &ty_param_name
.as_str(),
1273 &assoc_name
.as_str(),
1278 // Checks that bounds contains exactly one element and reports appropriate
1279 // errors otherwise.
1280 fn one_bound_for_assoc_type(&self,
1281 bounds
: Vec
<ty
::PolyTraitRef
<'tcx
>>,
1282 ty_param_name
: &str,
1285 -> Result
<ty
::PolyTraitRef
<'tcx
>, ErrorReported
>
1287 if bounds
.is_empty() {
1288 span_err
!(self.tcx().sess
, span
, E0220
,
1289 "associated type `{}` not found for `{}`",
1292 return Err(ErrorReported
);
1295 if bounds
.len() > 1 {
1296 let mut err
= struct_span_err
!(
1297 self.tcx().sess
, span
, E0221
,
1298 "ambiguous associated type `{}` in bounds of `{}`",
1301 err
.span_label(span
, &format
!("ambiguous associated type `{}`", assoc_name
));
1303 for bound
in &bounds
{
1304 span_note
!(&mut err
, span
,
1305 "associated type `{}` could derive from `{}`",
1312 Ok(bounds
[0].clone())
1315 // Create a type from a path to an associated type.
1316 // For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
1317 // and item_segment is the path segment for D. We return a type and a def for
1319 // Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
1320 // parameter or Self.
1321 fn associated_path_def_to_ty(&self,
1325 item_segment
: &hir
::PathSegment
)
1328 let tcx
= self.tcx();
1329 let assoc_name
= item_segment
.name
;
1331 debug
!("associated_path_def_to_ty: {:?}::{}", ty
, assoc_name
);
1333 tcx
.prohibit_type_params(slice
::ref_slice(item_segment
));
1335 // Find the type of the associated item, and the trait where the associated
1336 // item is declared.
1337 let bound
= match (&ty
.sty
, ty_path_def
) {
1338 (_
, Def
::SelfTy(Some(trait_did
), Some(impl_id
))) => {
1339 // For Def::SelfTy() values inlined from another crate, the
1340 // impl_id will be DUMMY_NODE_ID, which would cause problems
1341 // here. But we should never run into an impl from another crate
1343 assert
!(impl_id
!= ast
::DUMMY_NODE_ID
);
1345 // `Self` in an impl of a trait - we have a concrete self type and a
1347 let trait_ref
= tcx
.impl_trait_ref(tcx
.map
.local_def_id(impl_id
)).unwrap();
1348 let trait_ref
= if let Some(free_substs
) = self.get_free_substs() {
1349 trait_ref
.subst(tcx
, free_substs
)
1354 if self.ensure_super_predicates(span
, trait_did
).is_err() {
1355 return (tcx
.types
.err
, Def
::Err
);
1358 let candidates
: Vec
<ty
::PolyTraitRef
> =
1359 traits
::supertraits(tcx
, ty
::Binder(trait_ref
))
1360 .filter(|r
| self.trait_defines_associated_type_named(r
.def_id(),
1364 match self.one_bound_for_assoc_type(candidates
,
1366 &assoc_name
.as_str(),
1369 Err(ErrorReported
) => return (tcx
.types
.err
, Def
::Err
),
1372 (&ty
::TyParam(_
), Def
::SelfTy(Some(trait_did
), None
)) => {
1373 let trait_node_id
= tcx
.map
.as_local_node_id(trait_did
).unwrap();
1374 match self.find_bound_for_assoc_item(trait_node_id
,
1375 keywords
::SelfType
.name(),
1379 Err(ErrorReported
) => return (tcx
.types
.err
, Def
::Err
),
1382 (&ty
::TyParam(_
), Def
::TyParam(_
, _
, param_did
, param_name
)) => {
1383 let param_node_id
= tcx
.map
.as_local_node_id(param_did
).unwrap();
1384 match self.find_bound_for_assoc_item(param_node_id
,
1389 Err(ErrorReported
) => return (tcx
.types
.err
, Def
::Err
),
1393 self.report_ambiguous_associated_type(span
,
1396 &assoc_name
.as_str());
1397 return (tcx
.types
.err
, Def
::Err
);
1401 let trait_did
= bound
.0.def_id
;
1402 let ty
= self.projected_ty_from_poly_trait_ref(span
, bound
, assoc_name
);
1404 let item_did
= if let Some(trait_id
) = tcx
.map
.as_local_node_id(trait_did
) {
1405 // `ty::trait_items` used below requires information generated
1406 // by type collection, which may be in progress at this point.
1407 match tcx
.map
.expect_item(trait_id
).node
{
1408 hir
::ItemTrait(_
, _
, _
, ref trait_items
) => {
1409 let item
= trait_items
.iter()
1410 .find(|i
| i
.name
== assoc_name
)
1411 .expect("missing associated type");
1412 tcx
.map
.local_def_id(item
.id
)
1417 let trait_items
= tcx
.trait_items(trait_did
);
1418 let item
= trait_items
.iter().find(|i
| i
.name() == assoc_name
);
1419 item
.expect("missing associated type").def_id()
1422 (ty
, Def
::AssociatedTy(trait_did
, item_did
))
1425 fn qpath_to_ty(&self,
1426 rscope
: &RegionScope
,
1428 param_mode
: PathParamMode
,
1429 opt_self_ty
: Option
<Ty
<'tcx
>>,
1430 trait_def_id
: DefId
,
1431 trait_segment
: &hir
::PathSegment
,
1432 item_segment
: &hir
::PathSegment
)
1435 let tcx
= self.tcx();
1437 tcx
.prohibit_type_params(slice
::ref_slice(item_segment
));
1439 let self_ty
= if let Some(ty
) = opt_self_ty
{
1442 let path_str
= tcx
.item_path_str(trait_def_id
);
1443 self.report_ambiguous_associated_type(span
,
1446 &item_segment
.name
.as_str());
1447 return tcx
.types
.err
;
1450 debug
!("qpath_to_ty: self_type={:?}", self_ty
);
1452 let trait_ref
= self.ast_path_to_mono_trait_ref(rscope
,
1459 debug
!("qpath_to_ty: trait_ref={:?}", trait_ref
);
1461 self.projected_ty(span
, trait_ref
, item_segment
.name
)
1464 /// Convert a type supplied as value for a type argument from AST into our
1465 /// our internal representation. This is the same as `ast_ty_to_ty` but that
1466 /// it applies the object lifetime default.
1470 /// * `this`, `rscope`: the surrounding context
1471 /// * `decl_generics`: the generics of the struct/enum/trait declaration being
1473 /// * `index`: the index of the type parameter being instantiated from the list
1474 /// (we assume it is in the `TypeSpace`)
1475 /// * `region_substs`: a partial substitution consisting of
1476 /// only the region type parameters being supplied to this type.
1477 /// * `ast_ty`: the ast representation of the type being supplied
1478 pub fn ast_ty_arg_to_ty(&self,
1479 rscope
: &RegionScope
,
1480 decl_generics
: &ty
::Generics
<'tcx
>,
1482 region_substs
: &Substs
<'tcx
>,
1486 let tcx
= self.tcx();
1488 if let Some(def
) = decl_generics
.types
.opt_get(TypeSpace
, index
) {
1489 let object_lifetime_default
= def
.object_lifetime_default
.subst(tcx
, region_substs
);
1490 let rscope1
= &ObjectLifetimeDefaultRscope
::new(rscope
, object_lifetime_default
);
1491 self.ast_ty_to_ty(rscope1
, ast_ty
)
1493 self.ast_ty_to_ty(rscope
, ast_ty
)
1497 // Check the base def in a PathResolution and convert it to a Ty. If there are
1498 // associated types in the PathResolution, these will need to be separately
1500 fn base_def_to_ty(&self,
1501 rscope
: &RegionScope
,
1503 param_mode
: PathParamMode
,
1505 opt_self_ty
: Option
<Ty
<'tcx
>>,
1506 base_path_ref_id
: ast
::NodeId
,
1507 base_segments
: &[hir
::PathSegment
])
1509 let tcx
= self.tcx();
1511 debug
!("base_def_to_ty(def={:?}, opt_self_ty={:?}, base_segments={:?})",
1512 def
, opt_self_ty
, base_segments
);
1515 Def
::Trait(trait_def_id
) => {
1516 // N.B. this case overlaps somewhat with
1517 // TyObjectSum, see that fn for details
1518 let mut projection_bounds
= Vec
::new();
1521 self.object_path_to_poly_trait_ref(rscope
,
1526 base_segments
.last().unwrap(),
1527 &mut projection_bounds
);
1529 tcx
.prohibit_type_params(base_segments
.split_last().unwrap().1);
1530 self.trait_ref_to_object_type(rscope
,
1536 Def
::Enum(did
) | Def
::TyAlias(did
) | Def
::Struct(did
) => {
1537 tcx
.prohibit_type_params(base_segments
.split_last().unwrap().1);
1538 self.ast_path_to_ty(rscope
,
1542 base_segments
.last().unwrap())
1544 Def
::TyParam(space
, index
, _
, name
) => {
1545 tcx
.prohibit_type_params(base_segments
);
1546 tcx
.mk_param(space
, index
, name
)
1548 Def
::SelfTy(_
, Some(impl_id
)) => {
1549 // Self in impl (we know the concrete type).
1551 // For Def::SelfTy() values inlined from another crate, the
1552 // impl_id will be DUMMY_NODE_ID, which would cause problems
1553 // here. But we should never run into an impl from another crate
1555 assert
!(impl_id
!= ast
::DUMMY_NODE_ID
);
1557 tcx
.prohibit_type_params(base_segments
);
1558 let ty
= tcx
.node_id_to_type(impl_id
);
1559 if let Some(free_substs
) = self.get_free_substs() {
1560 ty
.subst(tcx
, free_substs
)
1565 Def
::SelfTy(Some(_
), None
) => {
1567 tcx
.prohibit_type_params(base_segments
);
1570 Def
::AssociatedTy(trait_did
, _
) => {
1571 tcx
.prohibit_type_params(&base_segments
[..base_segments
.len()-2]);
1572 self.qpath_to_ty(rscope
,
1577 &base_segments
[base_segments
.len()-2],
1578 base_segments
.last().unwrap())
1581 // Used as sentinel by callers to indicate the `<T>::A::B::C` form.
1582 // FIXME(#22519) This part of the resolution logic should be
1583 // avoided entirely for that form, once we stop needed a Def
1584 // for `associated_path_def_to_ty`.
1585 // Fixing this will also let use resolve <Self>::Foo the same way we
1586 // resolve Self::Foo, at the moment we can't resolve the former because
1587 // we don't have the trait information around, which is just sad.
1589 assert
!(base_segments
.is_empty());
1591 opt_self_ty
.expect("missing T in <T>::a::b::c")
1593 Def
::PrimTy(prim_ty
) => {
1594 tcx
.prim_ty_to_ty(base_segments
, prim_ty
)
1597 self.set_tainted_by_errors();
1598 return self.tcx().types
.err
;
1601 struct_span_err
!(tcx
.sess
, span
, E0248
,
1602 "found value `{}` used as a type",
1603 tcx
.item_path_str(def
.def_id()))
1604 .span_label(span
, &format
!("value used as a type"))
1606 return self.tcx().types
.err
;
1611 // Resolve possibly associated type path into a type and final definition.
1612 // Note that both base_segments and assoc_segments may be empty, although not at same time.
1613 pub fn finish_resolving_def_to_ty(&self,
1614 rscope
: &RegionScope
,
1616 param_mode
: PathParamMode
,
1618 opt_self_ty
: Option
<Ty
<'tcx
>>,
1619 base_path_ref_id
: ast
::NodeId
,
1620 base_segments
: &[hir
::PathSegment
],
1621 assoc_segments
: &[hir
::PathSegment
])
1622 -> (Ty
<'tcx
>, Def
) {
1623 // Convert the base type.
1624 debug
!("finish_resolving_def_to_ty(base_def={:?}, \
1625 base_segments={:?}, \
1626 assoc_segments={:?})",
1630 let base_ty
= self.base_def_to_ty(rscope
,
1637 debug
!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", base_ty
);
1639 // If any associated type segments remain, attempt to resolve them.
1640 let (mut ty
, mut def
) = (base_ty
, base_def
);
1641 for segment
in assoc_segments
{
1642 debug
!("finish_resolving_def_to_ty: segment={:?}", segment
);
1643 // This is pretty bad (it will fail except for T::A and Self::A).
1644 let (new_ty
, new_def
) = self.associated_path_def_to_ty(span
, ty
, def
, segment
);
1648 if def
== Def
::Err
{
1655 /// Parses the programmer's textual representation of a type into our
1656 /// internal notion of a type.
1657 pub fn ast_ty_to_ty(&self, rscope
: &RegionScope
, ast_ty
: &hir
::Ty
) -> Ty
<'tcx
> {
1658 debug
!("ast_ty_to_ty(id={:?}, ast_ty={:?})",
1661 let tcx
= self.tcx();
1663 let cache
= self.ast_ty_to_ty_cache();
1664 match cache
.borrow().get(&ast_ty
.id
) {
1665 Some(ty
) => { return ty; }
1669 let result_ty
= match ast_ty
.node
{
1670 hir
::TyVec(ref ty
) => {
1671 tcx
.mk_slice(self.ast_ty_to_ty(rscope
, &ty
))
1673 hir
::TyObjectSum(ref ty
, ref bounds
) => {
1674 match self.ast_ty_to_trait_ref(rscope
, &ty
, bounds
) {
1675 Ok((trait_ref
, projection_bounds
)) => {
1676 self.trait_ref_to_object_type(rscope
,
1682 Err(ErrorReported
) => {
1683 self.tcx().types
.err
1687 hir
::TyPtr(ref mt
) => {
1688 tcx
.mk_ptr(ty
::TypeAndMut
{
1689 ty
: self.ast_ty_to_ty(rscope
, &mt
.ty
),
1693 hir
::TyRptr(ref region
, ref mt
) => {
1694 let r
= self.opt_ast_region_to_region(rscope
, ast_ty
.span
, region
);
1695 debug
!("TyRef r={:?}", r
);
1697 &ObjectLifetimeDefaultRscope
::new(
1699 ty
::ObjectLifetimeDefault
::Specific(r
));
1700 let t
= self.ast_ty_to_ty(rscope1
, &mt
.ty
);
1701 tcx
.mk_ref(tcx
.mk_region(r
), ty
::TypeAndMut {ty: t, mutbl: mt.mutbl}
)
1706 hir
::TyTup(ref fields
) => {
1707 let flds
= fields
.iter()
1708 .map(|t
| self.ast_ty_to_ty(rscope
, &t
))
1712 hir
::TyBareFn(ref bf
) => {
1713 require_c_abi_if_variadic(tcx
, &bf
.decl
, bf
.abi
, ast_ty
.span
);
1714 let anon_scope
= rscope
.anon_type_scope();
1715 let (bare_fn_ty
, _
) =
1716 self.ty_of_method_or_bare_fn(bf
.unsafety
,
1723 // Find any late-bound regions declared in return type that do
1724 // not appear in the arguments. These are not wellformed.
1728 // for<'a> fn() -> &'a str <-- 'a is bad
1729 // for<'a> fn(&'a String) -> &'a str <-- 'a is ok
1731 // Note that we do this check **here** and not in
1732 // `ty_of_bare_fn` because the latter is also used to make
1733 // the types for fn items, and we do not want to issue a
1734 // warning then. (Once we fix #32330, the regions we are
1735 // checking for here would be considered early bound
1737 let inputs
= bare_fn_ty
.sig
.inputs();
1738 let late_bound_in_args
= tcx
.collect_constrained_late_bound_regions(&inputs
);
1739 let output
= bare_fn_ty
.sig
.output();
1740 let late_bound_in_ret
= tcx
.collect_referenced_late_bound_regions(&output
);
1741 for br
in late_bound_in_ret
.difference(&late_bound_in_args
) {
1742 let br_name
= match *br
{
1743 ty
::BrNamed(_
, name
, _
) => name
,
1746 bf
.decl
.output
.span(),
1747 "anonymous bound region {:?} in return but not args",
1752 lint
::builtin
::HR_LIFETIME_IN_ASSOC_TYPE
,
1755 format
!("return type references lifetime `{}`, \
1756 which does not appear in the trait input types",
1759 tcx
.mk_fn_ptr(bare_fn_ty
)
1761 hir
::TyPolyTraitRef(ref bounds
) => {
1762 self.conv_ty_poly_trait_ref(rscope
, ast_ty
.span
, bounds
)
1764 hir
::TyImplTrait(ref bounds
) => {
1765 use collect
::{compute_bounds, SizedByDefault}
;
1767 // Create the anonymized type.
1768 let def_id
= tcx
.map
.local_def_id(ast_ty
.id
);
1769 if let Some(anon_scope
) = rscope
.anon_type_scope() {
1770 let substs
= anon_scope
.fresh_substs(tcx
);
1771 let ty
= tcx
.mk_anon(tcx
.map
.local_def_id(ast_ty
.id
), substs
);
1773 // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
1774 let bounds
= compute_bounds(self, ty
, bounds
,
1775 SizedByDefault
::Yes
,
1778 let predicates
= bounds
.predicates(tcx
, ty
);
1779 let predicates
= tcx
.lift_to_global(&predicates
).unwrap();
1780 tcx
.predicates
.borrow_mut().insert(def_id
, ty
::GenericPredicates
{
1781 predicates
: VecPerParamSpace
::new(vec
![], vec
![], predicates
)
1786 span_err
!(tcx
.sess
, ast_ty
.span
, E0562
,
1787 "`impl Trait` not allowed outside of function \
1788 and inherent method return types");
1792 hir
::TyPath(ref maybe_qself
, ref path
) => {
1793 debug
!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself
, path
);
1794 let path_res
= tcx
.expect_resolution(ast_ty
.id
);
1795 let base_ty_end
= path
.segments
.len() - path_res
.depth
;
1796 let opt_self_ty
= maybe_qself
.as_ref().map(|qself
| {
1797 self.ast_ty_to_ty(rscope
, &qself
.ty
)
1799 let (ty
, def
) = self.finish_resolving_def_to_ty(rscope
,
1801 PathParamMode
::Explicit
,
1805 &path
.segments
[..base_ty_end
],
1806 &path
.segments
[base_ty_end
..]);
1808 // Write back the new resolution.
1809 if path_res
.depth
!= 0 {
1810 tcx
.def_map
.borrow_mut().insert(ast_ty
.id
, PathResolution
::new(def
));
1815 hir
::TyFixedLengthVec(ref ty
, ref e
) => {
1816 if let Ok(length
) = eval_length(tcx
.global_tcx(), &e
, "array length") {
1817 tcx
.mk_array(self.ast_ty_to_ty(rscope
, &ty
), length
)
1819 self.tcx().types
.err
1822 hir
::TyTypeof(ref _e
) => {
1823 span_err
!(tcx
.sess
, ast_ty
.span
, E0516
,
1824 "`typeof` is a reserved keyword but unimplemented");
1828 // TyInfer also appears as the type of arguments or return
1829 // values in a ExprClosure, or as
1830 // the type of local variables. Both of these cases are
1831 // handled specially and will not descend into this routine.
1832 self.ty_infer(None
, None
, None
, ast_ty
.span
)
1836 cache
.borrow_mut().insert(ast_ty
.id
, result_ty
);
1841 pub fn ty_of_arg(&self,
1842 rscope
: &RegionScope
,
1844 expected_ty
: Option
<Ty
<'tcx
>>)
1848 hir
::TyInfer
if expected_ty
.is_some() => expected_ty
.unwrap(),
1849 hir
::TyInfer
=> self.ty_infer(None
, None
, None
, a
.ty
.span
),
1850 _
=> self.ast_ty_to_ty(rscope
, &a
.ty
),
1854 pub fn ty_of_method(&self,
1855 sig
: &hir
::MethodSig
,
1856 untransformed_self_ty
: Ty
<'tcx
>,
1857 anon_scope
: Option
<AnonTypeScope
>)
1858 -> (&'tcx ty
::BareFnTy
<'tcx
>, ty
::ExplicitSelfCategory
) {
1859 self.ty_of_method_or_bare_fn(sig
.unsafety
,
1861 Some(untransformed_self_ty
),
1867 pub fn ty_of_bare_fn(&self,
1868 unsafety
: hir
::Unsafety
,
1871 anon_scope
: Option
<AnonTypeScope
>)
1872 -> &'tcx ty
::BareFnTy
<'tcx
> {
1873 self.ty_of_method_or_bare_fn(unsafety
, abi
, None
, decl
, None
, anon_scope
).0
1876 fn ty_of_method_or_bare_fn(&self,
1877 unsafety
: hir
::Unsafety
,
1879 opt_untransformed_self_ty
: Option
<Ty
<'tcx
>>,
1881 arg_anon_scope
: Option
<AnonTypeScope
>,
1882 ret_anon_scope
: Option
<AnonTypeScope
>)
1883 -> (&'tcx ty
::BareFnTy
<'tcx
>, ty
::ExplicitSelfCategory
)
1885 debug
!("ty_of_method_or_bare_fn");
1887 // New region names that appear inside of the arguments of the function
1888 // declaration are bound to that function type.
1889 let rb
= MaybeWithAnonTypes
::new(BindingRscope
::new(), arg_anon_scope
);
1891 // `implied_output_region` is the region that will be assumed for any
1892 // region parameters in the return type. In accordance with the rules for
1893 // lifetime elision, we can determine it in two ways. First (determined
1894 // here), if self is by-reference, then the implied output region is the
1895 // region of the self parameter.
1896 let (self_ty
, explicit_self_category
) = match (opt_untransformed_self_ty
, decl
.get_self()) {
1897 (Some(untransformed_self_ty
), Some(explicit_self
)) => {
1898 let self_type
= self.determine_self_type(&rb
, untransformed_self_ty
,
1900 (Some(self_type
.0), self_type
.1)
1902 _
=> (None
, ty
::ExplicitSelfCategory
::Static
),
1905 // HACK(eddyb) replace the fake self type in the AST with the actual type.
1906 let arg_params
= if self_ty
.is_some() {
1911 let arg_tys
: Vec
<Ty
> =
1912 arg_params
.iter().map(|a
| self.ty_of_arg(&rb
, a
, None
)).collect();
1913 let arg_pats
: Vec
<String
> =
1914 arg_params
.iter().map(|a
| pprust
::pat_to_string(&a
.pat
)).collect();
1916 // Second, if there was exactly one lifetime (either a substitution or a
1917 // reference) in the arguments, then any anonymous regions in the output
1918 // have that lifetime.
1919 let implied_output_region
= match explicit_self_category
{
1920 ty
::ExplicitSelfCategory
::ByReference(region
, _
) => Ok(region
),
1921 _
=> self.find_implied_output_region(&arg_tys
, arg_pats
)
1924 let output_ty
= match decl
.output
{
1925 hir
::Return(ref output
) =>
1926 self.convert_ty_with_lifetime_elision(implied_output_region
,
1929 hir
::DefaultReturn(..) => self.tcx().mk_nil(),
1932 (self.tcx().mk_bare_fn(ty
::BareFnTy
{
1935 sig
: ty
::Binder(ty
::FnSig
{
1936 inputs
: self_ty
.into_iter().chain(arg_tys
).collect(),
1938 variadic
: decl
.variadic
1940 }), explicit_self_category
)
1943 fn determine_self_type
<'a
>(&self,
1944 rscope
: &RegionScope
,
1945 untransformed_self_ty
: Ty
<'tcx
>,
1946 explicit_self
: &hir
::ExplicitSelf
)
1947 -> (Ty
<'tcx
>, ty
::ExplicitSelfCategory
)
1949 return match explicit_self
.node
{
1950 SelfKind
::Value(..) => {
1951 (untransformed_self_ty
, ty
::ExplicitSelfCategory
::ByValue
)
1953 SelfKind
::Region(ref lifetime
, mutability
) => {
1955 self.opt_ast_region_to_region(
1960 self.tcx().mk_region(region
),
1962 ty
: untransformed_self_ty
,
1965 ty
::ExplicitSelfCategory
::ByReference(region
, mutability
))
1967 SelfKind
::Explicit(ref ast_type
, _
) => {
1968 let explicit_type
= self.ast_ty_to_ty(rscope
, &ast_type
);
1970 // We wish to (for now) categorize an explicit self
1971 // declaration like `self: SomeType` into either `self`,
1972 // `&self`, `&mut self`, or `Box<self>`. We do this here
1973 // by some simple pattern matching. A more precise check
1974 // is done later in `check_method_self_type()`.
1979 // impl Foo for &T {
1980 // // Legal declarations:
1981 // fn method1(self: &&T); // ExplicitSelfCategory::ByReference
1982 // fn method2(self: &T); // ExplicitSelfCategory::ByValue
1983 // fn method3(self: Box<&T>); // ExplicitSelfCategory::ByBox
1985 // // Invalid cases will be caught later by `check_method_self_type`:
1986 // fn method_err1(self: &mut T); // ExplicitSelfCategory::ByReference
1990 // To do the check we just count the number of "modifiers"
1991 // on each type and compare them. If they are the same or
1992 // the impl has more, we call it "by value". Otherwise, we
1993 // look at the outermost modifier on the method decl and
1994 // call it by-ref, by-box as appropriate. For method1, for
1995 // example, the impl type has one modifier, but the method
1996 // type has two, so we end up with
1997 // ExplicitSelfCategory::ByReference.
1999 let impl_modifiers
= count_modifiers(untransformed_self_ty
);
2000 let method_modifiers
= count_modifiers(explicit_type
);
2002 debug
!("determine_explicit_self_category(self_info.untransformed_self_ty={:?} \
2003 explicit_type={:?} \
2005 untransformed_self_ty
,
2010 let category
= if impl_modifiers
>= method_modifiers
{
2011 ty
::ExplicitSelfCategory
::ByValue
2013 match explicit_type
.sty
{
2014 ty
::TyRef(r
, mt
) => ty
::ExplicitSelfCategory
::ByReference(*r
, mt
.mutbl
),
2015 ty
::TyBox(_
) => ty
::ExplicitSelfCategory
::ByBox
,
2016 _
=> ty
::ExplicitSelfCategory
::ByValue
,
2020 (explicit_type
, category
)
2024 fn count_modifiers(ty
: Ty
) -> usize {
2026 ty
::TyRef(_
, mt
) => count_modifiers(mt
.ty
) + 1,
2027 ty
::TyBox(t
) => count_modifiers(t
) + 1,
2033 pub fn ty_of_closure(&self,
2034 unsafety
: hir
::Unsafety
,
2037 expected_sig
: Option
<ty
::FnSig
<'tcx
>>)
2038 -> ty
::ClosureTy
<'tcx
>
2040 debug
!("ty_of_closure(expected_sig={:?})",
2043 // new region names that appear inside of the fn decl are bound to
2044 // that function type
2045 let rb
= rscope
::BindingRscope
::new();
2047 let input_tys
: Vec
<_
> = decl
.inputs
.iter().enumerate().map(|(i
, a
)| {
2048 let expected_arg_ty
= expected_sig
.as_ref().and_then(|e
| {
2049 // no guarantee that the correct number of expected args
2051 if i
< e
.inputs
.len() {
2057 self.ty_of_arg(&rb
, a
, expected_arg_ty
)
2060 let expected_ret_ty
= expected_sig
.map(|e
| e
.output
);
2062 let is_infer
= match decl
.output
{
2063 hir
::Return(ref output
) if output
.node
== hir
::TyInfer
=> true,
2064 hir
::DefaultReturn(..) => true,
2068 let output_ty
= match decl
.output
{
2069 _
if is_infer
&& expected_ret_ty
.is_some() =>
2070 expected_ret_ty
.unwrap(),
2072 self.ty_infer(None
, None
, None
, decl
.output
.span()),
2073 hir
::Return(ref output
) =>
2074 self.ast_ty_to_ty(&rb
, &output
),
2075 hir
::DefaultReturn(..) => bug
!(),
2078 debug
!("ty_of_closure: input_tys={:?}", input_tys
);
2079 debug
!("ty_of_closure: output_ty={:?}", output_ty
);
2084 sig
: ty
::Binder(ty
::FnSig
{inputs
: input_tys
,
2086 variadic
: decl
.variadic
}),
2090 /// Given an existential type like `Foo+'a+Bar`, this routine converts
2091 /// the `'a` and `Bar` intos an `ExistentialBounds` struct.
2092 /// The `main_trait_refs` argument specifies the `Foo` -- it is absent
2093 /// for closures. Eventually this should all be normalized, I think,
2094 /// so that there is no "main trait ref" and instead we just have a flat
2095 /// list of bounds as the existential type.
2096 fn conv_existential_bounds(&self,
2097 rscope
: &RegionScope
,
2099 principal_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
2100 projection_bounds
: Vec
<ty
::PolyProjectionPredicate
<'tcx
>>,
2101 ast_bounds
: &[hir
::TyParamBound
])
2102 -> ty
::ExistentialBounds
<'tcx
>
2104 let partitioned_bounds
=
2105 partition_bounds(self.tcx(), span
, ast_bounds
);
2107 self.conv_existential_bounds_from_partitioned_bounds(
2108 rscope
, span
, principal_trait_ref
, projection_bounds
, partitioned_bounds
)
2111 fn conv_ty_poly_trait_ref(&self,
2112 rscope
: &RegionScope
,
2114 ast_bounds
: &[hir
::TyParamBound
])
2117 let mut partitioned_bounds
= partition_bounds(self.tcx(), span
, &ast_bounds
[..]);
2119 let mut projection_bounds
= Vec
::new();
2120 let main_trait_bound
= if !partitioned_bounds
.trait_bounds
.is_empty() {
2121 let trait_bound
= partitioned_bounds
.trait_bounds
.remove(0);
2122 self.instantiate_poly_trait_ref(rscope
,
2125 &mut projection_bounds
)
2127 span_err
!(self.tcx().sess
, span
, E0224
,
2128 "at least one non-builtin trait is required for an object type");
2129 return self.tcx().types
.err
;
2133 self.conv_existential_bounds_from_partitioned_bounds(rscope
,
2135 main_trait_bound
.clone(),
2137 partitioned_bounds
);
2139 self.make_object_type(span
, main_trait_bound
, bounds
)
2142 pub fn conv_existential_bounds_from_partitioned_bounds(&self,
2143 rscope
: &RegionScope
,
2145 principal_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
2146 projection_bounds
: Vec
<ty
::PolyProjectionPredicate
<'tcx
>>, // Empty for boxed closures
2147 partitioned_bounds
: PartitionedBounds
)
2148 -> ty
::ExistentialBounds
<'tcx
>
2150 let PartitionedBounds
{ builtin_bounds
,
2155 if !trait_bounds
.is_empty() {
2156 let b
= &trait_bounds
[0];
2157 let span
= b
.trait_ref
.path
.span
;
2158 struct_span_err
!(self.tcx().sess
, span
, E0225
,
2159 "only the builtin traits can be used as closure or object bounds")
2160 .span_label(span
, &format
!("non-builtin trait used as bounds"))
2165 self.compute_object_lifetime_bound(span
,
2167 principal_trait_ref
,
2170 let region_bound
= match region_bound
{
2173 match rscope
.object_lifetime_default(span
) {
2176 span_err
!(self.tcx().sess
, span
, E0228
,
2177 "the lifetime bound for this object type cannot be deduced \
2178 from context; please supply an explicit bound");
2185 debug
!("region_bound: {:?}", region_bound
);
2187 ty
::ExistentialBounds
::new(region_bound
, builtin_bounds
, projection_bounds
)
2190 /// Given the bounds on an object, determines what single region bound (if any) we can
2191 /// use to summarize this type. The basic idea is that we will use the bound the user
2192 /// provided, if they provided one, and otherwise search the supertypes of trait bounds
2193 /// for region bounds. It may be that we can derive no bound at all, in which case
2194 /// we return `None`.
2195 fn compute_object_lifetime_bound(&self,
2197 explicit_region_bounds
: &[&hir
::Lifetime
],
2198 principal_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
2199 builtin_bounds
: ty
::BuiltinBounds
)
2200 -> Option
<ty
::Region
> // if None, use the default
2202 let tcx
= self.tcx();
2204 debug
!("compute_opt_region_bound(explicit_region_bounds={:?}, \
2205 principal_trait_ref={:?}, builtin_bounds={:?})",
2206 explicit_region_bounds
,
2207 principal_trait_ref
,
2210 if explicit_region_bounds
.len() > 1 {
2211 span_err
!(tcx
.sess
, explicit_region_bounds
[1].span
, E0226
,
2212 "only a single explicit lifetime bound is permitted");
2215 if !explicit_region_bounds
.is_empty() {
2216 // Explicitly specified region bound. Use that.
2217 let r
= explicit_region_bounds
[0];
2218 return Some(ast_region_to_region(tcx
, r
));
2221 if let Err(ErrorReported
) =
2222 self.ensure_super_predicates(span
, principal_trait_ref
.def_id()) {
2223 return Some(ty
::ReStatic
);
2226 // No explicit region bound specified. Therefore, examine trait
2227 // bounds and see if we can derive region bounds from those.
2228 let derived_region_bounds
=
2229 object_region_bounds(tcx
, &principal_trait_ref
, builtin_bounds
);
2231 // If there are no derived region bounds, then report back that we
2232 // can find no region bound. The caller will use the default.
2233 if derived_region_bounds
.is_empty() {
2237 // If any of the derived region bounds are 'static, that is always
2239 if derived_region_bounds
.iter().any(|r
| ty
::ReStatic
== *r
) {
2240 return Some(ty
::ReStatic
);
2243 // Determine whether there is exactly one unique region in the set
2244 // of derived region bounds. If so, use that. Otherwise, report an
2246 let r
= derived_region_bounds
[0];
2247 if derived_region_bounds
[1..].iter().any(|r1
| r
!= *r1
) {
2248 span_err
!(tcx
.sess
, span
, E0227
,
2249 "ambiguous lifetime bound, explicit lifetime bound required");
2255 pub struct PartitionedBounds
<'a
> {
2256 pub builtin_bounds
: ty
::BuiltinBounds
,
2257 pub trait_bounds
: Vec
<&'a hir
::PolyTraitRef
>,
2258 pub region_bounds
: Vec
<&'a hir
::Lifetime
>,
2261 /// Divides a list of bounds from the AST into three groups: builtin bounds (Copy, Sized etc),
2262 /// general trait bounds, and region bounds.
2263 pub fn partition_bounds
<'a
, 'b
, 'gcx
, 'tcx
>(tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
2265 ast_bounds
: &'b
[hir
::TyParamBound
])
2266 -> PartitionedBounds
<'b
>
2268 let mut builtin_bounds
= ty
::BuiltinBounds
::empty();
2269 let mut region_bounds
= Vec
::new();
2270 let mut trait_bounds
= Vec
::new();
2271 for ast_bound
in ast_bounds
{
2273 hir
::TraitTyParamBound(ref b
, hir
::TraitBoundModifier
::None
) => {
2274 match tcx
.expect_def(b
.trait_ref
.ref_id
) {
2275 Def
::Trait(trait_did
) => {
2276 if tcx
.try_add_builtin_trait(trait_did
,
2277 &mut builtin_bounds
) {
2278 let segments
= &b
.trait_ref
.path
.segments
;
2279 let parameters
= &segments
[segments
.len() - 1].parameters
;
2280 if !parameters
.types().is_empty() {
2281 check_type_argument_count(tcx
, b
.trait_ref
.path
.span
,
2282 parameters
.types().len(), 0, 0);
2284 if !parameters
.lifetimes().is_empty() {
2285 report_lifetime_number_error(tcx
, b
.trait_ref
.path
.span
,
2286 parameters
.lifetimes().len(), 0);
2288 continue; // success
2292 // Not a trait? that's an error, but it'll get
2296 trait_bounds
.push(b
);
2298 hir
::TraitTyParamBound(_
, hir
::TraitBoundModifier
::Maybe
) => {}
2299 hir
::RegionTyParamBound(ref l
) => {
2300 region_bounds
.push(l
);
2306 builtin_bounds
: builtin_bounds
,
2307 trait_bounds
: trait_bounds
,
2308 region_bounds
: region_bounds
,
2312 fn check_type_argument_count(tcx
: TyCtxt
, span
: Span
, supplied
: usize,
2313 required
: usize, accepted
: usize) {
2314 if supplied
< required
{
2315 let expected
= if required
< accepted
{
2320 struct_span_err
!(tcx
.sess
, span
, E0243
, "wrong number of type arguments")
2323 &format
!("{} {} type arguments, found {}", expected
, required
, supplied
)
2326 } else if supplied
> accepted
{
2327 let expected
= if required
== 0 {
2328 "expected no".to_string()
2329 } else if required
< accepted
{
2330 format
!("expected at most {}", accepted
)
2332 format
!("expected {}", accepted
)
2335 struct_span_err
!(tcx
.sess
, span
, E0244
, "wrong number of type arguments")
2338 &format
!("{} type arguments, found {}", expected
, supplied
)
2344 fn report_lifetime_number_error(tcx
: TyCtxt
, span
: Span
, number
: usize, expected
: usize) {
2345 let label
= if number
< expected
{
2347 format
!("expected {} lifetime parameter", expected
)
2349 format
!("expected {} lifetime parameters", expected
)
2352 let additional
= number
- expected
;
2353 if additional
== 1 {
2354 "unexpected lifetime parameter".to_string()
2356 format
!("{} unexpected lifetime parameters", additional
)
2359 struct_span_err
!(tcx
.sess
, span
, E0107
,
2360 "wrong number of lifetime parameters: expected {}, found {}",
2362 .span_label(span
, &label
)
2366 // A helper struct for conveniently grouping a set of bounds which we pass to
2367 // and return from functions in multiple places.
2368 #[derive(PartialEq, Eq, Clone, Debug)]
2369 pub struct Bounds
<'tcx
> {
2370 pub region_bounds
: Vec
<ty
::Region
>,
2371 pub builtin_bounds
: ty
::BuiltinBounds
,
2372 pub trait_bounds
: Vec
<ty
::PolyTraitRef
<'tcx
>>,
2373 pub projection_bounds
: Vec
<ty
::PolyProjectionPredicate
<'tcx
>>,
2376 impl<'a
, 'gcx
, 'tcx
> Bounds
<'tcx
> {
2377 pub fn predicates(&self, tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>, param_ty
: Ty
<'tcx
>)
2378 -> Vec
<ty
::Predicate
<'tcx
>>
2380 let mut vec
= Vec
::new();
2382 for builtin_bound
in &self.builtin_bounds
{
2383 match tcx
.trait_ref_for_builtin_bound(builtin_bound
, param_ty
) {
2384 Ok(trait_ref
) => { vec.push(trait_ref.to_predicate()); }
2385 Err(ErrorReported
) => { }
2389 for ®ion_bound
in &self.region_bounds
{
2390 // account for the binder being introduced below; no need to shift `param_ty`
2391 // because, at present at least, it can only refer to early-bound regions
2392 let region_bound
= ty
::fold
::shift_region(region_bound
, 1);
2393 vec
.push(ty
::Binder(ty
::OutlivesPredicate(param_ty
, region_bound
)).to_predicate());
2396 for bound_trait_ref
in &self.trait_bounds
{
2397 vec
.push(bound_trait_ref
.to_predicate());
2400 for projection
in &self.projection_bounds
{
2401 vec
.push(projection
.to_predicate());