@@ -28,24 +28,24 @@ pub(super) fn get_builtin_impls(
28
28
trait_ : TraitId ,
29
29
mut callback : impl FnMut ( Impl ) ,
30
30
) {
31
+ // Note: since impl_datum needs to be infallible, we need to make sure here
32
+ // that we have all prerequisites to build the respective impls.
31
33
if let Ty :: Apply ( ApplicationTy { ctor : TypeCtor :: Closure { def, expr } , .. } ) = ty {
32
34
for & fn_trait in [ super :: FnTrait :: FnOnce , super :: FnTrait :: FnMut , super :: FnTrait :: Fn ] . iter ( )
33
35
{
34
36
if let Some ( actual_trait) = get_fn_trait ( db, krate, fn_trait) {
35
37
if trait_ == actual_trait {
36
38
let impl_ = super :: ClosureFnTraitImplData { def : * def, expr : * expr, fn_trait } ;
37
- callback ( Impl :: ClosureFnTraitImpl ( impl_) ) ;
39
+ if check_closure_fn_trait_impl_prerequisites ( db, krate, impl_) {
40
+ callback ( Impl :: ClosureFnTraitImpl ( impl_) ) ;
41
+ }
38
42
}
39
43
}
40
44
}
41
45
}
42
46
}
43
47
44
- pub ( super ) fn impl_datum (
45
- db : & impl HirDatabase ,
46
- krate : CrateId ,
47
- impl_ : Impl ,
48
- ) -> Option < BuiltinImplData > {
48
+ pub ( super ) fn impl_datum ( db : & impl HirDatabase , krate : CrateId , impl_ : Impl ) -> BuiltinImplData {
49
49
match impl_ {
50
50
Impl :: ImplBlock ( _) => unreachable ! ( ) ,
51
51
Impl :: ClosureFnTraitImpl ( data) => closure_fn_trait_impl_datum ( db, krate, data) ,
@@ -65,21 +65,38 @@ pub(super) fn associated_ty_value(
65
65
}
66
66
}
67
67
68
+ fn check_closure_fn_trait_impl_prerequisites (
69
+ db : & impl HirDatabase ,
70
+ krate : CrateId ,
71
+ data : super :: ClosureFnTraitImplData ,
72
+ ) -> bool {
73
+ // the respective Fn/FnOnce/FnMut trait needs to exist
74
+ if get_fn_trait ( db, krate, data. fn_trait ) . is_none ( ) {
75
+ return false ;
76
+ }
77
+
78
+ // FIXME: there are more assumptions that we should probably check here:
79
+ // the traits having no type params, FnOnce being a supertrait
80
+
81
+ // the FnOnce trait needs to exist and have an assoc type named Output
82
+ let fn_once_trait = match get_fn_trait ( db, krate, super :: FnTrait :: FnOnce ) {
83
+ Some ( t) => t,
84
+ None => return false ,
85
+ } ;
86
+ db. trait_data ( fn_once_trait) . associated_type_by_name ( & name ! [ Output ] ) . is_some ( )
87
+ }
88
+
68
89
fn closure_fn_trait_impl_datum (
69
90
db : & impl HirDatabase ,
70
91
krate : CrateId ,
71
92
data : super :: ClosureFnTraitImplData ,
72
- ) -> Option < BuiltinImplData > {
93
+ ) -> BuiltinImplData {
73
94
// for some closure |X, Y| -> Z:
74
95
// impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V }
75
96
76
- let trait_ = get_fn_trait ( db, krate, data. fn_trait ) ?; // get corresponding fn trait
77
-
78
- // validate FnOnce trait, since we need it in the assoc ty value definition
79
- // and don't want to return a valid value only to find out later that FnOnce
80
- // is broken
81
- let fn_once_trait = get_fn_trait ( db, krate, super :: FnTrait :: FnOnce ) ?;
82
- let _output = db. trait_data ( fn_once_trait) . associated_type_by_name ( & name ! [ Output ] ) ?;
97
+ let trait_ = get_fn_trait ( db, krate, data. fn_trait ) // get corresponding fn trait
98
+ // the existence of the Fn trait has been checked before
99
+ . expect ( "fn trait for closure impl missing" ) ;
83
100
84
101
let num_args: u16 = match & db. body ( data. def . into ( ) ) [ data. expr ] {
85
102
Expr :: Lambda { args, .. } => args. len ( ) as u16 ,
@@ -107,12 +124,12 @@ fn closure_fn_trait_impl_datum(
107
124
108
125
let output_ty_id = AssocTyValue :: ClosureFnTraitImplOutput ( data. clone ( ) ) ;
109
126
110
- Some ( BuiltinImplData {
127
+ BuiltinImplData {
111
128
num_vars : num_args as usize + 1 ,
112
129
trait_ref,
113
130
where_clauses : Vec :: new ( ) ,
114
131
assoc_ty_values : vec ! [ output_ty_id] ,
115
- } )
132
+ }
116
133
}
117
134
118
135
fn closure_fn_trait_output_assoc_ty_value (
0 commit comments