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.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 //! Under certain circumstances we will coerce from one type to another,
14 //! for example by auto-borrowing. This occurs in situations where the
15 //! compiler has a firm 'expected type' that was supplied from the user,
16 //! and where the actual type is similar to that expected type in purpose
17 //! but not in representation (so actual subtyping is inappropriate).
21 //! Note that if we are expecting a reference, we will *reborrow*
22 //! even if the argument provided was already a reference. This is
23 //! useful for freezing mut/const things (that is, when the expected is &T
24 //! but you have &const T or &mut T) and also for avoiding the linearity
25 //! of mut things (when the expected is &mut T and you have &mut T). See
26 //! the various `src/test/run-pass/coerce-reborrow-*.rs` tests for
27 //! examples of where this is useful.
31 //! When deciding what type coercions to consider, we do not attempt to
32 //! resolve any type variables we may encounter. This is because `b`
33 //! represents the expected type "as the user wrote it", meaning that if
34 //! the user defined a generic function like
36 //! fn foo<A>(a: A, b: A) { ... }
38 //! and then we wrote `foo(&1, @2)`, we will not auto-borrow
39 //! either argument. In older code we went to some lengths to
40 //! resolve the `b` variable, which could mean that we'd
41 //! auto-borrow later arguments but not earlier ones, which
42 //! seems very confusing.
46 //! However, right now, if the user manually specifies the
47 //! values for the type variables, as so:
49 //! foo::<&int>(@1, @2)
51 //! then we *will* auto-borrow, because we can't distinguish this from a
52 //! function that declared `&int`. This is inconsistent but it's easiest
53 //! at the moment. The right thing to do, I think, is to consider the
54 //! *unsubstituted* type when deciding whether to auto-borrow, but the
55 //! *substituted* type when considering the bounds and so forth. But most
56 //! of our methods don't give access to the unsubstituted type, and
57 //! rightly so because they'd be error-prone. So maybe the thing to do is
58 //! to actually determine the kind of coercions that should occur
59 //! separately and pass them in. Or maybe it's ok as is. Anyway, it's
60 //! sort of a minor point so I've opted to leave it for later---after all
61 //! we may want to adjust precisely when coercions occur.
66 use rustc::infer::{Coercion, InferOk, TypeOrigin, TypeTrace};
67 use rustc::traits::{self, ObligationCause};
68 use rustc::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef};
69 use rustc::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer};
70 use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
71 use rustc::ty::adjustment::AdjustNeverToAny;
72 use rustc::ty::{self, LvaluePreference, TypeAndMut, Ty};
73 use rustc::ty::fold::TypeFoldable;
74 use rustc::ty::error::TypeError;
75 use rustc::ty::relate::RelateResult;
76 use util::common::indent;
78 use std::cell::RefCell;
79 use std::collections::VecDeque;
82 struct Coerce<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
83 fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
86 unsizing_obligations: RefCell<Vec<traits::PredicateObligation<'tcx>>>,
89 impl<'a, 'gcx, 'tcx> Deref for Coerce<'a, 'gcx, 'tcx> {
90 type Target = FnCtxt<'a, 'gcx, 'tcx>;
91 fn deref(&self) -> &Self::Target {
96 type CoerceResult<'tcx> = RelateResult<'tcx, (Ty<'tcx>, AutoAdjustment<'tcx>)>;
98 fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
99 to_mutbl: hir::Mutability)
100 -> RelateResult<'tcx, ()> {
101 match (from_mutbl, to_mutbl) {
102 (hir::MutMutable, hir::MutMutable) |
103 (hir::MutImmutable, hir::MutImmutable) |
104 (hir::MutMutable, hir::MutImmutable) => Ok(()),
105 (hir::MutImmutable, hir::MutMutable) => Err(TypeError::Mutability)
109 impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
110 fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, origin: TypeOrigin) -> Self {
115 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 let trace = TypeTrace::types(self.origin, false, a, b);
123 self.lub(false, trace, &a, &b)
124 .map(|InferOk { value, obligations }| {
125 // FIXME(#32730) propagate obligations
126 assert!(obligations.is_empty());
130 self.sub(false, trace, &a, &b)
131 .map(|InferOk { value, obligations }| {
132 // FIXME(#32730) propagate obligations
133 assert!(obligations.is_empty());
140 /// Unify two types (using sub or lub) and produce a noop coercion.
141 fn unify_and_identity(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
142 self.unify(&a, &b).and_then(|ty| self.identity(ty))
145 /// Synthesize an identity adjustment.
146 fn identity(&self, ty: Ty<'tcx>) -> CoerceResult<'tcx> {
147 Ok((ty, AdjustDerefRef(AutoDerefRef {
154 fn coerce<'a, E, I>(&self,
158 -> CoerceResult<'tcx>
159 // FIXME(eddyb) use copyable iterators when that becomes ergonomic.
161 I: IntoIterator<Item=&'a hir::Expr> {
163 let a = self.shallow_resolve(a);
164 debug!("Coerce.tys({:?} => {:?})", a, b);
166 // Just ignore error types.
167 if a.references_error() || b.references_error() {
168 return self.identity(b);
172 return Ok((b, AdjustNeverToAny(b)));
175 // Consider coercing the subtype to a DST
176 let unsize = self.coerce_unsized(a, b);
181 // Examine the supertype and consider auto-borrowing.
183 // Note: does not attempt to resolve type variables we encounter.
184 // See above for details.
186 ty::TyRawPtr(mt_b) => {
187 return self.coerce_unsafe_ptr(a, b, mt_b.mutbl);
190 ty::TyRef(r_b, mt_b) => {
191 return self.coerce_borrowed_pointer(exprs, a, b, r_b, mt_b);
198 ty::TyFnDef(_, _, a_f) => {
199 // Function items are coercible to any closure
200 // type; function pointers are not (that would
201 // require double indirection).
202 self.coerce_from_fn_item(a, a_f, b)
204 ty::TyFnPtr(a_f) => {
205 // We permit coercion of fn pointers to drop the
207 self.coerce_from_fn_pointer(a, a_f, b)
210 // Otherwise, just use unification rules.
211 self.unify_and_identity(a, b)
216 /// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
217 /// To match `A` with `B`, autoderef will be performed,
218 /// calling `deref`/`deref_mut` where necessary.
219 fn coerce_borrowed_pointer<'a, E, I>(&self,
223 r_b: &'tcx ty::Region,
224 mt_b: TypeAndMut<'tcx>)
225 -> CoerceResult<'tcx>
226 // FIXME(eddyb) use copyable iterators when that becomes ergonomic.
228 I: IntoIterator<Item=&'a hir::Expr>
231 debug!("coerce_borrowed_pointer(a={:?}, b={:?})", a, b);
233 // If we have a parameter of type `&M T_a` and the value
234 // provided is `expr`, we will be adding an implicit borrow,
235 // meaning that we convert `f(expr)` to `f(&M *expr)`. Therefore,
236 // to type check, we will construct the type that `&M*expr` would
239 let (r_a, mt_a) = match a.sty {
240 ty::TyRef(r_a, mt_a) => {
241 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
244 _ => return self.unify_and_identity(a, b)
247 let span = self.origin.span();
249 let mut first_error = None;
250 let mut r_borrow_var = None;
251 let mut autoderef = self.autoderef(span, a);
252 let mut success = None;
254 for (referent_ty, autoderefs) in autoderef.by_ref() {
256 // Don't let this pass, otherwise it would cause
257 // &T to autoref to &&T.
261 // At this point, we have deref'd `a` to `referent_ty`. So
262 // imagine we are coercing from `&'a mut Vec<T>` to `&'b mut [T]`.
263 // In the autoderef loop for `&'a mut Vec<T>`, we would get
266 // - `&'a mut Vec<T>` -- 0 derefs, just ignore it
267 // - `Vec<T>` -- 1 deref
268 // - `[T]` -- 2 deref
270 // At each point after the first callback, we want to
271 // check to see whether this would match out target type
272 // (`&'b mut [T]`) if we autoref'd it. We can't just
273 // compare the referent types, though, because we still
274 // have to consider the mutability. E.g., in the case
275 // we've been considering, we have an `&mut` reference, so
276 // the `T` in `[T]` needs to be unified with equality.
278 // Therefore, we construct reference types reflecting what
279 // the types will be after we do the final auto-ref and
280 // compare those. Note that this means we use the target
281 // mutability [1], since it may be that we are coercing
282 // from `&mut T` to `&U`.
284 // One fine point concerns the region that we use. We
285 // choose the region such that the region of the final
286 // type that results from `unify` will be the region we
287 // want for the autoref:
289 // - if in sub mode, that means we want to use `'b` (the
290 // region from the target reference) for both
291 // pointers [2]. This is because sub mode (somewhat
292 // arbitrarily) returns the subtype region. In the case
293 // where we are coercing to a target type, we know we
294 // want to use that target type region (`'b`) because --
295 // for the program to type-check -- it must be the
296 // smaller of the two.
297 // - One fine point. It may be surprising that we can
298 // use `'b` without relating `'a` and `'b`. The reason
299 // that this is ok is that what we produce is
300 // effectively a `&'b *x` expression (if you could
301 // annotate the region of a borrow), and regionck has
302 // code that adds edges from the region of a borrow
303 // (`'b`, here) into the regions in the borrowed
304 // expression (`*x`, here). (Search for "link".)
305 // - if in lub mode, things can get fairly complicated. The
306 // easiest thing is just to make a fresh
307 // region variable [4], which effectively means we defer
308 // the decision to region inference (and regionck, which will add
309 // some more edges to this variable). However, this can wind up
310 // creating a crippling number of variables in some cases --
311 // e.g. #32278 -- so we optimize one particular case [3].
312 // Let me try to explain with some examples:
313 // - The "running example" above represents the simple case,
314 // where we have one `&` reference at the outer level and
315 // ownership all the rest of the way down. In this case,
316 // we want `LUB('a, 'b)` as the resulting region.
317 // - However, if there are nested borrows, that region is
318 // too strong. Consider a coercion from `&'a &'x Rc<T>` to
319 // `&'b T`. In this case, `'a` is actually irrelevant.
320 // The pointer we want is `LUB('x, 'b`). If we choose `LUB('a,'b)`
321 // we get spurious errors (`run-pass/regions-lub-ref-ref-rc.rs`).
322 // (The errors actually show up in borrowck, typically, because
323 // this extra edge causes the region `'a` to be inferred to something
324 // too big, which then results in borrowck errors.)
325 // - We could track the innermost shared reference, but there is already
326 // code in regionck that has the job of creating links between
327 // the region of a borrow and the regions in the thing being
328 // borrowed (here, `'a` and `'x`), and it knows how to handle
329 // all the various cases. So instead we just make a region variable
330 // and let regionck figure it out.
331 let r = if !self.use_lub {
333 } else if autoderefs == 1 {
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
341 r_borrow_var.unwrap()
343 let derefd_ty_a = self.tcx.mk_ref(r, TypeAndMut {
345 mutbl: mt_b.mutbl // [1] above
347 match self.unify(derefd_ty_a, b) {
348 Ok(ty) => { success = Some((ty, autoderefs)); break },
350 if first_error.is_none() {
351 first_error = Some(err);
357 // Extract type or return an error. We return the first error
358 // we got, which should be from relating the "base" type
359 // (e.g., in example above, the failure from relating `Vec<T>`
360 // to the target type), since that should be the least
362 let (ty, autoderefs) = match success {
365 let err = first_error.expect("coerce_borrowed_pointer had no error");
366 debug!("coerce_borrowed_pointer: failed with err = {:?}", err);
371 // This commits the obligations to the fulfillcx. After this succeeds,
372 // this snapshot can't be rolled back.
373 autoderef.finalize(LvaluePreference::from_mutbl(mt_b.mutbl), exprs());
375 // Now apply the autoref. We have to extract the region out of
376 // the final ref type we got.
377 if ty == a && mt_a.mutbl == hir::MutImmutable && autoderefs == 1 {
378 // As a special case, if we would produce `&'a *x`, that's
379 // a total no-op. We end up with the type `&'a T` just as
380 // we started with. In that case, just skip it
381 // altogether. This is just an optimization.
383 // Note that for `&mut`, we DO want to reborrow --
384 // otherwise, this would be a move, which might be an
385 // error. For example `foo(self.x)` where `self` and
386 // `self.x` both have `&mut `type would be a move of
387 // `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
388 // which is a borrow.
389 assert_eq!(mt_b.mutbl, hir::MutImmutable); // can only coerce &T -> &U
390 return self.identity(ty);
392 let r_borrow = match ty.sty {
393 ty::TyRef(r_borrow, _) => r_borrow,
394 _ => span_bug!(span, "expected a ref type, got {:?}", ty)
396 let autoref = Some(AutoPtr(r_borrow, mt_b.mutbl));
397 debug!("coerce_borrowed_pointer: succeeded ty={:?} autoderefs={:?} autoref={:?}",
398 ty, autoderefs, autoref);
399 Ok((ty, AdjustDerefRef(AutoDerefRef {
400 autoderefs: autoderefs,
407 // &[T; n] or &mut [T; n] -> &[T]
408 // or &mut [T; n] -> &mut [T]
409 // or &Concrete -> &Trait, etc.
410 fn coerce_unsized(&self,
413 -> CoerceResult<'tcx> {
414 debug!("coerce_unsized(source={:?}, target={:?})",
418 let traits = (self.tcx.lang_items.unsize_trait(),
419 self.tcx.lang_items.coerce_unsized_trait());
420 let (unsize_did, coerce_unsized_did) = if let (Some(u), Some(cu)) = traits {
423 debug!("Missing Unsize or CoerceUnsized traits");
424 return Err(TypeError::Mismatch);
427 // Note, we want to avoid unnecessary unsizing. We don't want to coerce to
428 // a DST unless we have to. This currently comes out in the wash since
429 // we can't unify [T] with U. But to properly support DST, we need to allow
430 // that, at which point we will need extra checks on the target here.
432 // Handle reborrows before selecting `Source: CoerceUnsized<Target>`.
433 let (source, reborrow) = match (&source.sty, &target.sty) {
434 (&ty::TyRef(_, mt_a), &ty::TyRef(_, mt_b)) => {
435 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
437 let coercion = Coercion(self.origin.span());
438 let r_borrow = self.next_region_var(coercion);
439 (mt_a.ty, Some(AutoPtr(r_borrow, mt_b.mutbl)))
441 (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) => {
442 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
443 (mt_a.ty, Some(AutoUnsafe(mt_b.mutbl)))
447 let source = source.adjust_for_autoref(self.tcx, reborrow);
449 let mut selcx = traits::SelectionContext::new(self);
451 // Use a FIFO queue for this custom fulfillment procedure.
452 let mut queue = VecDeque::new();
453 let mut leftover_predicates = vec![];
455 // Create an obligation for `Source: CoerceUnsized<Target>`.
456 let cause = ObligationCause::misc(self.origin.span(), self.body_id);
457 queue.push_back(self.tcx.predicate_for_trait_def(cause,
463 // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
464 // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
465 // inference might unify those two inner type variables later.
466 let traits = [coerce_unsized_did, unsize_did];
467 while let Some(obligation) = queue.pop_front() {
468 debug!("coerce_unsized resolve step: {:?}", obligation);
469 let trait_ref = match obligation.predicate {
470 ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
474 leftover_predicates.push(obligation);
478 match selcx.select(&obligation.with(trait_ref)) {
479 // Uncertain or unimplemented.
480 Ok(None) | Err(traits::Unimplemented) => {
481 debug!("coerce_unsized: early return - can't prove obligation");
482 return Err(TypeError::Mismatch);
485 // Object safety violations or miscellaneous.
487 self.report_selection_error(&obligation, &err, None);
488 // Treat this like an obligation and follow through
489 // with the unsizing - the lack of a coercion should
490 // be silent, as it causes a type mismatch later.
493 Ok(Some(vtable)) => {
494 for obligation in vtable.nested_obligations() {
495 queue.push_back(obligation);
501 *self.unsizing_obligations.borrow_mut() = leftover_predicates;
503 let adjustment = AutoDerefRef {
504 autoderefs: if reborrow.is_some() { 1 } else { 0 },
508 debug!("Success, coerced with {:?}", adjustment);
509 Ok((target, AdjustDerefRef(adjustment)))
512 fn coerce_from_fn_pointer(&self,
514 fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
516 -> CoerceResult<'tcx>
519 * Attempts to coerce from the type of a Rust function item
520 * into a closure or a `proc`.
523 let b = self.shallow_resolve(b);
524 debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
526 if let ty::TyFnPtr(fn_ty_b) = b.sty {
527 match (fn_ty_a.unsafety, fn_ty_b.unsafety) {
528 (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
529 let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
530 return self.unify_and_identity(unsafe_a, b).map(|(ty, _)| {
531 (ty, AdjustUnsafeFnPointer)
537 self.unify_and_identity(a, b)
540 fn coerce_from_fn_item(&self,
542 fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
544 -> CoerceResult<'tcx> {
546 * Attempts to coerce from the type of a Rust function item
547 * into a closure or a `proc`.
550 let b = self.shallow_resolve(b);
551 debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
555 let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a);
556 self.unify_and_identity(a_fn_pointer, b).map(|(ty, _)| {
557 (ty, AdjustReifyFnPointer)
560 _ => self.unify_and_identity(a, b)
564 fn coerce_unsafe_ptr(&self,
567 mutbl_b: hir::Mutability)
568 -> CoerceResult<'tcx> {
569 debug!("coerce_unsafe_ptr(a={:?}, b={:?})",
573 let (is_ref, mt_a) = match a.sty {
574 ty::TyRef(_, mt) => (true, mt),
575 ty::TyRawPtr(mt) => (false, mt),
577 return self.unify_and_identity(a, b);
581 // Check that the types which they point at are compatible.
582 let a_unsafe = self.tcx.mk_ptr(ty::TypeAndMut{ mutbl: mutbl_b, ty: mt_a.ty });
583 let (ty, noop) = self.unify_and_identity(a_unsafe, b)?;
584 coerce_mutbls(mt_a.mutbl, mutbl_b)?;
586 // Although references and unsafe ptrs have the same
587 // representation, we still register an AutoDerefRef so that
588 // regionck knows that the region for `a` must be valid here.
590 AdjustDerefRef(AutoDerefRef {
592 autoref: Some(AutoUnsafe(mutbl_b)),
595 } else if mt_a.mutbl != mutbl_b {
596 AdjustMutToConstPointer
603 fn apply<'a, 'b, 'gcx, 'tcx, E, I>(coerce: &mut Coerce<'a, 'gcx, 'tcx>,
607 -> CoerceResult<'tcx>
609 I: IntoIterator<Item=&'b hir::Expr> {
611 let (ty, adjustment) = indent(|| coerce.coerce(exprs, a, b))?;
613 let fcx = coerce.fcx;
614 if let AdjustDerefRef(auto) = adjustment {
615 if auto.unsize.is_some() {
616 let mut obligations = coerce.unsizing_obligations.borrow_mut();
617 for obligation in obligations.drain(..) {
618 fcx.register_predicate(obligation);
626 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
627 /// Attempt to coerce an expression to a type, and return the
628 /// adjusted type of the expression, if successful.
629 /// Adjustments are only recorded if the coercion succeeded.
630 /// The expressions *must not* have any pre-existing adjustments.
631 pub fn try_coerce(&self,
634 -> RelateResult<'tcx, Ty<'tcx>> {
635 let source = self.resolve_type_vars_with_obligations(self.expr_ty(expr));
636 debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
638 let mut coerce = Coerce::new(self, TypeOrigin::ExprAssignable(expr.span));
639 self.commit_if_ok(|_| {
640 let (ty, adjustment) =
641 apply(&mut coerce, &|| Some(expr), source, target)?;
642 if !adjustment.is_identity() {
643 debug!("Success, coerced with {:?}", adjustment);
644 match self.tables.borrow().adjustments.get(&expr.id) {
645 None | Some(&AdjustNeverToAny(..)) => (),
646 _ => bug!("expr already has an adjustment on it!"),
648 self.write_adjustment(expr.id, adjustment);
654 /// Given some expressions, their known unified type and another expression,
655 /// tries to unify the types, potentially inserting coercions on any of the
656 /// provided expressions and returns their LUB (aka "common supertype").
657 pub fn try_find_coercion_lub<'b, E, I>(&self,
662 -> RelateResult<'tcx, Ty<'tcx>>
663 // FIXME(eddyb) use copyable iterators when that becomes ergonomic.
665 I: IntoIterator<Item=&'b hir::Expr> {
667 let prev_ty = self.resolve_type_vars_with_obligations(prev_ty);
668 let new_ty = self.resolve_type_vars_with_obligations(self.expr_ty(new));
669 debug!("coercion::try_find_lub({:?}, {:?})", prev_ty, new_ty);
671 let trace = TypeTrace::types(origin, true, prev_ty, new_ty);
673 // Special-case that coercion alone cannot handle:
674 // Two function item types of differing IDs or Substs.
675 match (&prev_ty.sty, &new_ty.sty) {
676 (&ty::TyFnDef(a_def_id, a_substs, a_fty),
677 &ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
678 // The signature must always match.
679 let fty = self.lub(true, trace.clone(), &a_fty, &b_fty)
680 .map(|InferOk { value, obligations }| {
681 // FIXME(#32730) propagate obligations
682 assert!(obligations.is_empty());
686 if a_def_id == b_def_id {
687 // Same function, maybe the parameters match.
688 let substs = self.commit_if_ok(|_| {
689 self.lub(true, trace.clone(), &a_substs, &b_substs)
690 .map(|InferOk { value, obligations }| {
691 // FIXME(#32730) propagate obligations
692 assert!(obligations.is_empty());
697 if let Ok(substs) = substs {
698 // We have a LUB of prev_ty and new_ty, just return it.
699 return Ok(self.tcx.mk_fn_def(a_def_id, substs, fty));
703 // Reify both sides and return the reified fn pointer type.
704 for expr in exprs().into_iter().chain(Some(new)) {
705 // No adjustments can produce a fn item, so this should never trip.
706 assert!(!self.tables.borrow().adjustments.contains_key(&expr.id));
707 self.write_adjustment(expr.id, AdjustReifyFnPointer);
709 return Ok(self.tcx.mk_fn_ptr(fty));
714 let mut coerce = Coerce::new(self, origin);
715 coerce.use_lub = true;
717 // First try to coerce the new expression to the type of the previous ones,
718 // but only if the new expression has no coercion already applied to it.
719 let mut first_error = None;
720 if !self.tables.borrow().adjustments.contains_key(&new.id) {
721 let result = self.commit_if_ok(|_| {
722 apply(&mut coerce, &|| Some(new), new_ty, prev_ty)
725 Ok((ty, adjustment)) => {
726 if !adjustment.is_identity() {
727 self.write_adjustment(new.id, adjustment);
731 Err(e) => first_error = Some(e)
735 // Then try to coerce the previous expressions to the type of the new one.
736 // This requires ensuring there are no coercions applied to *any* of the
737 // previous expressions, other than noop reborrows (ignoring lifetimes).
738 for expr in exprs() {
739 let noop = match self.tables.borrow().adjustments.get(&expr.id) {
740 Some(&AdjustDerefRef(AutoDerefRef {
742 autoref: Some(AutoPtr(_, mutbl_adj)),
744 })) => match self.expr_ty(expr).sty {
745 ty::TyRef(_, mt_orig) => {
746 // Reborrow that we can safely ignore.
747 mutbl_adj == mt_orig.mutbl
751 Some(&AdjustNeverToAny(_)) => true,
757 return self.commit_if_ok(|_| {
758 self.lub(true, trace.clone(), &prev_ty, &new_ty)
759 .map(|InferOk { value, obligations }| {
760 // FIXME(#32730) propagate obligations
761 assert!(obligations.is_empty());
768 match self.commit_if_ok(|_| apply(&mut coerce, &exprs, prev_ty, new_ty)) {
770 // Avoid giving strange errors on failed attempts.
771 if let Some(e) = first_error {
774 self.commit_if_ok(|_| {
775 self.lub(true, trace, &prev_ty, &new_ty)
776 .map(|InferOk { value, obligations }| {
777 // FIXME(#32730) propagate obligations
778 assert!(obligations.is_empty());
784 Ok((ty, adjustment)) => {
785 if !adjustment.is_identity() {
786 for expr in exprs() {
787 let previous = self.tables.borrow().adjustments.get(&expr.id).cloned();
788 if let Some(AdjustNeverToAny(_)) = previous {
789 self.write_adjustment(expr.id, AdjustNeverToAny(ty));
791 self.write_adjustment(expr.id, adjustment);