Skip to content

Conversation

@montekki
Copy link
Contributor

Fixes #3877

So, basically even if the parameters are omitted from the impl block, check the parameters in trait if they have a default type, and if they do go from hir to ast::TypeArg. I've added a helper for that but I am not sure that it's a proper way to go from hir to ast here.

Copy link
Member

@flodiebold flodiebold left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exciting! Yeah, I think I have a better way to get the AST, see comment.

.filter_map(|(k, v)| match v {
Some(v) => Some((k, v)),
None => match k.default(source_scope.db)? {
TypeRef::Path(path) => Some((
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't look into the type ref here -- it's naming a type, we want to put that type into the code, there should be no need to special-case. And this should of course also work for types that aren't single-ident paths (&Foo, foo::Bar, ...).

The other thing is that the default is written in the scope of the trait declaration, and might not resolve here at the impl site. So we need to qualify it.

I think we can solve both problems at the same time:

  • instead of using db.generic_params(), which gives us just the unresolved TypeRef, we can use db.generic_defaults(), which will give us the resolved Ty.
  • and then we can use the existing infrastructure to print the type using the display_source_code function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should replace ast_transform with display_source_code altogether?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we're quite there yet, considering formatting, handling of type aliases, etc...

TypeRef::Path(path) => Some((
k,
ast::make::type_arg(&format!("{}", path.mod_path().as_ident()?))
.type_ref()?,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems unnecessary to add a make::type_arg when we actually just want the type_ref?

ra_db = { path = "../ra_db" }
ra_ide_db = { path = "../ra_ide_db" }
hir = { path = "../ra_hir", package = "ra_hir" }
hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ide crates should only depend on hir directly, hir_xxx is sort of private stuff for compiler internals.

.filter_map(|(k, v)| match v {
Some(v) => Some((k, v)),
None => match k.default(source_scope.db)? {
TypeRef::Path(path) => Some((
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should replace ast_transform with display_source_code altogether?

@montekki
Copy link
Contributor Author

Tried fixing; the indexing into Substs is different from indexing into types and looks kind of ugly though

pub fn default(self, db: &dyn HirDatabase) -> Option<Ty> {
let params = db.generic_defaults(self.id.parent);
let local_idx: u32 = self.id.local_id.into_raw().into();
params.get(local_idx as usize).map(|d| d.clone())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm yeah local_idx isn't necessarily the correct index here. There's a function that will give you the correct index in ra_hir_ty::utils, but it's currently private to that crate: generics(db, parent_def).param_idx(param_id). let's maybe just export that as a function from ra_hir_ty? i.e.

pub fn param_idx(db, param: TypeParamId) -> Option<usize> { generics(db, param.parent).param_idx(param) }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, .map(|d| d.clone()) = .cloned(), I think

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, and this function should wrap the Ty in a code_model::Type 😬

@flodiebold
Copy link
Member

bors r+

@bors
Copy link
Contributor

bors bot commented May 14, 2020

@bors bors bot merged commit f1587ac into rust-lang:master May 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"Implement missing members" doesn't handle default generic type parameters

3 participants