Don't generate useless InheritTypes interfaces

Interfaces with no descendant need neither a Base trait nor upcast functions,
and interfaces with no ancestors neither a Derived trait nor downcast functions.
This commit is contained in:
Anthony Ramine 2015-09-25 02:06:55 +02:00
parent a7208869f2
commit e24b8ab644
2 changed files with 78 additions and 51 deletions

View file

@ -5811,42 +5811,69 @@ class GlobalGenRoots():
CGGeneric("use std::mem;\n\n")] CGGeneric("use std::mem;\n\n")]
for descriptor in descriptors: for descriptor in descriptors:
name = descriptor.name name = descriptor.name
protos = [CGGeneric("""\ chain = descriptor.prototypeChain
upcast = (descriptor.interface.getUserData("hasConcreteDescendant", False) or
descriptor.interface.getUserData("hasProxyDescendant", False))
downcast = len(chain) != 1
if upcast or downcast:
# Define a dummy structure to hold the cast functions.
allprotos.append(CGGeneric("pub struct %sCast;\n\n" % name))
if upcast:
# Define a `FooBase` trait for subclasses to implement, as well as the
# `FooCast::from_*` methods that use it.
allprotos.append(CGGeneric("""\
/// Types which are derived from `%(name)s` and can be freely converted /// Types which are derived from `%(name)s` and can be freely converted
/// to `%(name)s` /// to `%(name)s`
pub trait %(name)sBase : Sized {}\n""" % {'name': name})] pub trait %(baseTrait)s: Sized {}
for proto in descriptor.prototypeChain:
protos += [CGGeneric('impl %s for %s {}\n' % (proto + 'Base', impl %(name)sCast {
descriptor.concreteType))]
derived = [CGGeneric("""\
/// Types which `%(name)s` derives from
pub trait %(name)sDerived : Sized { fn %(method)s(&self) -> bool; }\n""" %
{'name': name, 'method': 'is_' + name.lower()})]
for protoName in descriptor.prototypeChain[1:-1]:
protoDescriptor = config.getDescriptor(protoName)
delegate = string.Template("""\
impl ${selfName} for ${baseName} {
#[inline] #[inline]
fn ${fname}(&self) -> bool { /// Upcast an instance of a derived class of `%(name)s` to `%(name)s`
let base: &${parentName} = ${parentName}Cast::from_ref(self); pub fn from_ref<T: %(baseTrait)s + Reflectable>(derived: &T) -> &%(name)s {
base.${fname}() unsafe { mem::transmute(derived) }
}
#[inline]
#[allow(unrooted_must_root)]
pub fn from_layout_js<T: %(baseTrait)s + Reflectable>(derived: &LayoutJS<T>) -> LayoutJS<%(name)s> {
unsafe { mem::transmute_copy(derived) }
}
#[inline]
pub fn from_root<T: %(baseTrait)s + Reflectable>(derived: Root<T>) -> Root<%(name)s> {
unsafe { mem::transmute(derived) }
} }
} }
""").substitute({'fname': 'is_' + name.lower(),
'selfName': name + 'Derived',
'baseName': protoDescriptor.concreteType,
'parentName': protoDescriptor.prototypeChain[-2]})
derived += [CGGeneric(delegate)]
derived += [CGGeneric('\n')]
cast = [CGGeneric(string.Template("""\ """ % {'baseTrait': name + 'Base', 'name': name}))
pub struct ${name}Cast; else:
impl ${name}Cast { # The `FooBase` trait is not defined, so avoid implementing it by
# removing `Foo` itself from the chain.
chain = descriptor.prototypeChain[:-1]
# Implement `BarBase` for `Foo`, for all `Bar` that `Foo` inherits from.
for baseName in chain:
allprotos.append(CGGeneric("impl %s for %s {}\n" % (baseName + 'Base', name)))
if chain:
allprotos.append(CGGeneric("\n"))
if downcast:
# Define a `FooDerived` trait for superclasses to implement,
# as well as the `FooCast::to_*` methods that use it.
allprotos.append(CGGeneric("""\
/// Types which `%(name)s` derives from
pub trait %(derivedTrait)s: Sized {
fn %(methodName)s(&self) -> bool;
}
impl %(name)sCast {
#[inline] #[inline]
/// Downcast an instance of a base class of `${name}` to an instance of /// Downcast an instance of a base class of `${name}` to an instance of
/// `${name}`, if it internally is an instance of `${name}` /// `${name}`, if it internally is an instance of `${name}`
pub fn to_ref<'a, T: ${toBound}+Reflectable>(base: &'a T) -> Option<&'a ${name}> { pub fn to_ref<T: %(derivedTrait)s + Reflectable>(base: &T) -> Option<&%(name)s> {
match base.${checkFn}() { match base.%(methodName)s() {
true => Some(unsafe { mem::transmute(base) }), true => Some(unsafe { mem::transmute(base) }),
false => None false => None
} }
@ -5854,9 +5881,9 @@ impl ${name}Cast {
#[inline] #[inline]
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn to_layout_js<T: ${toBound}+Reflectable>(base: &LayoutJS<T>) -> Option<LayoutJS<${name}>> { pub fn to_layout_js<T: %(derivedTrait)s + Reflectable>(base: &LayoutJS<T>) -> Option<LayoutJS<%(name)s>> {
unsafe { unsafe {
match (*base.unsafe_get()).${checkFn}() { match (*base.unsafe_get()).%(methodName)s() {
true => Some(mem::transmute_copy(base)), true => Some(mem::transmute_copy(base)),
false => None false => None
} }
@ -5864,36 +5891,36 @@ impl ${name}Cast {
} }
#[inline] #[inline]
pub fn to_root<T: ${toBound}+Reflectable>(base: Root<T>) -> Option<Root<${name}>> { pub fn to_root<T: %(derivedTrait)s + Reflectable>(base: Root<T>) -> Option<Root<%(name)s>> {
match base.r().${checkFn}() { match base.%(methodName)s() {
true => Some(unsafe { mem::transmute(base) }), true => Some(unsafe { mem::transmute(base) }),
false => None false => None
} }
} }
}
#[inline] """ % {'derivedTrait': name + 'Derived', 'name': name, 'methodName': 'is_' + name.lower()}))
/// Upcast an instance of a derived class of `${name}` to `${name}`
pub fn from_ref<'a, T: ${fromBound}+Reflectable>(derived: &'a T) -> &'a ${name} {
unsafe { mem::transmute(derived) }
}
# Implement the `FooDerived` trait for non-root superclasses by deferring to
# the direct superclass. This leaves the implementation of the `FooDerived`
# trait for the root superclass to manual code. `FooDerived` is not
# implemented for `Foo` itself.
for baseName in descriptor.prototypeChain[1:-1]:
args = {
'baseName': baseName,
'derivedTrait': name + 'Derived',
'methodName': 'is_' + name.lower(),
'parentName': config.getDescriptor(baseName).prototypeChain[-2],
}
allprotos.append(CGGeneric("""\
impl %(derivedTrait)s for %(baseName)s {
#[inline] #[inline]
#[allow(unrooted_must_root)] fn %(methodName)s(&self) -> bool {
pub fn from_layout_js<T: ${fromBound}+Reflectable>(derived: &LayoutJS<T>) -> LayoutJS<${name}> { %(parentName)sCast::from_ref(self).%(methodName)s()
unsafe { mem::transmute_copy(derived) }
}
#[inline]
pub fn from_root<T: ${fromBound}+Reflectable>(derived: Root<T>) -> Root<${name}> {
unsafe { mem::transmute(derived) }
} }
} }
""").substitute({'checkFn': 'is_' + name.lower(),
'name': name,
'fromBound': name + 'Base',
'toBound': name + 'Derived'}))]
allprotos += protos + derived + cast """ % args))
curr = CGList(allprotos) curr = CGList(allprotos)
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)

View file

@ -227,9 +227,9 @@ class Descriptor(DescriptorProvider):
if self.proxy: if self.proxy:
iface = self.interface iface = self.interface
while iface: while iface.parent:
iface.setUserData('hasProxyDescendant', True)
iface = iface.parent iface = iface.parent
iface.setUserData('hasProxyDescendant', True)
self.name = interface.identifier.name self.name = interface.identifier.name