coercion.rs 35.0 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::hir::def_id::DefId;
67 68
use rustc::infer::{Coercion, InferOk, TypeTrace};
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
69
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
E
est31 已提交
70
use rustc::ty::{self, LvaluePreference, TypeAndMut,
71
                Ty, ClosureSubsts};
72 73
use rustc::ty::fold::TypeFoldable;
use rustc::ty::error::TypeError;
74
use rustc::ty::relate::RelateResult;
75
use rustc::ty::subst::Subst;
76
use syntax::abi;
E
est31 已提交
77
use syntax::feature_gate;
78
use util::common::indent;
79

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

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

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

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

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(()),
107
        (hir::MutImmutable, hir::MutMutable) => Err(TypeError::Mutability),
108 109
    }
}
110

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

121
    fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
122
        self.commit_if_ok(|_| {
123
            let trace = TypeTrace::types(&self.cause, false, a, b);
124
            if self.use_lub {
125
                self.lub(false, trace, &a, &b)
126
                    .map(|ok| self.register_infer_ok_obligations(ok))
127
            } else {
128
                self.sub(false, trace, &a, &b)
129
                    .map(|InferOk { value, obligations }| {
130
                        self.fcx.register_predicates(obligations);
131 132
                        value
                    })
133
            }
134 135 136 137 138 139
        })
    }

    /// 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))
140 141 142 143
    }

    /// Synthesize an identity adjustment.
    fn identity(&self, ty: Ty<'tcx>) -> CoerceResult<'tcx> {
144 145 146 147 148
        Ok((ty, Adjust::DerefRef {
            autoderefs: 0,
            autoref: None,
            unsize: false,
        }))
149 150
    }

151
    fn coerce<'a, E, I>(&self, exprs: &E, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx>
152
        where E: Fn() -> I,
153 154
              I: IntoIterator<Item = &'a hir::Expr>
    {
155

156
        let a = self.shallow_resolve(a);
157
        debug!("Coerce.tys({:?} => {:?})", a, b);
158 159 160

        // Just ignore error types.
        if a.references_error() || b.references_error() {
161
            return self.identity(b);
162 163
        }

A
Andrew Cann 已提交
164
        if a.is_never() {
165
            return Ok((b, Adjust::NeverToAny));
A
Andrew Cann 已提交
166 167
        }

N
Nick Cameron 已提交
168
        // Consider coercing the subtype to a DST
169
        let unsize = self.coerce_unsized(a, b);
N
Nick Cameron 已提交
170 171 172 173
        if unsize.is_ok() {
            return unsize;
        }

174 175 176 177
        // Examine the supertype and consider auto-borrowing.
        //
        // Note: does not attempt to resolve type variables we encounter.
        // See above for details.
178
        match b.sty {
179
            ty::TyRawPtr(mt_b) => {
180
                return self.coerce_unsafe_ptr(a, b, mt_b.mutbl);
181 182
            }

183
            ty::TyRef(r_b, mt_b) => {
184
                return self.coerce_borrowed_pointer(exprs, a, b, r_b, mt_b);
185 186
            }

187 188
            _ => {}
        }
189

190
        match a.sty {
V
Vadim Petrochenkov 已提交
191
            ty::TyFnDef(.., a_f) => {
192 193 194
                // Function items are coercible to any closure
                // type; function pointers are not (that would
                // require double indirection).
T
Taylor Cramer 已提交
195
                // Additionally, we permit coercion of function
196
                // items to drop the unsafe qualifier.
197
                self.coerce_from_fn_item(a, a_f, b)
198
            }
199
            ty::TyFnPtr(a_f) => {
200 201 202 203
                // We permit coercion of fn pointers to drop the
                // unsafe qualifier.
                self.coerce_from_fn_pointer(a, a_f, b)
            }
204 205 206 207 208
            ty::TyClosure(def_id_a, substs_a) => {
                // Non-capturing closures are coercible to
                // function pointers
                self.coerce_closure_to_fn(a, def_id_a, substs_a, b)
            }
209
            _ => {
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
                                         -> CoerceResult<'tcx>
        where E: Fn() -> I,
227
              I: IntoIterator<Item = &'a hir::Expr>
228
    {
229 230

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

232 233 234 235 236 237
        // 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 已提交
238
        let (r_a, mt_a) = match a.sty {
239
            ty::TyRef(r_a, mt_a) => {
J
Jorge Aparicio 已提交
240
                coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
N
Niko Matsakis 已提交
241
                (r_a, mt_a)
S
Seo Sanghyeon 已提交
242
            }
243
            _ => return self.unify_and_identity(a, b),
244
        };
245

246
        let span = self.cause.span;
247

248
        let mut first_error = None;
249
        let mut r_borrow_var = None;
250 251 252 253 254
        let mut autoderef = self.autoderef(span, a);
        let mut success = None;

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

            // 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`.
            //
283
            // One fine point concerns the region that we use. We
284 285 286 287
            // choose the region such that the region of the final
            // type that results from `unify` will be the region we
            // want for the autoref:
            //
288 289 290
            // - 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
291 292 293 294 295
            //   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.
296 297 298 299 300 301 302 303
            //   - 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".)
304 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
            // - 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
332
            } else if autoderefs == 1 {
333 334
                r_a // [3] above
            } else {
335 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(r); // [4] above
340 341 342
                }
                r_borrow_var.unwrap()
            };
343 344 345 346 347
            let derefd_ty_a = self.tcx.mk_ref(r,
                                              TypeAndMut {
                                                  ty: referent_ty,
                                                  mutbl: mt_b.mutbl, // [1] above
                                              });
348
            match self.unify(derefd_ty_a, b) {
349 350 351 352
                Ok(ty) => {
                    success = Some((ty, autoderefs));
                    break;
                }
353 354 355 356
                Err(err) => {
                    if first_error.is_none() {
                        first_error = Some(err);
                    }
357 358
                }
            }
359
        }
360

361 362 363 364 365
        // 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.
366 367
        let (ty, autoderefs) = match success {
            Some(d) => d,
368
            None => {
369 370 371
                let err = first_error.expect("coerce_borrowed_pointer had no error");
                debug!("coerce_borrowed_pointer: failed with err = {:?}", err);
                return Err(err);
372
            }
373 374
        };

375 376
        // This commits the obligations to the fulfillcx. After this succeeds,
        // this snapshot can't be rolled back.
377 378
        autoderef.finalize(LvaluePreference::from_mutbl(mt_b.mutbl), exprs());

379 380
        // Now apply the autoref. We have to extract the region out of
        // the final ref type we got.
N
Niko Matsakis 已提交
381 382 383 384 385 386 387 388 389 390 391 392
        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.
393
            assert_eq!(mt_b.mutbl, hir::MutImmutable); // can only coerce &T -> &U
N
Niko Matsakis 已提交
394 395
            return self.identity(ty);
        }
396
        let r_borrow = match ty.sty {
397
            ty::TyRef(r_borrow, _) => r_borrow,
398
            _ => span_bug!(span, "expected a ref type, got {:?}", ty),
399
        };
400
        let autoref = Some(AutoBorrow::Ref(r_borrow, mt_b.mutbl));
401
        debug!("coerce_borrowed_pointer: succeeded ty={:?} autoderefs={:?} autoref={:?}",
402 403 404
               ty,
               autoderefs,
               autoref);
405 406 407 408 409
        Ok((ty, Adjust::DerefRef {
            autoderefs: autoderefs,
            autoref: autoref,
            unsize: false,
        }))
410 411 412
    }


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

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

N
Nick Cameron 已提交
428 429 430
        // 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 已提交
431
        // that, at which point we will need extra checks on the target here.
N
Nick Cameron 已提交
432

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

438
                let coercion = Coercion(self.cause.span);
439
                let r_borrow = self.next_region_var(coercion);
440
                (mt_a.ty, Some(AutoBorrow::Ref(r_borrow, 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(AutoBorrow::RawPtr(mt_b.mutbl)))
445
            }
446
            _ => (source, None),
N
Nick Cameron 已提交
447
        };
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
        let cause = ObligationCause::misc(self.cause.span, self.body_id);
458 459
        queue.push_back(self.tcx
            .predicate_for_trait_def(cause, coerce_unsized_did, 0, source, &[target]));
N
Nick Cameron 已提交
460 461 462 463 464 465

        // 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() {
466
            debug!("coerce_unsized resolve step: {:?}", obligation);
467 468
            let trait_ref = match obligation.predicate {
                ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => tr.clone(),
N
Nick Cameron 已提交
469 470 471 472 473 474 475
                _ => {
                    leftover_predicates.push(obligation);
                    continue;
                }
            };
            match selcx.select(&obligation.with(trait_ref)) {
                // Uncertain or unimplemented.
476 477
                Ok(None) |
                Err(traits::Unimplemented) => {
N
Nick Cameron 已提交
478
                    debug!("coerce_unsized: early return - can't prove obligation");
479
                    return Err(TypeError::Mismatch);
N
Nick Cameron 已提交
480
                }
N
Nick Cameron 已提交
481 482 483

                // Object safety violations or miscellaneous.
                Err(err) => {
484
                    self.report_selection_error(&obligation, &err);
N
Nick Cameron 已提交
485 486 487 488 489 490
                    // 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)) => {
491 492 493
                    for obligation in vtable.nested_obligations() {
                        queue.push_back(obligation);
                    }
N
Nick Cameron 已提交
494
                }
N
Nick Cameron 已提交
495
            }
N
Nick Cameron 已提交
496 497
        }

498
        *self.unsizing_obligations.borrow_mut() = leftover_predicates;
499

500
        let adjustment = Adjust::DerefRef {
501 502
            autoderefs: if reborrow.is_some() { 1 } else { 0 },
            autoref: reborrow,
503
            unsize: true,
504
        };
505
        debug!("Success, coerced with {:?}", adjustment);
506
        Ok((target, adjustment))
N
Nick Cameron 已提交
507
    }
508

509 510
    fn coerce_from_safe_fn(&self,
                           a: Ty<'tcx>,
511
                           fn_ty_a: ty::PolyFnSig<'tcx>,
512 513 514
                           b: Ty<'tcx>)
                           -> CoerceResult<'tcx> {
        if let ty::TyFnPtr(fn_ty_b) = b.sty {
515
            match (fn_ty_a.unsafety(), fn_ty_b.unsafety()) {
516 517 518
                (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
                    let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
                    return self.unify_and_identity(unsafe_a, b)
519
                        .map(|(ty, _)| (ty, Adjust::UnsafeFnPointer));
520 521 522 523 524 525 526
                }
                _ => {}
            }
        }
        self.unify_and_identity(a, b)
    }

527
    fn coerce_from_fn_pointer(&self,
528
                              a: Ty<'tcx>,
529
                              fn_ty_a: ty::PolyFnSig<'tcx>,
530 531 532 533 534
                              b: Ty<'tcx>)
                              -> CoerceResult<'tcx> {
        //! Attempts to coerce from the type of a Rust function item
        //! into a closure or a `proc`.
        //!
535

536
        let b = self.shallow_resolve(b);
537
        debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
538

539
        self.coerce_from_safe_fn(a, fn_ty_a, b)
540 541
    }

542 543
    fn coerce_from_fn_item(&self,
                           a: Ty<'tcx>,
544
                           fn_ty_a: ty::PolyFnSig<'tcx>,
545
                           b: Ty<'tcx>)
546
                           -> CoerceResult<'tcx> {
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.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b)
558
                    .map(|(ty, _)| (ty, Adjust::ReifyFnPointer))
559
            }
560
            _ => self.unify_and_identity(a, b),
561
        }
562 563
    }

564 565 566 567 568 569 570 571 572 573 574 575
    fn coerce_closure_to_fn(&self,
                           a: Ty<'tcx>,
                           def_id_a: DefId,
                           substs_a: ClosureSubsts<'tcx>,
                           b: Ty<'tcx>)
                           -> CoerceResult<'tcx> {
        //! Attempts to coerce from the type of a non-capturing closure
        //! into a function pointer.
        //!

        let b = self.shallow_resolve(b);

E
est31 已提交
576
        let node_id_a = self.tcx.hir.as_local_node_id(def_id_a).unwrap();
577 578
        match b.sty {
            ty::TyFnPtr(_) if self.tcx.with_freevars(node_id_a, |v| v.is_empty()) => {
E
est31 已提交
579 580 581 582 583 584 585 586
                if !self.tcx.sess.features.borrow().closure_to_fn_coercion {
                    feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
                                                   "closure_to_fn_coercion",
                                                   self.cause.span,
                                                   feature_gate::GateIssue::Language,
                                                   feature_gate::CLOSURE_TO_FN_COERCION);
                    return self.unify_and_identity(a, b);
                }
587 588 589 590
                // We coerce the closure, which has fn type
                //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
                // to
                //     `fn(arg0,arg1,...) -> _`
591
                let sig = self.closure_type(def_id_a).subst(self.tcx, substs_a.substs);
E
est31 已提交
592 593 594
                let converted_sig = sig.map_bound(|s| {
                    let params_iter = match s.inputs()[0].sty {
                        ty::TyTuple(params, _) => {
595 596 597 598
                            params.into_iter().cloned()
                        }
                        _ => bug!(),
                    };
599 600 601 602 603 604 605
                    self.tcx.mk_fn_sig(
                        params_iter,
                        s.output(),
                        s.variadic,
                        hir::Unsafety::Normal,
                        abi::Abi::Rust
                    )
606
                });
607
                let pointer_ty = self.tcx.mk_fn_ptr(converted_sig);
608 609 610 611 612 613 614 615 616
                debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})",
                       a, b, pointer_ty);
                self.unify_and_identity(pointer_ty, b)
                    .map(|(ty, _)| (ty, Adjust::ClosureFnPointer))
            }
            _ => self.unify_and_identity(a, b),
        }
    }

617 618 619
    fn coerce_unsafe_ptr(&self,
                         a: Ty<'tcx>,
                         b: Ty<'tcx>,
620
                         mutbl_b: hir::Mutability)
621
                         -> CoerceResult<'tcx> {
622
        debug!("coerce_unsafe_ptr(a={:?}, b={:?})", a, b);
623

624 625 626
        let (is_ref, mt_a) = match a.sty {
            ty::TyRef(_, mt) => (true, mt),
            ty::TyRawPtr(mt) => (false, mt),
627
            _ => {
628
                return self.unify_and_identity(a, b);
629 630 631
            }
        };

632
        // Check that the types which they point at are compatible.
633 634 635 636
        let a_unsafe = self.tcx.mk_ptr(ty::TypeAndMut {
            mutbl: mutbl_b,
            ty: mt_a.ty,
        });
J
Jorge Aparicio 已提交
637 638
        let (ty, noop) = self.unify_and_identity(a_unsafe, b)?;
        coerce_mutbls(mt_a.mutbl, mutbl_b)?;
N
Niko Matsakis 已提交
639

640
        // Although references and unsafe ptrs have the same
641
        // representation, we still register an Adjust::DerefRef so that
642
        // regionck knows that the region for `a` must be valid here.
643 644
        Ok((ty,
            if is_ref {
645
                Adjust::DerefRef {
646
                    autoderefs: 1,
647 648 649
                    autoref: Some(AutoBorrow::RawPtr(mutbl_b)),
                    unsize: false,
                }
650
            } else if mt_a.mutbl != mutbl_b {
651
                Adjust::MutToConstPointer
652 653 654
            } else {
                noop
            }))
655 656
    }
}
657

658 659 660 661
fn apply<'a, 'b, 'gcx, 'tcx, E, I>(coerce: &mut Coerce<'a, 'gcx, 'tcx>,
                                   exprs: &E,
                                   a: Ty<'tcx>,
                                   b: Ty<'tcx>)
662
                                   -> RelateResult<'tcx, Adjustment<'tcx>>
663
    where E: Fn() -> I,
664 665
          I: IntoIterator<Item = &'b hir::Expr>
{
666

667
    let (ty, adjust) = indent(|| coerce.coerce(exprs, a, b))?;
668

669
    let fcx = coerce.fcx;
670 671 672 673
    if let Adjust::DerefRef { unsize: true, .. } = adjust {
        let mut obligations = coerce.unsizing_obligations.borrow_mut();
        for obligation in obligations.drain(..) {
            fcx.register_predicate(obligation);
674 675 676
        }
    }

677 678 679 680
    Ok(Adjustment {
        kind: adjust,
        target: ty
    })
681 682
}

683
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
684 685 686 687 688 689
    /// 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,
690
                      expr_ty: Ty<'tcx>,
691 692
                      target: Ty<'tcx>)
                      -> RelateResult<'tcx, Ty<'tcx>> {
693
        let source = self.resolve_type_vars_with_obligations(expr_ty);
694
        debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
695

696 697
        let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);
        let mut coerce = Coerce::new(self, cause);
698
        self.commit_if_ok(|_| {
699
            let adjustment = apply(&mut coerce, &|| Some(expr), source, target)?;
700 701
            if !adjustment.is_identity() {
                debug!("Success, coerced with {:?}", adjustment);
A
Andrew Cann 已提交
702
                match self.tables.borrow().adjustments.get(&expr.id) {
703
                    None |
704
                    Some(&Adjustment { kind: Adjust::NeverToAny, .. }) => (),
A
Andrew Cann 已提交
705 706
                    _ => bug!("expr already has an adjustment on it!"),
                };
707
                self.write_adjustment(expr.id, adjustment);
708
            }
709
            Ok(adjustment.target)
710
        })
711 712
    }

713 714 715 716
    /// 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,
717
                                           cause: &ObligationCause<'tcx>,
718 719
                                           exprs: E,
                                           prev_ty: Ty<'tcx>,
720 721
                                           new: &'b hir::Expr,
                                           new_ty: Ty<'tcx>)
722 723
                                           -> RelateResult<'tcx, Ty<'tcx>>
        where E: Fn() -> I,
724 725
              I: IntoIterator<Item = &'b hir::Expr>
    {
726

727
        let prev_ty = self.resolve_type_vars_with_obligations(prev_ty);
728
        let new_ty = self.resolve_type_vars_with_obligations(new_ty);
729
        debug!("coercion::try_find_lub({:?}, {:?})", prev_ty, new_ty);
730

731
        let trace = TypeTrace::types(cause, true, prev_ty, new_ty);
732

733 734 735
        // Special-case that coercion alone cannot handle:
        // Two function item types of differing IDs or Substs.
        match (&prev_ty.sty, &new_ty.sty) {
736
            (&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
737 738
                // The signature must always match.
                let fty = self.lub(true, trace.clone(), &a_fty, &b_fty)
739
                              .map(|ok| self.register_infer_ok_obligations(ok))?;
740 741 742 743 744

                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)
745
                            .map(|ok| self.register_infer_ok_obligations(ok))
746 747 748 749 750 751 752 753 754
                    });

                    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.
755
                let fn_ptr = self.tcx.mk_fn_ptr(fty);
756
                for expr in exprs().into_iter().chain(Some(new)) {
757 758
                    // No adjustments can produce a fn item, so this should never trip.
                    assert!(!self.tables.borrow().adjustments.contains_key(&expr.id));
759 760 761 762
                    self.write_adjustment(expr.id, Adjustment {
                        kind: Adjust::ReifyFnPointer,
                        target: fn_ptr
                    });
763
                }
764
                return Ok(fn_ptr);
765 766 767 768
            }
            _ => {}
        }

769
        let mut coerce = Coerce::new(self, cause.clone());
770 771 772 773 774 775
        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) {
776
            let result = self.commit_if_ok(|_| apply(&mut coerce, &|| Some(new), new_ty, prev_ty));
777
            match result {
778
                Ok(adjustment) => {
779 780 781
                    if !adjustment.is_identity() {
                        self.write_adjustment(new.id, adjustment);
                    }
782
                    return Ok(adjustment.target);
783
                }
784
                Err(e) => first_error = Some(e),
785
            }
786 787
        }

788 789 790
        // 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).
791
        for expr in exprs() {
792 793 794 795 796 797
            let noop = match self.tables.borrow().adjustments.get(&expr.id).map(|adj| adj.kind) {
                Some(Adjust::DerefRef {
                    autoderefs: 1,
                    autoref: Some(AutoBorrow::Ref(_, mutbl_adj)),
                    unsize: false
                }) => {
798 799 800 801 802 803
                    match self.node_ty(expr.id).sty {
                        ty::TyRef(_, mt_orig) => {
                            // Reborrow that we can safely ignore.
                            mutbl_adj == mt_orig.mutbl
                        }
                        _ => false,
804
                    }
805
                }
806
                Some(Adjust::NeverToAny) => true,
807
                Some(_) => false,
808
                None => true,
809 810 811 812 813
            };

            if !noop {
                return self.commit_if_ok(|_| {
                    self.lub(true, trace.clone(), &prev_ty, &new_ty)
814
                        .map(|ok| self.register_infer_ok_obligations(ok))
815
                });
816 817
            }
        }
818

819
        match self.commit_if_ok(|_| apply(&mut coerce, &exprs, prev_ty, new_ty)) {
820 821 822 823 824 825 826
            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)
827
                            .map(|ok| self.register_infer_ok_obligations(ok))
828
                    })
829 830
                }
            }
831
            Ok(adjustment) => {
832
                if !adjustment.is_identity() {
833
                    let mut tables = self.tables.borrow_mut();
834
                    for expr in exprs() {
835 836 837 838 839 840
                        if let Some(&mut Adjustment {
                            kind: Adjust::NeverToAny,
                            ref mut target
                        }) = tables.adjustments.get_mut(&expr.id) {
                            *target = adjustment.target;
                            continue;
841
                        }
842
                        tables.adjustments.insert(expr.id, adjustment);
843 844
                    }
                }
845
                Ok(adjustment.target)
846
            }
847
        }
848 849
    }
}