]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/coercion.rs
Changed issue number to 36105
[rust.git] / src / librustc_typeck / check / coercion.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
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.
10
11 //! # Type Coercion
12 //!
13 //! Under certain circumstances we will coerce from one type to another,
14 //! for example by auto-borrowing.  This occurs in situations where the
15 //! compiler has a firm 'expected type' that was supplied from the user,
16 //! and where the actual type is similar to that expected type in purpose
17 //! but not in representation (so actual subtyping is inappropriate).
18 //!
19 //! ## Reborrowing
20 //!
21 //! Note that if we are expecting a reference, we will *reborrow*
22 //! even if the argument provided was already a reference.  This is
23 //! useful for freezing mut/const things (that is, when the expected is &T
24 //! but you have &const T or &mut T) and also for avoiding the linearity
25 //! of mut things (when the expected is &mut T and you have &mut T).  See
26 //! the various `src/test/run-pass/coerce-reborrow-*.rs` tests for
27 //! examples of where this is useful.
28 //!
29 //! ## Subtle note
30 //!
31 //! When deciding what type coercions to consider, we do not attempt to
32 //! resolve any type variables we may encounter.  This is because `b`
33 //! represents the expected type "as the user wrote it", meaning that if
34 //! the user defined a generic function like
35 //!
36 //!    fn foo<A>(a: A, b: A) { ... }
37 //!
38 //! and then we wrote `foo(&1, @2)`, we will not auto-borrow
39 //! either argument.  In older code we went to some lengths to
40 //! resolve the `b` variable, which could mean that we'd
41 //! auto-borrow later arguments but not earlier ones, which
42 //! seems very confusing.
43 //!
44 //! ## Subtler note
45 //!
46 //! However, right now, if the user manually specifies the
47 //! values for the type variables, as so:
48 //!
49 //!    foo::<&int>(@1, @2)
50 //!
51 //! then we *will* auto-borrow, because we can't distinguish this from a
52 //! function that declared `&int`.  This is inconsistent but it's easiest
53 //! at the moment. The right thing to do, I think, is to consider the
54 //! *unsubstituted* type when deciding whether to auto-borrow, but the
55 //! *substituted* type when considering the bounds and so forth. But most
56 //! of our methods don't give access to the unsubstituted type, and
57 //! rightly so because they'd be error-prone.  So maybe the thing to do is
58 //! to actually determine the kind of coercions that should occur
59 //! separately and pass them in.  Or maybe it's ok as is.  Anyway, it's
60 //! sort of a minor point so I've opted to leave it for later---after all
61 //! we may want to adjust precisely when coercions occur.
62
63 use check::{FnCtxt};
64
65 use rustc::hir;
66 use rustc::infer::{Coercion, InferOk, TypeOrigin, TypeTrace};
67 use rustc::traits::{self, ObligationCause};
68 use rustc::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef};
69 use rustc::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer};
70 use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
71 use rustc::ty::adjustment::AdjustNeverToAny;
72 use rustc::ty::{self, LvaluePreference, TypeAndMut, Ty};
73 use rustc::ty::fold::TypeFoldable;
74 use rustc::ty::error::TypeError;
75 use rustc::ty::relate::RelateResult;
76 use util::common::indent;
77
78 use std::cell::RefCell;
79 use std::collections::VecDeque;
80 use std::ops::Deref;
81
82 struct Coerce<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
83     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
84     origin: TypeOrigin,
85     use_lub: bool,
86     unsizing_obligations: RefCell<Vec<traits::PredicateObligation<'tcx>>>,
87 }
88
89 impl<'a, 'gcx, 'tcx> Deref for Coerce<'a, 'gcx, 'tcx> {
90     type Target = FnCtxt<'a, 'gcx, 'tcx>;
91     fn deref(&self) -> &Self::Target {
92         &self.fcx
93     }
94 }
95
96 type CoerceResult<'tcx> = RelateResult<'tcx, (Ty<'tcx>, AutoAdjustment<'tcx>)>;
97
98 fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
99                        to_mutbl: hir::Mutability)
100                        -> RelateResult<'tcx, ()> {
101     match (from_mutbl, to_mutbl) {
102         (hir::MutMutable, hir::MutMutable) |
103         (hir::MutImmutable, hir::MutImmutable) |
104         (hir::MutMutable, hir::MutImmutable) => Ok(()),
105         (hir::MutImmutable, hir::MutMutable) => Err(TypeError::Mutability)
106     }
107 }
108
109 impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
110     fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, origin: TypeOrigin) -> Self {
111         Coerce {
112             fcx: fcx,
113             origin: origin,
114             use_lub: false,
115             unsizing_obligations: RefCell::new(vec![])
116         }
117     }
118
119     fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
120         self.commit_if_ok(|_| {
121             let trace = TypeTrace::types(self.origin, false, a, b);
122             if self.use_lub {
123                 self.lub(false, trace, &a, &b)
124                     .map(|InferOk { value, obligations }| {
125                         // FIXME(#32730) propagate obligations
126                         assert!(obligations.is_empty());
127                         value
128                     })
129             } else {
130                 self.sub(false, trace, &a, &b)
131                     .map(|InferOk { value, obligations }| {
132                         // FIXME(#32730) propagate obligations
133                         assert!(obligations.is_empty());
134                         value
135                     })
136             }
137         })
138     }
139
140     /// Unify two types (using sub or lub) and produce a noop coercion.
141     fn unify_and_identity(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
142         self.unify(&a, &b).and_then(|ty| self.identity(ty))
143     }
144
145     /// Synthesize an identity adjustment.
146     fn identity(&self, ty: Ty<'tcx>) -> CoerceResult<'tcx> {
147         Ok((ty, AdjustDerefRef(AutoDerefRef {
148             autoderefs: 0,
149             autoref: None,
150             unsize: None
151         })))
152     }
153
154     fn coerce<'a, E, I>(&self,
155                         exprs: &E,
156                         a: Ty<'tcx>,
157                         b: Ty<'tcx>)
158                         -> CoerceResult<'tcx>
159         // FIXME(eddyb) use copyable iterators when that becomes ergonomic.
160         where E: Fn() -> I,
161               I: IntoIterator<Item=&'a hir::Expr> {
162
163         let a = self.shallow_resolve(a);
164         debug!("Coerce.tys({:?} => {:?})", a, b);
165
166         // Just ignore error types.
167         if a.references_error() || b.references_error() {
168             return self.identity(b);
169         }
170
171         if a.is_never() {
172             return Ok((b, AdjustNeverToAny(b)));
173         }
174
175         // Consider coercing the subtype to a DST
176         let unsize = self.coerce_unsized(a, b);
177         if unsize.is_ok() {
178             return unsize;
179         }
180
181         // Examine the supertype and consider auto-borrowing.
182         //
183         // Note: does not attempt to resolve type variables we encounter.
184         // See above for details.
185         match b.sty {
186             ty::TyRawPtr(mt_b) => {
187                 return self.coerce_unsafe_ptr(a, b, mt_b.mutbl);
188             }
189
190             ty::TyRef(r_b, mt_b) => {
191                 return self.coerce_borrowed_pointer(exprs, a, b, r_b, mt_b);
192             }
193
194             _ => {}
195         }
196
197         match a.sty {
198             ty::TyFnDef(_, _, a_f) => {
199                 // Function items are coercible to any closure
200                 // type; function pointers are not (that would
201                 // require double indirection).
202                 self.coerce_from_fn_item(a, a_f, b)
203             }
204             ty::TyFnPtr(a_f) => {
205                 // We permit coercion of fn pointers to drop the
206                 // unsafe qualifier.
207                 self.coerce_from_fn_pointer(a, a_f, b)
208             }
209             _ => {
210                 // Otherwise, just use unification rules.
211                 self.unify_and_identity(a, b)
212             }
213         }
214     }
215
216     /// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
217     /// To match `A` with `B`, autoderef will be performed,
218     /// calling `deref`/`deref_mut` where necessary.
219     fn coerce_borrowed_pointer<'a, E, I>(&self,
220                                          exprs: &E,
221                                          a: Ty<'tcx>,
222                                          b: Ty<'tcx>,
223                                          r_b: &'tcx ty::Region,
224                                          mt_b: TypeAndMut<'tcx>)
225                                          -> CoerceResult<'tcx>
226         // FIXME(eddyb) use copyable iterators when that becomes ergonomic.
227         where E: Fn() -> I,
228               I: IntoIterator<Item=&'a hir::Expr>
229     {
230
231         debug!("coerce_borrowed_pointer(a={:?}, b={:?})", a, b);
232
233         // If we have a parameter of type `&M T_a` and the value
234         // provided is `expr`, we will be adding an implicit borrow,
235         // meaning that we convert `f(expr)` to `f(&M *expr)`.  Therefore,
236         // to type check, we will construct the type that `&M*expr` would
237         // yield.
238
239         let (r_a, mt_a) = match a.sty {
240             ty::TyRef(r_a, mt_a) => {
241                 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
242                 (r_a, mt_a)
243             }
244             _ => return self.unify_and_identity(a, b)
245         };
246
247         let span = self.origin.span();
248
249         let mut first_error = None;
250         let mut r_borrow_var = None;
251         let mut autoderef = self.autoderef(span, a);
252         let mut success = None;
253
254         for (referent_ty, autoderefs) in autoderef.by_ref() {
255             if autoderefs == 0 {
256                 // Don't let this pass, otherwise it would cause
257                 // &T to autoref to &&T.
258                 continue
259             }
260
261             // At this point, we have deref'd `a` to `referent_ty`.  So
262             // imagine we are coercing from `&'a mut Vec<T>` to `&'b mut [T]`.
263             // In the autoderef loop for `&'a mut Vec<T>`, we would get
264             // three callbacks:
265             //
266             // - `&'a mut Vec<T>` -- 0 derefs, just ignore it
267             // - `Vec<T>` -- 1 deref
268             // - `[T]` -- 2 deref
269             //
270             // At each point after the first callback, we want to
271             // check to see whether this would match out target type
272             // (`&'b mut [T]`) if we autoref'd it. We can't just
273             // compare the referent types, though, because we still
274             // have to consider the mutability. E.g., in the case
275             // we've been considering, we have an `&mut` reference, so
276             // the `T` in `[T]` needs to be unified with equality.
277             //
278             // Therefore, we construct reference types reflecting what
279             // the types will be after we do the final auto-ref and
280             // compare those. Note that this means we use the target
281             // mutability [1], since it may be that we are coercing
282             // from `&mut T` to `&U`.
283             //
284             // One fine point concerns the region that we use. We
285             // choose the region such that the region of the final
286             // type that results from `unify` will be the region we
287             // want for the autoref:
288             //
289             // - if in sub mode, that means we want to use `'b` (the
290             //   region from the target reference) for both
291             //   pointers [2]. This is because sub mode (somewhat
292             //   arbitrarily) returns the subtype region.  In the case
293             //   where we are coercing to a target type, we know we
294             //   want to use that target type region (`'b`) because --
295             //   for the program to type-check -- it must be the
296             //   smaller of the two.
297             //   - One fine point. It may be surprising that we can
298             //     use `'b` without relating `'a` and `'b`. The reason
299             //     that this is ok is that what we produce is
300             //     effectively a `&'b *x` expression (if you could
301             //     annotate the region of a borrow), and regionck has
302             //     code that adds edges from the region of a borrow
303             //     (`'b`, here) into the regions in the borrowed
304             //     expression (`*x`, here).  (Search for "link".)
305             // - if in lub mode, things can get fairly complicated. The
306             //   easiest thing is just to make a fresh
307             //   region variable [4], which effectively means we defer
308             //   the decision to region inference (and regionck, which will add
309             //   some more edges to this variable). However, this can wind up
310             //   creating a crippling number of variables in some cases --
311             //   e.g. #32278 -- so we optimize one particular case [3].
312             //   Let me try to explain with some examples:
313             //   - The "running example" above represents the simple case,
314             //     where we have one `&` reference at the outer level and
315             //     ownership all the rest of the way down. In this case,
316             //     we want `LUB('a, 'b)` as the resulting region.
317             //   - However, if there are nested borrows, that region is
318             //     too strong. Consider a coercion from `&'a &'x Rc<T>` to
319             //     `&'b T`. In this case, `'a` is actually irrelevant.
320             //     The pointer we want is `LUB('x, 'b`). If we choose `LUB('a,'b)`
321             //     we get spurious errors (`run-pass/regions-lub-ref-ref-rc.rs`).
322             //     (The errors actually show up in borrowck, typically, because
323             //     this extra edge causes the region `'a` to be inferred to something
324             //     too big, which then results in borrowck errors.)
325             //   - We could track the innermost shared reference, but there is already
326             //     code in regionck that has the job of creating links between
327             //     the region of a borrow and the regions in the thing being
328             //     borrowed (here, `'a` and `'x`), and it knows how to handle
329             //     all the various cases. So instead we just make a region variable
330             //     and let regionck figure it out.
331             let r = if !self.use_lub {
332                 r_b // [2] above
333             } else if autoderefs == 1 {
334                 r_a // [3] above
335             } else {
336                 if r_borrow_var.is_none() { // create var lazilly, at most once
337                     let coercion = Coercion(span);
338                     let r = self.next_region_var(coercion);
339                     r_borrow_var = Some(self.tcx.mk_region(r)); // [4] above
340                 }
341                 r_borrow_var.unwrap()
342             };
343             let derefd_ty_a = self.tcx.mk_ref(r, TypeAndMut {
344                 ty: referent_ty,
345                 mutbl: mt_b.mutbl // [1] above
346             });
347             match self.unify(derefd_ty_a, b) {
348                 Ok(ty) => { success = Some((ty, autoderefs)); break },
349                 Err(err) => {
350                     if first_error.is_none() {
351                         first_error = Some(err);
352                     }
353                 }
354             }
355         }
356
357         // Extract type or return an error. We return the first error
358         // we got, which should be from relating the "base" type
359         // (e.g., in example above, the failure from relating `Vec<T>`
360         // to the target type), since that should be the least
361         // confusing.
362         let (ty, autoderefs) = match success {
363             Some(d) => d,
364             None => {
365                 let err = first_error.expect("coerce_borrowed_pointer had no error");
366                 debug!("coerce_borrowed_pointer: failed with err = {:?}", err);
367                 return Err(err);
368             }
369         };
370
371         // This commits the obligations to the fulfillcx. After this succeeds,
372         // this snapshot can't be rolled back.
373         autoderef.finalize(LvaluePreference::from_mutbl(mt_b.mutbl), exprs());
374
375         // Now apply the autoref. We have to extract the region out of
376         // the final ref type we got.
377         if ty == a && mt_a.mutbl == hir::MutImmutable && autoderefs == 1 {
378             // As a special case, if we would produce `&'a *x`, that's
379             // a total no-op. We end up with the type `&'a T` just as
380             // we started with.  In that case, just skip it
381             // altogether. This is just an optimization.
382             //
383             // Note that for `&mut`, we DO want to reborrow --
384             // otherwise, this would be a move, which might be an
385             // error. For example `foo(self.x)` where `self` and
386             // `self.x` both have `&mut `type would be a move of
387             // `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
388             // which is a borrow.
389             assert_eq!(mt_b.mutbl, hir::MutImmutable); // can only coerce &T -> &U
390             return self.identity(ty);
391         }
392         let r_borrow = match ty.sty {
393             ty::TyRef(r_borrow, _) => r_borrow,
394             _ => span_bug!(span, "expected a ref type, got {:?}", ty)
395         };
396         let autoref = Some(AutoPtr(r_borrow, mt_b.mutbl));
397         debug!("coerce_borrowed_pointer: succeeded ty={:?} autoderefs={:?} autoref={:?}",
398                ty, autoderefs, autoref);
399         Ok((ty, AdjustDerefRef(AutoDerefRef {
400             autoderefs: autoderefs,
401             autoref: autoref,
402             unsize: None
403         })))
404     }
405
406
407     // &[T; n] or &mut [T; n] -> &[T]
408     // or &mut [T; n] -> &mut [T]
409     // or &Concrete -> &Trait, etc.
410     fn coerce_unsized(&self,
411                       source: Ty<'tcx>,
412                       target: Ty<'tcx>)
413                       -> CoerceResult<'tcx> {
414         debug!("coerce_unsized(source={:?}, target={:?})",
415                source,
416                target);
417
418         let traits = (self.tcx.lang_items.unsize_trait(),
419                       self.tcx.lang_items.coerce_unsized_trait());
420         let (unsize_did, coerce_unsized_did) = if let (Some(u), Some(cu)) = traits {
421             (u, cu)
422         } else {
423             debug!("Missing Unsize or CoerceUnsized traits");
424             return Err(TypeError::Mismatch);
425         };
426
427         // Note, we want to avoid unnecessary unsizing. We don't want to coerce to
428         // a DST unless we have to. This currently comes out in the wash since
429         // we can't unify [T] with U. But to properly support DST, we need to allow
430         // that, at which point we will need extra checks on the target here.
431
432         // Handle reborrows before selecting `Source: CoerceUnsized<Target>`.
433         let (source, reborrow) = match (&source.sty, &target.sty) {
434             (&ty::TyRef(_, mt_a), &ty::TyRef(_, mt_b)) => {
435                 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
436
437                 let coercion = Coercion(self.origin.span());
438                 let r_borrow = self.next_region_var(coercion);
439                 let region = self.tcx.mk_region(r_borrow);
440                 (mt_a.ty, Some(AutoPtr(region, mt_b.mutbl)))
441             }
442             (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) => {
443                 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
444                 (mt_a.ty, Some(AutoUnsafe(mt_b.mutbl)))
445             }
446             _ => (source, None)
447         };
448         let source = source.adjust_for_autoref(self.tcx, reborrow);
449
450         let mut selcx = traits::SelectionContext::new(self);
451
452         // Use a FIFO queue for this custom fulfillment procedure.
453         let mut queue = VecDeque::new();
454         let mut leftover_predicates = vec![];
455
456         // Create an obligation for `Source: CoerceUnsized<Target>`.
457         let cause = ObligationCause::misc(self.origin.span(), self.body_id);
458         queue.push_back(self.tcx.predicate_for_trait_def(cause,
459                                                          coerce_unsized_did,
460                                                          0,
461                                                          source,
462                                                          vec![target]));
463
464         // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
465         // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
466         // inference might unify those two inner type variables later.
467         let traits = [coerce_unsized_did, unsize_did];
468         while let Some(obligation) = queue.pop_front() {
469             debug!("coerce_unsized resolve step: {:?}", obligation);
470             let trait_ref =  match obligation.predicate {
471                 ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
472                     tr.clone()
473                 }
474                 _ => {
475                     leftover_predicates.push(obligation);
476                     continue;
477                 }
478             };
479             match selcx.select(&obligation.with(trait_ref)) {
480                 // Uncertain or unimplemented.
481                 Ok(None) | Err(traits::Unimplemented) => {
482                     debug!("coerce_unsized: early return - can't prove obligation");
483                     return Err(TypeError::Mismatch);
484                 }
485
486                 // Object safety violations or miscellaneous.
487                 Err(err) => {
488                     self.report_selection_error(&obligation, &err, None);
489                     // Treat this like an obligation and follow through
490                     // with the unsizing - the lack of a coercion should
491                     // be silent, as it causes a type mismatch later.
492                 }
493
494                 Ok(Some(vtable)) => {
495                     for obligation in vtable.nested_obligations() {
496                         queue.push_back(obligation);
497                     }
498                 }
499             }
500         }
501
502         *self.unsizing_obligations.borrow_mut() = leftover_predicates;
503
504         let adjustment = AutoDerefRef {
505             autoderefs: if reborrow.is_some() { 1 } else { 0 },
506             autoref: reborrow,
507             unsize: Some(target)
508         };
509         debug!("Success, coerced with {:?}", adjustment);
510         Ok((target, AdjustDerefRef(adjustment)))
511     }
512
513     fn coerce_from_fn_pointer(&self,
514                            a: Ty<'tcx>,
515                            fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
516                            b: Ty<'tcx>)
517                            -> CoerceResult<'tcx>
518     {
519         /*!
520          * Attempts to coerce from the type of a Rust function item
521          * into a closure or a `proc`.
522          */
523
524         let b = self.shallow_resolve(b);
525         debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
526
527         if let ty::TyFnPtr(fn_ty_b) = b.sty {
528             match (fn_ty_a.unsafety, fn_ty_b.unsafety) {
529                 (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
530                     let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
531                     return self.unify_and_identity(unsafe_a, b).map(|(ty, _)| {
532                         (ty, AdjustUnsafeFnPointer)
533                     });
534                 }
535                 _ => {}
536             }
537         }
538         self.unify_and_identity(a, b)
539     }
540
541     fn coerce_from_fn_item(&self,
542                            a: Ty<'tcx>,
543                            fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
544                            b: Ty<'tcx>)
545                            -> CoerceResult<'tcx> {
546         /*!
547          * Attempts to coerce from the type of a Rust function item
548          * into a closure or a `proc`.
549          */
550
551         let b = self.shallow_resolve(b);
552         debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
553
554         match b.sty {
555             ty::TyFnPtr(_) => {
556                 let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a);
557                 self.unify_and_identity(a_fn_pointer, b).map(|(ty, _)| {
558                     (ty, AdjustReifyFnPointer)
559                 })
560             }
561             _ => self.unify_and_identity(a, b)
562         }
563     }
564
565     fn coerce_unsafe_ptr(&self,
566                          a: Ty<'tcx>,
567                          b: Ty<'tcx>,
568                          mutbl_b: hir::Mutability)
569                          -> CoerceResult<'tcx> {
570         debug!("coerce_unsafe_ptr(a={:?}, b={:?})",
571                a,
572                b);
573
574         let (is_ref, mt_a) = match a.sty {
575             ty::TyRef(_, mt) => (true, mt),
576             ty::TyRawPtr(mt) => (false, mt),
577             _ => {
578                 return self.unify_and_identity(a, b);
579             }
580         };
581
582         // Check that the types which they point at are compatible.
583         let a_unsafe = self.tcx.mk_ptr(ty::TypeAndMut{ mutbl: mutbl_b, ty: mt_a.ty });
584         let (ty, noop) = self.unify_and_identity(a_unsafe, b)?;
585         coerce_mutbls(mt_a.mutbl, mutbl_b)?;
586
587         // Although references and unsafe ptrs have the same
588         // representation, we still register an AutoDerefRef so that
589         // regionck knows that the region for `a` must be valid here.
590         Ok((ty, if is_ref {
591             AdjustDerefRef(AutoDerefRef {
592                 autoderefs: 1,
593                 autoref: Some(AutoUnsafe(mutbl_b)),
594                 unsize: None
595             })
596         } else if mt_a.mutbl != mutbl_b {
597             AdjustMutToConstPointer
598         } else {
599             noop
600         }))
601     }
602 }
603
604 fn apply<'a, 'b, 'gcx, 'tcx, E, I>(coerce: &mut Coerce<'a, 'gcx, 'tcx>,
605                                    exprs: &E,
606                                    a: Ty<'tcx>,
607                                    b: Ty<'tcx>)
608                                    -> CoerceResult<'tcx>
609     where E: Fn() -> I,
610           I: IntoIterator<Item=&'b hir::Expr> {
611
612     let (ty, adjustment) = indent(|| coerce.coerce(exprs, a, b))?;
613
614     let fcx = coerce.fcx;
615     if let AdjustDerefRef(auto) = adjustment {
616         if auto.unsize.is_some() {
617             let mut obligations = coerce.unsizing_obligations.borrow_mut();
618             for obligation in obligations.drain(..) {
619                 fcx.register_predicate(obligation);
620             }
621         }
622     }
623
624     Ok((ty, adjustment))
625 }
626
627 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
628     /// Attempt to coerce an expression to a type, and return the
629     /// adjusted type of the expression, if successful.
630     /// Adjustments are only recorded if the coercion succeeded.
631     /// The expressions *must not* have any pre-existing adjustments.
632     pub fn try_coerce(&self,
633                       expr: &hir::Expr,
634                       target: Ty<'tcx>)
635                       -> RelateResult<'tcx, Ty<'tcx>> {
636         let source = self.resolve_type_vars_with_obligations(self.expr_ty(expr));
637         debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
638
639         let mut coerce = Coerce::new(self, TypeOrigin::ExprAssignable(expr.span));
640         self.commit_if_ok(|_| {
641             let (ty, adjustment) =
642                 apply(&mut coerce, &|| Some(expr), source, target)?;
643             if !adjustment.is_identity() {
644                 debug!("Success, coerced with {:?}", adjustment);
645                 match self.tables.borrow().adjustments.get(&expr.id) {
646                     None | Some(&AdjustNeverToAny(..)) => (),
647                     _ => bug!("expr already has an adjustment on it!"),
648                 };
649                 self.write_adjustment(expr.id, adjustment);
650             }
651             Ok(ty)
652         })
653     }
654
655     /// Given some expressions, their known unified type and another expression,
656     /// tries to unify the types, potentially inserting coercions on any of the
657     /// provided expressions and returns their LUB (aka "common supertype").
658     pub fn try_find_coercion_lub<'b, E, I>(&self,
659                                            origin: TypeOrigin,
660                                            exprs: E,
661                                            prev_ty: Ty<'tcx>,
662                                            new: &'b hir::Expr)
663                                            -> RelateResult<'tcx, Ty<'tcx>>
664         // FIXME(eddyb) use copyable iterators when that becomes ergonomic.
665         where E: Fn() -> I,
666               I: IntoIterator<Item=&'b hir::Expr> {
667
668         let prev_ty = self.resolve_type_vars_with_obligations(prev_ty);
669         let new_ty = self.resolve_type_vars_with_obligations(self.expr_ty(new));
670         debug!("coercion::try_find_lub({:?}, {:?})", prev_ty, new_ty);
671
672         let trace = TypeTrace::types(origin, true, prev_ty, new_ty);
673
674         // Special-case that coercion alone cannot handle:
675         // Two function item types of differing IDs or Substs.
676         match (&prev_ty.sty, &new_ty.sty) {
677             (&ty::TyFnDef(a_def_id, a_substs, a_fty),
678              &ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
679                 // The signature must always match.
680                 let fty = self.lub(true, trace.clone(), &a_fty, &b_fty)
681                     .map(|InferOk { value, obligations }| {
682                         // FIXME(#32730) propagate obligations
683                         assert!(obligations.is_empty());
684                         value
685                     })?;
686
687                 if a_def_id == b_def_id {
688                     // Same function, maybe the parameters match.
689                     let substs = self.commit_if_ok(|_| {
690                         self.lub(true, trace.clone(), &a_substs, &b_substs)
691                             .map(|InferOk { value, obligations }| {
692                                 // FIXME(#32730) propagate obligations
693                                 assert!(obligations.is_empty());
694                                 value
695                             })
696                     });
697
698                     if let Ok(substs) = substs {
699                         // We have a LUB of prev_ty and new_ty, just return it.
700                         return Ok(self.tcx.mk_fn_def(a_def_id, substs, fty));
701                     }
702                 }
703
704                 // Reify both sides and return the reified fn pointer type.
705                 for expr in exprs().into_iter().chain(Some(new)) {
706                     // No adjustments can produce a fn item, so this should never trip.
707                     assert!(!self.tables.borrow().adjustments.contains_key(&expr.id));
708                     self.write_adjustment(expr.id, AdjustReifyFnPointer);
709                 }
710                 return Ok(self.tcx.mk_fn_ptr(fty));
711             }
712             _ => {}
713         }
714
715         let mut coerce = Coerce::new(self, origin);
716         coerce.use_lub = true;
717
718         // First try to coerce the new expression to the type of the previous ones,
719         // but only if the new expression has no coercion already applied to it.
720         let mut first_error = None;
721         if !self.tables.borrow().adjustments.contains_key(&new.id) {
722             let result = self.commit_if_ok(|_| {
723                 apply(&mut coerce, &|| Some(new), new_ty, prev_ty)
724             });
725             match result {
726                 Ok((ty, adjustment)) => {
727                     if !adjustment.is_identity() {
728                         self.write_adjustment(new.id, adjustment);
729                     }
730                     return Ok(ty);
731                 }
732                 Err(e) => first_error = Some(e)
733             }
734         }
735
736         // Then try to coerce the previous expressions to the type of the new one.
737         // This requires ensuring there are no coercions applied to *any* of the
738         // previous expressions, other than noop reborrows (ignoring lifetimes).
739         for expr in exprs() {
740             let noop = match self.tables.borrow().adjustments.get(&expr.id) {
741                 Some(&AdjustDerefRef(AutoDerefRef {
742                     autoderefs: 1,
743                     autoref: Some(AutoPtr(_, mutbl_adj)),
744                     unsize: None
745                 })) => match self.expr_ty(expr).sty {
746                     ty::TyRef(_, mt_orig) => {
747                         // Reborrow that we can safely ignore.
748                         mutbl_adj == mt_orig.mutbl
749                     }
750                     _ => false
751                 },
752                 Some(&AdjustNeverToAny(_)) => true,
753                 Some(_) => false,
754                 None => true
755             };
756
757             if !noop {
758                 return self.commit_if_ok(|_| {
759                     self.lub(true, trace.clone(), &prev_ty, &new_ty)
760                         .map(|InferOk { value, obligations }| {
761                             // FIXME(#32730) propagate obligations
762                             assert!(obligations.is_empty());
763                             value
764                         })
765                 });
766             }
767         }
768
769         match self.commit_if_ok(|_| apply(&mut coerce, &exprs, prev_ty, new_ty)) {
770             Err(_) => {
771                 // Avoid giving strange errors on failed attempts.
772                 if let Some(e) = first_error {
773                     Err(e)
774                 } else {
775                     self.commit_if_ok(|_| {
776                         self.lub(true, trace, &prev_ty, &new_ty)
777                             .map(|InferOk { value, obligations }| {
778                                 // FIXME(#32730) propagate obligations
779                                 assert!(obligations.is_empty());
780                                 value
781                             })
782                     })
783                 }
784             }
785             Ok((ty, adjustment)) => {
786                 if !adjustment.is_identity() {
787                     for expr in exprs() {
788                         let previous = self.tables.borrow().adjustments.get(&expr.id).cloned();
789                         if let Some(AdjustNeverToAny(_)) = previous {
790                             self.write_adjustment(expr.id, AdjustNeverToAny(ty));
791                         } else {
792                             self.write_adjustment(expr.id, adjustment);
793                         }
794                     }
795                 }
796                 Ok(ty)
797             }
798         }
799     }
800 }