1 // Copyright 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.
13 use check
::{self, FnCtxt, NoPreference, PreferMutLvalue, callee, demand}
;
14 use check
::UnresolvedTypeAction
;
15 use middle
::mem_categorization
::Typer
;
16 use middle
::subst
::{self}
;
18 use middle
::ty
::{self, Ty}
;
19 use middle
::ty
::{MethodCall
, MethodCallee
, MethodObject
, MethodOrigin
,
20 MethodParam
, MethodStatic
, MethodTraitObject
, MethodTypeParam
};
21 use middle
::ty_fold
::TypeFoldable
;
23 use middle
::infer
::InferCtxt
;
25 use syntax
::codemap
::Span
;
26 use std
::iter
::repeat
;
28 struct ConfirmContext
<'a
, 'tcx
:'a
> {
29 fcx
: &'a FnCtxt
<'a
, 'tcx
>,
31 self_expr
: &'tcx ast
::Expr
,
32 call_expr
: &'tcx ast
::Expr
,
35 struct InstantiatedMethodSig
<'tcx
> {
36 /// Function signature of the method being invoked. The 0th
37 /// argument is the receiver.
38 method_sig
: ty
::FnSig
<'tcx
>,
40 /// Substitutions for all types/early-bound-regions declared on
42 all_substs
: subst
::Substs
<'tcx
>,
44 /// Generic bounds on the method's parameters which must be added
45 /// as pending obligations.
46 method_predicates
: ty
::InstantiatedPredicates
<'tcx
>,
49 pub fn confirm
<'a
, 'tcx
>(fcx
: &FnCtxt
<'a
, 'tcx
>,
51 self_expr
: &'tcx ast
::Expr
,
52 call_expr
: &'tcx ast
::Expr
,
53 unadjusted_self_ty
: Ty
<'tcx
>,
54 pick
: probe
::Pick
<'tcx
>,
55 supplied_method_types
: Vec
<Ty
<'tcx
>>)
58 debug
!("confirm(unadjusted_self_ty={:?}, pick={:?}, supplied_method_types={:?})",
61 supplied_method_types
);
63 let mut confirm_cx
= ConfirmContext
::new(fcx
, span
, self_expr
, call_expr
);
64 confirm_cx
.confirm(unadjusted_self_ty
, pick
, supplied_method_types
)
67 impl<'a
,'tcx
> ConfirmContext
<'a
,'tcx
> {
68 fn new(fcx
: &'a FnCtxt
<'a
, 'tcx
>,
70 self_expr
: &'tcx ast
::Expr
,
71 call_expr
: &'tcx ast
::Expr
)
72 -> ConfirmContext
<'a
, 'tcx
>
74 ConfirmContext { fcx: fcx, span: span, self_expr: self_expr, call_expr: call_expr }
78 unadjusted_self_ty
: Ty
<'tcx
>,
79 pick
: probe
::Pick
<'tcx
>,
80 supplied_method_types
: Vec
<Ty
<'tcx
>>)
83 // Adjust the self expression the user provided and obtain the adjusted type.
84 let self_ty
= self.adjust_self_ty(unadjusted_self_ty
, &pick
);
86 // Make sure nobody calls `drop()` explicitly.
87 self.enforce_illegal_method_limitations(&pick
);
89 // Create substitutions for the method's type parameters.
90 let (rcvr_substs
, method_origin
) =
91 self.fresh_receiver_substs(self_ty
, &pick
);
92 let (method_types
, method_regions
) =
93 self.instantiate_method_substs(&pick
, supplied_method_types
);
94 let all_substs
= rcvr_substs
.with_method(method_types
, method_regions
);
95 debug
!("all_substs={:?}", all_substs
);
97 // Create the final signature for the method, replacing late-bound regions.
98 let InstantiatedMethodSig
{
99 method_sig
, all_substs
, method_predicates
100 } = self.instantiate_method_sig(&pick
, all_substs
);
101 let method_self_ty
= method_sig
.inputs
[0];
103 // Unify the (adjusted) self type with what the method expects.
104 self.unify_receivers(self_ty
, method_self_ty
);
106 // Add any trait/regions obligations specified on the method's type parameters.
107 self.add_obligations(&pick
, &all_substs
, &method_predicates
);
109 // Create the final `MethodCallee`.
110 let method_ty
= pick
.item
.as_opt_method().unwrap();
111 let fty
= ty
::mk_bare_fn(self.tcx(), None
, self.tcx().mk_bare_fn(ty
::BareFnTy
{
112 sig
: ty
::Binder(method_sig
),
113 unsafety
: method_ty
.fty
.unsafety
,
114 abi
: method_ty
.fty
.abi
.clone(),
116 let callee
= MethodCallee
{
117 origin
: method_origin
,
122 // If this is an `&mut self` method, bias the receiver
123 // expression towards mutability (this will switch
124 // e.g. `Deref` to `DerefMut` in overloaded derefs and so on).
125 self.fixup_derefs_on_method_receiver_if_necessary(&callee
);
130 ///////////////////////////////////////////////////////////////////////////
133 fn adjust_self_ty(&mut self,
134 unadjusted_self_ty
: Ty
<'tcx
>,
135 pick
: &probe
::Pick
<'tcx
>)
138 let (autoref
, unsize
) = if let Some(mutbl
) = pick
.autoref
{
139 let region
= self.infcx().next_region_var(infer
::Autoref(self.span
));
140 let autoref
= ty
::AutoPtr(self.tcx().mk_region(region
), mutbl
);
141 (Some(autoref
), pick
.unsize
.map(|target
| {
142 ty
::adjust_ty_for_autoref(self.tcx(), target
, Some(autoref
))
145 // No unsizing should be performed without autoref (at
146 // least during method dispach). This is because we
147 // currently only unsize `[T;N]` to `[T]`, and naturally
148 // that must occur being a reference.
149 assert
!(pick
.unsize
.is_none());
153 // Commit the autoderefs by calling `autoderef again, but this
154 // time writing the results into the various tables.
155 let (autoderefd_ty
, n
, result
) = check
::autoderef(self.fcx
,
158 Some(self.self_expr
),
159 UnresolvedTypeAction
::Error
,
162 if n
== pick
.autoderefs
{
168 assert_eq
!(n
, pick
.autoderefs
);
169 assert_eq
!(result
, Some(()));
171 // Write out the final adjustment.
172 self.fcx
.write_adjustment(self.self_expr
.id
,
173 ty
::AdjustDerefRef(ty
::AutoDerefRef
{
174 autoderefs
: pick
.autoderefs
,
179 if let Some(target
) = unsize
{
182 ty
::adjust_ty_for_autoref(self.tcx(), autoderefd_ty
, autoref
)
186 ///////////////////////////////////////////////////////////////////////////
189 /// Returns a set of substitutions for the method *receiver* where all type and region
190 /// parameters are instantiated with fresh variables. This substitution does not include any
191 /// parameters declared on the method itself.
193 /// Note that this substitution may include late-bound regions from the impl level. If so,
194 /// these are instantiated later in the `instantiate_method_sig` routine.
195 fn fresh_receiver_substs(&mut self,
197 pick
: &probe
::Pick
<'tcx
>)
198 -> (subst
::Substs
<'tcx
>, MethodOrigin
<'tcx
>)
201 probe
::InherentImplPick(impl_def_id
) => {
202 assert
!(ty
::impl_trait_ref(self.tcx(), impl_def_id
).is_none(),
203 "impl {:?} is not an inherent impl", impl_def_id
);
204 let impl_polytype
= check
::impl_self_ty(self.fcx
, self.span
, impl_def_id
);
206 (impl_polytype
.substs
, MethodStatic(pick
.item
.def_id()))
209 probe
::ObjectPick(trait_def_id
, method_num
, vtable_index
) => {
210 self.extract_trait_ref(self_ty
, |this
, object_ty
, data
| {
211 // The object data has no entry for the Self
212 // Type. For the purposes of this method call, we
213 // substitute the object type itself. This
214 // wouldn't be a sound substitution in all cases,
215 // since each instance of the object type is a
216 // different existential and hence could match
217 // distinct types (e.g., if `Self` appeared as an
218 // argument type), but those cases have already
219 // been ruled out when we deemed the trait to be
221 let original_poly_trait_ref
=
222 data
.principal_trait_ref_with_self_ty(this
.tcx(), object_ty
);
223 let upcast_poly_trait_ref
=
224 this
.upcast(original_poly_trait_ref
.clone(), trait_def_id
);
225 let upcast_trait_ref
=
226 this
.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref
);
227 debug
!("original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
228 original_poly_trait_ref
,
231 let substs
= upcast_trait_ref
.substs
.clone();
232 let origin
= MethodTraitObject(MethodObject
{
233 trait_ref
: upcast_trait_ref
,
234 object_trait_id
: trait_def_id
,
235 method_num
: method_num
,
236 vtable_index
: vtable_index
,
242 probe
::ExtensionImplPick(impl_def_id
, method_num
) => {
243 // The method being invoked is the method as defined on the trait,
244 // so return the substitutions from the trait. Consider:
246 // impl<A,B,C> Trait<A,B> for Foo<C> { ... }
248 // If we instantiate A, B, and C with $A, $B, and $C
249 // respectively, then we want to return the type
250 // parameters from the trait ([$A,$B]), not those from
251 // the impl ([$A,$B,$C]) not the receiver type ([$C]).
252 let impl_polytype
= check
::impl_self_ty(self.fcx
, self.span
, impl_def_id
);
254 self.fcx
.instantiate_type_scheme(
256 &impl_polytype
.substs
,
257 &ty
::impl_trait_ref(self.tcx(), impl_def_id
).unwrap());
258 let origin
= MethodTypeParam(MethodParam
{ trait_ref
: impl_trait_ref
.clone(),
259 method_num
: method_num
,
260 impl_def_id
: Some(impl_def_id
) });
261 (impl_trait_ref
.substs
.clone(), origin
)
264 probe
::TraitPick(trait_def_id
, method_num
) => {
265 let trait_def
= ty
::lookup_trait_def(self.tcx(), trait_def_id
);
267 // Make a trait reference `$0 : Trait<$1...$n>`
268 // consisting entirely of type variables. Later on in
269 // the process we will unify the transformed-self-type
270 // of the method with the actual type in order to
271 // unify some of these variables.
272 let substs
= self.infcx().fresh_substs_for_trait(self.span
,
274 self.infcx().next_ty_var());
277 ty
::TraitRef
::new(trait_def_id
, self.tcx().mk_substs(substs
.clone()));
278 let origin
= MethodTypeParam(MethodParam
{ trait_ref
: trait_ref
,
279 method_num
: method_num
,
280 impl_def_id
: None
});
284 probe
::WhereClausePick(ref poly_trait_ref
, method_num
) => {
285 // Where clauses can have bound regions in them. We need to instantiate
286 // those to convert from a poly-trait-ref to a trait-ref.
287 let trait_ref
= self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref
);
288 let substs
= trait_ref
.substs
.clone();
289 let origin
= MethodTypeParam(MethodParam
{ trait_ref
: trait_ref
,
290 method_num
: method_num
,
291 impl_def_id
: None
});
297 fn extract_trait_ref
<R
, F
>(&mut self, self_ty
: Ty
<'tcx
>, mut closure
: F
) -> R
where
298 F
: FnMut(&mut ConfirmContext
<'a
, 'tcx
>, Ty
<'tcx
>, &ty
::TraitTy
<'tcx
>) -> R
,
300 // If we specified that this is an object method, then the
301 // self-type ought to be something that can be dereferenced to
302 // yield an object-type (e.g., `&Object` or `Box<Object>`
305 let (_
, _
, result
) = check
::autoderef(self.fcx
,
309 UnresolvedTypeAction
::Error
,
313 ty
::TyTrait(ref data
) => Some(closure(self, ty
, &**data
)),
321 self.tcx().sess
.span_bug(
323 &format
!("self-type `{}` for ObjectPick never dereferenced to an object",
329 fn instantiate_method_substs(&mut self,
330 pick
: &probe
::Pick
<'tcx
>,
331 supplied_method_types
: Vec
<Ty
<'tcx
>>)
332 -> (Vec
<Ty
<'tcx
>>, Vec
<ty
::Region
>)
334 // Determine the values for the generic parameters of the method.
335 // If they were not explicitly supplied, just construct fresh
337 let num_supplied_types
= supplied_method_types
.len();
338 let num_method_types
= pick
.item
.as_opt_method().unwrap()
339 .generics
.types
.len(subst
::FnSpace
);
341 if num_supplied_types
== 0 {
342 self.fcx
.infcx().next_ty_vars(num_method_types
)
343 } else if num_method_types
== 0 {
344 span_err
!(self.tcx().sess
, self.span
, E0035
,
345 "does not take type parameters");
346 self.fcx
.infcx().next_ty_vars(num_method_types
)
347 } else if num_supplied_types
!= num_method_types
{
348 span_err
!(self.tcx().sess
, self.span
, E0036
,
349 "incorrect number of type parameters given for this method");
350 repeat(self.tcx().types
.err
).take(num_method_types
).collect()
352 supplied_method_types
356 // Create subst for early-bound lifetime parameters, combining
357 // parameters from the type and those from the method.
359 // FIXME -- permit users to manually specify lifetimes
361 self.fcx
.infcx().region_vars_for_defs(
363 pick
.item
.as_opt_method().unwrap()
364 .generics
.regions
.get_slice(subst
::FnSpace
));
366 (method_types
, method_regions
)
369 fn unify_receivers(&mut self,
371 method_self_ty
: Ty
<'tcx
>)
373 match self.fcx
.mk_subty(false, infer
::Misc(self.span
), self_ty
, method_self_ty
) {
376 self.tcx().sess
.span_bug(
378 &format
!("{} was a subtype of {} but now is not?",
379 self_ty
, method_self_ty
));
384 ///////////////////////////////////////////////////////////////////////////
387 fn instantiate_method_sig(&mut self,
388 pick
: &probe
::Pick
<'tcx
>,
389 all_substs
: subst
::Substs
<'tcx
>)
390 -> InstantiatedMethodSig
<'tcx
>
392 debug
!("instantiate_method_sig(pick={:?}, all_substs={:?})",
396 // Instantiate the bounds on the method with the
397 // type/early-bound-regions substitutions performed. There can
398 // be no late-bound regions appearing here.
399 let method_predicates
= pick
.item
.as_opt_method().unwrap()
400 .predicates
.instantiate(self.tcx(), &all_substs
);
401 let method_predicates
= self.fcx
.normalize_associated_types_in(self.span
,
404 debug
!("method_predicates after subst = {:?}",
407 // Instantiate late-bound regions and substitute the trait
408 // parameters into the method type to get the actual method type.
410 // NB: Instantiate late-bound regions first so that
411 // `instantiate_type_scheme` can normalize associated types that
412 // may reference those regions.
413 let method_sig
= self.replace_late_bound_regions_with_fresh_var(
414 &pick
.item
.as_opt_method().unwrap().fty
.sig
);
415 debug
!("late-bound lifetimes from method instantiated, method_sig={:?}",
418 let method_sig
= self.fcx
.instantiate_type_scheme(self.span
, &all_substs
, &method_sig
);
419 debug
!("type scheme substituted, method_sig={:?}",
422 InstantiatedMethodSig
{
423 method_sig
: method_sig
,
424 all_substs
: all_substs
,
425 method_predicates
: method_predicates
,
429 fn add_obligations(&mut self,
430 pick
: &probe
::Pick
<'tcx
>,
431 all_substs
: &subst
::Substs
<'tcx
>,
432 method_predicates
: &ty
::InstantiatedPredicates
<'tcx
>) {
433 debug
!("add_obligations: pick={:?} all_substs={:?} method_predicates={:?}",
438 self.fcx
.add_obligations_for_parameters(
439 traits
::ObligationCause
::misc(self.span
, self.fcx
.body_id
),
442 self.fcx
.add_default_region_param_bounds(
447 ///////////////////////////////////////////////////////////////////////////
450 /// When we select a method with an `&mut self` receiver, we have to go convert any
451 /// auto-derefs, indices, etc from `Deref` and `Index` into `DerefMut` and `IndexMut`
453 fn fixup_derefs_on_method_receiver_if_necessary(&self,
454 method_callee
: &MethodCallee
) {
455 let sig
= match method_callee
.ty
.sty
{
456 ty
::TyBareFn(_
, ref f
) => f
.sig
.clone(),
460 match sig
.0.inputs
[0].sty
{
461 ty
::TyRef(_
, ty
::mt
{
463 mutbl
: ast
::MutMutable
,
468 // Gather up expressions we want to munge.
469 let mut exprs
= Vec
::new();
470 exprs
.push(self.self_expr
);
472 let last
= exprs
[exprs
.len() - 1];
474 ast
::ExprParen(ref expr
) |
475 ast
::ExprField(ref expr
, _
) |
476 ast
::ExprTupField(ref expr
, _
) |
477 ast
::ExprIndex(ref expr
, _
) |
478 ast
::ExprUnary(ast
::UnDeref
, ref expr
) => exprs
.push(&**expr
),
483 debug
!("fixup_derefs_on_method_receiver_if_necessary: exprs={:?}",
486 // Fix up autoderefs and derefs.
487 for (i
, &expr
) in exprs
.iter().rev().enumerate() {
489 let autoderef_count
= match self.fcx
494 Some(&ty
::AdjustDerefRef(ref adj
)) => adj
.autoderefs
,
498 debug
!("fixup_derefs_on_method_receiver_if_necessary: i={} expr={:?} \
500 i
, expr
, autoderef_count
);
502 if autoderef_count
> 0 {
503 check
::autoderef(self.fcx
,
505 self.fcx
.expr_ty(expr
),
507 UnresolvedTypeAction
::Error
,
510 if autoderefs
== autoderef_count
+ 1 {
518 // Don't retry the first one or we might infinite loop!
521 ast
::ExprIndex(ref base_expr
, ref index_expr
) => {
522 // If this is an overloaded index, the
523 // adjustment will include an extra layer of
524 // autoref because the method is an &self/&mut
525 // self method. We have to peel it off to get
526 // the raw adjustment that `try_index_step`
527 // expects. This is annoying and horrible. We
528 // ought to recode this routine so it doesn't
529 // (ab)use the normal type checking paths.
530 let adj
= self.fcx
.inh
.adjustments
.borrow().get(&base_expr
.id
).cloned();
531 let (autoderefs
, unsize
) = match adj
{
532 Some(ty
::AdjustDerefRef(adr
)) => match adr
.autoref
{
534 assert
!(adr
.unsize
.is_none());
535 (adr
.autoderefs
, None
)
537 Some(ty
::AutoPtr(_
, _
)) => {
538 (adr
.autoderefs
, adr
.unsize
.map(|target
| {
539 ty
::deref(target
, false)
540 .expect("fixup: AutoPtr is not &T").ty
544 self.tcx().sess
.span_bug(
546 &format
!("unexpected adjustment autoref {:?}",
552 self.tcx().sess
.span_bug(
554 "unexpected adjustment type");
558 let (adjusted_base_ty
, unsize
) = if let Some(target
) = unsize
{
561 (self.fcx
.adjust_expr_ty(base_expr
,
562 Some(&ty
::AdjustDerefRef(ty
::AutoDerefRef
{
563 autoderefs
: autoderefs
,
568 let index_expr_ty
= self.fcx
.expr_ty(&**index_expr
);
570 let result
= check
::try_index_step(
572 MethodCall
::expr(expr
.id
),
581 if let Some((input_ty
, return_ty
)) = result
{
582 demand
::suptype(self.fcx
, index_expr
.span
, input_ty
, index_expr_ty
);
584 let expr_ty
= self.fcx
.expr_ty(&*expr
);
585 demand
::suptype(self.fcx
, expr
.span
, expr_ty
, return_ty
);
588 ast
::ExprUnary(ast
::UnDeref
, ref base_expr
) => {
589 // if this is an overloaded deref, then re-evaluate with
590 // a preference for mut
591 let method_call
= MethodCall
::expr(expr
.id
);
592 if self.fcx
.inh
.method_map
.borrow().contains_key(&method_call
) {
593 check
::try_overloaded_deref(
598 self.fcx
.expr_ty(&**base_expr
),
608 ///////////////////////////////////////////////////////////////////////////
611 fn tcx(&self) -> &'a ty
::ctxt
<'tcx
> {
615 fn infcx(&self) -> &'a InferCtxt
<'a
, 'tcx
> {
619 fn enforce_illegal_method_limitations(&self, pick
: &probe
::Pick
) {
620 // Disallow calls to the method `drop` defined in the `Drop` trait.
621 match pick
.item
.container() {
622 ty
::TraitContainer(trait_def_id
) => {
623 callee
::check_legal_trait_for_method_call(self.fcx
.ccx
, self.span
, trait_def_id
)
625 ty
::ImplContainer(..) => {
626 // Since `drop` is a trait method, we expect that any
627 // potential calls to it will wind up in the other
628 // arm. But just to be sure, check that the method id
629 // does not appear in the list of destructors.
630 assert
!(!self.tcx().destructors
.borrow().contains(&pick
.item
.def_id()));
636 source_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
637 target_trait_def_id
: ast
::DefId
)
638 -> ty
::PolyTraitRef
<'tcx
>
640 let upcast_trait_refs
= traits
::upcast(self.tcx(),
641 source_trait_ref
.clone(),
642 target_trait_def_id
);
644 // must be exactly one trait ref or we'd get an ambig error etc
645 if upcast_trait_refs
.len() != 1 {
646 self.tcx().sess
.span_bug(
648 &format
!("cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
654 upcast_trait_refs
.into_iter().next().unwrap()
657 fn replace_late_bound_regions_with_fresh_var
<T
>(&self, value
: &ty
::Binder
<T
>) -> T
658 where T
: TypeFoldable
<'tcx
>
660 self.infcx().replace_late_bound_regions_with_fresh_var(
661 self.span
, infer
::FnCall
, value
).0