Implement feature(more_qualified_paths)#19956
Implement feature(more_qualified_paths)#19956WaffleLapkin wants to merge 1 commit intorust-lang:masterfrom
feature(more_qualified_paths)#19956Conversation
crates/hir-ty/src/infer.rs
Outdated
|
|
||
| self.resolve_variant_on_alias(ty, unresolved, mod_path) | ||
| } | ||
| TypeNs::TraitId(_trait_id) => { |
There was a problem hiding this comment.
This is mostly copied from the SelfType branch above and this feels very weird. For example the loop always does a single iteration...
There was a problem hiding this comment.
The loop does not always do a single iteration, in the case Self::AssocType::EnumVariant it does two. However it seems you copied that incorrectly?
There was a problem hiding this comment.
Rrright. The reason I copied it like that is that I couldn't find a way to get the type (E in <E as Trait>::Assoc::ES) for the ty variable on first iteration.
I found a way to get the type, but you'll probably know a better one ^^'
There was a problem hiding this comment.
Hmm... It seems your logic should indeed be different from Self, and you don't need a loop. Since there is no sense to code like Trait::EnumVariant, you can have straight control flow: lower assoc types (lower_partly_resolved_path(), but it expects no unresolved segments so you may need to adapt it or ignore_last_segment()), then check if you have an addition segment, in which case try to resolve an enum variant from the type (ty.as_adt() then extract an enum out of it).
38a3d65 to
e2710df
Compare
|
What I can't so far figure out is how to make this work for enums. Example: enum E {
ES { a: u32 },
ET(u32),
}
impl Trait for E {
type Assoc = Self;
}
let <E>::ES { a } = (<E>::ES { a: 0 }) else { panic!() };
let <E>::ET(a) = <E>::ET(0) else { panic!() };
let <E as Trait>::Assoc::ES { a } = (<E as Trait>::Assoc::ES { a: 0 }) else { panic!() };
let <E as Trait>::Assoc::ET(a) = <E as Trait>::Assoc::ET(0) else { panic!() };Out of all these r-a can only resolve |
|
The reason To resolve if let Some(type_anchor) = path.type_anchor() {
let segments = path.segments();
if segments.len() != 1 {
return (self.err_ty(), None);
}
let ty = ctx.lower_ty(type_anchor);
if let Some((AdtId::EnumId(id), _)) = ty.as_adt() {
let enum_data = self.db.enum_variants(id);
if let Some(variant) = enum_data.variant(segments.first().unwrap().name) {
// FIXME: Report error if there are generics on the variant.
return (ty, Some(variant.into()));
}
} else {
// FIXME: Report an error.
return (self.err_ty(), None);
}
}Also, I'll be happy if you could deduplicate the code for handling |
e2710df to
da7c176
Compare
|
Don't be afraid to ask for help should you need it! |
fab04fe to
1fd0369
Compare
Specifically, this allows the following patterns and expressions which
were not allowed before:
```rust
let <T as Trait>::Assoc { a } = <T as Trait>::Assoc { a: 0 };
let (<E as Trait>::Assoc::ES { a } | <E as Trait>::Assoc::ET(a))
= <E as Trait>::Assoc::ES { a: 0 };
let (<E>::ES { a } | <E>::ET(a)) = <E>::ES { a: 0 };
```
1fd0369 to
64f9379
Compare
|
@ChayimFriedman2 thanks for your advise! I think I was able to implement the feature in a way which doesn't look that bad ^^' Do you know where I could add tests for this? |
crates/hir-ty/src/tests/traits.rs, you can look at existing tests there. |
|
This probably needs some adjustment for pattern path completions as well. Not necessary for this PR, just a note, can give pointers if you want to add that to this PR though. Seems like we complete the |
|
@ChayimFriedman2 I'm currently a bit stuck. While adding tests I figured out that I can check if the type ancor is |
|
Use |
|
☔ The latest upstream changes (possibly #21804) made this pull request unmergeable. Please resolve the merge conflicts. |
|
@WaffleLapkin do you want to work on this? If not, can I take this from you? |
Example: