~ chicken-core (chicken-5) 57641c946030cc387f8194f72c298f4487e4e934


commit 57641c946030cc387f8194f72c298f4487e4e934
Author:     megane <meganeka@gmail.com>
AuthorDate: Sun Dec 1 12:59:26 2019 +0200
Commit:     Evan Hanson <evhan@foldling.org>
CommitDate: Fri Dec 27 10:45:39 2019 -0600

    Let scrutinizer infer types for foreign types with retconv/argconv given
    
    Not doing any annotation gives the scrutinizer a change to infer the
    reconverted arguments. Which it in many cases can do.
    
    For example this:
    
      (define-foreign-type retconverted-foreign-int int identity ->string)
      (foreign-lambda retconverted-foreign-int "rand")
    
    Gets converted to something like this:
    
      (set! g14 chicken.string#->string)
      (lambda () (g14 (##core#inline stub23 (##core#undefined))
    
    Which the scrutinizer can handle.
    
     * chicken-ffi-syntax.scm (annotate-foreign-procedure): Don't annotate
       if scrutinizer can infer types
    
       Ideally we could drop the annotation here completely if
       create-foreign-stub just annotated the return type of the stub call:
    
         (##core#inline stub25 (##core#undefined))
         =>
         (the fixnum (##core#inline stub25 (##core#undefined)))
    
       Generally the scrutinizer can infer the argument types if they are
       converted by enforcing functions like this:
    
         (lambda (int2730)
           (##core#inline
            stub28
            (##core#undefined)
            (##sys#foreign-fixnum-argument int2730)))
         =>
         (fixnum -> *)
    
     * tests/typematch-tests.scm: Expect more specific type now
    
    Signed-off-by: Evan Hanson <evhan@foldling.org>

diff --git a/chicken-ffi-syntax.scm b/chicken-ffi-syntax.scm
index b6ec4d5b..c78d0934 100644
--- a/chicken-ffi-syntax.scm
+++ b/chicken-ffi-syntax.scm
@@ -214,16 +214,32 @@
 ;;; Aliases for internal forms
 
 (define (annotate-foreign-procedure e argtypes rtype)
-  `(##core#the
-    (procedure ,(map (cut chicken.compiler.support#foreign-type->scrutiny-type <> 'arg)
-		     (chicken.syntax#strip-syntax argtypes))
-	       ,@(if rtype
-		     (list (chicken.compiler.support#foreign-type->scrutiny-type
-			    (chicken.syntax#strip-syntax rtype) 'result))
-		     ;; special case for C_values(...). Only triggered by foreign-primitive.
-		     '*))
-    #f
-    ,e))
+  (let ((scrut-atypes (map (cut chicken.compiler.support#foreign-type->scrutiny-type <> 'arg)
+			   (chicken.syntax#strip-syntax argtypes)))
+	(scrut-rtype (and rtype
+			  (chicken.compiler.support#foreign-type->scrutiny-type
+			   (chicken.syntax#strip-syntax rtype) 'result))))
+    ;; Don't add type annotation if the scrutinizer can infer the same
+    ;; or better.
+    ;;
+    ;; At least these cases should work:
+    ;;
+    ;;   (-> <some-known-type>)	=> annotate
+    ;;   (-> *)			=> no annotation
+    ;;   (* ... -> *)		=> no annotation
+    ;;
+    (if (and (or (not rtype) (eq? scrut-rtype '*))
+	     (every (cut eq? '* <>) scrut-atypes))
+	e
+	`(##core#the
+	  (procedure ,scrut-atypes
+		     ,@(if rtype
+			   (list scrut-rtype)
+			   ;; Special case for C_values(...). Only
+			   ;; triggered by foreign-primitive.
+			   '*))
+	  #f
+	  ,e))))
 
 (##sys#extend-macro-environment
  'define-foreign-type
diff --git a/tests/typematch-tests.scm b/tests/typematch-tests.scm
index 59ba506c..42a97ac9 100644
--- a/tests/typematch-tests.scm
+++ b/tests/typematch-tests.scm
@@ -438,8 +438,7 @@
 ;; when the return type should be whatever the retconvert argument
 ;; to define-foreign-type returns (string in this case)
 (let ((retconverted (foreign-lambda retconverted-foreign-int "rand")))
-  (infer-not fixnum (retconverted))
-  (infer-not integer (retconverted)) )
+  (infer string (retconverted)))
 
 (let ((argconverted (foreign-lambda argconverted-foreign-int "rand")))
   ;; Currently types with only argconvert get a retconvert as well,
Trap