Skip to content

Commit

Permalink
[mypyc] Raise "non-trait base must be first..." error less frequently (
Browse files Browse the repository at this point in the history
…#14468)

It would raise even if there were only non-trait bases, leading to this
slightly confusing situation:

class A: pass
class B: pass
class C(A, B): pass # E: Non-trait bases must appear first in parent
list
# E: Multiple inheritance is not supported (except for traits)

Now the bases must include a non-trait *and* the first base must be a
trait to error. This leads to some false-negatives when there's more
than one non-trait base, but in that case, it's better to only tell the
user that multiple inheritance is not supported.

See also:
mypyc/mypyc#826 (comment)
  • Loading branch information
ichard26 authored Feb 5, 2023
1 parent 332bb2d commit 27f51fc
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 4 deletions.
8 changes: 6 additions & 2 deletions mypyc/irbuild/prepare.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,12 @@ def prepare_class_def(

# Set up the parent class
bases = [mapper.type_to_ir[base.type] for base in info.bases if base.type in mapper.type_to_ir]
if not all(c.is_trait for c in bases[1:]):
errors.error("Non-trait bases must appear first in parent list", path, cdef.line)
if len(bases) > 1 and any(not c.is_trait for c in bases) and bases[0].is_trait:
# If the first base is a non-trait, don't ever error here. While it is correct
# to error if a trait comes before the next non-trait base (e.g. non-trait, trait,
# non-trait), it's pointless, confusing noise from the bigger issue: multiple
# inheritance is *not* supported.
errors.error("Non-trait base must appear first in parent list", path, cdef.line)
ir.traits = [c for c in bases if c.is_trait]

mro = [] # All mypyc base classes
Expand Down
18 changes: 16 additions & 2 deletions mypyc/test-data/commandline.test
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class PureTrait:
pass

@trait
class Trait1(Concrete1):
class Trait1:
pass

class Concrete2:
Expand All @@ -164,9 +164,23 @@ class Trait2(Concrete2):
class NonExt(Concrete1): # E: Non-extension classes may not inherit from extension classes
pass

class Nope(Trait1, Concrete2): # E: Non-trait bases must appear first in parent list # E: Multiple inheritance is not supported (except for traits)

class NopeMultipleInheritance(Concrete1, Concrete2): # E: Multiple inheritance is not supported (except for traits)
pass

class NopeMultipleInheritanceAndBadOrder(Concrete1, Trait1, Concrete2): # E: Multiple inheritance is not supported (except for traits)
pass

class NopeMultipleInheritanceAndBadOrder2(Concrete1, Concrete2, Trait1): # E: Multiple inheritance is not supported (except for traits)
pass

class NopeMultipleInheritanceAndBadOrder3(Trait1, Concrete1, Concrete2): # E: Non-trait base must appear first in parent list # E: Multiple inheritance is not supported (except for traits)
pass

class NopeBadOrder(Trait1, Concrete2): # E: Non-trait base must appear first in parent list
pass


@decorator
class NonExt2:
@property # E: Property setters not supported in non-extension classes
Expand Down

0 comments on commit 27f51fc

Please sign in to comment.