@@ -40,15 +40,17 @@ use std::sync::Arc;
40
40
use chalk_ir:: {
41
41
fold:: { Shift , TypeFoldable } ,
42
42
interner:: HasInterner ,
43
- NoSolution , UniverseIndex ,
43
+ NoSolution ,
44
44
} ;
45
45
use hir_def:: { expr:: ExprId , type_ref:: Rawness , TypeOrConstParamId } ;
46
46
use hir_expand:: name;
47
47
use itertools:: Either ;
48
48
use traits:: FnTrait ;
49
49
use utils:: Generics ;
50
50
51
- use crate :: { consteval:: unknown_const, db:: HirDatabase , utils:: generics} ;
51
+ use crate :: {
52
+ consteval:: unknown_const, db:: HirDatabase , infer:: unify:: InferenceTable , utils:: generics,
53
+ } ;
52
54
53
55
pub use autoderef:: autoderef;
54
56
pub use builder:: { ParamKind , TyBuilder } ;
@@ -533,53 +535,31 @@ pub fn callable_sig_from_fnonce(
533
535
let fn_once_trait = FnTrait :: FnOnce . get_id ( db, krate) ?;
534
536
let output_assoc_type = db. trait_data ( fn_once_trait) . associated_type_by_name ( & name ! [ Output ] ) ?;
535
537
538
+ let mut table = InferenceTable :: new ( db, env. clone ( ) ) ;
536
539
let b = TyBuilder :: trait_ref ( db, fn_once_trait) ;
537
540
if b. remaining ( ) != 2 {
538
541
return None ;
539
542
}
540
- let fn_once = b. push ( self_ty. clone ( ) ) . fill_with_bound_vars ( DebruijnIndex :: INNERMOST , 0 ) . build ( ) ;
541
- let kinds = fn_once
542
- . substitution
543
- . iter ( Interner )
544
- . skip ( 1 )
545
- . map ( |x| {
546
- let vk = match x. data ( Interner ) {
547
- chalk_ir:: GenericArgData :: Ty ( _) => {
548
- chalk_ir:: VariableKind :: Ty ( chalk_ir:: TyVariableKind :: General )
549
- }
550
- chalk_ir:: GenericArgData :: Lifetime ( _) => chalk_ir:: VariableKind :: Lifetime ,
551
- chalk_ir:: GenericArgData :: Const ( c) => {
552
- chalk_ir:: VariableKind :: Const ( c. data ( Interner ) . ty . clone ( ) )
553
- }
554
- } ;
555
- chalk_ir:: WithKind :: new ( vk, UniverseIndex :: ROOT )
556
- } )
557
- . collect :: < Vec < _ > > ( ) ;
558
-
559
- // FIXME: chalk refuses to solve `<Self as FnOnce<^0.0>>::Output == ^0.1`, so we first solve
560
- // `<Self as FnOnce<^0.0>>` and then replace `^0.0` with the concrete argument tuple.
561
- let trait_env = env. env . clone ( ) ;
562
- let obligation = InEnvironment { goal : fn_once. cast ( Interner ) , environment : trait_env } ;
563
- let canonical =
564
- Canonical { binders : CanonicalVarKinds :: from_iter ( Interner , kinds) , value : obligation } ;
565
- let subst = match db. trait_solve ( krate, canonical) {
566
- Some ( Solution :: Unique ( vars) ) => vars. value . subst ,
567
- _ => return None ,
568
- } ;
569
- let args = subst. at ( Interner , 0 ) . ty ( Interner ) ?;
570
- let params = match args. kind ( Interner ) {
571
- chalk_ir:: TyKind :: Tuple ( _, subst) => {
572
- subst. iter ( Interner ) . filter_map ( |arg| arg. ty ( Interner ) . cloned ( ) ) . collect :: < Vec < _ > > ( )
573
- }
574
- _ => return None ,
575
- } ;
576
543
577
- let fn_once =
578
- TyBuilder :: trait_ref ( db, fn_once_trait) . push ( self_ty. clone ( ) ) . push ( args. clone ( ) ) . build ( ) ;
579
- let projection =
580
- TyBuilder :: assoc_type_projection ( db, output_assoc_type, Some ( fn_once. substitution ) ) . build ( ) ;
544
+ // Register two obligations:
545
+ // - Self: FnOnce<?args_ty>
546
+ // - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
547
+ let args_ty = table. new_type_var ( ) ;
548
+ let trait_ref = b. push ( self_ty. clone ( ) ) . push ( args_ty. clone ( ) ) . build ( ) ;
549
+ let projection = TyBuilder :: assoc_type_projection (
550
+ db,
551
+ output_assoc_type,
552
+ Some ( trait_ref. substitution . clone ( ) ) ,
553
+ )
554
+ . build ( ) ;
555
+ table. register_obligation ( trait_ref. cast ( Interner ) ) ;
556
+ let ret_ty = table. normalize_projection_ty ( projection) ;
557
+
558
+ let ret_ty = table. resolve_completely ( ret_ty) ;
559
+ let args_ty = table. resolve_completely ( args_ty) ;
581
560
582
- let ret_ty = db. normalize_projection ( projection, env) ;
561
+ let params =
562
+ args_ty. as_tuple ( ) ?. iter ( Interner ) . map ( |it| it. assert_ty_ref ( Interner ) ) . cloned ( ) . collect ( ) ;
583
563
584
564
Some ( CallableSig :: from_params_and_return ( params, ret_ty, false , Safety :: Safe ) )
585
565
}
0 commit comments