Update rustfmt configuration

parent 31ff9880
Pipeline #35863 passed with stages
in 7 minutes
......@@ -5,4 +5,4 @@ newline_style = "Unix"
format_strings = true
normalize_comments = true
use_field_init_shorthand = true
edition = "Edition2018"
edition = "2018"
// use lalrpop_intern::InternedString;
use parser::keywords;
use proc_macro2::Ident;
use syn::punctuated::Punctuated;
use syn::{Attribute, Lit};
use parser::keywords;
use syn::token;
use syn::spanned::Spanned;
use syn::token;
use syn::{Attribute, Lit};
use syn::{Block, FieldsNamed, FnArg, Path, ReturnType, Type};
pub struct Program {
......@@ -50,7 +50,8 @@ pub fn get_program_classes<'a>(program: &'a Program) -> Vec<&'a Class> {
} else {
None
}
}).collect()
})
.collect()
}
pub struct Class {
......@@ -90,21 +91,20 @@ pub enum ImplItemKind {
ReserveSlots(Lit),
}
impl ImplItemKind
{
impl ImplItemKind {
pub fn ident_span(&self) -> ::proc_macro2::Span {
match self {
ImplItemKind::Method(ImplItemMethod { ref name, ..}) => name.span(),
ImplItemKind::Prop(ImplProp { ref name, ..}) => name.span(),
ImplItemKind::Method(ImplItemMethod { ref name, .. }) => name.span(),
ImplItemKind::Prop(ImplProp { ref name, .. }) => name.span(),
ImplItemKind::ReserveSlots(ref l) => l.span(),
}
}
}
pub struct ImplItemMethod {
pub public: Option<Token![pub]>, // requires body
pub public: Option<Token![pub]>, // requires body
pub virtual_: Option<Token![virtual]>, // implies public, doesn't need body
pub signal: Option<keywords::signal>, // ignore
pub signal: Option<keywords::signal>, // ignore
pub fn_: Token![fn],
pub name: Ident,
pub parem_token: token::Paren,
......@@ -113,16 +113,13 @@ pub struct ImplItemMethod {
pub body: ImplItemMethodBlock,
}
pub enum ImplItemMethodBlock
{
pub enum ImplItemMethodBlock {
Block(Block),
Empty(Token![;]),
}
impl ImplItemMethodBlock
{
pub fn as_ref(&self) -> Option<&Block>
{
impl ImplItemMethodBlock {
pub fn as_ref(&self) -> Option<&Block> {
match self {
ImplItemMethodBlock::Block(ref b) => Some(b),
ImplItemMethodBlock::Empty(_) => None,
......
......@@ -28,7 +28,7 @@ pub mod tests {
fn checks_empty_class() -> Result<()> {
let raw = "class Foo {}";
let program : ast::Program = ::syn::parse_str(raw)?;
let program: ast::Program = ::syn::parse_str(raw)?;
check_program(&program)
}
......
......@@ -4,13 +4,13 @@ use quote::ToTokens;
use xml::writer::{EmitterConfig, XmlEvent};
use xml::EventWriter;
use hir::{Program, Class, Slot, Method, Ty, FnArg};
use glib_utils::*;
use gen::names::Names;
use glib_utils::*;
use hir::{Class, FnArg, Method, Program, Slot, Ty};
use errors::*;
use xml::writer::{Result as EmitterResult};
use xml::writer::Result as EmitterResult;
pub fn generate(program: &Program) -> Result<()> {
for class in program.classes.iter() {
......@@ -22,7 +22,8 @@ pub fn generate(program: &Program) -> Result<()> {
pub fn generate_gir(class: &Class) -> Result<()> {
if let Some(ref s) = class.gir {
let mut f = File::create(&s.value()).map_err(|err| Error::new(s.span(), err.to_string()))?;;
let mut f =
File::create(&s.value()).map_err(|err| Error::new(s.span(), err.to_string()))?;;
generate_gir_xml(class, &mut f).map_err(|err| Error::new(s.span(), err.to_string()))?;
}
......@@ -30,11 +31,8 @@ pub fn generate_gir(class: &Class) -> Result<()> {
Ok(())
}
fn generate_gir_xml(class: &Class, f: &mut File) -> EmitterResult<()>
{
let mut w = EmitterConfig::new()
.perform_indent(true)
.create_writer(f);
fn generate_gir_xml(class: &Class, f: &mut File) -> EmitterResult<()> {
let mut w = EmitterConfig::new().perform_indent(true).create_writer(f);
let name = class.name.to_string();
let lower_name = lower_case_instance_name(&name).to_string();
......@@ -51,37 +49,42 @@ fn generate_gir_xml(class: &Class, f: &mut File) -> EmitterResult<()>
// the dep should be `("GLib", "2.0")` lib and version
let deps: Vec<(&str, &str)> = vec![];
w.write(XmlEvent::start_element("repository")
.attr("version", "1.2")
.attr("xmlns", "http://www.gtk.org/introspection/core/1.0")
.attr("xmlns:c", "http://www.gtk.org/introspection/c/1.0")
.attr("xmlns:glib", "http://www.gtk.org/introspection/glib/1.0"))?;
w.write(
XmlEvent::start_element("repository")
.attr("version", "1.2")
.attr("xmlns", "http://www.gtk.org/introspection/core/1.0")
.attr("xmlns:c", "http://www.gtk.org/introspection/c/1.0")
.attr("xmlns:glib", "http://www.gtk.org/introspection/glib/1.0"),
)?;
// <include name="GLib" version="2.0"/>
for (name, version) in deps {
w.write(XmlEvent::start_element("include")
.attr("name", name)
.attr("version", version)
w.write(
XmlEvent::start_element("include")
.attr("name", name)
.attr("version", version),
)?;
w.write(XmlEvent::end_element())?;
}
w.write(XmlEvent::start_element("namespace")
.attr("name", &name)
.attr("c:identifier-prefixes", &name)
.attr("c:symbol-prefixes", &lower_name)
.attr("version", &version)
.attr("shared-library", &slib)
w.write(
XmlEvent::start_element("namespace")
.attr("name", &name)
.attr("c:identifier-prefixes", &name)
.attr("c:symbol-prefixes", &lower_name)
.attr("version", &version)
.attr("shared-library", &slib),
)?;
w.write(XmlEvent::start_element("class")
.attr("name", &name)
.attr("c:type", &name)
.attr("glib:type-name", &name)
.attr("c:symbol-prefix", &lower_name)
.attr("glib:type-struct", &names.vtable().to_string())
.attr("glib:get-type", &names.get_type_fn().to_string())
.attr("parent", &parent_name)
w.write(
XmlEvent::start_element("class")
.attr("name", &name)
.attr("c:type", &name)
.attr("glib:type-name", &name)
.attr("c:symbol-prefix", &lower_name)
.attr("glib:type-struct", &names.vtable().to_string())
.attr("glib:get-type", &names.get_type_fn().to_string())
.attr("parent", &parent_name),
)?;
gen_constructor_xml(&mut w, &names)?;
......@@ -129,31 +132,43 @@ fn gen_slot_xml(w: &mut EventWriter<&mut File>, names: &Names, slot: &Slot) -> E
let name = sig.name.to_string();
let identifier = names.exported_fn(&sig.name).to_string();
let output_ctype = type_to_ctype(&sig.output);
w.write(XmlEvent::start_element("method")
.attr("name", &name)
.attr("c:identifier", &identifier)
w.write(
XmlEvent::start_element("method")
.attr("name", &name)
.attr("c:identifier", &identifier),
)?;
// FIXME, calculate the ownership transfer for pointer types
w.write(XmlEvent::start_element("return-value").attr("transfer-ownership", "none"))?;
w.write(XmlEvent::start_element("type").attr("name", &output_ctype)
.attr("c:type", &output_ctype))?;
w.write(
XmlEvent::start_element("type")
.attr("name", &output_ctype)
.attr("c:type", &output_ctype),
)?;
w.write(XmlEvent::end_element())?; // closing type
w.write(XmlEvent::end_element())?; // closing return-value
// TODO: add parameters here
w.write(XmlEvent::start_element("parameters"))?;
for param in sig.inputs.iter() {
if let FnArg::Arg { ref name, ref ty, .. } = param {
if let FnArg::Arg {
ref name, ref ty, ..
} = param
{
let ownership = "none";
let ctype = type_to_ctype(ty);
w.write(XmlEvent::start_element("parameter")
.attr("name", &name.to_string())
.attr("transfer-ownership", ownership))?;
w.write(XmlEvent::start_element("type")
.attr("name", &ctype).attr("c:type", &ctype))?;
w.write(
XmlEvent::start_element("parameter")
.attr("name", &name.to_string())
.attr("transfer-ownership", ownership),
)?;
w.write(
XmlEvent::start_element("type")
.attr("name", &ctype)
.attr("c:type", &ctype),
)?;
w.write(XmlEvent::end_element())?; // closing type
w.write(XmlEvent::end_element())?; // closing parameter
......@@ -164,7 +179,7 @@ fn gen_slot_xml(w: &mut EventWriter<&mut File>, names: &Names, slot: &Slot) -> E
// TODO: add doc here?
w.write(XmlEvent::end_element())?;
},
}
_ => {
// VirtualMethod or Signal
}
......@@ -183,13 +198,18 @@ fn gen_constructor_xml(w: &mut EventWriter<&mut File>, names: &Names) -> Emitter
let identifier = names.exported_fn_from_str("new").to_string();
let name = names.instance().to_string();
let ctype = format!("{}*", name);
w.write(XmlEvent::start_element("constructor")
.attr("name", "new")
.attr("c:identifier", &identifier)
w.write(
XmlEvent::start_element("constructor")
.attr("name", "new")
.attr("c:identifier", &identifier),
)?;
w.write(XmlEvent::start_element("return-value").attr("transfer-ownership", "full"))?;
w.write(XmlEvent::start_element("type").attr("name", &name).attr("c:type", &ctype))?;
w.write(
XmlEvent::start_element("type")
.attr("name", &name)
.attr("c:type", &ctype),
)?;
w.write(XmlEvent::end_element())?; // closing type
w.write(XmlEvent::end_element())?; // closing return-value
......@@ -217,10 +237,11 @@ fn gen_record_xml(w: &mut EventWriter<&mut File>, names: &Names) -> EmitterResul
// disguised="1"
// glib:is-gtype-struct-for="Counter">
// </record>
w.write(XmlEvent::start_element("record")
.attr("name", &names.vtable().to_string())
.attr("disguised", "1")
.attr("glib:is-gtype-struct-for", &names.instance().to_string())
w.write(
XmlEvent::start_element("record")
.attr("name", &names.vtable().to_string())
.attr("disguised", "1")
.attr("glib:is-gtype-struct-for", &names.instance().to_string()),
)?;
w.write(XmlEvent::end_element())?;
......
......@@ -33,7 +33,8 @@ pub fn slot_assignments<'ast>(names: &Names, slots: &[Slot<'ast>]) -> Vec<TokenS
vtable.#signalname = Some(#InstanceNameFfi::#trampoline_name);
})
}
}).collect::<Vec<_>>()
})
.collect::<Vec<_>>()
}
// If you rename this function, or move stuff out of it, please
......@@ -84,7 +85,8 @@ pub fn instance_slot_trampolines<'ast>(
Slot::VirtualMethod(VirtualMethod { ref sig, .. }) => Some(tokens(sig, None)),
Slot::Signal(ref signal) => Some(tokens(&signal.sig, None)),
}).collect::<Vec<_>>();
})
.collect::<Vec<_>>();
if let Some(overrides) = overrides {
ret.extend(
......@@ -193,9 +195,8 @@ pub fn extern_methods<'ast>(names: &Names, slots: &[Slot<'ast>]) -> Vec<TokenStr
.iter()
.filter_map(|slot| {
match *slot {
Slot::Method(Method { public: false, .. }) => None, /* these don't get exposed
* in the C API */
Slot::Method(Method { public: false, .. }) => None, // these don't get exposed
// in the C API
Slot::Method(Method {
public: true,
ref sig,
......@@ -245,5 +246,6 @@ pub fn extern_methods<'ast>(names: &Names, slots: &[Slot<'ast>]) -> Vec<TokenStr
Slot::Signal(_) => None, // these don't get exposed in the C API
}
}).collect()
})
.collect()
}
......@@ -7,6 +7,7 @@ use std::fmt::Display;
mod boilerplate;
mod class;
mod cstringliteral;
pub mod gir;
mod imp;
mod instance_ext;
mod interface;
......@@ -15,7 +16,6 @@ mod properties;
mod signals;
mod signatures;
mod slots;
pub mod gir;
use self::class::ClassContext;
use self::interface::InterfaceContext;
......@@ -29,7 +29,8 @@ pub fn codegen(program: &Program) -> TokenStream {
.map(|class| {
let cx = ClassContext::new(program, class);
cx.gen_class()
}).collect::<Vec<_>>();
})
.collect::<Vec<_>>();
let interface_tokens = program
.interfaces
......@@ -37,7 +38,8 @@ pub fn codegen(program: &Program) -> TokenStream {
.map(|iface| {
let cx = InterfaceContext::new(program, iface);
cx.gen_interface()
}).collect::<Vec<_>>();
})
.collect::<Vec<_>>();
quote! {
#(#class_tokens)*
......
......@@ -15,7 +15,8 @@ pub fn properties_enum<'ast>(properties: &[Property<'ast>]) -> TokenStream {
let name = &prop.name;
let index = (i as u32) + 1;
quote! { #name = #index }
}).collect();
})
.collect();
quote! {
#[repr(u32)]
......@@ -42,7 +43,8 @@ pub fn property_setter<'ast>(properties: &[Property<'ast>]) -> TokenStream {
#body
}
}
}).collect();
})
.collect();
quote! {
#[allow(dead_code, unused_variables)]
......@@ -80,7 +82,8 @@ pub fn property_getter<'ast>(properties: &[Property<'ast>]) -> TokenStream {
}
}
}
}).collect();
})
.collect();
quote! {
#[allow(dead_code, unused_variables)]
......@@ -116,7 +119,8 @@ pub fn set_properties<'ast>(properties: &[Property<'ast>]) -> Vec<TokenStream> {
}
}
}
}).collect()
})
.collect()
}
pub fn get_properties<'ast>(properties: &[Property<'ast>]) -> Vec<TokenStream> {
......@@ -142,7 +146,8 @@ pub fn get_properties<'ast>(properties: &[Property<'ast>]) -> Vec<TokenStream> {
value.get::<#type_>().unwrap()
}
}
}).collect()
})
.collect()
}
pub fn set_properties_fn<'ast>(properties: &[Property<'ast>]) -> Vec<TokenStream> {
......@@ -158,7 +163,8 @@ pub fn set_properties_fn<'ast>(properties: &[Property<'ast>]) -> Vec<TokenStream
quote! {
fn #name(&self, v: #type_);
}
}).collect()
})
.collect()
}
pub fn get_properties_fn<'ast>(properties: &[Property<'ast>]) -> Vec<TokenStream> {
......@@ -174,7 +180,8 @@ pub fn get_properties_fn<'ast>(properties: &[Property<'ast>]) -> Vec<TokenStream
quote! {
fn #name(&self) -> #type_;
}
}).collect()
})
.collect()
}
fn prop_registration<'ast>(properties: &[Property<'ast>]) -> Vec<TokenStream> {
......@@ -213,7 +220,8 @@ fn prop_registration<'ast>(properties: &[Property<'ast>]) -> Vec<TokenStream> {
//| gobject_ffi::G_PARAM_CONSTRUCT_ONLY,
));
}
}).collect()
})
.collect()
}
pub fn properties_registration<'ast>(properties: &[Property<'ast>]) -> TokenStream {
......
......@@ -63,7 +63,8 @@ pub fn signal_emit_methods<'ast>(
}
}
}
}).collect()
})
.collect()
}
pub fn signal_id_names<'ast>(signals: impl Iterator<Item = &'ast Signal<'ast>>) -> Vec<Ident> {
......@@ -92,7 +93,10 @@ pub fn signal_declarations<'ast>(
assert!(!signal.sig.inputs.is_empty());
let n_params = (signal.sig.inputs.len() - 1) as u32;
let param_gtypes: Vec<Path> = signal.sig.inputs.iter()
let param_gtypes: Vec<Path> = signal
.sig
.inputs
.iter()
.skip(1) // skip &self
.map(|arg| {
if let FnArg::Arg { ref ty, .. } = arg {
......@@ -125,7 +129,8 @@ pub fn signal_declarations<'ast>(
mut_override(param_gtypes.as_ptr())
);
}
}).collect()
})
.collect()
}
pub fn signal_trampolines<'ast>(
......@@ -165,7 +170,8 @@ pub fn signal_trampolines<'ast>(
#ret
}
}
}).collect()
})
.collect()
}
/// From a signal called `foo`, generate `foo_signal_id`. This is used to
......
......@@ -117,18 +117,21 @@ impl<'ast> ToTokens for ToGlibType<'ast> {
Ty::Char(ref i) | Ty::Bool(ref i) => {
(quote! {
<#i as ToGlib>::GlibType
}).to_tokens(tokens);
})
.to_tokens(tokens);
}
Ty::Borrowed(ref t) => {
(quote! {
<#t as GlibPtrDefault>::GlibType
}).to_tokens(tokens);
})
.to_tokens(tokens);
}
Ty::Integer(ref i) => i.to_tokens(tokens),
Ty::Owned(ref t) => {
(quote! {
<#t as GlibPtrDefault>::GlibType
}).to_tokens(tokens);
})
.to_tokens(tokens);
}
}
}
......@@ -146,17 +149,20 @@ impl<'ast, T: ToTokens> ToTokens for ToGlib<'ast, T> {
Ty::Char(ref i) | Ty::Bool(ref i) => {
(quote! {
<#i as ToGlib>::to_glib(&#expr)
}).to_tokens(tokens);
})
.to_tokens(tokens);
}
Ty::Borrowed(ref t) => {
(quote! {
<#t as ToGlibPtr<_>>::to_glib_none(#expr).0
}).to_tokens(tokens);
})
.to_tokens(tokens);
}
Ty::Owned(ref t) => {
(quote! {
<#t as ToGlibPtr<_>>::to_glib_full(&#expr)
}).to_tokens(tokens);
})
.to_tokens(tokens);
}
}
}
......@@ -167,20 +173,23 @@ struct FromGlib<'ast>(&'ast Ty<'ast>, TokenStream);
impl<'ast> ToTokens for FromGlib<'ast> {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
FromGlib(Ty::Unit, inner) => { inner.to_tokens(tokens); }, // no conversion necessary
FromGlib(Ty::Unit, inner) => {
inner.to_tokens(tokens);
} // no conversion necessary
FromGlib(Ty::Char(ref i), inner) | FromGlib(Ty::Bool(ref i), inner) => {
tokens.extend(quote! {
<#i as FromGlib<_>>::from_glib(#inner)
}) },
FromGlib(Ty::Borrowed(ref t), inner) => {
tokens.extend(quote! {
&<#t as FromGlibPtrBorrow<_>>::from_glib_borrow(#inner)
}) },
})
}
FromGlib(Ty::Borrowed(ref t), inner) => tokens.extend(quote! {
&<#t as FromGlibPtrBorrow<_>>::from_glib_borrow(#inner)
}),
FromGlib(Ty::Integer(_), inner) => inner.to_tokens(tokens), // no conversion necessary
FromGlib(Ty::Owned(t), inner) => {
tokens.extend(quote! {
unsafe { <#t as FromGlibPtrFull<_>>::from_glib_full(#inner) }
}); }
});
}
}
}
}
......
......@@ -28,7 +28,8 @@ impl<'ast> ToTokens for SlotDeclaration<'ast> {
this: *mut #InstanceNameFfi,
#inputs
) -> #output>,
}).to_tokens(tokens);
})
.to_tokens(tokens);
}
Slot::Signal(ref signal) => {
......@@ -41,7 +42,8 @@ impl<'ast> ToTokens for SlotDeclaration<'ast> {
this: *mut #InstanceNameFfi,
#inputs
) -> #output>,
}).to_tokens(tokens);
})
.to_tokens(tokens);
}
}
}
......
......@@ -24,7 +24,8 @@ pub fn tokens_ParentInstance(class: &ast::Class) -> TokenStream {
let mut tokens = TokenStream::new();
path.to_tokens(&mut tokens);
tokens
}).unwrap_or_else(tokens_GObject)
})
.unwrap_or_else(tokens_GObject)
}
pub fn tokens_ParentInstanceFfi(class: &ast::Class) -> TokenStream {
......
......@@ -12,7 +12,7 @@ use proc_macro2::{Ident, Span, TokenStream};
use quote::ToTokens;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{self, parse_str, Block, Field, Path, ReturnType, Type, LitStr};
use syn::{self, parse_str, Block, Field, LitStr, Path, ReturnType, Type};
use super::ast;
use super::checking::*;
......@@ -177,23 +177,38 @@ impl<'ast> Classes<'ast> {
self.items.iter().find(|c| c.1.name == name).unwrap().1
}
fn extract_gir_from_attribute(class: &'ast ast::Class) -> Result<Option<LitStr>>
{
fn extract_gir_from_attribute(class: &'ast ast::Class) -> Result<Option<LitStr>> {
let mut res = None;
for attr in class.attrs.iter() {
if let Some(syn::Meta::List(metalist)) = attr.interpret_meta() {
if metalist.ident == "generate_gir" {
if metalist.nested.len() != 1 {
return Err(Error::new(metalist.ident.span(), "Only one generate_gir allowed"));
return Err(Error::new(
metalist.ident.span(),
"Only one generate_gir allowed",
));
}
match metalist.nested.into_iter().next().expect("Length checked above") {
match metalist
.nested
.into_iter()
.next()
.expect("Length checked above")
{
syn::NestedMeta::Literal(syn::Lit::Str(litstr)) => {
if res.is_some() {
return Err(Error::new(metalist.ident.span(), "multiple generate_gir attributes found"));
return Err(Error::new(
metalist.ident.span(),
"multiple generate_gir attributes found",
));
}
res = Some(litstr);
},
_ => { return Err(Error::new(metalist.ident.span(), "generate_gir expects one string literal"));}
}
_ => {
return Err(Error::new(
metalist.ident.span(),
"generate_gir expects one string literal",
));
}
}
}
}
......@@ -220,7 +235,10 @@ impl<'ast> Classes<'ast> {
},
);
if prev.is_some() {
return Err(Error::new(ast_class.name.span(), format!("redefinition of class `{}`", ast_class.name)));
return Err(Error::new(
ast_class.name.span(),
format!("redefinition of class `{}`", ast_class.name),
));
}
Ok(())
}
......@@ -228,7 +246,10 @@ impl<'ast> Classes<'ast> {
fn add_impl(&mut self, impl_: &'ast ast::Impl) -> Result<()> {
let class = match self.items.get_mut(&impl_.self_path) {
Some(class) => class,
None => { Err(Error::new(impl_.self_path.span(), format!("impl for class that doesn't exist: {}", impl_.self_path)))? },
None => Err(Error::new(
impl_.self_path.span(),
format!("impl for class that doesn't exist: {}", impl_.self_path),
))?,
};
match *impl_ {
ast::Impl {
......@@ -240,20 +261,35 @@ impl<'ast> Classes<'ast> {
let item = match item.node {
ast::ImplItemKind::Method(ref m) => m,
ast::ImplItemKind::ReserveSlots(ref l) => {
return Err(Error::new(l.span(), "can't reserve slots in a parent class impl"));
return Err(Error::new(
l.span(),
"can't reserve slots in a parent class impl",
));
}
ast::ImplItemKind::Prop(ast::ImplProp { ref name, ..}) => {
return Err(Error::new(name.span(), "can't define props in a parent class impl"));
ast::ImplItemKind::Prop(ast::ImplProp { ref name, .. }) => {
return Err(Error::new(
name.span(),
"can't define props in a parent class impl",
));
}
};
if let Some(spanned) = &item.signal {
return Err(Error::new(spanned.span(), "can't implement signals for parent classes"));
return Err(Error::new(
spanned.span(),
"can't implement signals for parent classes",
));
}
if !item.virtual_.is_some() {
return Err(Error::new(item.name.span(), "can only implement virtual functions for parent classes"));
return Err(Error::new(
item.name.span(),
"can only implement virtual functions for parent classes",
));
}
if let Some(spanned) = &item.public {
return Err(Error::new(spanned.span(), "overrides are always public, no `pub` needed"));
return Err(Error::new(
spanned.span(),
"overrides are always public, no `pub` needed",
));
}
let method = match Slot::translate_from_method(item)? {
Slot::VirtualMethod(VirtualMethod {
......@@ -265,7 +301,10 @@ impl<'ast> Classes<'ast> {
body,
},
Slot::VirtualMethod(VirtualMethod { .. }) => {
return Err(Error::new(item.name.span(), "overrides must provide a body for virtual methods"));
return Err(Error::new(
item.name.span(),
"overrides must provide a body for virtual methods",
));
}
_ => unreachable!(),
};
......@@ -328,21 +367,29 @@ impl<'ast> Slot<'ast> {