qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 07/12] qapi/schema: make QAPISourceInfo mandatory


From: Eduardo Habkost
Subject: Re: [PATCH v2 07/12] qapi/schema: make QAPISourceInfo mandatory
Date: Wed, 13 Jan 2021 19:29:44 -0500

On Wed, Jan 13, 2021 at 06:04:29PM -0500, John Snow wrote:
> On 1/13/21 11:12 AM, Markus Armbruster wrote:
> > John Snow <jsnow@redhat.com> writes:
> > 
> > > Signed-off-by: John Snow <jsnow@redhat.com>
> > > 
> > > ---
> > > 
> > > The event_enum_members change might become irrelevant after a
> > > forthcoming (?) patch by Markus, but didn't have it in-hand at time of
> > > publishing.
> > 
> > It's in my "[PATCH 00/11] Drop support for QAPIGen without a file name",
> > which includes parts of your v1.  The parts that are new should be
> > injected into your series so they replace your "[PATCH v2 09/12]
> > qapi/gen: move write method to QAPIGenC, make fname a str".  Holler if
> > you need help.
> > 
> > > Signed-off-by: John Snow <jsnow@redhat.com>
> > > ---
> > >   scripts/qapi/events.py |  2 +-
> > >   scripts/qapi/schema.py | 25 ++++++++++++++-----------
> > >   scripts/qapi/types.py  |  9 +++++----
> > >   scripts/qapi/visit.py  |  6 +++---
> > >   4 files changed, 23 insertions(+), 19 deletions(-)
> > > 
> > > diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
> > > index 9851653b9d1..9ba4f109028 100644
> > > --- a/scripts/qapi/events.py
> > > +++ b/scripts/qapi/events.py
> > > @@ -225,7 +225,7 @@ def visit_event(self,
> > >                                             self._event_emit_name))
> > >           # Note: we generate the enum member regardless of @ifcond, to
> > >           # keep the enumeration usable in target-independent code.
> > > -        self._event_enum_members.append(QAPISchemaEnumMember(name, None))
> > > +        self._event_enum_members.append(QAPISchemaEnumMember(name, info))
> > 
> > This "enum" is not supposed to be erroneous.  If it is, it's a bug.
> > 
> > Your patch changes how the code behaves should such a bug bite here.
> > Before, we crash.  Afterwards, we report the bug using @info, which I'd
> > expect to produce utterly confusing error messages.
> > 
> 
> It doesn't change the behavior *here*, though. It changes it whenever this
> info object is used in another context. ... and who knows when or where or
> why it is being used, or by whom.
> 
> I'll have to play with this. I'm not sure there's any way to coax a bug to
> happen here that I am aware of right away. Can you think of how to will one
> into existence?
> 
> > My comments on PATCH 06 apply: how the code should behave here is a
> > design issue that should be kept out of this patch series.
> > 
> > If you need to pass a value other than None to help with static typing,
> > then pass a suitable poison info that will crash right where None
> > crashes now.

I don't understand what would be the point of inventing something
that behaves exactly like None but makes type checking less
useful.

With None/Optional, mypy gives us a way to be 100% sure the
object isn't going to invalid.  With a poison value, mypy can't
tell us anymore if the code risks crashing at runtime.

> > 
> 
> I think we need to, yes; or we probably really, really want to. Making the
> info parameter optional really adds a lot of unidiomatic type-checking
> confetti when we go to use info, and in many more contexts than just this
> sorta-built-in-enum; it will creep badly.

Which methods would require unidiomatic type-checking because of
None/Optional?

> 
> So, I gotta pass ...something here. but what? You want poison, but I think
> it's not right to fundamentally poison all built-ins.
> 
> Mmmmmmm. Maybe per-instance poison can be done? We actually share info
> objects, but I can make poisoned copies. Using next_line() as a basis:
> 
>     def poison(self: T) -> T:
>         info = copy.copy(self)
>         info.poisoned = True
>         return info
> 
> probably almost anything I do is not going to make a lot of sense unless I
> can actually replicate and test the different error scenarios to prove that
> we didn't make the error spaghetti unknowably worse. I see it as
> functionally inevitable that I have to audit this and make sure we get good
> error messages anyway, so ... maybe I just ought to do that now anyway.
> 
> > >   def gen_events(schema: QAPISchema,
> > > diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
> > > index 720449feee4..0449771dfe5 100644
> > > --- a/scripts/qapi/schema.py
> > > +++ b/scripts/qapi/schema.py
> > > @@ -23,6 +23,7 @@
> > >   from .error import QAPIError, QAPISemError
> > >   from .expr import check_exprs
> > >   from .parser import QAPISchemaParser
> > > +from .source import QAPISourceInfo
> > >   class QAPISchemaEntity:
> > > @@ -36,10 +37,10 @@ def __init__(self, name, info, doc, ifcond=None, 
> > > features=None):
> > >           self.name = name
> > >           self._module = None
> > >           # For explicitly defined entities, info points to the (explicit)
> > > -        # definition.  For builtins (and their arrays), info is None.
> > > -        # For implicitly defined entities, info points to a place that
> > > -        # triggered the implicit definition (there may be more than one
> > > -        # such place).
> > > +        # definition. For built-in types (and their arrays), info is a
> > > +        # special object that evaluates to False. For implicitly defined
> > > +        # entities, info points to a place that triggered the implicit
> > > +        # definition (there may be more than one such place).
> > >           self.info = info
> > >           self.doc = doc
> > >           self._ifcond = ifcond or []
> > > @@ -68,7 +69,7 @@ def check_doc(self):
> > >       def _set_module(self, schema, info):
> > >           assert self._checked
> > > -        self._module = schema.module_by_fname(info and info.fname)
> > > +        self._module = schema.module_by_fname(info.fname if info else 
> > > None)
> > 
> > Looks unrelated.
> > 
> 
> Hmm, it sorta is. I have apparently edited this patch since I sent it, but
> there was some tomfoolery over how "x and y" statements behave and this edit
> was necessary at the time.
> 
> "info and info.fname" returned None when info could actually be None, but
> when it was updated to be a special source object, we could accidentally
> pass that special source object as the name -- instead of None. Not good.
> 
> I think I re-ordered some patches such that I can just pass in "info.fname"
> unconditionally instead as of this patch.
> 
> > >           self._module.add_entity(self)
> > >       def set_module(self, schema):
> > [...]
> > 
> 

-- 
Eduardo




reply via email to

[Prev in Thread] Current Thread [Next in Thread]