@@ -22,6 +22,8 @@ use crate::{
22
22
Solution , Substitution , Ty , TyBuilder , TyExt , TyKind ,
23
23
} ;
24
24
25
+ use super :: unify:: InferenceTable ;
26
+
25
27
pub ( crate ) type CoerceResult = Result < InferOk < ( Vec < Adjustment > , Ty ) > , TypeError > ;
26
28
27
29
/// Do not require any adjustments, i.e. coerce `x -> x`.
@@ -84,8 +86,8 @@ impl CoerceMany {
84
86
} ;
85
87
if let Some ( sig) = sig {
86
88
let target_ty = TyKind :: Function ( sig. to_fn_ptr ( ) ) . intern ( Interner ) ;
87
- let result1 = ctx. coerce_inner ( self . expected_ty . clone ( ) , & target_ty) ;
88
- let result2 = ctx. coerce_inner ( expr_ty. clone ( ) , & target_ty) ;
89
+ let result1 = ctx. table . coerce_inner ( self . expected_ty . clone ( ) , & target_ty) ;
90
+ let result2 = ctx. table . coerce_inner ( expr_ty. clone ( ) , & target_ty) ;
89
91
if let ( Ok ( result1) , Ok ( result2) ) = ( result1, result2) {
90
92
ctx. table . register_infer_ok ( result1) ;
91
93
ctx. table . register_infer_ok ( result2) ;
@@ -126,16 +128,31 @@ impl<'a> InferenceContext<'a> {
126
128
expr : Option < ExprId > ,
127
129
from_ty : & Ty ,
128
130
to_ty : & Ty ,
129
- ) -> InferResult < Ty > {
131
+ ) -> Result < Ty , TypeError > {
132
+ let from_ty = self . resolve_ty_shallow ( from_ty) ;
133
+ let to_ty = self . resolve_ty_shallow ( to_ty) ;
134
+ let ( adjustments, ty) = self . table . coerce ( & from_ty, & to_ty) ?;
135
+ if let Some ( expr) = expr {
136
+ self . write_expr_adj ( expr, adjustments) ;
137
+ }
138
+ Ok ( ty)
139
+ }
140
+ }
141
+
142
+ impl < ' a > InferenceTable < ' a > {
143
+ /// Unify two types, but may coerce the first one to the second one
144
+ /// using "implicit coercion rules" if needed.
145
+ pub ( crate ) fn coerce (
146
+ & mut self ,
147
+ from_ty : & Ty ,
148
+ to_ty : & Ty ,
149
+ ) -> Result < ( Vec < Adjustment > , Ty ) , TypeError > {
130
150
let from_ty = self . resolve_ty_shallow ( from_ty) ;
131
151
let to_ty = self . resolve_ty_shallow ( to_ty) ;
132
152
match self . coerce_inner ( from_ty, & to_ty) {
133
153
Ok ( InferOk { value : ( adjustments, ty) , goals } ) => {
134
- if let Some ( expr) = expr {
135
- self . write_expr_adj ( expr, adjustments) ;
136
- }
137
- self . table . register_infer_ok ( InferOk { value : ( ) , goals } ) ;
138
- Ok ( InferOk { value : ty, goals : Vec :: new ( ) } )
154
+ self . register_infer_ok ( InferOk { value : ( ) , goals } ) ;
155
+ Ok ( ( adjustments, ty) )
139
156
}
140
157
Err ( e) => {
141
158
// FIXME deal with error
@@ -154,7 +171,7 @@ impl<'a> InferenceContext<'a> {
154
171
//
155
172
// here, we would coerce from `!` to `?T`.
156
173
if let TyKind :: InferenceVar ( tv, TyVariableKind :: General ) = to_ty. kind ( Interner ) {
157
- self . table . set_diverging ( * tv, true ) ;
174
+ self . set_diverging ( * tv, true ) ;
158
175
}
159
176
return success ( simple ( Adjust :: NeverToAny ) ( to_ty. clone ( ) ) , to_ty. clone ( ) , vec ! [ ] ) ;
160
177
}
@@ -203,8 +220,7 @@ impl<'a> InferenceContext<'a> {
203
220
where
204
221
F : FnOnce ( Ty ) -> Vec < Adjustment > ,
205
222
{
206
- self . table
207
- . try_unify ( t1, t2)
223
+ self . try_unify ( t1, t2)
208
224
. and_then ( |InferOk { goals, .. } | success ( f ( t1. clone ( ) ) , t1. clone ( ) , goals) )
209
225
}
210
226
@@ -259,9 +275,9 @@ impl<'a> InferenceContext<'a> {
259
275
// details of coercion errors though, so I think it's useful to leave
260
276
// the structure like it is.
261
277
262
- let snapshot = self . table . snapshot ( ) ;
278
+ let snapshot = self . snapshot ( ) ;
263
279
264
- let mut autoderef = Autoderef :: new ( & mut self . table , from_ty. clone ( ) ) ;
280
+ let mut autoderef = Autoderef :: new ( self , from_ty. clone ( ) ) ;
265
281
let mut first_error = None ;
266
282
let mut found = None ;
267
283
@@ -317,7 +333,7 @@ impl<'a> InferenceContext<'a> {
317
333
let InferOk { value : ty, goals } = match found {
318
334
Some ( d) => d,
319
335
None => {
320
- self . table . rollback_to ( snapshot) ;
336
+ self . rollback_to ( snapshot) ;
321
337
let err = first_error. expect ( "coerce_borrowed_pointer had no error" ) ;
322
338
return Err ( err) ;
323
339
}
@@ -513,7 +529,7 @@ impl<'a> InferenceContext<'a> {
513
529
let coerce_from =
514
530
reborrow. as_ref ( ) . map_or_else ( || from_ty. clone ( ) , |( _, adj) | adj. target . clone ( ) ) ;
515
531
516
- let krate = self . resolver . krate ( ) . unwrap ( ) ;
532
+ let krate = self . trait_env . krate ;
517
533
let coerce_unsized_trait =
518
534
match self . db . lang_item ( krate, SmolStr :: new_inline ( "coerce_unsized" ) ) {
519
535
Some ( LangItemTarget :: TraitId ( trait_) ) => trait_,
@@ -546,7 +562,7 @@ impl<'a> InferenceContext<'a> {
546
562
match solution {
547
563
Solution :: Unique ( v) => {
548
564
canonicalized. apply_solution (
549
- & mut self . table ,
565
+ self ,
550
566
Canonical {
551
567
binders : v. binders ,
552
568
// FIXME handle constraints
@@ -556,7 +572,7 @@ impl<'a> InferenceContext<'a> {
556
572
}
557
573
Solution :: Ambig ( Guidance :: Definite ( subst) ) => {
558
574
// FIXME need to record an obligation here
559
- canonicalized. apply_solution ( & mut self . table , subst)
575
+ canonicalized. apply_solution ( self , subst)
560
576
}
561
577
// FIXME actually we maybe should also accept unknown guidance here
562
578
_ => return Err ( TypeError ) ,
0 commit comments