@@ -40,15 +40,17 @@ use std::sync::Arc;
4040use chalk_ir:: {
4141 fold:: { Shift , TypeFoldable } ,
4242 interner:: HasInterner ,
43- NoSolution , UniverseIndex ,
43+ NoSolution ,
4444} ;
4545use hir_def:: { expr:: ExprId , type_ref:: Rawness , TypeOrConstParamId } ;
4646use hir_expand:: name;
4747use itertools:: Either ;
4848use traits:: FnTrait ;
4949use utils:: Generics ;
5050
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+ } ;
5254
5355pub use autoderef:: autoderef;
5456pub use builder:: { ParamKind , TyBuilder } ;
@@ -533,53 +535,31 @@ pub fn callable_sig_from_fnonce(
533535 let fn_once_trait = FnTrait :: FnOnce . get_id ( db, krate) ?;
534536 let output_assoc_type = db. trait_data ( fn_once_trait) . associated_type_by_name ( & name ! [ Output ] ) ?;
535537
538+ let mut table = InferenceTable :: new ( db, env. clone ( ) ) ;
536539 let b = TyBuilder :: trait_ref ( db, fn_once_trait) ;
537540 if b. remaining ( ) != 2 {
538541 return None ;
539542 }
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- } ;
576543
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) ;
581560
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 ( ) ;
583563
584564 Some ( CallableSig :: from_params_and_return ( params, ret_ty, false , Safety :: Safe ) )
585565}
0 commit comments