-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
feat: implement lifetime elision #22927
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
54ecc5b
711812c
9ffa4fb
6526ecd
519237a
9217af3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -6,10 +6,12 @@ mod tests; | |||||
| use std::iter; | ||||||
|
|
||||||
| use crate::{ | ||||||
| ModuleDefId, | ||||||
| expr_store::{ | ||||||
| lower::{ExprCollector, generics::ImplTraitLowerFn}, | ||||||
| lower::{ElisionBinderSource, ExprCollector, generics::ImplTraitLowerFn}, | ||||||
| path::NormalPath, | ||||||
| }, | ||||||
| item_scope::BuiltinShadowMode, | ||||||
| type_ref::LifetimeRef, | ||||||
| }; | ||||||
|
|
||||||
|
|
@@ -39,7 +41,7 @@ thread_local! { | |||||
| // If you modify the logic of the lowering, make sure to check if `hir_segment_to_ast_segment()` | ||||||
| // also needs an update. | ||||||
| pub(super) fn lower_path( | ||||||
| collector: &mut ExprCollector<'_>, | ||||||
| collector: &mut ExprCollector<'_, '_>, | ||||||
| mut path: ast::Path, | ||||||
| impl_trait_lower_fn: ImplTraitLowerFn<'_>, | ||||||
| ) -> Option<Path> { | ||||||
|
|
@@ -101,11 +103,13 @@ pub(super) fn lower_path( | |||||
| .generic_arg_list() | ||||||
| .and_then(|it| collector.lower_generic_args(it, impl_trait_lower_fn)) | ||||||
| .or_else(|| { | ||||||
| collector.lower_generic_args_from_fn_path( | ||||||
| segment.parenthesized_arg_list(), | ||||||
| segment.ret_type(), | ||||||
| impl_trait_lower_fn, | ||||||
| ) | ||||||
| collector.with_type_bound_source(ElisionBinderSource::ForBinder, |this| { | ||||||
| this.lower_generic_args_from_fn_path( | ||||||
| segment.parenthesized_arg_list(), | ||||||
| segment.ret_type(), | ||||||
| impl_trait_lower_fn, | ||||||
| ) | ||||||
| }) | ||||||
| }) | ||||||
| .or_else(|| { | ||||||
| segment.return_type_syntax().map(|_| GenericArgs::return_type_notation()) | ||||||
|
|
@@ -256,11 +260,46 @@ pub(super) fn lower_path( | |||||
| *last_segment_args = None; | ||||||
| } | ||||||
|
|
||||||
| let segments_len = segments.len(); | ||||||
| let mod_path = Interned::new(ModPath::from_segments(kind, segments)); | ||||||
|
|
||||||
| let (resolved_module_def_id, is_trait_assoc_item) = { | ||||||
| let (per_ns, remaining_idx) = collector.def_map.resolve_path( | ||||||
| collector.local_def_map, | ||||||
| collector.db, | ||||||
| collector.module, | ||||||
| &mod_path, | ||||||
| BuiltinShadowMode::Module, | ||||||
| None, | ||||||
| ); | ||||||
| let def = per_ns.types.map(|item| item.def); | ||||||
|
|
||||||
| let is_trait_assoc_item = matches!(def, Some(ModuleDefId::TraitId(..))) | ||||||
| && remaining_idx.is_some_and(|idx| idx > 0); | ||||||
| (def, is_trait_assoc_item) | ||||||
| }; | ||||||
|
|
||||||
| if collector.lifetime_elision_kind.can_elide() && !is_trait_assoc_item { | ||||||
| let args_in_source = generic_args.last().and_then(|g| g.as_ref()); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Then push back. So
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mush I like to do it, I can't get the resize correct with pop and push 😅 |
||||||
| let merged_args_with_elided = | ||||||
| collector.collect_path_elided_lifetimes(resolved_module_def_id, args_in_source); | ||||||
| match &merged_args_with_elided { | ||||||
| // there are elided args | ||||||
| Some(_) => { | ||||||
| if args_in_source.is_none() { | ||||||
| generic_args.resize(segments_len, None); | ||||||
| } | ||||||
| if let Some(args) = generic_args.last_mut() { | ||||||
| *args = merged_args_with_elided | ||||||
| } | ||||||
| } | ||||||
| _ => {} // there are no elided args | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| if let Some(old_lifetimes_constrained_by_input) = old_lifetimes_constrained_by_input { | ||||||
| let type_alias_constrained_lifetimes = collector.get_constrained_lifetimes_if_type_alias( | ||||||
| &mod_path, | ||||||
| resolved_module_def_id, | ||||||
| generic_args.last().and_then(|g| g.as_ref()), | ||||||
| ); | ||||||
| if let Some(lifetimes) = type_alias_constrained_lifetimes { | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately this is not correct; lifetimes in trait's assoc types can still be elided, but only for the trait, not for the assoc type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you give an example? I have lot of unknowns here.