@@ -9,7 +9,7 @@ use smol_str::SmolStr;
99use crate :: ExternalQueries ;
1010use crate :: context:: CheckContext ;
1111use crate :: core:: substitute:: SubstituteName ;
12- use crate :: core:: { Depth , Name , RowField , RowType , RowTypeId , Type , TypeId , normalise} ;
12+ use crate :: core:: { Depth , Name , RowField , RowType , RowTypeId , Type , TypeId , normalise, toolkit } ;
1313use crate :: error:: ErrorKind ;
1414use crate :: source:: types;
1515use crate :: state:: { CheckState , UnificationEntry } ;
@@ -126,20 +126,40 @@ where
126126 // on both positions; it's impossible to generate any constraint
127127 // dictionaries at this position.
128128 ( Type :: Function ( t1_argument, t1_result) , Type :: Function ( t2_argument, t2_result) ) => {
129- Ok ( subtype_with :: < NonElaborating , Q > ( state, context, t2_argument, t1_argument) ?
130- && subtype_with :: < NonElaborating , Q > ( state, context, t1_result, t2_result) ?)
129+ subtype_function :: < Q > (
130+ state,
131+ context,
132+ ( t1_argument, t1_result) ,
133+ ( t2_argument, t2_result) ,
134+ )
131135 }
132136
133- // Normalise Type::Function into Type::Application before unification
134- // This is explained in intern_function_application, it simplifies the
135- // subtyping rule tremendously vs. pattern matching Type::Application
137+ // Preserve function subtyping on the application representation.
136138 ( Type :: Application ( _, _) , Type :: Function ( t2_argument, t2_result) ) => {
137- let t2 = context. intern_function_application ( t2_argument, t2_result) ;
138- subtype_with :: < P , Q > ( state, context, t1, t2)
139+ if let Some ( ( t1_argument, t1_result) ) = toolkit:: decompose_function ( state, context, t1) ?
140+ {
141+ subtype_function :: < Q > (
142+ state,
143+ context,
144+ ( t1_argument, t1_result) ,
145+ ( t2_argument, t2_result) ,
146+ )
147+ } else {
148+ unify ( state, context, t1, t2)
149+ }
139150 }
140151 ( Type :: Function ( t1_argument, t1_result) , Type :: Application ( _, _) ) => {
141- let t1 = context. intern_function_application ( t1_argument, t1_result) ;
142- subtype_with :: < P , Q > ( state, context, t1, t2)
152+ if let Some ( ( t2_argument, t2_result) ) = toolkit:: decompose_function ( state, context, t2) ?
153+ {
154+ subtype_function :: < Q > (
155+ state,
156+ context,
157+ ( t1_argument, t1_result) ,
158+ ( t2_argument, t2_result) ,
159+ )
160+ } else {
161+ unify ( state, context, t1, t2)
162+ }
143163 }
144164
145165 // Forall-R
@@ -225,6 +245,21 @@ where
225245 }
226246}
227247
248+ fn subtype_function < Q > (
249+ state : & mut CheckState ,
250+ context : & CheckContext < Q > ,
251+ t1 : ( TypeId , TypeId ) ,
252+ t2 : ( TypeId , TypeId ) ,
253+ ) -> QueryResult < bool >
254+ where
255+ Q : ExternalQueries ,
256+ {
257+ let ( t1_argument, t1_result) = t1;
258+ let ( t2_argument, t2_result) = t2;
259+ Ok ( subtype_with :: < NonElaborating , Q > ( state, context, t2_argument, t1_argument) ?
260+ && subtype_with :: < NonElaborating , Q > ( state, context, t1_result, t2_result) ?)
261+ }
262+
228263pub fn unify < Q > (
229264 state : & mut CheckState ,
230265 context : & CheckContext < Q > ,
0 commit comments