user1983: I want to use String or Text in a Datum, like this:
import PlutusTx.Prelude

newtype MyDatum = MyDatum {userReadableStuff :: BuiltinString}
PlutusTx.unstableMakeIsData ''MyDatum

but the complier complains:
• No instance for (PlutusTx.IsData BuiltinString)
    arising from a use of ‘PlutusTx.fromBuiltinData’
• In the second argument of ‘(<*>)’, namely
    ‘PlutusTx.fromBuiltinData arg_a2lNn’
  In the second argument of ‘PlutusTx.Builtins.matchList’, namely
    ‘(pure MyDatum <*> PlutusTx.fromBuiltinData arg_a2lNn)’
  In the expression:
    ((PlutusTx.Builtins.matchList t_a2lNq)
       (pure MyDatum <*> PlutusTx.fromBuiltinData arg_a2lNn))
      (\ _ _ -> Nothing)typecheck(-Wdeferred-type-errors)
• No instance for (PlutusTx.IsData BuiltinString)
    arising from a use of ‘PlutusTx.toBuiltinData’
• In the first argument of ‘PlutusTx.Builtins.Internal.mkCons’, namely
    ‘(PlutusTx.toBuiltinData arg_a2lNi)’
  In the second argument of ‘PlutusTx.Builtins.Internal.mkConstr’, namely
    ‘((PlutusTx.Builtins.Internal.mkCons
         (PlutusTx.toBuiltinData arg_a2lNi))
        (PlutusTx.Builtins.Internal.mkNilData
           PlutusTx.Builtins.Internal.unitval))’
  In the expression:
    (PlutusTx.Builtins.Internal.mkConstr 0)
      ((PlutusTx.Builtins.Internal.mkCons
          (PlutusTx.toBuiltinData arg_a2lNi))
         (PlutusTx.Builtins.Internal.mkNilData
            PlutusTx.Builtins.Internal.unitval))typecheck(-Wdeferred-type-errors)
• No instance for (PlutusTx.IsData BuiltinString)
    arising from a use of ‘PlutusTx.unsafeFromBuiltinData’
• In the first argument of ‘MyDatum’, namely
    ‘(PlutusTx.unsafeFromBuiltinData arg_a2lNv)’
  In the expression:
    MyDatum (PlutusTx.unsafeFromBuiltinData arg_a2lNv)
  In the expression:
    let
      t_a2lNy = PlutusTx.Builtins.Internal.snd tup_a2lNu
      arg_a2lNv = PlutusTx.Builtins.Internal.head t_a2lNy
    in MyDatum (PlutusTx.unsafeFromBuiltinData arg_a2lNv)typecheck(-Wdeferred-type-errors)

I could use ByteString -- about which the compiler has no complaints, and then use helper functions for
Text <-> ByteString, as shown at end of this.  But what I really want is for end user to see the datum in the script, and be able to read directly from the datum.

user387: Not really sure what you mean by "end user to see the datum in the script" and how having a Text or String in the datum would make any difference to this. Datums are not easily visible to everyone and certainly not to "end users".
However, if you want to use BuiltinString in MyDatum, you could write your own instances for ToData, FromData and UnsafeFromData via BuiltinByteString and encodeUtf8/decodeUtf8 from PlutusTx.Builtins.
Something like the following could work:
instance ToData MyDatum where
  toBuiltinData = toBuiltinData . encodeUtf8 . userReadableStuff

instance FromData MyDatum where
  fromBuiltinData = MyDatum . decodeUtf8 <$> fromBuiltinData

instance UnsafeFromData MyDatum where
  unsafeFromBuiltinData = MyDatum . decodeUtf8 . unsafeFromBuiltinData

Note: I had a quick look at the implementation of the builtin encodeUtf8, this might not be what you expect (it seems to be currently ASCII encoding and truncating any code points outside of the 8bit range).

1983: <p>I want to use String or Text in a Datum, like this:</p>
<pre><code>import PlutusTx.Prelude

newtype MyDatum = MyDatum {userReadableStuff :: BuiltinString}
PlutusTx.unstableMakeIsData ''MyDatum
</code></pre>
<p>but the complier complains:</p>
<pre><code>• No instance for (PlutusTx.IsData BuiltinString)
    arising from a use of ‘PlutusTx.fromBuiltinData’
• In the second argument of ‘(&lt;*&gt;)’, namely
    ‘PlutusTx.fromBuiltinData arg_a2lNn’
  In the second argument of ‘PlutusTx.Builtins.matchList’, namely
    ‘(pure MyDatum &lt;*&gt; PlutusTx.fromBuiltinData arg_a2lNn)’
  In the expression:
    ((PlutusTx.Builtins.matchList t_a2lNq)
       (pure MyDatum &lt;*&gt; PlutusTx.fromBuiltinData arg_a2lNn))
      (\ _ _ -&gt; Nothing)typecheck(-Wdeferred-type-errors)
• No instance for (PlutusTx.IsData BuiltinString)
    arising from a use of ‘PlutusTx.toBuiltinData’
• In the first argument of ‘PlutusTx.Builtins.Internal.mkCons’, namely
    ‘(PlutusTx.toBuiltinData arg_a2lNi)’
  In the second argument of ‘PlutusTx.Builtins.Internal.mkConstr’, namely
    ‘((PlutusTx.Builtins.Internal.mkCons
         (PlutusTx.toBuiltinData arg_a2lNi))
        (PlutusTx.Builtins.Internal.mkNilData
           PlutusTx.Builtins.Internal.unitval))’
  In the expression:
    (PlutusTx.Builtins.Internal.mkConstr 0)
      ((PlutusTx.Builtins.Internal.mkCons
          (PlutusTx.toBuiltinData arg_a2lNi))
         (PlutusTx.Builtins.Internal.mkNilData
            PlutusTx.Builtins.Internal.unitval))typecheck(-Wdeferred-type-errors)
• No instance for (PlutusTx.IsData BuiltinString)
    arising from a use of ‘PlutusTx.unsafeFromBuiltinData’
• In the first argument of ‘MyDatum’, namely
    ‘(PlutusTx.unsafeFromBuiltinData arg_a2lNv)’
  In the expression:
    MyDatum (PlutusTx.unsafeFromBuiltinData arg_a2lNv)
  In the expression:
    let
      t_a2lNy = PlutusTx.Builtins.Internal.snd tup_a2lNu
      arg_a2lNv = PlutusTx.Builtins.Internal.head t_a2lNy
    in MyDatum (PlutusTx.unsafeFromBuiltinData arg_a2lNv)typecheck(-Wdeferred-type-errors)
</code></pre>
<p>I could use <code>ByteString</code> -- about which the compiler has no complaints, and then use helper functions for
<code>Text</code> &lt;-&gt; <code>ByteString</code>, as <a href="https://stackoverflow.com/questions/7357775/text-or-bytestring">shown at end of this</a>.  But what I really want is for end user to see the datum in the script, and be able to read directly from the datum.</p>
 387: <p>Not really sure what you mean by &quot;end user to see the datum in the script&quot; and how having a <code>Text</code> or <code>String</code> in the datum would make any difference to this. Datums are not easily visible to everyone and certainly not to &quot;end users&quot;.</p>
<p>However, if you want to use <code>BuiltinString</code> in <code>MyDatum</code>, you could write your own instances for <code>ToData</code>, <code>FromData</code> and <code>UnsafeFromData</code> via <code>BuiltinByteString</code> and <code>encodeUtf8</code>/<code>decodeUtf8</code> from <code>PlutusTx.Builtins</code>.</p>
<p>Something like the following could work:</p>
<pre><code>instance ToData MyDatum where
  toBuiltinData = toBuiltinData . encodeUtf8 . userReadableStuff

instance FromData MyDatum where
  fromBuiltinData = MyDatum . decodeUtf8 &lt;$&gt; fromBuiltinData

instance UnsafeFromData MyDatum where
  unsafeFromBuiltinData = MyDatum . decodeUtf8 . unsafeFromBuiltinData
</code></pre>
<p>Note: I had a quick look at the implementation of the builtin <code>encodeUtf8</code>, this might not be what you expect (it seems to be currently ASCII encoding and truncating any code points outside of the 8bit range).</p>
