if a struct has a new or a from method that does the same as a struct constructor, then that method should be used instead of the struct constructor.
Obviously the usage of a struct constructor inside the new or from method should not be linted.
I'd like to work on this :)
great! if you have any questions, don't hesitate to ask
I have been looking into the API and am currently not sure on how to get information from the LateContext struct.
fn check_expr(&mut self, ctx: &LateContext, e: &Expr) {
if let Expr_::ExprStruct(ref path, _, _) = e.node {
println!("{:?}\n\n", path);
// get the struct name
// get the methods of struct and check if a factory method is defined
// ^ how to get the above info from ctx ??
}
}
Is this the right way to go ? 😄
Jup good start. Have you tried searching the clippy codebase for other uses of exprstruct?
The usual start point into information from rustc is the TyCtxt. It is a certified god object and has gazillions of functions. The LateContext has a tcx field that gives you the TyCtxt. You should be able to call the expr_type function to get the type of the struct. Maybe there's a DefId in there. I'm not on a pc right now, so this is as much as I can give you from the top of my head
@oli-obk *expr_ty
The list of methods a type has should be somewhere in the cstore (another almighty type, just search it in Clippy). We don't use the actual name of the struct anywhere but to display error messages, it's meaningless (use a::Foo as Bar; type Baz = Bar; use b::Quz as Foo; … which is which? :smile:), cx.tcx.expr_ty gives the type of an expression, when the type is a structure it has an DefId you can use to get information about that type.
I have been trying to get the list of methods of a struct from cstore ( https://manishearth.github.io/rust-internals-docs/rustc/middle/cstore/trait.CrateStore.html )
with the following code.
fn check_expr(&mut self, ctx: &LateContext, e: &Expr) {
if let Expr_::ExprStruct(ref path, _, _) = e.node {
let ty = ctx.tcx.expr_ty(e);
if let TypeVariants::TyAdt(ref def, _) = ty.sty {
let a = ctx.tcx.sess.cstore.impl_items(def.did);
}
}
}
But calling any method in cstore with def.did panics. I am not sure on what I am missing here.
the DefId you have is the one of the struct YourType block, but most methods expect a DefId of the impl YourType {} block. I think you need to do ctx.tcx.inherent_impls.borrow().get(&def_id) to get the inherent impls, and then iterate over the methods in those impls.