@@ -436,13 +436,29 @@ abstract class InheritingContainer extends Container {
436
436
/// and so unlike other `public*` methods, is not a strict subset of
437
437
/// [directInterfaces] (the direct interfaces).
438
438
List <DefinedElementType > get publicInterfaces {
439
+ var interfaceElements = < InterfaceElement > {};
439
440
var interfaces = < DefinedElementType > [];
441
+
442
+ // Only interfaces with unique elements should be returned. Elements can
443
+ // implement an interface through multiple inheritance routes (e.g.
444
+ // `List<E>` implements `Iterable<E>` but also `_ListIterable<E>` which
445
+ // implements `EfficientLengthIterable<T>` which implements `Iterable<T>`),
446
+ // but there is no chance of type arguments differing, as that is illegal.
447
+ void addInterfaceIfUnique (DefinedElementType type) {
448
+ var firstPublicSuperElement = type.modelElement.element;
449
+ if (firstPublicSuperElement is InterfaceElement ) {
450
+ if (interfaceElements.add (firstPublicSuperElement)) {
451
+ interfaces.add (type);
452
+ }
453
+ }
454
+ }
455
+
440
456
for (var interface in directInterfaces) {
441
457
var interfaceElement = interface .modelElement;
442
458
443
459
/// Do not recurse if we can find an element here.
444
460
if (interfaceElement.canonicalModelElement != null ) {
445
- interfaces. add (interface );
461
+ addInterfaceIfUnique (interface );
446
462
continue ;
447
463
}
448
464
// Public types used to be unconditionally exposed here. However,
@@ -466,9 +482,9 @@ abstract class InheritingContainer extends Container {
466
482
}
467
483
var publicSuperChain = interfaceElement.superChain.wherePublic;
468
484
if (publicSuperChain.isNotEmpty) {
469
- interfaces. add (publicSuperChain.first);
485
+ addInterfaceIfUnique (publicSuperChain.first);
470
486
}
471
- interfaces. addAll ( interfaceElement.publicInterfaces);
487
+ interfaceElement.publicInterfaces. forEach (addInterfaceIfUnique );
472
488
}
473
489
return interfaces;
474
490
}
0 commit comments