diff --git a/haskell-gi.cabal b/haskell-gi.cabal
--- a/haskell-gi.cabal
+++ b/haskell-gi.cabal
@@ -1,5 +1,5 @@
 name:                haskell-gi
-version:             0.26.15
+version:             0.26.16
 synopsis:            Generate Haskell bindings for GObject Introspection capable libraries
 description:         Generate Haskell bindings for GObject Introspection capable libraries. This includes most notably
                      GTK, but many other libraries in the GObject ecosystem provide introspection data too.
@@ -31,7 +31,7 @@
   default-language:    Haskell2010
   pkgconfig-depends:   gobject-introspection-1.0 >= 1.32, gobject-2.0 >= 2.32
   build-depends:       base >= 4.11 && < 5,
-                       haskell-gi-base >= 0.26.5 && <0.27,
+                       haskell-gi-base >= 0.26.9 && <0.27,
                        Cabal >= 1.24,
                        attoparsec >= 0.13,
                        containers,
diff --git a/lib/Data/GI/CodeGen/Callable.hs b/lib/Data/GI/CodeGen/Callable.hs
--- a/lib/Data/GI/CodeGen/Callable.hs
+++ b/lib/Data/GI/CodeGen/Callable.hs
@@ -391,17 +391,24 @@
   name' <- prepareInArg arg
   ft <- foreignType $ argType arg
   allocInfo <- typeAllocInfo (argType arg)
+
   case allocInfo of
     Just (TypeAlloc allocator n) -> do
-         wrapMaybe arg >>= bool
-            (do
-              name'' <- genConversion (prime name') $
-                        literal $ M $ allocator <>
-                                    " :: " <> typeShow (io ft)
-              line $ "memcpy " <> name'' <> " " <> name' <> " " <> tshow n
-              return name'')
-             -- The semantics of this case are somewhat undefined.
-            (notImplementedError "Nullable inout structs not supported")
+      when (transfer arg == TransferNothing && not (argCallerAllocates arg)) $
+        -- Although meaningful, this is almost always a bug in the
+        -- introspection data. Better not generating code than
+        -- generating code that crashes.
+        notImplementedError "‘transfer-ownership=none’ ‘caller-allocates=0’ inout structs not supported"
+
+      wrapMaybe arg >>= bool
+        (do
+            name'' <- genConversion (prime name') $
+                      literal $ M $ allocator <>
+                          " :: " <> typeShow (io ft)
+            line $ "memcpy " <> name'' <> " " <> name' <> " " <> tshow n
+            return name'')
+        -- The semantics of this case are somewhat undefined.
+        (notImplementedError "Nullable inout structs not supported")
     Nothing -> do
       if argCallerAllocates arg
       then return name'
diff --git a/lib/Data/GI/CodeGen/Properties.hs b/lib/Data/GI/CodeGen/Properties.hs
--- a/lib/Data/GI/CodeGen/Properties.hs
+++ b/lib/Data/GI/CodeGen/Properties.hs
@@ -448,6 +448,8 @@
     transferType <- if writable || constructOnly
                     then propTransferType (propType prop)
                     else return "()"
+    let puttable = readable && writable && inConstraint == ("(~) " <> outType)
+
     let allowedOps = (if writable
                       then ["'AttrSet", "'AttrConstruct"]
                       else [])
@@ -460,6 +462,9 @@
                      <> (if isNullable && propWriteNullable prop /= Just False
                          then ["'AttrClear"]
                          else [])
+                     <> (if puttable
+                         then ["'AttrPut"]
+                         else [])
     it <- infoType owner prop
     export docSection it
     api <- findAPIByName owner
@@ -483,6 +488,9 @@
             line $ "type AttrOrigin " <> it <> " = " <> name
             line $ "attrGet = " <> getter
             line $ "attrSet = " <> setter
+            if puttable
+              then line $ "attrPut = " <> setter
+              else line $ "attrPut = undefined"
             if writable || constructOnly
               then do line $ "attrTransfer _ v = do"
                       indent $ genPropTransfer "v" (propType prop)
