diff options
author | Anthony Ramine <n.oxyde@gmail.com> | 2015-09-25 02:06:55 +0200 |
---|---|---|
committer | Anthony Ramine <n.oxyde@gmail.com> | 2015-10-02 16:15:12 +0200 |
commit | e24b8ab644129d9718d6f8175106adc8cdc63ee9 (patch) | |
tree | e4ceb1fe2e06d7bdff9346a42afb9a9f3773972f /components/script/dom | |
parent | a7208869f2903e36f9b2f540b55b50283d7df466 (diff) | |
download | servo-e24b8ab644129d9718d6f8175106adc8cdc63ee9.tar.gz servo-e24b8ab644129d9718d6f8175106adc8cdc63ee9.zip |
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.
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 129 | ||||
-rw-r--r-- | components/script/dom/bindings/codegen/Configuration.py | 4 |
2 files changed, 80 insertions, 53 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index eddeecb5086..49c0cf52cbc 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -5811,42 +5811,69 @@ class GlobalGenRoots(): CGGeneric("use std::mem;\n\n")] for descriptor in descriptors: 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 /// to `%(name)s` -pub trait %(name)sBase : Sized {}\n""" % {'name': name})] - for proto in descriptor.prototypeChain: - protos += [CGGeneric('impl %s for %s {}\n' % (proto + 'Base', - 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} { +pub trait %(baseTrait)s: Sized {} + +impl %(name)sCast { + #[inline] + /// Upcast an instance of a derived class of `%(name)s` to `%(name)s` + pub fn from_ref<T: %(baseTrait)s + Reflectable>(derived: &T) -> &%(name)s { + unsafe { mem::transmute(derived) } + } + #[inline] - fn ${fname}(&self) -> bool { - let base: &${parentName} = ${parentName}Cast::from_ref(self); - base.${fname}() + #[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("""\ -pub struct ${name}Cast; -impl ${name}Cast { + +""" % {'baseTrait': name + 'Base', 'name': name})) + else: + # 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] /// Downcast an instance of a base class of `${name}` to an instance of /// `${name}`, if it internally is an instance of `${name}` - pub fn to_ref<'a, T: ${toBound}+Reflectable>(base: &'a T) -> Option<&'a ${name}> { - match base.${checkFn}() { + pub fn to_ref<T: %(derivedTrait)s + Reflectable>(base: &T) -> Option<&%(name)s> { + match base.%(methodName)s() { true => Some(unsafe { mem::transmute(base) }), false => None } @@ -5854,9 +5881,9 @@ impl ${name}Cast { #[inline] #[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 { - match (*base.unsafe_get()).${checkFn}() { + match (*base.unsafe_get()).%(methodName)s() { true => Some(mem::transmute_copy(base)), false => None } @@ -5864,36 +5891,36 @@ impl ${name}Cast { } #[inline] - pub fn to_root<T: ${toBound}+Reflectable>(base: Root<T>) -> Option<Root<${name}>> { - match base.r().${checkFn}() { + pub fn to_root<T: %(derivedTrait)s + Reflectable>(base: Root<T>) -> Option<Root<%(name)s>> { + match base.%(methodName)s() { true => Some(unsafe { mem::transmute(base) }), false => None } } +} +""" % {'derivedTrait': name + 'Derived', 'name': name, 'methodName': 'is_' + name.lower()})) + + # 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] - /// 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) } - } - - #[inline] - #[allow(unrooted_must_root)] - pub fn from_layout_js<T: ${fromBound}+Reflectable>(derived: &LayoutJS<T>) -> LayoutJS<${name}> { - unsafe { mem::transmute_copy(derived) } - } - - #[inline] - pub fn from_root<T: ${fromBound}+Reflectable>(derived: Root<T>) -> Root<${name}> { - unsafe { mem::transmute(derived) } + fn %(methodName)s(&self) -> bool { + %(parentName)sCast::from_ref(self).%(methodName)s() } } -""").substitute({'checkFn': 'is_' + name.lower(), - 'name': name, - 'fromBound': name + 'Base', - 'toBound': name + 'Derived'}))] - allprotos += protos + derived + cast +""" % args)) curr = CGList(allprotos) curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py index 5e1c8844276..a8179c5be95 100644 --- a/components/script/dom/bindings/codegen/Configuration.py +++ b/components/script/dom/bindings/codegen/Configuration.py @@ -227,9 +227,9 @@ class Descriptor(DescriptorProvider): if self.proxy: iface = self.interface - while iface: - iface.setUserData('hasProxyDescendant', True) + while iface.parent: iface = iface.parent + iface.setUserData('hasProxyDescendant', True) self.name = interface.identifier.name |