]> git.lizzy.rs Git - rust.git/blob - crates/hir-ty/src/infer/coerce.rs
rustc_typeck to rustc_hir_analysis
[rust.git] / crates / hir-ty / src / infer / coerce.rs
1 //! Coercion logic. Coercions are certain type conversions that can implicitly
2 //! happen in certain places, e.g. weakening `&mut` to `&` or deref coercions
3 //! like going from `&Vec<T>` to `&[T]`.
4 //!
5 //! See <https://doc.rust-lang.org/nomicon/coercions.html> and
6 //! `rustc_hir_analysis/check/coercion.rs`.
7
8 use std::{iter, sync::Arc};
9
10 use chalk_ir::{cast::Cast, BoundVar, Goal, Mutability, TyVariableKind};
11 use hir_def::{expr::ExprId, lang_item::LangItemTarget};
12 use stdx::always;
13 use syntax::SmolStr;
14
15 use crate::{
16     autoderef::{Autoderef, AutoderefKind},
17     db::HirDatabase,
18     infer::{
19         Adjust, Adjustment, AutoBorrow, InferOk, InferenceContext, OverloadedDeref, PointerCast,
20         TypeError, TypeMismatch,
21     },
22     static_lifetime, Canonical, DomainGoal, FnPointer, FnSig, Guidance, InEnvironment, Interner,
23     Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind,
24 };
25
26 use super::unify::InferenceTable;
27
28 pub(crate) type CoerceResult = Result<InferOk<(Vec<Adjustment>, Ty)>, TypeError>;
29
30 /// Do not require any adjustments, i.e. coerce `x -> x`.
31 fn identity(_: Ty) -> Vec<Adjustment> {
32     vec![]
33 }
34
35 fn simple(kind: Adjust) -> impl FnOnce(Ty) -> Vec<Adjustment> {
36     move |target| vec![Adjustment { kind, target }]
37 }
38
39 /// This always returns `Ok(...)`.
40 fn success(
41     adj: Vec<Adjustment>,
42     target: Ty,
43     goals: Vec<InEnvironment<Goal<Interner>>>,
44 ) -> CoerceResult {
45     Ok(InferOk { goals, value: (adj, target) })
46 }
47
48 #[derive(Clone, Debug)]
49 pub(super) struct CoerceMany {
50     expected_ty: Ty,
51 }
52
53 impl CoerceMany {
54     pub(super) fn new(expected: Ty) -> Self {
55         CoerceMany { expected_ty: expected }
56     }
57
58     /// Merge two types from different branches, with possible coercion.
59     ///
60     /// Mostly this means trying to coerce one to the other, but
61     ///  - if we have two function types for different functions or closures, we need to
62     ///    coerce both to function pointers;
63     ///  - if we were concerned with lifetime subtyping, we'd need to look for a
64     ///    least upper bound.
65     pub(super) fn coerce(
66         &mut self,
67         ctx: &mut InferenceContext<'_>,
68         expr: Option<ExprId>,
69         expr_ty: &Ty,
70     ) {
71         let expr_ty = ctx.resolve_ty_shallow(expr_ty);
72         self.expected_ty = ctx.resolve_ty_shallow(&self.expected_ty);
73
74         // Special case: two function types. Try to coerce both to
75         // pointers to have a chance at getting a match. See
76         // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916
77         let sig = match (self.expected_ty.kind(Interner), expr_ty.kind(Interner)) {
78             (TyKind::FnDef(..) | TyKind::Closure(..), TyKind::FnDef(..) | TyKind::Closure(..)) => {
79                 // FIXME: we're ignoring safety here. To be more correct, if we have one FnDef and one Closure,
80                 // we should be coercing the closure to a fn pointer of the safety of the FnDef
81                 cov_mark::hit!(coerce_fn_reification);
82                 let sig =
83                     self.expected_ty.callable_sig(ctx.db).expect("FnDef without callable sig");
84                 Some(sig)
85             }
86             _ => None,
87         };
88         if let Some(sig) = sig {
89             let target_ty = TyKind::Function(sig.to_fn_ptr()).intern(Interner);
90             let result1 = ctx.table.coerce_inner(self.expected_ty.clone(), &target_ty);
91             let result2 = ctx.table.coerce_inner(expr_ty.clone(), &target_ty);
92             if let (Ok(result1), Ok(result2)) = (result1, result2) {
93                 ctx.table.register_infer_ok(result1);
94                 ctx.table.register_infer_ok(result2);
95                 return self.expected_ty = target_ty;
96             }
97         }
98
99         // It might not seem like it, but order is important here: If the expected
100         // type is a type variable and the new one is `!`, trying it the other
101         // way around first would mean we make the type variable `!`, instead of
102         // just marking it as possibly diverging.
103         if ctx.coerce(expr, &expr_ty, &self.expected_ty).is_ok() {
104             /* self.expected_ty is already correct */
105         } else if ctx.coerce(expr, &self.expected_ty, &expr_ty).is_ok() {
106             self.expected_ty = expr_ty;
107         } else {
108             if let Some(id) = expr {
109                 ctx.result.type_mismatches.insert(
110                     id.into(),
111                     TypeMismatch { expected: self.expected_ty.clone(), actual: expr_ty },
112                 );
113             }
114             cov_mark::hit!(coerce_merge_fail_fallback);
115             /* self.expected_ty is already correct */
116         }
117     }
118
119     pub(super) fn complete(self) -> Ty {
120         self.expected_ty
121     }
122 }
123
124 pub fn could_coerce(
125     db: &dyn HirDatabase,
126     env: Arc<TraitEnvironment>,
127     tys: &Canonical<(Ty, Ty)>,
128 ) -> bool {
129     coerce(db, env, tys).is_ok()
130 }
131
132 pub(crate) fn coerce(
133     db: &dyn HirDatabase,
134     env: Arc<TraitEnvironment>,
135     tys: &Canonical<(Ty, Ty)>,
136 ) -> Result<(Vec<Adjustment>, Ty), TypeError> {
137     let mut table = InferenceTable::new(db, env);
138     let vars = table.fresh_subst(tys.binders.as_slice(Interner));
139     let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner);
140     let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner);
141     let (adjustments, ty) = table.coerce(&ty1_with_vars, &ty2_with_vars)?;
142     // default any type vars that weren't unified back to their original bound vars
143     // (kind of hacky)
144     let find_var = |iv| {
145         vars.iter(Interner).position(|v| match v.interned() {
146             chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(Interner),
147             chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(Interner),
148             chalk_ir::GenericArgData::Const(c) => c.inference_var(Interner),
149         } == Some(iv))
150     };
151     let fallback = |iv, kind, default, binder| match kind {
152         chalk_ir::VariableKind::Ty(_ty_kind) => find_var(iv)
153             .map_or(default, |i| BoundVar::new(binder, i).to_ty(Interner).cast(Interner)),
154         chalk_ir::VariableKind::Lifetime => find_var(iv)
155             .map_or(default, |i| BoundVar::new(binder, i).to_lifetime(Interner).cast(Interner)),
156         chalk_ir::VariableKind::Const(ty) => find_var(iv)
157             .map_or(default, |i| BoundVar::new(binder, i).to_const(Interner, ty).cast(Interner)),
158     };
159     // FIXME also map the types in the adjustments
160     Ok((adjustments, table.resolve_with_fallback(ty, &fallback)))
161 }
162
163 impl<'a> InferenceContext<'a> {
164     /// Unify two types, but may coerce the first one to the second one
165     /// using "implicit coercion rules" if needed.
166     pub(super) fn coerce(
167         &mut self,
168         expr: Option<ExprId>,
169         from_ty: &Ty,
170         to_ty: &Ty,
171     ) -> Result<Ty, TypeError> {
172         let from_ty = self.resolve_ty_shallow(from_ty);
173         let to_ty = self.resolve_ty_shallow(to_ty);
174         let (adjustments, ty) = self.table.coerce(&from_ty, &to_ty)?;
175         if let Some(expr) = expr {
176             self.write_expr_adj(expr, adjustments);
177         }
178         Ok(ty)
179     }
180 }
181
182 impl<'a> InferenceTable<'a> {
183     /// Unify two types, but may coerce the first one to the second one
184     /// using "implicit coercion rules" if needed.
185     pub(crate) fn coerce(
186         &mut self,
187         from_ty: &Ty,
188         to_ty: &Ty,
189     ) -> Result<(Vec<Adjustment>, Ty), TypeError> {
190         let from_ty = self.resolve_ty_shallow(from_ty);
191         let to_ty = self.resolve_ty_shallow(to_ty);
192         match self.coerce_inner(from_ty, &to_ty) {
193             Ok(InferOk { value: (adjustments, ty), goals }) => {
194                 self.register_infer_ok(InferOk { value: (), goals });
195                 Ok((adjustments, ty))
196             }
197             Err(e) => {
198                 // FIXME deal with error
199                 Err(e)
200             }
201         }
202     }
203
204     fn coerce_inner(&mut self, from_ty: Ty, to_ty: &Ty) -> CoerceResult {
205         if from_ty.is_never() {
206             // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
207             // type variable, we want `?T` to fallback to `!` if not
208             // otherwise constrained. An example where this arises:
209             //
210             //     let _: Option<?T> = Some({ return; });
211             //
212             // here, we would coerce from `!` to `?T`.
213             if let TyKind::InferenceVar(tv, TyVariableKind::General) = to_ty.kind(Interner) {
214                 self.set_diverging(*tv, true);
215             }
216             return success(simple(Adjust::NeverToAny)(to_ty.clone()), to_ty.clone(), vec![]);
217         }
218
219         // Consider coercing the subtype to a DST
220         if let Ok(ret) = self.try_coerce_unsized(&from_ty, to_ty) {
221             return Ok(ret);
222         }
223
224         // Examine the supertype and consider auto-borrowing.
225         match to_ty.kind(Interner) {
226             TyKind::Raw(mt, _) => return self.coerce_ptr(from_ty, to_ty, *mt),
227             TyKind::Ref(mt, _, _) => return self.coerce_ref(from_ty, to_ty, *mt),
228             _ => {}
229         }
230
231         match from_ty.kind(Interner) {
232             TyKind::FnDef(..) => {
233                 // Function items are coercible to any closure
234                 // type; function pointers are not (that would
235                 // require double indirection).
236                 // Additionally, we permit coercion of function
237                 // items to drop the unsafe qualifier.
238                 self.coerce_from_fn_item(from_ty, to_ty)
239             }
240             TyKind::Function(from_fn_ptr) => {
241                 // We permit coercion of fn pointers to drop the
242                 // unsafe qualifier.
243                 self.coerce_from_fn_pointer(from_ty.clone(), from_fn_ptr, to_ty)
244             }
245             TyKind::Closure(_, from_substs) => {
246                 // Non-capturing closures are coercible to
247                 // function pointers or unsafe function pointers.
248                 // It cannot convert closures that require unsafe.
249                 self.coerce_closure_to_fn(from_ty.clone(), from_substs, to_ty)
250             }
251             _ => {
252                 // Otherwise, just use unification rules.
253                 self.unify_and(&from_ty, to_ty, identity)
254             }
255         }
256     }
257
258     /// Unify two types (using sub or lub) and produce a specific coercion.
259     fn unify_and<F>(&mut self, t1: &Ty, t2: &Ty, f: F) -> CoerceResult
260     where
261         F: FnOnce(Ty) -> Vec<Adjustment>,
262     {
263         self.try_unify(t1, t2)
264             .and_then(|InferOk { goals, .. }| success(f(t1.clone()), t1.clone(), goals))
265     }
266
267     fn coerce_ptr(&mut self, from_ty: Ty, to_ty: &Ty, to_mt: Mutability) -> CoerceResult {
268         let (is_ref, from_mt, from_inner) = match from_ty.kind(Interner) {
269             TyKind::Ref(mt, _, ty) => (true, mt, ty),
270             TyKind::Raw(mt, ty) => (false, mt, ty),
271             _ => return self.unify_and(&from_ty, to_ty, identity),
272         };
273
274         coerce_mutabilities(*from_mt, to_mt)?;
275
276         // Check that the types which they point at are compatible.
277         let from_raw = TyKind::Raw(to_mt, from_inner.clone()).intern(Interner);
278
279         // Although references and unsafe ptrs have the same
280         // representation, we still register an Adjust::DerefRef so that
281         // regionck knows that the region for `a` must be valid here.
282         if is_ref {
283             self.unify_and(&from_raw, to_ty, |target| {
284                 vec![
285                     Adjustment { kind: Adjust::Deref(None), target: from_inner.clone() },
286                     Adjustment { kind: Adjust::Borrow(AutoBorrow::RawPtr(to_mt)), target },
287                 ]
288             })
289         } else if *from_mt != to_mt {
290             self.unify_and(
291                 &from_raw,
292                 to_ty,
293                 simple(Adjust::Pointer(PointerCast::MutToConstPointer)),
294             )
295         } else {
296             self.unify_and(&from_raw, to_ty, identity)
297         }
298     }
299
300     /// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
301     /// To match `A` with `B`, autoderef will be performed,
302     /// calling `deref`/`deref_mut` where necessary.
303     fn coerce_ref(&mut self, from_ty: Ty, to_ty: &Ty, to_mt: Mutability) -> CoerceResult {
304         let from_mt = match from_ty.kind(Interner) {
305             &TyKind::Ref(mt, _, _) => {
306                 coerce_mutabilities(mt, to_mt)?;
307                 mt
308             }
309             _ => return self.unify_and(&from_ty, to_ty, identity),
310         };
311
312         // NOTE: this code is mostly copied and adapted from rustc, and
313         // currently more complicated than necessary, carrying errors around
314         // etc.. This complication will become necessary when we actually track
315         // details of coercion errors though, so I think it's useful to leave
316         // the structure like it is.
317
318         let snapshot = self.snapshot();
319
320         let mut autoderef = Autoderef::new(self, from_ty.clone());
321         let mut first_error = None;
322         let mut found = None;
323
324         while let Some((referent_ty, autoderefs)) = autoderef.next() {
325             if autoderefs == 0 {
326                 // Don't let this pass, otherwise it would cause
327                 // &T to autoref to &&T.
328                 continue;
329             }
330
331             // At this point, we have deref'd `a` to `referent_ty`.  So
332             // imagine we are coercing from `&'a mut Vec<T>` to `&'b mut [T]`.
333             // In the autoderef loop for `&'a mut Vec<T>`, we would get
334             // three callbacks:
335             //
336             // - `&'a mut Vec<T>` -- 0 derefs, just ignore it
337             // - `Vec<T>` -- 1 deref
338             // - `[T]` -- 2 deref
339             //
340             // At each point after the first callback, we want to
341             // check to see whether this would match out target type
342             // (`&'b mut [T]`) if we autoref'd it. We can't just
343             // compare the referent types, though, because we still
344             // have to consider the mutability. E.g., in the case
345             // we've been considering, we have an `&mut` reference, so
346             // the `T` in `[T]` needs to be unified with equality.
347             //
348             // Therefore, we construct reference types reflecting what
349             // the types will be after we do the final auto-ref and
350             // compare those. Note that this means we use the target
351             // mutability [1], since it may be that we are coercing
352             // from `&mut T` to `&U`.
353             let lt = static_lifetime(); // FIXME: handle lifetimes correctly, see rustc
354             let derefd_from_ty = TyKind::Ref(to_mt, lt, referent_ty).intern(Interner);
355             match autoderef.table.try_unify(&derefd_from_ty, to_ty) {
356                 Ok(result) => {
357                     found = Some(result.map(|()| derefd_from_ty));
358                     break;
359                 }
360                 Err(err) => {
361                     if first_error.is_none() {
362                         first_error = Some(err);
363                     }
364                 }
365             }
366         }
367
368         // Extract type or return an error. We return the first error
369         // we got, which should be from relating the "base" type
370         // (e.g., in example above, the failure from relating `Vec<T>`
371         // to the target type), since that should be the least
372         // confusing.
373         let InferOk { value: ty, goals } = match found {
374             Some(d) => d,
375             None => {
376                 self.rollback_to(snapshot);
377                 let err = first_error.expect("coerce_borrowed_pointer had no error");
378                 return Err(err);
379             }
380         };
381         if ty == from_ty && from_mt == Mutability::Not && autoderef.step_count() == 1 {
382             // As a special case, if we would produce `&'a *x`, that's
383             // a total no-op. We end up with the type `&'a T` just as
384             // we started with.  In that case, just skip it
385             // altogether. This is just an optimization.
386             //
387             // Note that for `&mut`, we DO want to reborrow --
388             // otherwise, this would be a move, which might be an
389             // error. For example `foo(self.x)` where `self` and
390             // `self.x` both have `&mut `type would be a move of
391             // `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
392             // which is a borrow.
393             always!(to_mt == Mutability::Not); // can only coerce &T -> &U
394             return success(vec![], ty, goals);
395         }
396
397         let mut adjustments = auto_deref_adjust_steps(&autoderef);
398         adjustments
399             .push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(to_mt)), target: ty.clone() });
400
401         success(adjustments, ty, goals)
402     }
403
404     /// Attempts to coerce from the type of a Rust function item into a function pointer.
405     fn coerce_from_fn_item(&mut self, from_ty: Ty, to_ty: &Ty) -> CoerceResult {
406         match to_ty.kind(Interner) {
407             TyKind::Function(_) => {
408                 let from_sig = from_ty.callable_sig(self.db).expect("FnDef had no sig");
409
410                 // FIXME check ABI: Intrinsics are not coercible to function pointers
411                 // FIXME Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396)
412
413                 // FIXME rustc normalizes assoc types in the sig here, not sure if necessary
414
415                 let from_sig = from_sig.to_fn_ptr();
416                 let from_fn_pointer = TyKind::Function(from_sig.clone()).intern(Interner);
417                 let ok = self.coerce_from_safe_fn(
418                     from_fn_pointer.clone(),
419                     &from_sig,
420                     to_ty,
421                     |unsafe_ty| {
422                         vec![
423                             Adjustment {
424                                 kind: Adjust::Pointer(PointerCast::ReifyFnPointer),
425                                 target: from_fn_pointer,
426                             },
427                             Adjustment {
428                                 kind: Adjust::Pointer(PointerCast::UnsafeFnPointer),
429                                 target: unsafe_ty,
430                             },
431                         ]
432                     },
433                     simple(Adjust::Pointer(PointerCast::ReifyFnPointer)),
434                 )?;
435
436                 Ok(ok)
437             }
438             _ => self.unify_and(&from_ty, to_ty, identity),
439         }
440     }
441
442     fn coerce_from_fn_pointer(
443         &mut self,
444         from_ty: Ty,
445         from_f: &FnPointer,
446         to_ty: &Ty,
447     ) -> CoerceResult {
448         self.coerce_from_safe_fn(
449             from_ty,
450             from_f,
451             to_ty,
452             simple(Adjust::Pointer(PointerCast::UnsafeFnPointer)),
453             identity,
454         )
455     }
456
457     fn coerce_from_safe_fn<F, G>(
458         &mut self,
459         from_ty: Ty,
460         from_fn_ptr: &FnPointer,
461         to_ty: &Ty,
462         to_unsafe: F,
463         normal: G,
464     ) -> CoerceResult
465     where
466         F: FnOnce(Ty) -> Vec<Adjustment>,
467         G: FnOnce(Ty) -> Vec<Adjustment>,
468     {
469         if let TyKind::Function(to_fn_ptr) = to_ty.kind(Interner) {
470             if let (chalk_ir::Safety::Safe, chalk_ir::Safety::Unsafe) =
471                 (from_fn_ptr.sig.safety, to_fn_ptr.sig.safety)
472             {
473                 let from_unsafe =
474                     TyKind::Function(safe_to_unsafe_fn_ty(from_fn_ptr.clone())).intern(Interner);
475                 return self.unify_and(&from_unsafe, to_ty, to_unsafe);
476             }
477         }
478         self.unify_and(&from_ty, to_ty, normal)
479     }
480
481     /// Attempts to coerce from the type of a non-capturing closure into a
482     /// function pointer.
483     fn coerce_closure_to_fn(
484         &mut self,
485         from_ty: Ty,
486         from_substs: &Substitution,
487         to_ty: &Ty,
488     ) -> CoerceResult {
489         match to_ty.kind(Interner) {
490             // if from_substs is non-capturing (FIXME)
491             TyKind::Function(fn_ty) => {
492                 // We coerce the closure, which has fn type
493                 //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
494                 // to
495                 //     `fn(arg0,arg1,...) -> _`
496                 // or
497                 //     `unsafe fn(arg0,arg1,...) -> _`
498                 let safety = fn_ty.sig.safety;
499                 let pointer_ty = coerce_closure_fn_ty(from_substs, safety);
500                 self.unify_and(
501                     &pointer_ty,
502                     to_ty,
503                     simple(Adjust::Pointer(PointerCast::ClosureFnPointer(safety))),
504                 )
505             }
506             _ => self.unify_and(&from_ty, to_ty, identity),
507         }
508     }
509
510     /// Coerce a type using `from_ty: CoerceUnsized<ty_ty>`
511     ///
512     /// See: <https://doc.rust-lang.org/nightly/std/marker/trait.CoerceUnsized.html>
513     fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty) -> CoerceResult {
514         // These 'if' statements require some explanation.
515         // The `CoerceUnsized` trait is special - it is only
516         // possible to write `impl CoerceUnsized<B> for A` where
517         // A and B have 'matching' fields. This rules out the following
518         // two types of blanket impls:
519         //
520         // `impl<T> CoerceUnsized<T> for SomeType`
521         // `impl<T> CoerceUnsized<SomeType> for T`
522         //
523         // Both of these trigger a special `CoerceUnsized`-related error (E0376)
524         //
525         // We can take advantage of this fact to avoid performing unnecessary work.
526         // If either `source` or `target` is a type variable, then any applicable impl
527         // would need to be generic over the self-type (`impl<T> CoerceUnsized<SomeType> for T`)
528         // or generic over the `CoerceUnsized` type parameter (`impl<T> CoerceUnsized<T> for
529         // SomeType`).
530         //
531         // However, these are exactly the kinds of impls which are forbidden by
532         // the compiler! Therefore, we can be sure that coercion will always fail
533         // when either the source or target type is a type variable. This allows us
534         // to skip performing any trait selection, and immediately bail out.
535         if from_ty.is_ty_var() {
536             return Err(TypeError);
537         }
538         if to_ty.is_ty_var() {
539             return Err(TypeError);
540         }
541
542         // Handle reborrows before trying to solve `Source: CoerceUnsized<Target>`.
543         let reborrow = match (from_ty.kind(Interner), to_ty.kind(Interner)) {
544             (TyKind::Ref(from_mt, _, from_inner), &TyKind::Ref(to_mt, _, _)) => {
545                 coerce_mutabilities(*from_mt, to_mt)?;
546
547                 let lt = static_lifetime();
548                 Some((
549                     Adjustment { kind: Adjust::Deref(None), target: from_inner.clone() },
550                     Adjustment {
551                         kind: Adjust::Borrow(AutoBorrow::Ref(to_mt)),
552                         target: TyKind::Ref(to_mt, lt, from_inner.clone()).intern(Interner),
553                     },
554                 ))
555             }
556             (TyKind::Ref(from_mt, _, from_inner), &TyKind::Raw(to_mt, _)) => {
557                 coerce_mutabilities(*from_mt, to_mt)?;
558
559                 Some((
560                     Adjustment { kind: Adjust::Deref(None), target: from_inner.clone() },
561                     Adjustment {
562                         kind: Adjust::Borrow(AutoBorrow::RawPtr(to_mt)),
563                         target: TyKind::Raw(to_mt, from_inner.clone()).intern(Interner),
564                     },
565                 ))
566             }
567             _ => None,
568         };
569         let coerce_from =
570             reborrow.as_ref().map_or_else(|| from_ty.clone(), |(_, adj)| adj.target.clone());
571
572         let krate = self.trait_env.krate;
573         let coerce_unsized_trait =
574             match self.db.lang_item(krate, SmolStr::new_inline("coerce_unsized")) {
575                 Some(LangItemTarget::TraitId(trait_)) => trait_,
576                 _ => return Err(TypeError),
577             };
578
579         let coerce_unsized_tref = {
580             let b = TyBuilder::trait_ref(self.db, coerce_unsized_trait);
581             if b.remaining() != 2 {
582                 // The CoerceUnsized trait should have two generic params: Self and T.
583                 return Err(TypeError);
584             }
585             b.push(coerce_from).push(to_ty.clone()).build()
586         };
587
588         let goal: InEnvironment<DomainGoal> =
589             InEnvironment::new(&self.trait_env.env, coerce_unsized_tref.cast(Interner));
590
591         let canonicalized = self.canonicalize(goal);
592
593         // FIXME: rustc's coerce_unsized is more specialized -- it only tries to
594         // solve `CoerceUnsized` and `Unsize` goals at this point and leaves the
595         // rest for later. Also, there's some logic about sized type variables.
596         // Need to find out in what cases this is necessary
597         let solution = self
598             .db
599             .trait_solve(krate, canonicalized.value.clone().cast(Interner))
600             .ok_or(TypeError)?;
601
602         match solution {
603             Solution::Unique(v) => {
604                 canonicalized.apply_solution(
605                     self,
606                     Canonical {
607                         binders: v.binders,
608                         // FIXME handle constraints
609                         value: v.value.subst,
610                     },
611                 );
612             }
613             Solution::Ambig(Guidance::Definite(subst)) => {
614                 // FIXME need to record an obligation here
615                 canonicalized.apply_solution(self, subst)
616             }
617             // FIXME actually we maybe should also accept unknown guidance here
618             _ => return Err(TypeError),
619         };
620         let unsize =
621             Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), target: to_ty.clone() };
622         let adjustments = match reborrow {
623             None => vec![unsize],
624             Some((deref, autoref)) => vec![deref, autoref, unsize],
625         };
626         success(adjustments, to_ty.clone(), vec![])
627     }
628 }
629
630 fn coerce_closure_fn_ty(closure_substs: &Substitution, safety: chalk_ir::Safety) -> Ty {
631     let closure_sig = closure_substs.at(Interner, 0).assert_ty_ref(Interner).clone();
632     match closure_sig.kind(Interner) {
633         TyKind::Function(fn_ty) => TyKind::Function(FnPointer {
634             num_binders: fn_ty.num_binders,
635             sig: FnSig { safety, ..fn_ty.sig },
636             substitution: fn_ty.substitution.clone(),
637         })
638         .intern(Interner),
639         _ => TyKind::Error.intern(Interner),
640     }
641 }
642
643 fn safe_to_unsafe_fn_ty(fn_ty: FnPointer) -> FnPointer {
644     FnPointer {
645         num_binders: fn_ty.num_binders,
646         sig: FnSig { safety: chalk_ir::Safety::Unsafe, ..fn_ty.sig },
647         substitution: fn_ty.substitution,
648     }
649 }
650
651 fn coerce_mutabilities(from: Mutability, to: Mutability) -> Result<(), TypeError> {
652     match (from, to) {
653         (Mutability::Mut, Mutability::Mut | Mutability::Not)
654         | (Mutability::Not, Mutability::Not) => Ok(()),
655         (Mutability::Not, Mutability::Mut) => Err(TypeError),
656     }
657 }
658
659 pub(super) fn auto_deref_adjust_steps(autoderef: &Autoderef<'_, '_>) -> Vec<Adjustment> {
660     let steps = autoderef.steps();
661     let targets =
662         steps.iter().skip(1).map(|(_, ty)| ty.clone()).chain(iter::once(autoderef.final_ty()));
663     steps
664         .iter()
665         .map(|(kind, _source)| match kind {
666             // We do not know what kind of deref we require at this point yet
667             AutoderefKind::Overloaded => Some(OverloadedDeref(Mutability::Not)),
668             AutoderefKind::Builtin => None,
669         })
670         .zip(targets)
671         .map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target })
672         .collect()
673 }