]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/typeck/infer/coercion.rs
rollup merge of #17355 : gamazeps/issue17210
[rust.git] / src / librustc / middle / typeck / infer / 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 /*!
12
13 # Type Coercion
14
15 Under certain circumstances we will coerce from one type to another,
16 for example by auto-borrowing.  This occurs in situations where the
17 compiler has a firm 'expected type' that was supplied from the user,
18 and where the actual type is similar to that expected type in purpose
19 but not in representation (so actual subtyping is inappropriate).
20
21 ## Reborrowing
22
23 Note that if we are expecting a reference, we will *reborrow*
24 even if the argument provided was already a reference.  This is
25 useful for freezing mut/const things (that is, when the expected is &T
26 but you have &const T or &mut T) and also for avoiding the linearity
27 of mut things (when the expected is &mut T and you have &mut T).  See
28 the various `src/test/run-pass/coerce-reborrow-*.rs` tests for
29 examples of where this is useful.
30
31 ## Subtle note
32
33 When deciding what type coercions to consider, we do not attempt to
34 resolve any type variables we may encounter.  This is because `b`
35 represents the expected type "as the user wrote it", meaning that if
36 the user defined a generic function like
37
38    fn foo<A>(a: A, b: A) { ... }
39
40 and then we wrote `foo(&1, @2)`, we will not auto-borrow
41 either argument.  In older code we went to some lengths to
42 resolve the `b` variable, which could mean that we'd
43 auto-borrow later arguments but not earlier ones, which
44 seems very confusing.
45
46 ## Subtler note
47
48 However, right now, if the user manually specifies the
49 values for the type variables, as so:
50
51    foo::<&int>(@1, @2)
52
53 then we *will* auto-borrow, because we can't distinguish this from a
54 function that declared `&int`.  This is inconsistent but it's easiest
55 at the moment. The right thing to do, I think, is to consider the
56 *unsubstituted* type when deciding whether to auto-borrow, but the
57 *substituted* type when considering the bounds and so forth. But most
58 of our methods don't give access to the unsubstituted type, and
59 rightly so because they'd be error-prone.  So maybe the thing to do is
60 to actually determine the kind of coercions that should occur
61 separately and pass them in.  Or maybe it's ok as is.  Anyway, it's
62 sort of a minor point so I've opted to leave it for later---after all
63 we may want to adjust precisely when coercions occur.
64
65 */
66
67 use middle::subst;
68 use middle::ty::{AutoPtr, AutoDerefRef, AdjustDerefRef, AutoUnsize, AutoUnsafe};
69 use middle::ty::{mt};
70 use middle::ty;
71 use middle::typeck::infer::{CoerceResult, resolve_type, Coercion};
72 use middle::typeck::infer::combine::{CombineFields, Combine};
73 use middle::typeck::infer::sub::Sub;
74 use middle::typeck::infer::resolve::try_resolve_tvar_shallow;
75 use util::common::indenter;
76 use util::ppaux;
77 use util::ppaux::Repr;
78
79 use syntax::abi;
80 use syntax::ast;
81
82 // Note: Coerce is not actually a combiner, in that it does not
83 // conform to the same interface, though it performs a similar
84 // function.
85 pub struct Coerce<'f, 'tcx: 'f>(pub CombineFields<'f, 'tcx>);
86
87 impl<'f, 'tcx> Coerce<'f, 'tcx> {
88     pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f, 'tcx> {
89         let Coerce(ref v) = *self; v
90     }
91
92     pub fn tys(&self, a: ty::t, b: ty::t) -> CoerceResult {
93         debug!("Coerce.tys({} => {})",
94                a.repr(self.get_ref().infcx.tcx),
95                b.repr(self.get_ref().infcx.tcx));
96         let _indent = indenter();
97
98         // Special case: if the subtype is a sized array literal (`[T, ..n]`),
99         // then it would get auto-borrowed to `&[T, ..n]` and then DST-ified
100         // to `&[T]`. Doing it all at once makes the target code a bit more
101         // efficient and spares us from having to handle multiple coercions.
102         match ty::get(b).sty {
103             ty::ty_ptr(mt_b) | ty::ty_rptr(_, mt_b) => {
104                 match ty::get(mt_b.ty).sty {
105                     ty::ty_vec(_, None) => {
106                         let unsize_and_ref = self.unpack_actual_value(a, |sty_a| {
107                             self.coerce_unsized_with_borrow(a, sty_a, b, mt_b.mutbl)
108                         });
109                         if unsize_and_ref.is_ok() {
110                             return unsize_and_ref;
111                         }
112                     }
113                     _ => {}
114                 }
115             }
116             _ => {}
117         }
118
119         // Consider coercing the subtype to a DST
120         let unsize = self.unpack_actual_value(a, |sty_a| {
121             self.coerce_unsized(a, sty_a, b)
122         });
123         if unsize.is_ok() {
124             return unsize;
125         }
126
127         // Examine the supertype and consider auto-borrowing.
128         //
129         // Note: does not attempt to resolve type variables we encounter.
130         // See above for details.
131         match ty::get(b).sty {
132             ty::ty_ptr(mt_b) => {
133                 match ty::get(mt_b.ty).sty {
134                     ty::ty_str => {
135                         return self.unpack_actual_value(a, |sty_a| {
136                             self.coerce_unsafe_ptr(a, sty_a, b, ast::MutImmutable)
137                         });
138                     }
139
140                     ty::ty_trait(..) => {
141                         let result = self.unpack_actual_value(a, |sty_a| {
142                             self.coerce_unsafe_object(a, sty_a, b, mt_b.mutbl)
143                         });
144
145                         match result {
146                             Ok(t) => return Ok(t),
147                             Err(..) => {}
148                         }
149                     }
150
151                     _ => {
152                         return self.unpack_actual_value(a, |sty_a| {
153                             self.coerce_unsafe_ptr(a, sty_a, b, mt_b.mutbl)
154                         });
155                     }
156                 };
157             }
158
159             ty::ty_rptr(_, mt_b) => {
160                 match ty::get(mt_b.ty).sty {
161                     ty::ty_str => {
162                         return self.unpack_actual_value(a, |sty_a| {
163                             self.coerce_borrowed_pointer(a, sty_a, b, ast::MutImmutable)
164                         });
165                     }
166
167                     ty::ty_trait(..) => {
168                         let result = self.unpack_actual_value(a, |sty_a| {
169                             self.coerce_borrowed_object(a, sty_a, b, mt_b.mutbl)
170                         });
171
172                         match result {
173                             Ok(t) => return Ok(t),
174                             Err(..) => {}
175                         }
176                     }
177
178                     _ => {
179                         return self.unpack_actual_value(a, |sty_a| {
180                             self.coerce_borrowed_pointer(a, sty_a, b, mt_b.mutbl)
181                         });
182                     }
183                 };
184             }
185
186             ty::ty_closure(box ty::ClosureTy {
187                     store: ty::RegionTraitStore(..),
188                     ..
189                 }) => {
190                 return self.unpack_actual_value(a, |sty_a| {
191                     self.coerce_borrowed_fn(a, sty_a, b)
192                 });
193             }
194
195             _ => {}
196         }
197
198         self.unpack_actual_value(a, |sty_a| {
199             match *sty_a {
200                 ty::ty_bare_fn(ref a_f) => {
201                     // Bare functions are coercible to any closure type.
202                     //
203                     // FIXME(#3320) this should go away and be
204                     // replaced with proper inference, got a patch
205                     // underway - ndm
206                     self.coerce_from_bare_fn(a, a_f, b)
207                 }
208                 _ => {
209                     // Otherwise, just use subtyping rules.
210                     self.subtype(a, b)
211                 }
212             }
213         })
214     }
215
216     pub fn subtype(&self, a: ty::t, b: ty::t) -> CoerceResult {
217         match Sub(self.get_ref().clone()).tys(a, b) {
218             Ok(_) => Ok(None),         // No coercion required.
219             Err(ref e) => Err(*e)
220         }
221     }
222
223     pub fn unpack_actual_value<T>(&self, a: ty::t, f: |&ty::sty| -> T)
224                                   -> T {
225         match resolve_type(self.get_ref().infcx, None,
226                            a, try_resolve_tvar_shallow) {
227             Ok(t) => {
228                 f(&ty::get(t).sty)
229             }
230             Err(e) => {
231                 self.get_ref().infcx.tcx.sess.span_bug(
232                     self.get_ref().trace.origin.span(),
233                     format!("failed to resolve even without \
234                              any force options: {:?}", e).as_slice());
235             }
236         }
237     }
238
239     // ~T -> &T or &mut T -> &T (including where T = [U] or str)
240     pub fn coerce_borrowed_pointer(&self,
241                                    a: ty::t,
242                                    sty_a: &ty::sty,
243                                    b: ty::t,
244                                    mutbl_b: ast::Mutability)
245                                    -> CoerceResult {
246         debug!("coerce_borrowed_pointer(a={}, sty_a={:?}, b={})",
247                a.repr(self.get_ref().infcx.tcx), sty_a,
248                b.repr(self.get_ref().infcx.tcx));
249
250         // If we have a parameter of type `&M T_a` and the value
251         // provided is `expr`, we will be adding an implicit borrow,
252         // meaning that we convert `f(expr)` to `f(&M *expr)`.  Therefore,
253         // to type check, we will construct the type that `&M*expr` would
254         // yield.
255
256         let sub = Sub(self.get_ref().clone());
257         let coercion = Coercion(self.get_ref().trace.clone());
258         let r_borrow = self.get_ref().infcx.next_region_var(coercion);
259
260         let inner_ty = match *sty_a {
261             ty::ty_box(_) | ty::ty_uniq(_) => return Err(ty::terr_mismatch),
262             ty::ty_rptr(_, mt_a) => mt_a.ty,
263             _ => {
264                 return self.subtype(a, b);
265             }
266         };
267
268         let a_borrowed = ty::mk_rptr(self.get_ref().infcx.tcx,
269                                      r_borrow,
270                                      mt {ty: inner_ty, mutbl: mutbl_b});
271         try!(sub.tys(a_borrowed, b));
272
273         Ok(Some(AdjustDerefRef(AutoDerefRef {
274             autoderefs: 1,
275             autoref: Some(AutoPtr(r_borrow, mutbl_b, None))
276         })))
277     }
278
279     // [T, ..n] -> &[T] or &mut [T]
280     fn coerce_unsized_with_borrow(&self,
281                                   a: ty::t,
282                                   sty_a: &ty::sty,
283                                   b: ty::t,
284                                   mutbl_b: ast::Mutability)
285                                   -> CoerceResult {
286         debug!("coerce_unsized_with_borrow(a={}, sty_a={:?}, b={})",
287                a.repr(self.get_ref().infcx.tcx), sty_a,
288                b.repr(self.get_ref().infcx.tcx));
289
290         match *sty_a {
291             ty::ty_vec(t_a, Some(len)) => {
292                 let sub = Sub(self.get_ref().clone());
293                 let coercion = Coercion(self.get_ref().trace.clone());
294                 let r_borrow = self.get_ref().infcx.next_region_var(coercion);
295                 let unsized_ty = ty::mk_slice(self.get_ref().infcx.tcx, r_borrow,
296                                               mt {ty: t_a, mutbl: mutbl_b});
297                 try!(self.get_ref().infcx.try(|| sub.tys(unsized_ty, b)));
298                 Ok(Some(AdjustDerefRef(AutoDerefRef {
299                     autoderefs: 0,
300                     autoref: Some(ty::AutoPtr(r_borrow,
301                                               mutbl_b,
302                                               Some(box AutoUnsize(ty::UnsizeLength(len)))))
303                 })))
304             }
305             _ => Err(ty::terr_mismatch)
306         }
307     }
308
309     // &[T, ..n] or &mut [T, ..n] -> &[T]
310     // or &mut [T, ..n] -> &mut [T]
311     // or &Concrete -> &Trait, etc.
312     fn coerce_unsized(&self,
313                       a: ty::t,
314                       sty_a: &ty::sty,
315                       b: ty::t)
316                       -> CoerceResult {
317         debug!("coerce_unsized(a={}, sty_a={:?}, b={})",
318                a.repr(self.get_ref().infcx.tcx), sty_a,
319                b.repr(self.get_ref().infcx.tcx));
320
321         // Note, we want to avoid unnecessary unsizing. We don't want to coerce to
322         // a DST unless we have to. This currently comes out in the wash since
323         // we can't unify [T] with U. But to properly support DST, we need to allow
324         // that, at which point we will need extra checks on b here.
325
326         let sub = Sub(self.get_ref().clone());
327
328         let sty_b = &ty::get(b).sty;
329         match (sty_a, sty_b) {
330             (&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_rptr(_, mt_b)) => {
331                 self.unpack_actual_value(t_a, |sty_a| {
332                     match self.unsize_ty(t_a, sty_a, mt_b.ty) {
333                         Some((ty, kind)) => {
334                             if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
335                                 return Err(ty::terr_mutability);
336                             }
337
338                             let coercion = Coercion(self.get_ref().trace.clone());
339                             let r_borrow = self.get_ref().infcx.next_region_var(coercion);
340                             let ty = ty::mk_rptr(self.get_ref().infcx.tcx,
341                                                  r_borrow,
342                                                  ty::mt{ty: ty, mutbl: mt_b.mutbl});
343                             try!(self.get_ref().infcx.try(|| sub.tys(ty, b)));
344                             debug!("Success, coerced with AutoDerefRef(1, \
345                                     AutoPtr(AutoUnsize({:?})))", kind);
346                             Ok(Some(AdjustDerefRef(AutoDerefRef {
347                                 autoderefs: 1,
348                                 autoref: Some(ty::AutoPtr(r_borrow, mt_b.mutbl,
349                                                           Some(box AutoUnsize(kind))))
350                             })))
351                         }
352                         _ => Err(ty::terr_mismatch)
353                     }
354                 })
355             }
356             (&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_ptr(mt_b)) => {
357                 self.unpack_actual_value(t_a, |sty_a| {
358                     match self.unsize_ty(t_a, sty_a, mt_b.ty) {
359                         Some((ty, kind)) => {
360                             if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
361                                 return Err(ty::terr_mutability);
362                             }
363
364                             let ty = ty::mk_ptr(self.get_ref().infcx.tcx,
365                                                  ty::mt{ty: ty, mutbl: mt_b.mutbl});
366                             try!(self.get_ref().infcx.try(|| sub.tys(ty, b)));
367                             debug!("Success, coerced with AutoDerefRef(1, \
368                                     AutoPtr(AutoUnsize({:?})))", kind);
369                             Ok(Some(AdjustDerefRef(AutoDerefRef {
370                                 autoderefs: 1,
371                                 autoref: Some(ty::AutoUnsafe(mt_b.mutbl,
372                                                              Some(box AutoUnsize(kind))))
373                             })))
374                         }
375                         _ => Err(ty::terr_mismatch)
376                     }
377                 })
378             }
379             (&ty::ty_uniq(t_a), &ty::ty_uniq(t_b)) => {
380                 self.unpack_actual_value(t_a, |sty_a| {
381                     match self.unsize_ty(t_a, sty_a, t_b) {
382                         Some((ty, kind)) => {
383                             let ty = ty::mk_uniq(self.get_ref().infcx.tcx, ty);
384                             try!(self.get_ref().infcx.try(|| sub.tys(ty, b)));
385                             debug!("Success, coerced with AutoDerefRef(1, \
386                                     AutoUnsizeUniq({:?}))", kind);
387                             Ok(Some(AdjustDerefRef(AutoDerefRef {
388                                 autoderefs: 1,
389                                 autoref: Some(ty::AutoUnsizeUniq(kind))
390                             })))
391                         }
392                         _ => Err(ty::terr_mismatch)
393                     }
394                 })
395             }
396             _ => Err(ty::terr_mismatch)
397         }
398     }
399
400     // Takes a type and returns an unsized version along with the adjustment
401     // performed to unsize it.
402     // E.g., `[T, ..n]` -> `([T], UnsizeLength(n))`
403     fn unsize_ty(&self,
404                  ty_a: ty::t,
405                  sty_a: &ty::sty,
406                  ty_b: ty::t)
407                  -> Option<(ty::t, ty::UnsizeKind)> {
408         debug!("unsize_ty(sty_a={:?}, ty_b={})", sty_a, ty_b.repr(self.get_ref().infcx.tcx));
409
410         let tcx = self.get_ref().infcx.tcx;
411
412         self.unpack_actual_value(ty_b, |sty_b|
413             match (sty_a, sty_b) {
414                 (&ty::ty_vec(t_a, Some(len)), _) => {
415                     let ty = ty::mk_vec(tcx, t_a, None);
416                     Some((ty, ty::UnsizeLength(len)))
417                 }
418                 (&ty::ty_trait(..), &ty::ty_trait(..)) => None,
419                 (_, &ty::ty_trait(box ty::TyTrait { def_id, ref substs, bounds })) => {
420                     let ty = ty::mk_trait(tcx,
421                                           def_id,
422                                           substs.clone(),
423                                           bounds);
424                     Some((ty, ty::UnsizeVtable(ty::TyTrait { def_id: def_id,
425                                                              bounds: bounds,
426                                                              substs: substs.clone() },
427                                                ty_a)))
428                 }
429                 (&ty::ty_struct(did_a, ref substs_a), &ty::ty_struct(did_b, ref substs_b))
430                   if did_a == did_b => {
431                     debug!("unsizing a struct");
432                     // Try unsizing each type param in turn to see if we end up with ty_b.
433                     let ty_substs_a = substs_a.types.get_slice(subst::TypeSpace);
434                     let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace);
435                     assert!(ty_substs_a.len() == ty_substs_b.len());
436
437                     let sub = Sub(self.get_ref().clone());
438
439                     let mut result = None;
440                     let mut tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
441                     for (i, (tp_a, tp_b)) in tps {
442                         if self.get_ref().infcx.try(|| sub.tys(*tp_a, *tp_b)).is_ok() {
443                             continue;
444                         }
445                         match
446                             self.unpack_actual_value(
447                                 *tp_a,
448                                 |tp| self.unsize_ty(*tp_a, tp, *tp_b))
449                         {
450                             Some((new_tp, k)) => {
451                                 // Check that the whole types match.
452                                 let mut new_substs = substs_a.clone();
453                                 new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp;
454                                 let ty = ty::mk_struct(tcx, did_a, new_substs);
455                                 if self.get_ref().infcx.try(|| sub.tys(ty, ty_b)).is_err() {
456                                     debug!("Unsized type parameter '{}', but still \
457                                             could not match types {} and {}",
458                                            ppaux::ty_to_string(tcx, *tp_a),
459                                            ppaux::ty_to_string(tcx, ty),
460                                            ppaux::ty_to_string(tcx, ty_b));
461                                     // We can only unsize a single type parameter, so
462                                     // if we unsize one and it doesn't give us the
463                                     // type we want, then we won't succeed later.
464                                     break;
465                                 }
466
467                                 result = Some((ty, ty::UnsizeStruct(box k, i)));
468                                 break;
469                             }
470                             None => {}
471                         }
472                     }
473                     result
474                 }
475                 _ => None
476             }
477         )
478     }
479
480     fn coerce_borrowed_object(&self,
481                               a: ty::t,
482                               sty_a: &ty::sty,
483                               b: ty::t,
484                               b_mutbl: ast::Mutability) -> CoerceResult
485     {
486         let tcx = self.get_ref().infcx.tcx;
487
488         debug!("coerce_borrowed_object(a={}, sty_a={:?}, b={}, b_mutbl={})",
489                a.repr(tcx), sty_a,
490                b.repr(tcx), b_mutbl);
491
492         let coercion = Coercion(self.get_ref().trace.clone());
493         let r_a = self.get_ref().infcx.next_region_var(coercion);
494
495         self.coerce_object(a, sty_a, b, b_mutbl,
496                            |tr| ty::mk_rptr(tcx, r_a, ty::mt{ mutbl: b_mutbl, ty: tr }),
497                            || AutoPtr(r_a, b_mutbl, None))
498     }
499
500     fn coerce_unsafe_object(&self,
501                             a: ty::t,
502                             sty_a: &ty::sty,
503                             b: ty::t,
504                             b_mutbl: ast::Mutability) -> CoerceResult
505     {
506         let tcx = self.get_ref().infcx.tcx;
507
508         debug!("coerce_unsafe_object(a={}, sty_a={:?}, b={}, b_mutbl={})",
509                a.repr(tcx), sty_a,
510                b.repr(tcx), b_mutbl);
511
512         self.coerce_object(a, sty_a, b, b_mutbl,
513                            |tr| ty::mk_ptr(tcx, ty::mt{ mutbl: b_mutbl, ty: tr }),
514                            || AutoUnsafe(b_mutbl, None))
515     }
516
517     fn coerce_object(&self,
518                      a: ty::t,
519                      sty_a: &ty::sty,
520                      b: ty::t,
521                      b_mutbl: ast::Mutability,
522                      mk_ty: |ty::t| -> ty::t,
523                      mk_adjust: || -> ty::AutoRef) -> CoerceResult
524     {
525         let tcx = self.get_ref().infcx.tcx;
526
527         match *sty_a {
528             ty::ty_rptr(_, ty::mt{ty, mutbl}) => match ty::get(ty).sty {
529                 ty::ty_trait(box ty::TyTrait {
530                         def_id,
531                         ref substs,
532                         bounds,
533                         ..
534                     }) =>
535                 {
536                     debug!("mutbl={} b_mutbl={}", mutbl, b_mutbl);
537
538                     let tr = ty::mk_trait(tcx, def_id, substs.clone(), bounds);
539                     try!(self.subtype(mk_ty(tr), b));
540                     Ok(Some(AdjustDerefRef(AutoDerefRef {
541                         autoderefs: 1,
542                         autoref: Some(mk_adjust())
543                     })))
544                 }
545                 _ => {
546                     self.subtype(a, b)
547                 }
548             },
549             _ => {
550                 self.subtype(a, b)
551             }
552         }
553     }
554
555     pub fn coerce_borrowed_fn(&self,
556                               a: ty::t,
557                               sty_a: &ty::sty,
558                               b: ty::t)
559                               -> CoerceResult {
560         debug!("coerce_borrowed_fn(a={}, sty_a={:?}, b={})",
561                a.repr(self.get_ref().infcx.tcx), sty_a,
562                b.repr(self.get_ref().infcx.tcx));
563
564         match *sty_a {
565             ty::ty_bare_fn(ref f) => {
566                 self.coerce_from_bare_fn(a, f, b)
567             }
568             _ => {
569                 self.subtype(a, b)
570             }
571         }
572     }
573
574     fn coerce_from_bare_fn(&self, a: ty::t, fn_ty_a: &ty::BareFnTy, b: ty::t)
575                            -> CoerceResult {
576         /*!
577          *
578          * Attempts to coerce from a bare Rust function (`extern
579          * "Rust" fn`) into a closure or a `proc`.
580          */
581
582         self.unpack_actual_value(b, |sty_b| {
583
584             debug!("coerce_from_bare_fn(a={}, b={})",
585                    a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx));
586
587             if fn_ty_a.abi != abi::Rust || fn_ty_a.fn_style != ast::NormalFn {
588                 return self.subtype(a, b);
589             }
590
591             let fn_ty_b = match *sty_b {
592                 ty::ty_closure(ref f) => (*f).clone(),
593                 _ => return self.subtype(a, b)
594             };
595
596             let adj = ty::AdjustAddEnv(fn_ty_b.store);
597             let a_closure = ty::mk_closure(self.get_ref().infcx.tcx,
598                                            ty::ClosureTy {
599                                                 sig: fn_ty_a.sig.clone(),
600                                                 .. *fn_ty_b
601                                            });
602             try!(self.subtype(a_closure, b));
603             Ok(Some(adj))
604         })
605     }
606
607     pub fn coerce_unsafe_ptr(&self,
608                              a: ty::t,
609                              sty_a: &ty::sty,
610                              b: ty::t,
611                              mutbl_b: ast::Mutability)
612                              -> CoerceResult {
613         debug!("coerce_unsafe_ptr(a={}, sty_a={:?}, b={})",
614                a.repr(self.get_ref().infcx.tcx), sty_a,
615                b.repr(self.get_ref().infcx.tcx));
616
617         let mt_a = match *sty_a {
618             ty::ty_rptr(_, mt) => mt,
619             _ => {
620                 return self.subtype(a, b);
621             }
622         };
623
624         // Check that the types which they point at are compatible.
625         // Note that we don't adjust the mutability here. We cannot change
626         // the mutability and the kind of pointer in a single coercion.
627         let a_unsafe = ty::mk_ptr(self.get_ref().infcx.tcx, mt_a);
628         try!(self.subtype(a_unsafe, b));
629
630         // Although references and unsafe ptrs have the same
631         // representation, we still register an AutoDerefRef so that
632         // regionck knows that the region for `a` must be valid here.
633         Ok(Some(AdjustDerefRef(AutoDerefRef {
634             autoderefs: 1,
635             autoref: Some(ty::AutoUnsafe(mutbl_b, None))
636         })))
637     }
638 }
639
640 fn can_coerce_mutbls(from_mutbl: ast::Mutability,
641                      to_mutbl: ast::Mutability)
642                      -> bool {
643     match (from_mutbl, to_mutbl) {
644         (ast::MutMutable, ast::MutMutable) => true,
645         (ast::MutImmutable, ast::MutImmutable) => true,
646         (ast::MutMutable, ast::MutImmutable) => true,
647         (ast::MutImmutable, ast::MutMutable) => false,
648     }
649 }