coercion.rs 32.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

S
Steve Klabnik 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
//! # Type Coercion
//!
//! Under certain circumstances we will coerce from one type to another,
//! for example by auto-borrowing.  This occurs in situations where the
//! compiler has a firm 'expected type' that was supplied from the user,
//! and where the actual type is similar to that expected type in purpose
//! but not in representation (so actual subtyping is inappropriate).
//!
//! ## Reborrowing
//!
//! Note that if we are expecting a reference, we will *reborrow*
//! even if the argument provided was already a reference.  This is
//! useful for freezing mut/const things (that is, when the expected is &T
//! but you have &const T or &mut T) and also for avoiding the linearity
//! of mut things (when the expected is &mut T and you have &mut T).  See
//! the various `src/test/run-pass/coerce-reborrow-*.rs` tests for
//! examples of where this is useful.
//!
//! ## Subtle note
//!
//! When deciding what type coercions to consider, we do not attempt to
//! resolve any type variables we may encounter.  This is because `b`
//! represents the expected type "as the user wrote it", meaning that if
//! the user defined a generic function like
//!
//!    fn foo<A>(a: A, b: A) { ... }
//!
//! and then we wrote `foo(&1, @2)`, we will not auto-borrow
//! either argument.  In older code we went to some lengths to
//! resolve the `b` variable, which could mean that we'd
//! auto-borrow later arguments but not earlier ones, which
//! seems very confusing.
//!
//! ## Subtler note
//!
//! However, right now, if the user manually specifies the
//! values for the type variables, as so:
//!
//!    foo::<&int>(@1, @2)
//!
//! then we *will* auto-borrow, because we can't distinguish this from a
//! function that declared `&int`.  This is inconsistent but it's easiest
//! at the moment. The right thing to do, I think, is to consider the
//! *unsubstituted* type when deciding whether to auto-borrow, but the
//! *substituted* type when considering the bounds and so forth. But most
//! of our methods don't give access to the unsubstituted type, and
//! rightly so because they'd be error-prone.  So maybe the thing to do is
//! to actually determine the kind of coercions that should occur
//! separately and pass them in.  Or maybe it's ok as is.  Anyway, it's
//! sort of a minor point so I've opted to leave it for later---after all
//! 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 68 69 70
use rustc::traits::{self, ObligationCause};
use rustc::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef};
use rustc::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer};
use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
A
Andrew Cann 已提交
71 72
use rustc::ty::adjustment::AdjustNeverToAny;
use rustc::ty::{self, LvaluePreference, TypeAndMut, Ty};
73 74
use rustc::ty::fold::TypeFoldable;
use rustc::ty::error::TypeError;
75
use rustc::ty::relate::RelateResult;
76
use util::common::indent;
77

N
Nick Cameron 已提交
78 79
use std::cell::RefCell;
use std::collections::VecDeque;
80
use std::ops::Deref;
81

82 83
struct Coerce<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
    fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
84 85
    origin: TypeOrigin,
    use_lub: bool,
N
Nick Cameron 已提交
86
    unsizing_obligations: RefCell<Vec<traits::PredicateObligation<'tcx>>>,
87 88
}

89 90 91 92 93 94 95
impl<'a, 'gcx, 'tcx> Deref for Coerce<'a, 'gcx, 'tcx> {
    type Target = FnCtxt<'a, 'gcx, 'tcx>;
    fn deref(&self) -> &Self::Target {
        &self.fcx
    }
}

96 97 98 99 100 101 102 103 104 105 106 107
type CoerceResult<'tcx> = RelateResult<'tcx, (Ty<'tcx>, AutoAdjustment<'tcx>)>;

fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
                       to_mutbl: hir::Mutability)
                       -> RelateResult<'tcx, ()> {
    match (from_mutbl, to_mutbl) {
        (hir::MutMutable, hir::MutMutable) |
        (hir::MutImmutable, hir::MutImmutable) |
        (hir::MutMutable, hir::MutImmutable) => Ok(()),
        (hir::MutImmutable, hir::MutMutable) => Err(TypeError::Mutability)
    }
}
108

109 110
impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
    fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, origin: TypeOrigin) -> Self {
111 112 113
        Coerce {
            fcx: fcx,
            origin: origin,
114
            use_lub: false,
115 116 117 118
            unsizing_obligations: RefCell::new(vec![])
        }
    }

119
    fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
120
        self.commit_if_ok(|_| {
121 122
            let trace = TypeTrace::types(self.origin, false, a, b);
            if self.use_lub {
123
                self.lub(false, trace, &a, &b)
124
                    .map(|InferOk { value, obligations }| {
M
Masood Malekghassemi 已提交
125
                        // FIXME(#32730) propagate obligations
126 127 128
                        assert!(obligations.is_empty());
                        value
                    })
129
            } else {
130
                self.sub(false, trace, &a, &b)
131
                    .map(|InferOk { value, obligations }| {
M
Masood Malekghassemi 已提交
132
                        // FIXME(#32730) propagate obligations
133 134 135
                        assert!(obligations.is_empty());
                        value
                    })
136
            }
137 138 139 140 141 142
        })
    }

    /// Unify two types (using sub or lub) and produce a noop coercion.
    fn unify_and_identity(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
        self.unify(&a, &b).and_then(|ty| self.identity(ty))
143 144 145 146 147 148 149 150 151
    }

    /// Synthesize an identity adjustment.
    fn identity(&self, ty: Ty<'tcx>) -> CoerceResult<'tcx> {
        Ok((ty, AdjustDerefRef(AutoDerefRef {
            autoderefs: 0,
            autoref: None,
            unsize: None
        })))
152 153
    }

154 155 156 157 158 159 160 161
    fn coerce<'a, E, I>(&self,
                        exprs: &E,
                        a: Ty<'tcx>,
                        b: Ty<'tcx>)
                        -> CoerceResult<'tcx>
        // FIXME(eddyb) use copyable iterators when that becomes ergonomic.
        where E: Fn() -> I,
              I: IntoIterator<Item=&'a hir::Expr> {
162

163
        let a = self.shallow_resolve(a);
164
        debug!("Coerce.tys({:?} => {:?})", a, b);
165 166 167

        // Just ignore error types.
        if a.references_error() || b.references_error() {
168
            return self.identity(b);
169 170
        }

A
Andrew Cann 已提交
171 172
        if a.is_never() {
            return Ok((b, AdjustNeverToAny(b)));
A
Andrew Cann 已提交
173 174
        }

N
Nick Cameron 已提交
175
        // Consider coercing the subtype to a DST
176
        let unsize = self.coerce_unsized(a, b);
N
Nick Cameron 已提交
177 178 179 180
        if unsize.is_ok() {
            return unsize;
        }

181 182 183 184
        // Examine the supertype and consider auto-borrowing.
        //
        // Note: does not attempt to resolve type variables we encounter.
        // 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 200 201 202
                // Function items are coercible to any closure
                // type; function pointers are not (that would
                // require double indirection).
                self.coerce_from_fn_item(a, a_f, b)
203
            }
204
            ty::TyFnPtr(a_f) => {
205 206 207 208 209
                // We permit coercion of fn pointers to drop the
                // unsafe qualifier.
                self.coerce_from_fn_pointer(a, a_f, b)
            }
            _ => {
210
                // Otherwise, just use unification rules.
211
                self.unify_and_identity(a, b)
212 213
            }
        }
214 215
    }

216 217 218
    /// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
    /// To match `A` with `B`, autoderef will be performed,
    /// calling `deref`/`deref_mut` where necessary.
219 220 221 222
    fn coerce_borrowed_pointer<'a, E, I>(&self,
                                         exprs: &E,
                                         a: Ty<'tcx>,
                                         b: Ty<'tcx>,
223
                                         r_b: &'tcx ty::Region,
224
                                         mt_b: TypeAndMut<'tcx>)
225 226 227
                                         -> CoerceResult<'tcx>
        // FIXME(eddyb) use copyable iterators when that becomes ergonomic.
        where E: Fn() -> I,
228 229
              I: IntoIterator<Item=&'a hir::Expr>
    {
230 231

        debug!("coerce_borrowed_pointer(a={:?}, b={:?})", a, b);
232

233 234 235 236 237 238
        // If we have a parameter of type `&M T_a` and the value
        // provided is `expr`, we will be adding an implicit borrow,
        // meaning that we convert `f(expr)` to `f(&M *expr)`.  Therefore,
        // to type check, we will construct the type that `&M*expr` would
        // yield.

N
Niko Matsakis 已提交
239
        let (r_a, mt_a) = match a.sty {
240
            ty::TyRef(r_a, mt_a) => {
J
Jorge Aparicio 已提交
241
                coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
N
Niko Matsakis 已提交
242
                (r_a, mt_a)
S
Seo Sanghyeon 已提交
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 252 253 254 255
        let mut autoderef = self.autoderef(span, a);
        let mut success = None;

        for (referent_ty, autoderefs) in autoderef.by_ref() {
            if autoderefs == 0 {
256 257
                // Don't let this pass, otherwise it would cause
                // &T to autoref to &&T.
258
                continue
259
            }
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283

            // At this point, we have deref'd `a` to `referent_ty`.  So
            // imagine we are coercing from `&'a mut Vec<T>` to `&'b mut [T]`.
            // In the autoderef loop for `&'a mut Vec<T>`, we would get
            // three callbacks:
            //
            // - `&'a mut Vec<T>` -- 0 derefs, just ignore it
            // - `Vec<T>` -- 1 deref
            // - `[T]` -- 2 deref
            //
            // At each point after the first callback, we want to
            // check to see whether this would match out target type
            // (`&'b mut [T]`) if we autoref'd it. We can't just
            // compare the referent types, though, because we still
            // have to consider the mutability. E.g., in the case
            // we've been considering, we have an `&mut` reference, so
            // the `T` in `[T]` needs to be unified with equality.
            //
            // Therefore, we construct reference types reflecting what
            // the types will be after we do the final auto-ref and
            // compare those. Note that this means we use the target
            // mutability [1], since it may be that we are coercing
            // from `&mut T` to `&U`.
            //
284
            // One fine point concerns the region that we use. We
285 286 287 288
            // choose the region such that the region of the final
            // type that results from `unify` will be the region we
            // want for the autoref:
            //
289 290 291
            // - if in sub mode, that means we want to use `'b` (the
            //   region from the target reference) for both
            //   pointers [2]. This is because sub mode (somewhat
292 293 294 295 296
            //   arbitrarily) returns the subtype region.  In the case
            //   where we are coercing to a target type, we know we
            //   want to use that target type region (`'b`) because --
            //   for the program to type-check -- it must be the
            //   smaller of the two.
297 298 299 300 301 302 303 304
            //   - One fine point. It may be surprising that we can
            //     use `'b` without relating `'a` and `'b`. The reason
            //     that this is ok is that what we produce is
            //     effectively a `&'b *x` expression (if you could
            //     annotate the region of a borrow), and regionck has
            //     code that adds edges from the region of a borrow
            //     (`'b`, here) into the regions in the borrowed
            //     expression (`*x`, here).  (Search for "link".)
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
            // - if in lub mode, things can get fairly complicated. The
            //   easiest thing is just to make a fresh
            //   region variable [4], which effectively means we defer
            //   the decision to region inference (and regionck, which will add
            //   some more edges to this variable). However, this can wind up
            //   creating a crippling number of variables in some cases --
            //   e.g. #32278 -- so we optimize one particular case [3].
            //   Let me try to explain with some examples:
            //   - The "running example" above represents the simple case,
            //     where we have one `&` reference at the outer level and
            //     ownership all the rest of the way down. In this case,
            //     we want `LUB('a, 'b)` as the resulting region.
            //   - However, if there are nested borrows, that region is
            //     too strong. Consider a coercion from `&'a &'x Rc<T>` to
            //     `&'b T`. In this case, `'a` is actually irrelevant.
            //     The pointer we want is `LUB('x, 'b`). If we choose `LUB('a,'b)`
            //     we get spurious errors (`run-pass/regions-lub-ref-ref-rc.rs`).
            //     (The errors actually show up in borrowck, typically, because
            //     this extra edge causes the region `'a` to be inferred to something
            //     too big, which then results in borrowck errors.)
            //   - We could track the innermost shared reference, but there is already
            //     code in regionck that has the job of creating links between
            //     the region of a borrow and the regions in the thing being
            //     borrowed (here, `'a` and `'x`), and it knows how to handle
            //     all the various cases. So instead we just make a region variable
            //     and let regionck figure it out.
            let r = if !self.use_lub {
                r_b // [2] above
333
            } else if autoderefs == 1 {
334 335 336 337
                r_a // [3] above
            } else {
                if r_borrow_var.is_none() { // create var lazilly, at most once
                    let coercion = Coercion(span);
338 339
                    let r = self.next_region_var(coercion);
                    r_borrow_var = Some(self.tcx.mk_region(r)); // [4] above
340 341 342
                }
                r_borrow_var.unwrap()
            };
343
            let derefd_ty_a = self.tcx.mk_ref(r, TypeAndMut {
344 345 346 347
                ty: referent_ty,
                mutbl: mt_b.mutbl // [1] above
            });
            match self.unify(derefd_ty_a, b) {
348
                Ok(ty) => { success = Some((ty, autoderefs)); break },
349 350 351 352
                Err(err) => {
                    if first_error.is_none() {
                        first_error = Some(err);
                    }
353 354
                }
            }
355
        }
356

357 358 359 360 361
        // Extract type or return an error. We return the first error
        // we got, which should be from relating the "base" type
        // (e.g., in example above, the failure from relating `Vec<T>`
        // to the target type), since that should be the least
        // confusing.
362 363
        let (ty, autoderefs) = match success {
            Some(d) => d,
364
            None => {
365 366 367
                let err = first_error.expect("coerce_borrowed_pointer had no error");
                debug!("coerce_borrowed_pointer: failed with err = {:?}", err);
                return Err(err);
368
            }
369 370
        };

371 372
        // This commits the obligations to the fulfillcx. After this succeeds,
        // this snapshot can't be rolled back.
373 374
        autoderef.finalize(LvaluePreference::from_mutbl(mt_b.mutbl), exprs());

375 376
        // Now apply the autoref. We have to extract the region out of
        // the final ref type we got.
N
Niko Matsakis 已提交
377 378 379 380 381 382 383 384 385 386 387 388
        if ty == a && mt_a.mutbl == hir::MutImmutable && autoderefs == 1 {
            // As a special case, if we would produce `&'a *x`, that's
            // a total no-op. We end up with the type `&'a T` just as
            // we started with.  In that case, just skip it
            // altogether. This is just an optimization.
            //
            // Note that for `&mut`, we DO want to reborrow --
            // otherwise, this would be a move, which might be an
            // error. For example `foo(self.x)` where `self` and
            // `self.x` both have `&mut `type would be a move of
            // `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
            // which is a borrow.
389
            assert_eq!(mt_b.mutbl, hir::MutImmutable); // can only coerce &T -> &U
N
Niko Matsakis 已提交
390 391
            return self.identity(ty);
        }
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 398
        debug!("coerce_borrowed_pointer: succeeded ty={:?} autoderefs={:?} autoref={:?}",
               ty, autoderefs, autoref);
399 400 401 402 403
        Ok((ty, AdjustDerefRef(AutoDerefRef {
            autoderefs: autoderefs,
            autoref: autoref,
            unsize: None
        })))
404 405 406
    }


407 408
    // &[T; n] or &mut [T; n] -> &[T]
    // or &mut [T; n] -> &mut [T]
N
Nick Cameron 已提交
409 410
    // or &Concrete -> &Trait, etc.
    fn coerce_unsized(&self,
N
Nick Cameron 已提交
411 412
                      source: Ty<'tcx>,
                      target: Ty<'tcx>)
413
                      -> CoerceResult<'tcx> {
414 415 416
        debug!("coerce_unsized(source={:?}, target={:?})",
               source,
               target);
N
Nick Cameron 已提交
417

418 419
        let traits = (self.tcx.lang_items.unsize_trait(),
                      self.tcx.lang_items.coerce_unsized_trait());
N
Nick Cameron 已提交
420 421 422 423
        let (unsize_did, coerce_unsized_did) = if let (Some(u), Some(cu)) = traits {
            (u, cu)
        } else {
            debug!("Missing Unsize or CoerceUnsized traits");
424
            return Err(TypeError::Mismatch);
N
Nick Cameron 已提交
425
        };
426

N
Nick Cameron 已提交
427 428 429
        // Note, we want to avoid unnecessary unsizing. We don't want to coerce to
        // a DST unless we have to. This currently comes out in the wash since
        // we can't unify [T] with U. But to properly support DST, we need to allow
N
Nick Cameron 已提交
430
        // that, at which point we will need extra checks on the target here.
N
Nick Cameron 已提交
431

N
Nick Cameron 已提交
432 433
        // Handle reborrows before selecting `Source: CoerceUnsized<Target>`.
        let (source, reborrow) = match (&source.sty, &target.sty) {
434
            (&ty::TyRef(_, mt_a), &ty::TyRef(_, mt_b)) => {
J
Jorge Aparicio 已提交
435
                coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
N
Nick Cameron 已提交
436 437

                let coercion = Coercion(self.origin.span());
438 439
                let r_borrow = self.next_region_var(coercion);
                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)) => {
J
Jorge Aparicio 已提交
443
                coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
444
                (mt_a.ty, Some(AutoUnsafe(mt_b.mutbl)))
445
            }
N
Nick Cameron 已提交
446 447
            _ => (source, None)
        };
448
        let source = source.adjust_for_autoref(self.tcx, reborrow);
N
Nick Cameron 已提交
449

450
        let mut selcx = traits::SelectionContext::new(self);
N
Nick Cameron 已提交
451 452 453 454 455 456

        // Use a FIFO queue for this custom fulfillment procedure.
        let mut queue = VecDeque::new();
        let mut leftover_predicates = vec![];

        // Create an obligation for `Source: CoerceUnsized<Target>`.
457 458 459 460 461 462
        let cause = ObligationCause::misc(self.origin.span(), self.body_id);
        queue.push_back(self.tcx.predicate_for_trait_def(cause,
                                                         coerce_unsized_did,
                                                         0,
                                                         source,
                                                         vec![target]));
N
Nick Cameron 已提交
463 464 465 466 467 468

        // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
        // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
        // inference might unify those two inner type variables later.
        let traits = [coerce_unsized_did, unsize_did];
        while let Some(obligation) = queue.pop_front() {
469
            debug!("coerce_unsized resolve step: {:?}", obligation);
N
Nick Cameron 已提交
470 471 472 473 474 475 476 477 478 479 480 481
            let trait_ref =  match obligation.predicate {
                ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
                    tr.clone()
                }
                _ => {
                    leftover_predicates.push(obligation);
                    continue;
                }
            };
            match selcx.select(&obligation.with(trait_ref)) {
                // Uncertain or unimplemented.
                Ok(None) | Err(traits::Unimplemented) => {
N
Nick Cameron 已提交
482
                    debug!("coerce_unsized: early return - can't prove obligation");
483
                    return Err(TypeError::Mismatch);
N
Nick Cameron 已提交
484
                }
N
Nick Cameron 已提交
485 486 487

                // Object safety violations or miscellaneous.
                Err(err) => {
488
                    self.report_selection_error(&obligation, &err, None);
N
Nick Cameron 已提交
489 490 491 492 493 494
                    // Treat this like an obligation and follow through
                    // with the unsizing - the lack of a coercion should
                    // be silent, as it causes a type mismatch later.
                }

                Ok(Some(vtable)) => {
495 496 497
                    for obligation in vtable.nested_obligations() {
                        queue.push_back(obligation);
                    }
N
Nick Cameron 已提交
498
                }
N
Nick Cameron 已提交
499
            }
N
Nick Cameron 已提交
500 501
        }

502
        *self.unsizing_obligations.borrow_mut() = leftover_predicates;
503 504 505 506 507 508

        let adjustment = AutoDerefRef {
            autoderefs: if reborrow.is_some() { 1 } else { 0 },
            autoref: reborrow,
            unsize: Some(target)
        };
509
        debug!("Success, coerced with {:?}", adjustment);
510
        Ok((target, AdjustDerefRef(adjustment)))
N
Nick Cameron 已提交
511
    }
512

513 514 515 516 517 518 519 520 521 522 523
    fn coerce_from_fn_pointer(&self,
                           a: Ty<'tcx>,
                           fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
                           b: Ty<'tcx>)
                           -> CoerceResult<'tcx>
    {
        /*!
         * Attempts to coerce from the type of a Rust function item
         * into a closure or a `proc`.
         */

524
        let b = self.shallow_resolve(b);
525
        debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
526

527 528 529
        if let ty::TyFnPtr(fn_ty_b) = b.sty {
            match (fn_ty_a.unsafety, fn_ty_b.unsafety) {
                (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 533
                        (ty, AdjustUnsafeFnPointer)
                    });
534
                }
535
                _ => {}
536
            }
537
        }
538
        self.unify_and_identity(a, b)
539 540
    }

541 542
    fn coerce_from_fn_item(&self,
                           a: Ty<'tcx>,
H
Huon Wilson 已提交
543
                           fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
544
                           b: Ty<'tcx>)
545
                           -> CoerceResult<'tcx> {
546 547 548 549
        /*!
         * Attempts to coerce from the type of a Rust function item
         * into a closure or a `proc`.
         */
550

551
        let b = self.shallow_resolve(b);
552
        debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
553

554 555
        match b.sty {
            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 559
                    (ty, AdjustReifyFnPointer)
                })
560
            }
561
            _ => self.unify_and_identity(a, b)
562
        }
563 564
    }

565 566 567
    fn coerce_unsafe_ptr(&self,
                         a: Ty<'tcx>,
                         b: Ty<'tcx>,
568
                         mutbl_b: hir::Mutability)
569
                         -> CoerceResult<'tcx> {
570 571 572
        debug!("coerce_unsafe_ptr(a={:?}, b={:?})",
               a,
               b);
573

574 575 576
        let (is_ref, mt_a) = match a.sty {
            ty::TyRef(_, mt) => (true, mt),
            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 });
J
Jorge Aparicio 已提交
584 585
        let (ty, noop) = self.unify_and_identity(a_unsafe, b)?;
        coerce_mutbls(mt_a.mutbl, mutbl_b)?;
N
Niko Matsakis 已提交
586

587
        // Although references and unsafe ptrs have the same
N
Niko Matsakis 已提交
588
        // representation, we still register an AutoDerefRef so that
589
        // regionck knows that the region for `a` must be valid here.
590 591
        Ok((ty, if is_ref {
            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 600
            noop
        }))
601 602
    }
}
603

604 605 606 607 608
fn apply<'a, 'b, 'gcx, 'tcx, E, I>(coerce: &mut Coerce<'a, 'gcx, 'tcx>,
                                   exprs: &E,
                                   a: Ty<'tcx>,
                                   b: Ty<'tcx>)
                                   -> CoerceResult<'tcx>
609 610 611
    where E: Fn() -> I,
          I: IntoIterator<Item=&'b hir::Expr> {

J
Jorge Aparicio 已提交
612
    let (ty, adjustment) = indent(|| coerce.coerce(exprs, a, b))?;
613

614 615
    let fcx = coerce.fcx;
    if let AdjustDerefRef(auto) = adjustment {
N
Nick Cameron 已提交
616
        if auto.unsize.is_some() {
617 618
            let mut obligations = coerce.unsizing_obligations.borrow_mut();
            for obligation in obligations.drain(..) {
N
Nick Cameron 已提交
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 629 630 631 632 633 634 635 636 637
    /// Attempt to coerce an expression to a type, and return the
    /// adjusted type of the expression, if successful.
    /// Adjustments are only recorded if the coercion succeeded.
    /// The expressions *must not* have any pre-existing adjustments.
    pub fn try_coerce(&self,
                      expr: &hir::Expr,
                      target: Ty<'tcx>)
                      -> RelateResult<'tcx, Ty<'tcx>> {
        let source = self.resolve_type_vars_with_obligations(self.expr_ty(expr));
        debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
638

639 640 641 642 643 644
        let mut coerce = Coerce::new(self, TypeOrigin::ExprAssignable(expr.span));
        self.commit_if_ok(|_| {
            let (ty, adjustment) =
                apply(&mut coerce, &|| Some(expr), source, target)?;
            if !adjustment.is_identity() {
                debug!("Success, coerced with {:?}", adjustment);
645
                assert!(!self.tables.borrow().adjustments.contains_key(&expr.id));
646
                self.write_adjustment(expr.id, adjustment);
647
            }
648 649
            Ok(ty)
        })
650 651
    }

652 653 654 655 656 657 658 659 660 661 662 663
    /// Given some expressions, their known unified type and another expression,
    /// tries to unify the types, potentially inserting coercions on any of the
    /// provided expressions and returns their LUB (aka "common supertype").
    pub fn try_find_coercion_lub<'b, E, I>(&self,
                                           origin: TypeOrigin,
                                           exprs: E,
                                           prev_ty: Ty<'tcx>,
                                           new: &'b hir::Expr)
                                           -> RelateResult<'tcx, Ty<'tcx>>
        // FIXME(eddyb) use copyable iterators when that becomes ergonomic.
        where E: Fn() -> I,
              I: IntoIterator<Item=&'b hir::Expr> {
664

665 666 667
        let prev_ty = self.resolve_type_vars_with_obligations(prev_ty);
        let new_ty = self.resolve_type_vars_with_obligations(self.expr_ty(new));
        debug!("coercion::try_find_lub({:?}, {:?})", prev_ty, new_ty);
668

669
        let trace = TypeTrace::types(origin, true, prev_ty, new_ty);
670

671 672 673 674 675 676 677
        // Special-case that coercion alone cannot handle:
        // Two function item types of differing IDs or Substs.
        match (&prev_ty.sty, &new_ty.sty) {
            (&ty::TyFnDef(a_def_id, a_substs, a_fty),
             &ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
                // The signature must always match.
                let fty = self.lub(true, trace.clone(), &a_fty, &b_fty)
678
                    .map(|InferOk { value, obligations }| {
M
Masood Malekghassemi 已提交
679
                        // FIXME(#32730) propagate obligations
680 681
                        assert!(obligations.is_empty());
                        value
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
                    })?;

                if a_def_id == b_def_id {
                    // Same function, maybe the parameters match.
                    let substs = self.commit_if_ok(|_| {
                        self.lub(true, trace.clone(), &a_substs, &b_substs)
                            .map(|InferOk { value, obligations }| {
                                // FIXME(#32730) propagate obligations
                                assert!(obligations.is_empty());
                                value
                            })
                    });

                    if let Ok(substs) = substs {
                        // We have a LUB of prev_ty and new_ty, just return it.
                        return Ok(self.tcx.mk_fn_def(a_def_id, substs, fty));
                    }
                }

                // Reify both sides and return the reified fn pointer type.
                for expr in exprs().into_iter().chain(Some(new)) {
                    // No adjustments can produce a fn item, so this should never trip.
                    assert!(!self.tables.borrow().adjustments.contains_key(&expr.id));
                    self.write_adjustment(expr.id, AdjustReifyFnPointer);
                }
                return Ok(self.tcx.mk_fn_ptr(fty));
            }
            _ => {}
        }

        let mut coerce = Coerce::new(self, origin);
        coerce.use_lub = true;

        // First try to coerce the new expression to the type of the previous ones,
        // but only if the new expression has no coercion already applied to it.
        let mut first_error = None;
        if !self.tables.borrow().adjustments.contains_key(&new.id) {
            let result = self.commit_if_ok(|_| {
                apply(&mut coerce, &|| Some(new), new_ty, prev_ty)
721
            });
722 723 724 725 726 727 728 729 730
            match result {
                Ok((ty, adjustment)) => {
                    if !adjustment.is_identity() {
                        self.write_adjustment(new.id, adjustment);
                    }
                    return Ok(ty);
                }
                Err(e) => first_error = Some(e)
            }
731 732
        }

733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755
        // Then try to coerce the previous expressions to the type of the new one.
        // This requires ensuring there are no coercions applied to *any* of the
        // previous expressions, other than noop reborrows (ignoring lifetimes).
        for expr in exprs() {
            let noop = match self.tables.borrow().adjustments.get(&expr.id) {
                Some(&AdjustDerefRef(AutoDerefRef {
                    autoderefs: 1,
                    autoref: Some(AutoPtr(_, mutbl_adj)),
                    unsize: None
                })) => match self.expr_ty(expr).sty {
                    ty::TyRef(_, mt_orig) => {
                        // Reborrow that we can safely ignore.
                        mutbl_adj == mt_orig.mutbl
                    }
                    _ => false
                },
                Some(_) => false,
                None => true
            };

            if !noop {
                return self.commit_if_ok(|_| {
                    self.lub(true, trace.clone(), &prev_ty, &new_ty)
756
                        .map(|InferOk { value, obligations }| {
M
Masood Malekghassemi 已提交
757
                            // FIXME(#32730) propagate obligations
758 759 760
                            assert!(obligations.is_empty());
                            value
                        })
761
                });
762 763
            }
        }
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778

        match self.commit_if_ok(|_| apply(&mut coerce, &exprs, prev_ty, new_ty)) {
            Err(_) => {
                // Avoid giving strange errors on failed attempts.
                if let Some(e) = first_error {
                    Err(e)
                } else {
                    self.commit_if_ok(|_| {
                        self.lub(true, trace, &prev_ty, &new_ty)
                            .map(|InferOk { value, obligations }| {
                                // FIXME(#32730) propagate obligations
                                assert!(obligations.is_empty());
                                value
                            })
                    })
779 780
                }
            }
781 782 783 784 785 786 787 788
            Ok((ty, adjustment)) => {
                if !adjustment.is_identity() {
                    for expr in exprs() {
                        self.write_adjustment(expr.id, adjustment);
                    }
                }
                Ok(ty)
            }
789
        }
790 791
    }
}