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]`.
5 //! See <https://doc.rust-lang.org/nomicon/coercions.html> and
6 //! `rustc_hir_analysis/check/coercion.rs`.
8 use std
::{iter, sync::Arc}
;
10 use chalk_ir
::{cast::Cast, BoundVar, Goal, Mutability, TyVariableKind}
;
13 lang_item
::{LangItem, LangItemTarget}
,
18 autoderef
::{Autoderef, AutoderefKind}
,
21 Adjust
, Adjustment
, AutoBorrow
, InferOk
, InferenceContext
, OverloadedDeref
, PointerCast
,
22 TypeError
, TypeMismatch
,
24 static_lifetime
, Canonical
, DomainGoal
, FnPointer
, FnSig
, Guidance
, InEnvironment
, Interner
,
25 Solution
, Substitution
, TraitEnvironment
, Ty
, TyBuilder
, TyExt
, TyKind
,
28 use super::unify
::InferenceTable
;
30 pub(crate) type CoerceResult
= Result
<InferOk
<(Vec
<Adjustment
>, Ty
)>, TypeError
>;
32 /// Do not require any adjustments, i.e. coerce `x -> x`.
33 fn identity(_
: Ty
) -> Vec
<Adjustment
> {
37 fn simple(kind
: Adjust
) -> impl FnOnce(Ty
) -> Vec
<Adjustment
> {
38 move |target
| vec
![Adjustment { kind, target }
]
41 /// This always returns `Ok(...)`.
45 goals
: Vec
<InEnvironment
<Goal
<Interner
>>>,
47 Ok(InferOk { goals, value: (adj, target) }
)
50 #[derive(Clone, Debug)]
51 pub(super) struct CoerceMany
{
56 pub(super) fn new(expected
: Ty
) -> Self {
57 CoerceMany { expected_ty: expected }
60 /// Merge two types from different branches, with possible coercion.
62 /// Mostly this means trying to coerce one to the other, but
63 /// - if we have two function types for different functions or closures, we need to
64 /// coerce both to function pointers;
65 /// - if we were concerned with lifetime subtyping, we'd need to look for a
66 /// least upper bound.
69 ctx
: &mut InferenceContext
<'_
>,
73 let expr_ty
= ctx
.resolve_ty_shallow(expr_ty
);
74 self.expected_ty
= ctx
.resolve_ty_shallow(&self.expected_ty
);
76 // Special case: two function types. Try to coerce both to
77 // pointers to have a chance at getting a match. See
78 // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916
79 let sig
= match (self.expected_ty
.kind(Interner
), expr_ty
.kind(Interner
)) {
80 (TyKind
::FnDef(..) | TyKind
::Closure(..), TyKind
::FnDef(..) | TyKind
::Closure(..)) => {
81 // FIXME: we're ignoring safety here. To be more correct, if we have one FnDef and one Closure,
82 // we should be coercing the closure to a fn pointer of the safety of the FnDef
83 cov_mark
::hit
!(coerce_fn_reification
);
85 self.expected_ty
.callable_sig(ctx
.db
).expect("FnDef without callable sig");
90 if let Some(sig
) = sig
{
91 let target_ty
= TyKind
::Function(sig
.to_fn_ptr()).intern(Interner
);
92 let result1
= ctx
.table
.coerce_inner(self.expected_ty
.clone(), &target_ty
);
93 let result2
= ctx
.table
.coerce_inner(expr_ty
.clone(), &target_ty
);
94 if let (Ok(result1
), Ok(result2
)) = (result1
, result2
) {
95 ctx
.table
.register_infer_ok(result1
);
96 ctx
.table
.register_infer_ok(result2
);
97 return self.expected_ty
= target_ty
;
101 // It might not seem like it, but order is important here: If the expected
102 // type is a type variable and the new one is `!`, trying it the other
103 // way around first would mean we make the type variable `!`, instead of
104 // just marking it as possibly diverging.
105 if ctx
.coerce(expr
, &expr_ty
, &self.expected_ty
).is_ok() {
106 /* self.expected_ty is already correct */
107 } else if ctx
.coerce(expr
, &self.expected_ty
, &expr_ty
).is_ok() {
108 self.expected_ty
= expr_ty
;
110 if let Some(id
) = expr
{
111 ctx
.result
.type_mismatches
.insert(
113 TypeMismatch { expected: self.expected_ty.clone(), actual: expr_ty }
,
116 cov_mark
::hit
!(coerce_merge_fail_fallback
);
117 /* self.expected_ty is already correct */
121 pub(super) fn complete(self) -> Ty
{
127 db
: &dyn HirDatabase
,
128 env
: Arc
<TraitEnvironment
>,
129 tys
: &Canonical
<(Ty
, Ty
)>,
131 coerce(db
, env
, tys
).is_ok()
134 pub(crate) fn coerce(
135 db
: &dyn HirDatabase
,
136 env
: Arc
<TraitEnvironment
>,
137 tys
: &Canonical
<(Ty
, Ty
)>,
138 ) -> Result
<(Vec
<Adjustment
>, Ty
), TypeError
> {
139 let mut table
= InferenceTable
::new(db
, env
);
140 let vars
= table
.fresh_subst(tys
.binders
.as_slice(Interner
));
141 let ty1_with_vars
= vars
.apply(tys
.value
.0.clone(), Interner
);
142 let ty2_with_vars
= vars
.apply(tys
.value
.1.clone(), Interner
);
143 let (adjustments
, ty
) = table
.coerce(&ty1_with_vars
, &ty2_with_vars
)?
;
144 // default any type vars that weren't unified back to their original bound vars
146 let find_var
= |iv
| {
147 vars
.iter(Interner
).position(|v
| match v
.interned() {
148 chalk_ir
::GenericArgData
::Ty(ty
) => ty
.inference_var(Interner
),
149 chalk_ir
::GenericArgData
::Lifetime(lt
) => lt
.inference_var(Interner
),
150 chalk_ir
::GenericArgData
::Const(c
) => c
.inference_var(Interner
),
153 let fallback
= |iv
, kind
, default, binder
| match kind
{
154 chalk_ir
::VariableKind
::Ty(_ty_kind
) => find_var(iv
)
155 .map_or(default, |i
| BoundVar
::new(binder
, i
).to_ty(Interner
).cast(Interner
)),
156 chalk_ir
::VariableKind
::Lifetime
=> find_var(iv
)
157 .map_or(default, |i
| BoundVar
::new(binder
, i
).to_lifetime(Interner
).cast(Interner
)),
158 chalk_ir
::VariableKind
::Const(ty
) => find_var(iv
)
159 .map_or(default, |i
| BoundVar
::new(binder
, i
).to_const(Interner
, ty
).cast(Interner
)),
161 // FIXME also map the types in the adjustments
162 Ok((adjustments
, table
.resolve_with_fallback(ty
, &fallback
)))
165 impl<'a
> InferenceContext
<'a
> {
166 /// Unify two types, but may coerce the first one to the second one
167 /// using "implicit coercion rules" if needed.
168 pub(super) fn coerce(
170 expr
: Option
<ExprId
>,
173 ) -> Result
<Ty
, TypeError
> {
174 let from_ty
= self.resolve_ty_shallow(from_ty
);
175 let to_ty
= self.resolve_ty_shallow(to_ty
);
176 let (adjustments
, ty
) = self.table
.coerce(&from_ty
, &to_ty
)?
;
177 if let Some(expr
) = expr
{
178 self.write_expr_adj(expr
, adjustments
);
184 impl<'a
> InferenceTable
<'a
> {
185 /// Unify two types, but may coerce the first one to the second one
186 /// using "implicit coercion rules" if needed.
187 pub(crate) fn coerce(
191 ) -> Result
<(Vec
<Adjustment
>, Ty
), TypeError
> {
192 let from_ty
= self.resolve_ty_shallow(from_ty
);
193 let to_ty
= self.resolve_ty_shallow(to_ty
);
194 match self.coerce_inner(from_ty
, &to_ty
) {
195 Ok(InferOk { value: (adjustments, ty), goals }
) => {
196 self.register_infer_ok(InferOk { value: (), goals }
);
197 Ok((adjustments
, ty
))
200 // FIXME deal with error
206 fn coerce_inner(&mut self, from_ty
: Ty
, to_ty
: &Ty
) -> CoerceResult
{
207 if from_ty
.is_never() {
208 // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
209 // type variable, we want `?T` to fallback to `!` if not
210 // otherwise constrained. An example where this arises:
212 // let _: Option<?T> = Some({ return; });
214 // here, we would coerce from `!` to `?T`.
215 if let TyKind
::InferenceVar(tv
, TyVariableKind
::General
) = to_ty
.kind(Interner
) {
216 self.set_diverging(*tv
, true);
218 return success(simple(Adjust
::NeverToAny
)(to_ty
.clone()), to_ty
.clone(), vec
![]);
221 // Consider coercing the subtype to a DST
222 if let Ok(ret
) = self.try_coerce_unsized(&from_ty
, to_ty
) {
226 // Examine the supertype and consider auto-borrowing.
227 match to_ty
.kind(Interner
) {
228 TyKind
::Raw(mt
, _
) => return self.coerce_ptr(from_ty
, to_ty
, *mt
),
229 TyKind
::Ref(mt
, _
, _
) => return self.coerce_ref(from_ty
, to_ty
, *mt
),
233 match from_ty
.kind(Interner
) {
234 TyKind
::FnDef(..) => {
235 // Function items are coercible to any closure
236 // type; function pointers are not (that would
237 // require double indirection).
238 // Additionally, we permit coercion of function
239 // items to drop the unsafe qualifier.
240 self.coerce_from_fn_item(from_ty
, to_ty
)
242 TyKind
::Function(from_fn_ptr
) => {
243 // We permit coercion of fn pointers to drop the
245 self.coerce_from_fn_pointer(from_ty
.clone(), from_fn_ptr
, to_ty
)
247 TyKind
::Closure(_
, from_substs
) => {
248 // Non-capturing closures are coercible to
249 // function pointers or unsafe function pointers.
250 // It cannot convert closures that require unsafe.
251 self.coerce_closure_to_fn(from_ty
.clone(), from_substs
, to_ty
)
254 // Otherwise, just use unification rules.
255 self.unify_and(&from_ty
, to_ty
, identity
)
260 /// Unify two types (using sub or lub) and produce a specific coercion.
261 fn unify_and
<F
>(&mut self, t1
: &Ty
, t2
: &Ty
, f
: F
) -> CoerceResult
263 F
: FnOnce(Ty
) -> Vec
<Adjustment
>,
265 self.try_unify(t1
, t2
)
266 .and_then(|InferOk { goals, .. }
| success(f(t1
.clone()), t1
.clone(), goals
))
269 fn coerce_ptr(&mut self, from_ty
: Ty
, to_ty
: &Ty
, to_mt
: Mutability
) -> CoerceResult
{
270 let (is_ref
, from_mt
, from_inner
) = match from_ty
.kind(Interner
) {
271 TyKind
::Ref(mt
, _
, ty
) => (true, mt
, ty
),
272 TyKind
::Raw(mt
, ty
) => (false, mt
, ty
),
273 _
=> return self.unify_and(&from_ty
, to_ty
, identity
),
276 coerce_mutabilities(*from_mt
, to_mt
)?
;
278 // Check that the types which they point at are compatible.
279 let from_raw
= TyKind
::Raw(to_mt
, from_inner
.clone()).intern(Interner
);
281 // Although references and unsafe ptrs have the same
282 // representation, we still register an Adjust::DerefRef so that
283 // regionck knows that the region for `a` must be valid here.
285 self.unify_and(&from_raw
, to_ty
, |target
| {
287 Adjustment { kind: Adjust::Deref(None), target: from_inner.clone() }
,
288 Adjustment { kind: Adjust::Borrow(AutoBorrow::RawPtr(to_mt)), target }
,
291 } else if *from_mt
!= to_mt
{
295 simple(Adjust
::Pointer(PointerCast
::MutToConstPointer
)),
298 self.unify_and(&from_raw
, to_ty
, identity
)
302 /// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
303 /// To match `A` with `B`, autoderef will be performed,
304 /// calling `deref`/`deref_mut` where necessary.
305 fn coerce_ref(&mut self, from_ty
: Ty
, to_ty
: &Ty
, to_mt
: Mutability
) -> CoerceResult
{
306 let from_mt
= match from_ty
.kind(Interner
) {
307 &TyKind
::Ref(mt
, _
, _
) => {
308 coerce_mutabilities(mt
, to_mt
)?
;
311 _
=> return self.unify_and(&from_ty
, to_ty
, identity
),
314 // NOTE: this code is mostly copied and adapted from rustc, and
315 // currently more complicated than necessary, carrying errors around
316 // etc.. This complication will become necessary when we actually track
317 // details of coercion errors though, so I think it's useful to leave
318 // the structure like it is.
320 let snapshot
= self.snapshot();
322 let mut autoderef
= Autoderef
::new(self, from_ty
.clone());
323 let mut first_error
= None
;
324 let mut found
= None
;
326 while let Some((referent_ty
, autoderefs
)) = autoderef
.next() {
328 // Don't let this pass, otherwise it would cause
329 // &T to autoref to &&T.
333 // At this point, we have deref'd `a` to `referent_ty`. So
334 // imagine we are coercing from `&'a mut Vec<T>` to `&'b mut [T]`.
335 // In the autoderef loop for `&'a mut Vec<T>`, we would get
338 // - `&'a mut Vec<T>` -- 0 derefs, just ignore it
339 // - `Vec<T>` -- 1 deref
340 // - `[T]` -- 2 deref
342 // At each point after the first callback, we want to
343 // check to see whether this would match out target type
344 // (`&'b mut [T]`) if we autoref'd it. We can't just
345 // compare the referent types, though, because we still
346 // have to consider the mutability. E.g., in the case
347 // we've been considering, we have an `&mut` reference, so
348 // the `T` in `[T]` needs to be unified with equality.
350 // Therefore, we construct reference types reflecting what
351 // the types will be after we do the final auto-ref and
352 // compare those. Note that this means we use the target
353 // mutability [1], since it may be that we are coercing
354 // from `&mut T` to `&U`.
355 let lt
= static_lifetime(); // FIXME: handle lifetimes correctly, see rustc
356 let derefd_from_ty
= TyKind
::Ref(to_mt
, lt
, referent_ty
).intern(Interner
);
357 match autoderef
.table
.try_unify(&derefd_from_ty
, to_ty
) {
359 found
= Some(result
.map(|()| derefd_from_ty
));
363 if first_error
.is_none() {
364 first_error
= Some(err
);
370 // Extract type or return an error. We return the first error
371 // we got, which should be from relating the "base" type
372 // (e.g., in example above, the failure from relating `Vec<T>`
373 // to the target type), since that should be the least
375 let InferOk { value: ty, goals }
= match found
{
378 self.rollback_to(snapshot
);
379 let err
= first_error
.expect("coerce_borrowed_pointer had no error");
383 if ty
== from_ty
&& from_mt
== Mutability
::Not
&& autoderef
.step_count() == 1 {
384 // As a special case, if we would produce `&'a *x`, that's
385 // a total no-op. We end up with the type `&'a T` just as
386 // we started with. In that case, just skip it
387 // altogether. This is just an optimization.
389 // Note that for `&mut`, we DO want to reborrow --
390 // otherwise, this would be a move, which might be an
391 // error. For example `foo(self.x)` where `self` and
392 // `self.x` both have `&mut `type would be a move of
393 // `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
394 // which is a borrow.
395 always
!(to_mt
== Mutability
::Not
); // can only coerce &T -> &U
396 return success(vec
![], ty
, goals
);
399 let mut adjustments
= auto_deref_adjust_steps(&autoderef
);
401 .push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(to_mt)), target: ty.clone() }
);
403 success(adjustments
, ty
, goals
)
406 /// Attempts to coerce from the type of a Rust function item into a function pointer.
407 fn coerce_from_fn_item(&mut self, from_ty
: Ty
, to_ty
: &Ty
) -> CoerceResult
{
408 match to_ty
.kind(Interner
) {
409 TyKind
::Function(_
) => {
410 let from_sig
= from_ty
.callable_sig(self.db
).expect("FnDef had no sig");
412 // FIXME check ABI: Intrinsics are not coercible to function pointers
413 // FIXME Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396)
415 // FIXME rustc normalizes assoc types in the sig here, not sure if necessary
417 let from_sig
= from_sig
.to_fn_ptr();
418 let from_fn_pointer
= TyKind
::Function(from_sig
.clone()).intern(Interner
);
419 let ok
= self.coerce_from_safe_fn(
420 from_fn_pointer
.clone(),
426 kind
: Adjust
::Pointer(PointerCast
::ReifyFnPointer
),
427 target
: from_fn_pointer
,
430 kind
: Adjust
::Pointer(PointerCast
::UnsafeFnPointer
),
435 simple(Adjust
::Pointer(PointerCast
::ReifyFnPointer
)),
440 _
=> self.unify_and(&from_ty
, to_ty
, identity
),
444 fn coerce_from_fn_pointer(
450 self.coerce_from_safe_fn(
454 simple(Adjust
::Pointer(PointerCast
::UnsafeFnPointer
)),
459 fn coerce_from_safe_fn
<F
, G
>(
462 from_fn_ptr
: &FnPointer
,
468 F
: FnOnce(Ty
) -> Vec
<Adjustment
>,
469 G
: FnOnce(Ty
) -> Vec
<Adjustment
>,
471 if let TyKind
::Function(to_fn_ptr
) = to_ty
.kind(Interner
) {
472 if let (chalk_ir
::Safety
::Safe
, chalk_ir
::Safety
::Unsafe
) =
473 (from_fn_ptr
.sig
.safety
, to_fn_ptr
.sig
.safety
)
476 TyKind
::Function(safe_to_unsafe_fn_ty(from_fn_ptr
.clone())).intern(Interner
);
477 return self.unify_and(&from_unsafe
, to_ty
, to_unsafe
);
480 self.unify_and(&from_ty
, to_ty
, normal
)
483 /// Attempts to coerce from the type of a non-capturing closure into a
484 /// function pointer.
485 fn coerce_closure_to_fn(
488 from_substs
: &Substitution
,
491 match to_ty
.kind(Interner
) {
492 // if from_substs is non-capturing (FIXME)
493 TyKind
::Function(fn_ty
) => {
494 // We coerce the closure, which has fn type
495 // `extern "rust-call" fn((arg0,arg1,...)) -> _`
497 // `fn(arg0,arg1,...) -> _`
499 // `unsafe fn(arg0,arg1,...) -> _`
500 let safety
= fn_ty
.sig
.safety
;
501 let pointer_ty
= coerce_closure_fn_ty(from_substs
, safety
);
505 simple(Adjust
::Pointer(PointerCast
::ClosureFnPointer(safety
))),
508 _
=> self.unify_and(&from_ty
, to_ty
, identity
),
512 /// Coerce a type using `from_ty: CoerceUnsized<ty_ty>`
514 /// See: <https://doc.rust-lang.org/nightly/std/marker/trait.CoerceUnsized.html>
515 fn try_coerce_unsized(&mut self, from_ty
: &Ty
, to_ty
: &Ty
) -> CoerceResult
{
516 // These 'if' statements require some explanation.
517 // The `CoerceUnsized` trait is special - it is only
518 // possible to write `impl CoerceUnsized<B> for A` where
519 // A and B have 'matching' fields. This rules out the following
520 // two types of blanket impls:
522 // `impl<T> CoerceUnsized<T> for SomeType`
523 // `impl<T> CoerceUnsized<SomeType> for T`
525 // Both of these trigger a special `CoerceUnsized`-related error (E0376)
527 // We can take advantage of this fact to avoid performing unnecessary work.
528 // If either `source` or `target` is a type variable, then any applicable impl
529 // would need to be generic over the self-type (`impl<T> CoerceUnsized<SomeType> for T`)
530 // or generic over the `CoerceUnsized` type parameter (`impl<T> CoerceUnsized<T> for
533 // However, these are exactly the kinds of impls which are forbidden by
534 // the compiler! Therefore, we can be sure that coercion will always fail
535 // when either the source or target type is a type variable. This allows us
536 // to skip performing any trait selection, and immediately bail out.
537 if from_ty
.is_ty_var() {
538 return Err(TypeError
);
540 if to_ty
.is_ty_var() {
541 return Err(TypeError
);
544 // Handle reborrows before trying to solve `Source: CoerceUnsized<Target>`.
545 let reborrow
= match (from_ty
.kind(Interner
), to_ty
.kind(Interner
)) {
546 (TyKind
::Ref(from_mt
, _
, from_inner
), &TyKind
::Ref(to_mt
, _
, _
)) => {
547 coerce_mutabilities(*from_mt
, to_mt
)?
;
549 let lt
= static_lifetime();
551 Adjustment { kind: Adjust::Deref(None), target: from_inner.clone() }
,
553 kind
: Adjust
::Borrow(AutoBorrow
::Ref(to_mt
)),
554 target
: TyKind
::Ref(to_mt
, lt
, from_inner
.clone()).intern(Interner
),
558 (TyKind
::Ref(from_mt
, _
, from_inner
), &TyKind
::Raw(to_mt
, _
)) => {
559 coerce_mutabilities(*from_mt
, to_mt
)?
;
562 Adjustment { kind: Adjust::Deref(None), target: from_inner.clone() }
,
564 kind
: Adjust
::Borrow(AutoBorrow
::RawPtr(to_mt
)),
565 target
: TyKind
::Raw(to_mt
, from_inner
.clone()).intern(Interner
),
572 reborrow
.as_ref().map_or_else(|| from_ty
.clone(), |(_
, adj
)| adj
.target
.clone());
574 let krate
= self.trait_env
.krate
;
575 let coerce_unsized_trait
= match self.db
.lang_item(krate
, LangItem
::CoerceUnsized
) {
576 Some(LangItemTarget
::Trait(trait_
)) => trait_
,
577 _
=> return Err(TypeError
),
580 let coerce_unsized_tref
= {
581 let b
= TyBuilder
::trait_ref(self.db
, coerce_unsized_trait
);
582 if b
.remaining() != 2 {
583 // The CoerceUnsized trait should have two generic params: Self and T.
584 return Err(TypeError
);
586 b
.push(coerce_from
).push(to_ty
.clone()).build()
589 let goal
: InEnvironment
<DomainGoal
> =
590 InEnvironment
::new(&self.trait_env
.env
, coerce_unsized_tref
.cast(Interner
));
592 let canonicalized
= self.canonicalize(goal
);
594 // FIXME: rustc's coerce_unsized is more specialized -- it only tries to
595 // solve `CoerceUnsized` and `Unsize` goals at this point and leaves the
596 // rest for later. Also, there's some logic about sized type variables.
597 // Need to find out in what cases this is necessary
600 .trait_solve(krate
, canonicalized
.value
.clone().cast(Interner
))
604 Solution
::Unique(v
) => {
605 canonicalized
.apply_solution(
609 // FIXME handle constraints
610 value
: v
.value
.subst
,
614 Solution
::Ambig(Guidance
::Definite(subst
)) => {
615 // FIXME need to record an obligation here
616 canonicalized
.apply_solution(self, subst
)
618 // FIXME actually we maybe should also accept unknown guidance here
619 _
=> return Err(TypeError
),
622 Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), target: to_ty.clone() }
;
623 let adjustments
= match reborrow
{
624 None
=> vec
![unsize
],
625 Some((deref
, autoref
)) => vec
![deref
, autoref
, unsize
],
627 success(adjustments
, to_ty
.clone(), vec
![])
631 fn coerce_closure_fn_ty(closure_substs
: &Substitution
, safety
: chalk_ir
::Safety
) -> Ty
{
632 let closure_sig
= closure_substs
.at(Interner
, 0).assert_ty_ref(Interner
).clone();
633 match closure_sig
.kind(Interner
) {
634 TyKind
::Function(fn_ty
) => TyKind
::Function(FnPointer
{
635 num_binders
: fn_ty
.num_binders
,
636 sig
: FnSig { safety, ..fn_ty.sig }
,
637 substitution
: fn_ty
.substitution
.clone(),
640 _
=> TyKind
::Error
.intern(Interner
),
644 fn safe_to_unsafe_fn_ty(fn_ty
: FnPointer
) -> FnPointer
{
646 num_binders
: fn_ty
.num_binders
,
647 sig
: FnSig { safety: chalk_ir::Safety::Unsafe, ..fn_ty.sig }
,
648 substitution
: fn_ty
.substitution
,
652 fn coerce_mutabilities(from
: Mutability
, to
: Mutability
) -> Result
<(), TypeError
> {
654 (Mutability
::Mut
, Mutability
::Mut
| Mutability
::Not
)
655 | (Mutability
::Not
, Mutability
::Not
) => Ok(()),
656 (Mutability
::Not
, Mutability
::Mut
) => Err(TypeError
),
660 pub(super) fn auto_deref_adjust_steps(autoderef
: &Autoderef
<'_
, '_
>) -> Vec
<Adjustment
> {
661 let steps
= autoderef
.steps();
663 steps
.iter().skip(1).map(|(_
, ty
)| ty
.clone()).chain(iter
::once(autoderef
.final_ty()));
666 .map(|(kind
, _source
)| match kind
{
667 // We do not know what kind of deref we require at this point yet
668 AutoderefKind
::Overloaded
=> Some(OverloadedDeref(Mutability
::Not
)),
669 AutoderefKind
::Builtin
=> None
,
672 .map(|(autoderef
, target
)| Adjustment { kind: Adjust::Deref(autoderef), target }
)