From 40ff702a91872e2caef59c42558dbbe7a84017a2 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Fri, 17 Jul 2026 10:24:10 +0530 Subject: [PATCH 1/8] internal: implement lifetime elision --- crates/hir-def/src/expr_store/lower.rs | 645 +++++++++++++----- crates/hir-def/src/expr_store/lower/asm.rs | 1 + .../hir-def/src/expr_store/lower/generics.rs | 72 +- crates/hir-def/src/expr_store/lower/path.rs | 72 +- .../src/expr_store/lower/path/tests.rs | 6 +- crates/hir-def/src/expr_store/pretty.rs | 5 +- crates/hir-def/src/hir/generics.rs | 7 + crates/hir-def/src/hir/type_ref.rs | 3 +- crates/hir-def/src/lib.rs | 20 +- crates/hir-def/src/resolver.rs | 1 + crates/hir-def/src/signatures.rs | 7 +- crates/hir-expand/src/name.rs | 5 + crates/hir-ty/src/display.rs | 5 +- crates/hir-ty/src/lower.rs | 32 +- crates/hir-ty/src/variance.rs | 2 +- crates/hir/src/source_analyzer.rs | 24 +- 16 files changed, 691 insertions(+), 216 deletions(-) diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index 781241a620da..6b0268421cda 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -11,6 +11,7 @@ use std::{cell::OnceCell, mem}; use base_db::{FxIndexSet, SourceDatabase}; use cfg::CfgOptions; use either::Either; +use generics::LifetimeElisionFn; use hir_expand::{ HirFileId, InFile, MacroDefId, mod_path::ModPath, @@ -35,9 +36,9 @@ use thin_vec::ThinVec; use tt::TextRange; use crate::{ - AdtId, BlockId, BlockIdLt, ConstId, DefWithBodyId, FunctionId, GenericDefId, ImplId, - ItemContainerId, LoweringMode, MacroId, ModuleDefId, ModuleId, TraitId, TypeAliasId, - UnresolvedMacro, + AdtId, BlockId, BlockIdLt, ConstId, DefWithBodyId, FunctionId, GenericDefId, + HrtbLifetimeParamId, ImplId, ItemContainerId, LoweringMode, MacroId, ModuleDefId, ModuleId, + TraitId, TypeAliasId, UnresolvedMacro, attrs::AttrFlags, expr_store::{ Body, BodySourceMap, ExprPtr, ExprRoot, ExpressionStore, ExpressionStoreBuilder, @@ -52,7 +53,8 @@ use crate::{ Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, ClosureKind, CoroutineKind, CoroutineSource, Expr, ExprId, Item, Label, LabelId, Literal, LoopSource, MatchArm, Movability, OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, RecordSpread, - Statement, generics::GenericParams, + Statement, + generics::{ElidedSource, GenericParams}, }, item_scope::BuiltinShadowMode, lang_item::{LangItemTarget, LangItems}, @@ -205,8 +207,11 @@ pub(crate) fn lower_type_ref( ) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId) { let mut expr_collector = ExprCollector::new(db, module, type_ref.file_id, LoweringMode::Analysis); - let type_ref = - expr_collector.lower_type_ref_opt(type_ref.value, &mut ExprCollector::impl_trait_allocator); + let type_ref = expr_collector.lower_type_ref_opt( + type_ref.value, + &mut ExprCollector::impl_trait_allocator, + &mut ExprCollector::elided_lifetime_static_allocator, + ); let (store, source_map) = expr_collector.store.finish(); (store, source_map, type_ref) } @@ -236,22 +241,27 @@ pub(crate) fn lower_impl( ) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId, Option, GenericParams) { let mut expr_collector = ExprCollector::new(db, module, impl_syntax.file_id, LoweringMode::Analysis); - let self_ty = - expr_collector.lower_type_ref_opt_disallow_impl_trait(impl_syntax.value.self_ty()); - let trait_ = impl_syntax.value.trait_().and_then(|it| match &it { - ast::Type::PathType(path_type) => { - let path = expr_collector - .lower_path_type(path_type, &mut ExprCollector::impl_trait_allocator)?; - Some(TraitRef { path: expr_collector.alloc_path(path, AstPtr::new(&it)) }) - } - _ => None, - }); let mut collector = generics::GenericParamsCollector::new(impl_id.into()); collector.lower( &mut expr_collector, impl_syntax.value.generic_param_list(), impl_syntax.value.where_clause(), ); + let self_ty = expr_collector.lower_type_ref_opt_disallow_impl_trait( + impl_syntax.value.self_ty(), + &mut collector.lower_elided_lifetime_in_impl_header(), + ); + let trait_ = impl_syntax.value.trait_().and_then(|it| match &it { + ast::Type::PathType(path_type) => { + let path = expr_collector.lower_path_type( + path_type, + &mut ExprCollector::impl_trait_allocator, + &mut collector.lower_elided_lifetime_in_impl_header(), + )?; + Some(TraitRef { path: expr_collector.alloc_path(path, AstPtr::new(&it)) }) + } + _ => None, + }); let params = collector.finish(); let (store, source_map) = expr_collector.store.finish(); (store, source_map, self_ty, trait_, params) @@ -295,7 +305,11 @@ pub(crate) fn lower_type_alias( bounds .bounds() .map(|bound| { - expr_collector.lower_type_bound(bound, &mut ExprCollector::impl_trait_allocator) + expr_collector.lower_type_bound( + bound, + &mut ExprCollector::impl_trait_allocator, + &mut ExprCollector::elided_lifetime_error_allocator, + ) }) .collect() }) @@ -307,10 +321,13 @@ pub(crate) fn lower_type_alias( alias.value.where_clause(), ); let params = collector.finish(); - let type_ref = alias - .value - .ty() - .map(|ty| expr_collector.lower_type_ref(ty, &mut ExprCollector::impl_trait_allocator)); + let type_ref = alias.value.ty().map(|ty| { + expr_collector.lower_type_ref( + ty, + &mut ExprCollector::impl_trait_allocator, + &mut ExprCollector::elided_lifetime_error_allocator, + ) + }); let (store, source_map) = expr_collector.store.finish(); (store, source_map, params, bounds, type_ref) } @@ -335,64 +352,98 @@ pub(crate) fn lower_function( let mut params = vec![]; let mut has_self_param = false; let mut has_variadic = false; - collector.collect_impl_trait(&mut expr_collector, |collector, mut impl_trait_lower_fn| { - collector.with_lifetime_bound_scope(LifetimeBoundScope::Argument, |collector| { - if let Some(param_list) = fn_.value.param_list() { - if let Some(param) = param_list.self_param() { - let enabled = collector.check_cfg(¶m); - if enabled { - has_self_param = true; - params.push(match param.ty() { - Some(ty) => collector.lower_type_ref(ty, &mut impl_trait_lower_fn), - None => { - let self_type = collector.alloc_type_ref_desugared(TypeRef::Path( - Name::new_symbol_root(sym::Self_).into(), - )); - let lifetime = param - .lifetime() - .map(|lifetime| collector.lower_lifetime_ref(lifetime)); - match param.kind() { - ast::SelfParamKind::Owned => self_type, - ast::SelfParamKind::Ref => collector.alloc_type_ref_desugared( - TypeRef::Reference(Box::new(RefType { - ty: self_type, - lifetime, - mutability: Mutability::Shared, - })), - ), - ast::SelfParamKind::MutRef => collector - .alloc_type_ref_desugared(TypeRef::Reference(Box::new( - RefType { - ty: self_type, - lifetime, - mutability: Mutability::Mut, - }, - ))), + collector.collect_impl_trait( + &mut expr_collector, + |collector, mut impl_trait_lower_fn, mut lifetime_elision_fn| { + collector.with_lifetime_bound_scope(LifetimeBoundScope::Argument, |collector| { + if let Some(param_list) = fn_.value.param_list() { + if let Some(param) = param_list.self_param() { + let enabled = collector.check_cfg(¶m); + if enabled { + has_self_param = true; + params.push(match param.ty() { + Some(ty) => collector.with_self_lt_elision(|this| { + this.lower_type_ref( + ty, + &mut impl_trait_lower_fn, + &mut lifetime_elision_fn, + ) + }), + None => { + let self_type = collector.alloc_type_ref_desugared( + TypeRef::Path(Name::new_symbol_root(sym::Self_).into()), + ); + let lifetime = collector.with_self_lt_elision(|this| { + param + .lifetime() + .map(|lifetime| { + this.lower_lifetime_ref( + lifetime, + lifetime_elision_fn, + ) + }) + .or_else(|| match param.kind() { + ast::SelfParamKind::Ref + | ast::SelfParamKind::MutRef => { + Some(lifetime_elision_fn(this)) + } + ast::SelfParamKind::Owned => None, + }) + }); + match param.kind() { + ast::SelfParamKind::Owned => self_type, + ast::SelfParamKind::Ref => collector + .alloc_type_ref_desugared(TypeRef::Reference( + Box::new(RefType { + ty: self_type, + lifetime, + mutability: Mutability::Shared, + }), + )), + ast::SelfParamKind::MutRef => collector + .alloc_type_ref_desugared(TypeRef::Reference( + Box::new(RefType { + ty: self_type, + lifetime, + mutability: Mutability::Mut, + }), + )), + } } - } - }); + }); + } } - } - let p = param_list - .params() - .filter(|param| collector.check_cfg(param)) - .filter(|param| { - let is_variadic = param.dotdotdot_token().is_some(); - has_variadic |= is_variadic; - !is_variadic + let p = param_list + .params() + .filter(|param| collector.check_cfg(param)) + .filter(|param| { + let is_variadic = param.dotdotdot_token().is_some(); + has_variadic |= is_variadic; + !is_variadic + }) + .map(|param| param.ty()) + // FIXME + .collect::>(); + collector.with_param_lt_elision(|this| { + for p in p { + params.push(this.lower_type_ref_opt( + p, + &mut impl_trait_lower_fn, + &mut lifetime_elision_fn, + )); + } }) - .map(|param| param.ty()) - // FIXME - .collect::>(); - for p in p { - params.push(collector.lower_type_ref_opt(p, &mut impl_trait_lower_fn)); } - } - }) - }); + }) + }, + ); let return_type = fn_.value.ret_type().map(|ret_type| { expr_collector.with_lifetime_bound_scope(LifetimeBoundScope::Return, |this| { - this.lower_type_ref_opt(ret_type.ty(), &mut ExprCollector::impl_trait_allocator) + this.lower_type_ref_opt( + ret_type.ty(), + &mut ExprCollector::impl_trait_allocator, + &mut ExprCollector::elided_lifetime_placeholder_allocator, + ) }) }); collector.update_to_late_bound_lifetimes(&expr_collector.named_lifetime_store); @@ -464,7 +515,10 @@ pub struct ExprCollector<'db> { is_lowering_coroutine: bool, - for_type_binder: Option>, + elision_context: Option, + elision_binder_source: ElisionBinderSource, + + for_type_binder: Option<(ThinVec, ForBinderSource)>, /// Legacy (`macro_rules!`) macros can have multiple definitions and shadow each other, /// and we need to find the current definition. So we track the number of definitions we saw. @@ -565,6 +619,19 @@ impl BindingList { } } +#[derive(Debug)] +enum ForBinderSource { + FnPtrType, + ForType, + ForBound, +} + +#[derive(Debug)] +enum ElisionBinderSource { + Parent, + ForBinder, +} + #[derive(Debug, Default)] pub struct NamedLifetimeStore { lifetime_bound_scope: Option, @@ -638,6 +705,8 @@ impl<'db> ExprCollector<'db> { name_generator_index: 0, named_lifetime_store: NamedLifetimeStore::default(), for_type_binder: None, + elision_context: None, + elision_binder_source: ElisionBinderSource::Parent, }; result.store.inference_roots = Some(SmallVec::new()); result @@ -662,11 +731,13 @@ impl<'db> ExprCollector<'db> { pub(in crate::expr_store) fn lower_lifetime_ref( &mut self, lifetime: ast::Lifetime, + lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> LifetimeRefId { // FIXME: Keyword check? let lifetime_ref = match lifetime.text() { "" | "'" => LifetimeRef::Error, "'static" => LifetimeRef::Static, + "'_" if self.elision_context.is_some() => return lifetime_elision_fn(self), "'_" => LifetimeRef::Placeholder, text => LifetimeRef::Named(Name::new_lifetime(text)), }; @@ -676,9 +747,10 @@ impl<'db> ExprCollector<'db> { pub(in crate::expr_store) fn lower_lifetime_ref_opt( &mut self, lifetime: Option, + lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> LifetimeRefId { match lifetime { - Some(lifetime) => self.lower_lifetime_ref(lifetime), + Some(lifetime) => self.lower_lifetime_ref(lifetime, lifetime_elision_fn), None => self.alloc_lifetime_ref_desugared(LifetimeRef::Placeholder), } } @@ -688,47 +760,84 @@ impl<'db> ExprCollector<'db> { &mut self, node: ast::Type, impl_trait_lower_fn: ImplTraitLowerFn<'_>, + lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> TypeRefId { let ty = match &node { ast::Type::ParenType(inner) => { - return self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn); + return self.lower_type_ref_opt( + inner.ty(), + impl_trait_lower_fn, + lifetime_elision_fn, + ); } ast::Type::TupleType(inner) => TypeRef::Tuple(ThinVec::from_iter(Vec::from_iter( - inner.fields().map(|it| self.lower_type_ref(it, impl_trait_lower_fn)), + inner + .fields() + .map(|it| self.lower_type_ref(it, impl_trait_lower_fn, lifetime_elision_fn)), ))), ast::Type::NeverType(..) => TypeRef::Never, ast::Type::PathType(inner) => inner .path() - .and_then(|it| self.lower_path(it, impl_trait_lower_fn)) + .and_then(|it| self.lower_path(it, impl_trait_lower_fn, lifetime_elision_fn)) .map(TypeRef::Path) .unwrap_or(TypeRef::Error), ast::Type::PtrType(inner) => { - let inner_ty = self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn); + let inner_ty = + self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn, lifetime_elision_fn); let mutability = Mutability::from_mutable(inner.mut_token().is_some()); TypeRef::RawPtr(inner_ty, mutability) } ast::Type::ArrayType(inner) => { let len = self.lower_const_arg_opt(inner.const_arg()); TypeRef::Array(ArrayType { - ty: self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn), + ty: self.lower_type_ref_opt( + inner.ty(), + impl_trait_lower_fn, + lifetime_elision_fn, + ), len, }) } - ast::Type::SliceType(inner) => { - TypeRef::Slice(self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn)) - } + ast::Type::SliceType(inner) => TypeRef::Slice(self.lower_type_ref_opt( + inner.ty(), + impl_trait_lower_fn, + lifetime_elision_fn, + )), ast::Type::RefType(inner) => { - let inner_ty = self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn); - let lifetime = inner.lifetime().map(|lt| self.lower_lifetime_ref(lt)); + let inner_ty = + self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn, lifetime_elision_fn); + let lifetime = if let Some(lt) = inner.lifetime() { + Some(self.lower_lifetime_ref(lt, lifetime_elision_fn)) + } else { + Some(lifetime_elision_fn(self)) + }; let mutability = Mutability::from_mutable(inner.mut_token().is_some()); TypeRef::Reference(Box::new(RefType { ty: inner_ty, lifetime, mutability })) } ast::Type::InferType(_inner) => TypeRef::Placeholder, ast::Type::FnPtrType(inner) => { + let old_binder = match self.for_type_binder { + None | Some((_, ForBinderSource::FnPtrType | ForBinderSource::ForBound)) => { + self.for_type_binder.replace((ThinVec::new(), ForBinderSource::FnPtrType)) + } + Some((_, ForBinderSource::ForType)) => None, + }; + let old_elision_binder_source = + mem::replace(&mut self.elision_binder_source, ElisionBinderSource::ForBinder); + + let mut for_binder_elision_fn = + |ec: &mut ExprCollector<'_>| ec.lower_elided_lifetime_for_binder(); + let ret_ty = inner .ret_type() .and_then(|rt| rt.ty()) - .map(|it| self.lower_type_ref(it, impl_trait_lower_fn)) + .map(|it| { + self.lower_type_ref( + it, + impl_trait_lower_fn, + &mut Self::elided_lifetime_placeholder_allocator, + ) + }) .unwrap_or_else(|| self.alloc_type_ref_desugared(TypeRef::unit())); let mut is_varargs = false; let mut params = if let Some(pl) = inner.param_list() { @@ -739,7 +848,11 @@ impl<'db> ExprCollector<'db> { pl.params() .filter(|it| it.dotdotdot_token().is_none()) .map(|it| { - let type_ref = self.lower_type_ref_opt(it.ty(), impl_trait_lower_fn); + let type_ref = self.lower_type_ref_opt( + it.ty(), + impl_trait_lower_fn, + &mut for_binder_elision_fn, + ); let name = match it.pat() { Some(ast::Pat::IdentPat(it)) => Some( it.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing), @@ -761,7 +874,10 @@ impl<'db> ExprCollector<'db> { let abi = inner.abi().map(lower_abi).unwrap_or(ExternAbi::Rust); params.push((None, ret_ty)); - let binder = self.for_type_binder.take().map(|b| b.into()); + let binder = self.for_type_binder.take().map(|(b, _)| b.into()); + + self.for_type_binder = old_binder; + self.elision_binder_source = old_elision_binder_source; TypeRef::Fn(Box::new(FnType { is_varargs, is_unsafe: inner.unsafe_token().is_some(), @@ -773,9 +889,9 @@ impl<'db> ExprCollector<'db> { // for types are close enough for our purposes to the inner type for now... ast::Type::ForType(inner) => { let binder = self.lower_for_binder_opt(inner.for_binder()); - let old_for_binder = self.for_type_binder.replace(binder); - let ty = self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn); - self.for_type_binder = old_for_binder; + let ty = self.with_for_binder(binder, ForBinderSource::ForType, |ec| { + ec.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn, lifetime_elision_fn) + }); return ty; } ast::Type::ImplTraitType(inner) => { @@ -783,7 +899,8 @@ impl<'db> ExprCollector<'db> { // Disallow nested impl traits TypeRef::Error } else { - return self.with_outer_impl_trait_scope(true, |this| { + let old_elision_context = self.elision_context.take(); + let result = self.with_outer_impl_trait_scope(true, |this| { let is_argument_scope = this.is_argument_lt_bound_scope(); let type_bounds = this.with_lifetime_bound_scope( LifetimeBoundScope::ImplTrait { is_argument_scope }, @@ -791,18 +908,23 @@ impl<'db> ExprCollector<'db> { this.type_bounds_from_ast( inner.type_bound_list(), impl_trait_lower_fn, + lifetime_elision_fn, ) }, ); impl_trait_lower_fn(this, AstPtr::new(&node), type_bounds) }); + self.elision_context = old_elision_context; + return result; } } - ast::Type::DynTraitType(inner) => TypeRef::DynTrait( - self.type_bounds_from_ast(inner.type_bound_list(), impl_trait_lower_fn), - ), + ast::Type::DynTraitType(inner) => TypeRef::DynTrait(self.type_bounds_from_ast( + inner.type_bound_list(), + impl_trait_lower_fn, + lifetime_elision_fn, + )), ast::Type::PatternType(inner) => TypeRef::PatternType( - self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn), + self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn, lifetime_elision_fn), self.collect_ty_pat_opt(inner.pat()), ), ast::Type::MacroType(mt) => match mt.macro_call() { @@ -810,7 +932,7 @@ impl<'db> ExprCollector<'db> { let macro_ptr = AstPtr::new(&mcall); let src = self.expander.in_file(AstPtr::new(&node)); let id = self.collect_macro_call(mcall, macro_ptr, true, |this, expansion| { - this.lower_type_ref_opt(expansion, impl_trait_lower_fn) + this.lower_type_ref_opt(expansion, impl_trait_lower_fn, lifetime_elision_fn) }); self.store.types_map.insert(src, id); return id; @@ -821,17 +943,22 @@ impl<'db> ExprCollector<'db> { self.alloc_type_ref(ty, AstPtr::new(&node)) } - pub(crate) fn lower_type_ref_disallow_impl_trait(&mut self, node: ast::Type) -> TypeRefId { - self.lower_type_ref(node, &mut Self::impl_trait_error_allocator) + pub(crate) fn lower_type_ref_disallow_impl_trait( + &mut self, + node: ast::Type, + lifetime_elision_fn: LifetimeElisionFn<'_>, + ) -> TypeRefId { + self.lower_type_ref(node, &mut Self::impl_trait_error_allocator, lifetime_elision_fn) } pub(crate) fn lower_type_ref_opt( &mut self, node: Option, impl_trait_lower_fn: ImplTraitLowerFn<'_>, + lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> TypeRefId { match node { - Some(node) => self.lower_type_ref(node, impl_trait_lower_fn), + Some(node) => self.lower_type_ref(node, impl_trait_lower_fn, lifetime_elision_fn), None => self.alloc_error_type(), } } @@ -839,8 +966,9 @@ impl<'db> ExprCollector<'db> { pub(crate) fn lower_type_ref_opt_disallow_impl_trait( &mut self, node: Option, + lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> TypeRefId { - self.lower_type_ref_opt(node, &mut Self::impl_trait_error_allocator) + self.lower_type_ref_opt(node, &mut Self::impl_trait_error_allocator, lifetime_elision_fn) } fn alloc_type_ref(&mut self, type_ref: TypeRef, node: TypePtr) -> TypeRefId { @@ -851,6 +979,13 @@ impl<'db> ExprCollector<'db> { id } + fn push_elided_lifetime_in_for_binder(&mut self, name: Name) -> usize { + let (binder, _) = self.for_type_binder.as_mut().unwrap(); // Should not call this method without a for binder + let idx = binder.len(); + binder.push(name); + idx + } + fn alloc_lifetime_ref( &mut self, lifetime_ref: LifetimeRef, @@ -883,8 +1018,9 @@ impl<'db> ExprCollector<'db> { &mut self, ast: ast::Path, impl_trait_lower_fn: ImplTraitLowerFn<'_>, + lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> Option { - super::lower::path::lower_path(self, ast, impl_trait_lower_fn) + super::lower::path::lower_path(self, ast, impl_trait_lower_fn, lifetime_elision_fn) } fn with_outer_impl_trait_scope( @@ -898,6 +1034,71 @@ impl<'db> ExprCollector<'db> { result } + fn with_type_bound_source( + &mut self, + source: ElisionBinderSource, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + let old = mem::replace(&mut self.elision_binder_source, source); + let result = f(self); + self.elision_binder_source = old; + result + } + + fn with_self_lt_elision(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { + self.with_elision_context(ElidedSource::Self_, f) + } + + fn with_param_lt_elision(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { + self.with_elision_context(ElidedSource::Param, f) + } + + fn with_elision_context( + &mut self, + elision_context: ElidedSource, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + let old = self.elision_context.replace(elision_context); + let result = f(self); + self.elision_context = old; + result + } + + fn with_for_binder( + &mut self, + binder: Option>, + source: ForBinderSource, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + let old = match binder { + Some(binder) => self.for_type_binder.replace((binder, source)), + None => return f(self), + }; + let result = f(self); + self.for_type_binder = old; + result + } + + fn lower_elided_lifetime_for_binder(&mut self) -> LifetimeRefId { + let name = Name::anon_lifetime(); + let local_id = self.push_elided_lifetime_in_for_binder(name); + let param_id = HrtbLifetimeParamId(local_id); + let lifetime_ref = LifetimeRef::HrtbParam(param_id); + self.alloc_lifetime_ref_desugared(lifetime_ref) + } + + pub fn elided_lifetime_error_allocator(ec: &mut ExprCollector<'_>) -> LifetimeRefId { + ec.alloc_lifetime_ref_desugared(LifetimeRef::Error) + } + + pub fn elided_lifetime_placeholder_allocator(ec: &mut ExprCollector<'_>) -> LifetimeRefId { + ec.alloc_lifetime_ref_desugared(LifetimeRef::Placeholder) + } + + pub fn elided_lifetime_static_allocator(ec: &mut ExprCollector<'_>) -> LifetimeRefId { + ec.alloc_lifetime_ref_desugared(LifetimeRef::Static) + } + pub fn impl_trait_error_allocator( ec: &mut ExprCollector<'_>, ptr: TypePtr, @@ -925,18 +1126,21 @@ impl<'db> ExprCollector<'db> { args: Option, ret_type: Option, impl_trait_lower_fn: ImplTraitLowerFn<'_>, + lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> Option { let params = args?; let mut param_types = Vec::new(); for param in params.type_args() { - let type_ref = self.lower_type_ref_opt(param.ty(), impl_trait_lower_fn); + let type_ref = + self.lower_type_ref_opt(param.ty(), impl_trait_lower_fn, lifetime_elision_fn); param_types.push(type_ref); } let args = Box::new([GenericArg::Type( self.alloc_type_ref_desugared(TypeRef::Tuple(ThinVec::from_iter(param_types))), )]); let bindings = if let Some(ret_type) = ret_type { - let type_ref = self.lower_type_ref_opt(ret_type.ty(), impl_trait_lower_fn); + let type_ref = + self.lower_type_ref_opt(ret_type.ty(), impl_trait_lower_fn, lifetime_elision_fn); Box::new([AssociatedTypeBinding { name: Name::new_symbol_root(sym::Output), args: None, @@ -965,6 +1169,7 @@ impl<'db> ExprCollector<'db> { &mut self, node: ast::GenericArgList, impl_trait_lower_fn: ImplTraitLowerFn<'_>, + lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> Option { // This needs to be kept in sync with `hir_generic_arg_to_ast()`. let mut args = Vec::new(); @@ -972,7 +1177,11 @@ impl<'db> ExprCollector<'db> { for generic_arg in node.generic_args() { match generic_arg { ast::GenericArg::TypeArg(type_arg) => { - let type_ref = self.lower_type_ref_opt(type_arg.ty(), impl_trait_lower_fn); + let type_ref = self.lower_type_ref_opt( + type_arg.ty(), + impl_trait_lower_fn, + lifetime_elision_fn, + ); args.push(GenericArg::Type(type_ref)); } ast::GenericArg::AssocTypeArg(assoc_type_arg) => { @@ -987,18 +1196,30 @@ impl<'db> ExprCollector<'db> { let name = name_ref.as_name(); let args = assoc_type_arg .generic_arg_list() - .and_then(|args| this.lower_generic_args(args, impl_trait_lower_fn)) + .and_then(|args| { + this.lower_generic_args( + args, + impl_trait_lower_fn, + lifetime_elision_fn, + ) + }) .or_else(|| { assoc_type_arg .return_type_syntax() .map(|_| GenericArgs::return_type_notation()) }); - let type_ref = assoc_type_arg - .ty() - .map(|it| this.lower_type_ref(it, impl_trait_lower_fn)); + let type_ref = assoc_type_arg.ty().map(|it| { + this.lower_type_ref(it, impl_trait_lower_fn, lifetime_elision_fn) + }); let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { l.bounds() - .map(|it| this.lower_type_bound(it, impl_trait_lower_fn)) + .map(|it| { + this.lower_type_bound( + it, + impl_trait_lower_fn, + lifetime_elision_fn, + ) + }) .collect() } else { Box::default() @@ -1009,7 +1230,7 @@ impl<'db> ExprCollector<'db> { } ast::GenericArg::LifetimeArg(lifetime_arg) => { if let Some(lifetime) = lifetime_arg.lifetime() { - let lifetime_ref = self.lower_lifetime_ref(lifetime); + let lifetime_ref = self.lower_lifetime_ref(lifetime, lifetime_elision_fn); args.push(GenericArg::Lifetime(lifetime_ref)) } } @@ -1250,10 +1471,13 @@ impl<'db> ExprCollector<'db> { &mut self, type_bounds_opt: Option, impl_trait_lower_fn: ImplTraitLowerFn<'_>, + lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> ThinVec { if let Some(type_bounds) = type_bounds_opt { ThinVec::from_iter(Vec::from_iter( - type_bounds.bounds().map(|it| self.lower_type_bound(it, impl_trait_lower_fn)), + type_bounds + .bounds() + .map(|it| self.lower_type_bound(it, impl_trait_lower_fn, lifetime_elision_fn)), )) } else { ThinVec::from_iter([]) @@ -1264,8 +1488,9 @@ impl<'db> ExprCollector<'db> { &mut self, path_type: &ast::PathType, impl_trait_lower_fn: ImplTraitLowerFn<'_>, + lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> Option { - let path = self.lower_path(path_type.path()?, impl_trait_lower_fn)?; + let path = self.lower_path(path_type.path()?, impl_trait_lower_fn, lifetime_elision_fn)?; Some(path) } @@ -1273,44 +1498,50 @@ impl<'db> ExprCollector<'db> { &mut self, node: ast::TypeBound, impl_trait_lower_fn: ImplTraitLowerFn<'_>, + lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> TypeBound { let Some(kind) = node.kind() else { return TypeBound::Error }; match kind { ast::TypeBoundKind::PathType(binder, path_type) => { - let binder = self.lower_for_binder_opt(binder); + let binder = self.lower_for_binder_opt(binder).unwrap_or_default(); let m = match node.question_mark_token() { Some(_) => TraitBoundModifier::Maybe, None => TraitBoundModifier::None, }; - self.lower_path_type(&path_type, impl_trait_lower_fn) - .map(|p| { - let path = self.alloc_path(p, AstPtr::new(&path_type).upcast()); - if binder.is_empty() { - TypeBound::Path(path, m) - } else { - TypeBound::ForLifetime(binder, path) - } - }) - .unwrap_or(TypeBound::Error) + self.with_for_binder(Some(binder), ForBinderSource::ForBound, |ec| { + ec.lower_path_type(&path_type, impl_trait_lower_fn, lifetime_elision_fn) + .map(|p| { + let path = ec.alloc_path(p, AstPtr::new(&path_type).upcast()); + let binder = ec.for_type_binder.take(); + if let Some((binder, _)) = binder + && !binder.is_empty() + { + TypeBound::ForLifetime(binder, path) + } else { + TypeBound::Path(path, m) + } + }) + .unwrap_or(TypeBound::Error) + }) } ast::TypeBoundKind::Use(gal) => TypeBound::Use( gal.use_bound_generic_args() .map(|p| match p { ast::UseBoundGenericArg::Lifetime(l) => { - UseArgRef::Lifetime(self.lower_lifetime_ref(l)) + UseArgRef::Lifetime(self.lower_lifetime_ref(l, lifetime_elision_fn)) } ast::UseBoundGenericArg::NameRef(n) => UseArgRef::Name(n.as_name()), }) .collect(), ), ast::TypeBoundKind::Lifetime(lifetime) => { - TypeBound::Lifetime(self.lower_lifetime_ref(lifetime)) + TypeBound::Lifetime(self.lower_lifetime_ref(lifetime, lifetime_elision_fn)) } } } - fn lower_for_binder_opt(&mut self, binder: Option) -> ThinVec { - binder.map(|b| self.lower_for_binder(b)).unwrap_or_default() + fn lower_for_binder_opt(&mut self, binder: Option) -> Option> { + binder.map(|b| self.lower_for_binder(b)) } fn lower_for_binder(&mut self, binder: ForBinder) -> ThinVec { @@ -1501,7 +1732,7 @@ impl<'db> ExprCollector<'db> { let generic_args = e .generic_arg_list() .and_then(|it| { - self.lower_generic_args(it, &mut Self::impl_trait_error_allocator) + self.lower_generic_args(it, &mut Self::impl_trait_error_allocator, &mut Self::elided_lifetime_error_allocator) }) .map(Box::new); self.alloc_expr( @@ -1587,7 +1818,7 @@ impl<'db> ExprCollector<'db> { ast::Expr::RecordExpr(e) => { let path = e .path() - .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); + .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator, &mut Self::elided_lifetime_placeholder_allocator)); let Some(path) = path else { return Some(self.missing_expr()); }; @@ -1645,7 +1876,7 @@ impl<'db> ExprCollector<'db> { ast::Expr::TryExpr(e) => self.collect_try_operator(syntax_ptr, e), ast::Expr::CastExpr(e) => { let expr = self.collect_expr_opt(e.expr()); - let type_ref = self.lower_type_ref_opt_disallow_impl_trait(e.ty()); + let type_ref = self.lower_type_ref_opt_disallow_impl_trait(e.ty(), &mut Self::elided_lifetime_placeholder_allocator); self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) } ast::Expr::RefExpr(e) => { @@ -1683,7 +1914,8 @@ impl<'db> ExprCollector<'db> { let pat = this.collect_pat_top(param.pat()); let type_ref = - param.ty().map(|it| this.lower_type_ref_disallow_impl_trait(it)); + // FIXME: should closures elide if so how? + param.ty().map(|it| this.lower_type_ref_disallow_impl_trait(it, &mut Self::elided_lifetime_placeholder_allocator)); args.push(pat); arg_types.push(type_ref); } @@ -1691,7 +1923,7 @@ impl<'db> ExprCollector<'db> { let ret_type = e .ret_type() .and_then(|r| r.ty()) - .map(|it| this.lower_type_ref_disallow_impl_trait(it)); + .map(|it| this.lower_type_ref_disallow_impl_trait(it, &mut Self::elided_lifetime_placeholder_allocator)); let prev_is_lowering_coroutine = mem::take(&mut this.is_lowering_coroutine); let prev_try_block = this.current_try_block.take(); @@ -1861,7 +2093,7 @@ impl<'db> ExprCollector<'db> { ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr), ast::Expr::AsmExpr(e) => self.lower_inline_asm(e, syntax_ptr), ast::Expr::OffsetOfExpr(e) => { - let container = self.lower_type_ref_opt_disallow_impl_trait(e.ty()); + let container = self.lower_type_ref_opt_disallow_impl_trait(e.ty(), &mut Self::elided_lifetime_placeholder_allocator); let fields = e.fields().map(|it| it.as_name()).collect(); self.alloc_expr(Expr::OffsetOf(OffsetOf { container, fields }), syntax_ptr) } @@ -1872,7 +2104,11 @@ impl<'db> ExprCollector<'db> { fn collect_expr_path(&mut self, e: ast::PathExpr) -> Option<(Path, HygieneId)> { e.path().and_then(|path| { - let path = self.lower_path(path, &mut Self::impl_trait_error_allocator)?; + let path = self.lower_path( + path, + &mut Self::impl_trait_error_allocator, + &mut Self::elided_lifetime_placeholder_allocator, + )?; // Need to enable `mod_path.len() < 1` for `self`. let may_be_variable = matches!(&path, Path::BarePath(mod_path) if mod_path.len() <= 1); let hygiene = if may_be_variable { @@ -1980,9 +2216,13 @@ impl<'db> ExprCollector<'db> { } ast::Expr::CallExpr(e) => { let path = collect_path(self, e.expr()?)?; - let path = path - .path() - .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); + let path = path.path().and_then(|path| { + self.lower_path( + path, + &mut Self::impl_trait_error_allocator, + &mut Self::elided_lifetime_placeholder_allocator, + ) + }); let Some(path) = path else { return Some(self.missing_pat()); }; @@ -2013,9 +2253,13 @@ impl<'db> ExprCollector<'db> { id } ast::Expr::RecordExpr(e) => { - let path = e - .path() - .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); + let path = e.path().and_then(|path| { + self.lower_path( + path, + &mut Self::impl_trait_error_allocator, + &mut Self::elided_lifetime_placeholder_allocator, + ) + }); let Some(path) = path else { return Some(self.missing_pat()); }; @@ -2195,7 +2439,10 @@ impl<'db> ExprCollector<'db> { Some(ty) => { // `{ let : = ; }` let name = self.generate_new_name(); - let type_ref = self.lower_type_ref_disallow_impl_trait(ty); + let type_ref = self.lower_type_ref_disallow_impl_trait( + ty, + &mut Self::elided_lifetime_placeholder_allocator, + ); let binding = self.alloc_binding( name.clone(), BindingAnnotation::Unannotated, @@ -2574,7 +2821,12 @@ impl<'db> ExprCollector<'db> { return; } let pat = self.collect_pat_top(stmt.pat()); - let type_ref = stmt.ty().map(|it| self.lower_type_ref_disallow_impl_trait(it)); + let type_ref = stmt.ty().map(|it| { + self.lower_type_ref_disallow_impl_trait( + it, + &mut Self::elided_lifetime_placeholder_allocator, + ) + }); let initializer = stmt.initializer().map(|e| self.collect_expr(e)); let else_branch = stmt .let_else() @@ -2811,9 +3063,13 @@ impl<'db> ExprCollector<'db> { return pat; } ast::Pat::TupleStructPat(p) => { - let path = p - .path() - .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); + let path = p.path().and_then(|path| { + self.lower_path( + path, + &mut Self::impl_trait_error_allocator, + &mut Self::elided_lifetime_error_allocator, + ) + }); let Some(path) = path else { return self.missing_pat(); }; @@ -2830,9 +3086,13 @@ impl<'db> ExprCollector<'db> { Pat::Ref { pat, mutability } } ast::Pat::PathPat(p) => { - let path = p - .path() - .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); + let path = p.path().and_then(|path| { + self.lower_path( + path, + &mut Self::impl_trait_error_allocator, + &mut Self::elided_lifetime_error_allocator, + ) + }); path.map(Pat::Path).unwrap_or(Pat::Missing) } ast::Pat::OrPat(p) => 'b: { @@ -2879,9 +3139,13 @@ impl<'db> ExprCollector<'db> { } ast::Pat::WildcardPat(_) => Pat::Wild, ast::Pat::RecordPat(p) => { - let path = p - .path() - .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); + let path = p.path().and_then(|path| { + self.lower_path( + path, + &mut Self::impl_trait_error_allocator, + &mut Self::elided_lifetime_error_allocator, + ) + }); let Some(path) = path else { return self.missing_pat(); }; @@ -2974,7 +3238,11 @@ impl<'db> ExprCollector<'db> { ast::Pat::PathPat(p) => p .path() .and_then(|path| { - self.lower_path(path, &mut Self::impl_trait_error_allocator) + self.lower_path( + path, + &mut Self::impl_trait_error_allocator, + &mut Self::elided_lifetime_error_allocator, + ) }) .map(|parsed| self.alloc_expr_from_pat(Expr::Path(parsed), ptr)), // We only need to handle literal, ident (if bare) and path patterns here, @@ -3128,9 +3396,13 @@ impl<'db> ExprCollector<'db> { } } ast::Pat::PathPat(it) => { - let path = it - .path() - .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); + let path = it.path().and_then(|path| { + self.lower_path( + path, + &mut Self::impl_trait_error_allocator, + &mut Self::elided_lifetime_error_allocator, + ) + }); self.alloc_expr_from_pat(path.map(Expr::Path).unwrap_or(Expr::Missing), ptr) } ast::Pat::IdentPat(it) if it.is_simple_ident() => { @@ -3510,19 +3782,11 @@ impl<'db> ExprCollector<'db> { fn get_constrained_lifetimes_if_type_alias<'a>( &mut self, - mod_path: &'a ModPath, + module_def_id: Option, generic_args: Option<&'a GenericArgs>, ) -> Option + use<'a, 'db>> { let generic_args = generic_args?; - let r_path = self.def_map.resolve_path( - self.local_def_map, - self.db, - self.module, - mod_path, - BuiltinShadowMode::Module, - None, - ); - let ModuleDefId::TypeAliasId(id) = r_path.0.take_types()? else { return None }; + let ModuleDefId::TypeAliasId(id) = module_def_id? else { return None }; let constrained_lt_indices = get_constrained_lifetimes(self.db, id); let res = constrained_lt_indices.iter().filter_map(|&idx| { @@ -3590,6 +3854,55 @@ impl<'db> ExprCollector<'db> { Default::default() } } + + pub(crate) fn collect_path_elided_liftetimes( + &mut self, + module_def_id: Option, + args: Option<&GenericArgs>, + lifetime_elision_fn: LifetimeElisionFn<'_>, + ) -> Option { + let num_lifetime_args = args + .as_ref() + .map(|args| { + args.args.iter().filter(|arg| matches!(arg, GenericArg::Lifetime(..))).count() + }) + .unwrap_or_default(); + + let def = module_def_id.and_then(|def| def.as_generic_def_id()); + + let num_lifetime_params = + def.map(|def| GenericParams::of(self.db, def).len_lifetimes()).unwrap_or_default(); + + let mut elided_args = Vec::new(); + if num_lifetime_args == 0 { + // lifetime args does not exist in source + // call elided function for all lifetime params + for _ in 0..num_lifetime_params { + let lt_id = lifetime_elision_fn(self); + elided_args.push(GenericArg::Lifetime(lt_id)); + } + } + if !elided_args.is_empty() { + if let Some(prev_generic_args) = args { + elided_args.extend_from_slice(prev_generic_args.args.as_ref()); + Some(GenericArgs { + args: elided_args.into_boxed_slice(), + has_self_type: prev_generic_args.has_self_type, + bindings: prev_generic_args.bindings.clone(), + parenthesized: prev_generic_args.parenthesized, + }) + } else { + Some(GenericArgs { + args: elided_args.into_boxed_slice(), + has_self_type: false, + bindings: Box::default(), + parenthesized: GenericArgsParentheses::No, + }) + } + } else { + None + } + } } fn comma_follows_token(t: Option) -> bool { diff --git a/crates/hir-def/src/expr_store/lower/asm.rs b/crates/hir-def/src/expr_store/lower/asm.rs index fb0a5b0bf7a7..b80b52e6f416 100644 --- a/crates/hir-def/src/expr_store/lower/asm.rs +++ b/crates/hir-def/src/expr_store/lower/asm.rs @@ -166,6 +166,7 @@ impl ExprCollector<'_> { self.lower_path( p, &mut ExprCollector::impl_trait_error_allocator, + &mut ExprCollector::elided_lifetime_error_allocator, ) }) else { continue; diff --git a/crates/hir-def/src/expr_store/lower/generics.rs b/crates/hir-def/src/expr_store/lower/generics.rs index 65877fb627f2..06b6632fe290 100644 --- a/crates/hir-def/src/expr_store/lower/generics.rs +++ b/crates/hir-def/src/expr_store/lower/generics.rs @@ -11,7 +11,7 @@ use syntax::ast::{self, HasName, HasTypeBounds}; use thin_vec::ThinVec; use crate::{ - GenericDefId, TypeOrConstParamId, TypeParamId, + GenericDefId, LifetimeParamId, TypeOrConstParamId, TypeParamId, expr_store::{ TypePtr, lower::{ExprCollector, LifetimeBoundScope, NamedLifetimeStore}, @@ -29,6 +29,9 @@ pub(crate) type ImplTraitLowerFn<'l> = &'l mut dyn for<'ec, 'db> FnMut( ThinVec, ) -> TypeRefId; +pub(crate) type LifetimeElisionFn<'l> = + &'l mut dyn for<'ec, 'db> FnMut(&'ec mut ExprCollector<'db>) -> LifetimeRefId; + pub(crate) struct GenericParamsCollector { type_or_consts: Arena, lifetimes: Arena, @@ -72,7 +75,7 @@ impl GenericParamsCollector { pub(crate) fn collect_impl_trait( &mut self, ec: &mut ExprCollector<'_>, - cb: impl FnOnce(&mut ExprCollector<'_>, ImplTraitLowerFn<'_>) -> R, + cb: impl FnOnce(&mut ExprCollector<'_>, ImplTraitLowerFn<'_>, LifetimeElisionFn<'_>) -> R, ) -> R { cb( ec, @@ -81,9 +84,16 @@ impl GenericParamsCollector { &mut self.where_predicates, self.parent, ), + &mut Self::lower_elided_lifetime(&mut self.lifetimes, self.parent, false), ) } + pub(crate) fn lower_elided_lifetime_in_impl_header( + &mut self, + ) -> impl for<'ec, 'db> FnMut(&'ec mut ExprCollector<'db>) -> LifetimeRefId { + Self::lower_elided_lifetime(&mut self.lifetimes, self.parent, true) + } + pub(crate) fn finish(self) -> GenericParams { let Self { mut lifetimes, mut type_or_consts, where_predicates, parent: _ } = self; @@ -107,7 +117,11 @@ impl GenericParamsCollector { ast::GenericParam::TypeParam(type_param) => { let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); let default = type_param.default_type().map(|it| { - ec.lower_type_ref(it, &mut ExprCollector::impl_trait_error_allocator) + ec.lower_type_ref( + it, + &mut ExprCollector::impl_trait_error_allocator, + &mut ExprCollector::elided_lifetime_error_allocator, + ) }); let param = TypeParamData { name: Some(name.clone()), @@ -130,17 +144,22 @@ impl GenericParamsCollector { let ty = ec.lower_type_ref_opt( const_param.ty(), &mut ExprCollector::impl_trait_error_allocator, + &mut ExprCollector::elided_lifetime_error_allocator, ); let default = const_param.default_val().map(|it| ec.lower_const_arg(it)); let param = ConstParamData { name, ty, default }; self.type_or_consts.alloc(param.into()); } ast::GenericParam::LifetimeParam(lifetime_param) => { - let lifetime = ec.lower_lifetime_ref_opt(lifetime_param.lifetime()); + let lifetime = ec.lower_lifetime_ref_opt( + lifetime_param.lifetime(), + &mut ExprCollector::elided_lifetime_error_allocator, + ); if let LifetimeRef::Named(name) = &ec.store.lifetimes[lifetime] { let param = LifetimeParamData { name: name.clone(), bound_type: LifetimeBoundType::EarlyBound, + elided_source: None, }; let _idx = self.lifetimes.alloc(param); ec.with_lifetime_bound_scope(LifetimeBoundScope::WhereClause, |ec| { @@ -164,11 +183,16 @@ impl GenericParamsCollector { ec.with_lifetime_bound_scope(LifetimeBoundScope::WhereClause, |ec| { for pred in where_clause.predicates() { let target = if let Some(type_ref) = pred.ty() { - Either::Left( - ec.lower_type_ref(type_ref, &mut ExprCollector::impl_trait_error_allocator), - ) + Either::Left(ec.lower_type_ref( + type_ref, + &mut ExprCollector::impl_trait_error_allocator, + &mut ExprCollector::elided_lifetime_error_allocator, + )) } else if let Some(lifetime) = pred.lifetime() { - Either::Right(ec.lower_lifetime_ref(lifetime)) + Either::Right(ec.lower_lifetime_ref( + lifetime, + &mut ExprCollector::elided_lifetime_error_allocator, + )) } else { continue; }; @@ -185,6 +209,7 @@ impl GenericParamsCollector { }) .collect() }); + for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { self.lower_type_bound_as_predicate(ec, bound, lifetimes.as_deref(), target); } @@ -217,6 +242,7 @@ impl GenericParamsCollector { &mut self.where_predicates, self.parent, ), + &mut ExprCollector::elided_lifetime_error_allocator, ); let predicate = match (target, bound) { (_, TypeBound::Error | TypeBound::Use(_)) => return, @@ -304,4 +330,34 @@ impl GenericParamsCollector { lifetime.bound_type = LifetimeBoundType::LateBound } } + + fn lower_elided_lifetime( + lifetimes: &mut Arena, + parent: GenericDefId, + is_impl_header: bool, + ) -> impl for<'ec, 'db> FnMut(&'ec mut ExprCollector<'db>) -> LifetimeRefId { + move |ec| { + let elided_source = ec.elision_context.clone(); + + let lifetime_ref = + if matches!(ec.elision_binder_source, super::ElisionBinderSource::ForBinder) { + return ec.lower_elided_lifetime_for_binder(); + } else { + let bound_type = if is_impl_header { + LifetimeBoundType::EarlyBound + } else { + LifetimeBoundType::LateBound + }; + + let lifetime = LifetimeParamData { + name: Name::anon_lifetime(), + bound_type, + elided_source, + }; + let param_id = LifetimeParamId { parent, local_id: lifetimes.alloc(lifetime) }; + LifetimeRef::Param(param_id) + }; + ec.alloc_lifetime_ref_desugared(lifetime_ref) + } + } } diff --git a/crates/hir-def/src/expr_store/lower/path.rs b/crates/hir-def/src/expr_store/lower/path.rs index 8f71ea867dd5..9481729235aa 100644 --- a/crates/hir-def/src/expr_store/lower/path.rs +++ b/crates/hir-def/src/expr_store/lower/path.rs @@ -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, }; @@ -28,6 +30,8 @@ use crate::{ type_ref::TypeRef, }; +use super::generics::LifetimeElisionFn; + #[cfg(test)] thread_local! { /// This is used to test `hir_segment_to_ast_segment()`. It's a hack, but it makes testing much easier. @@ -42,6 +46,7 @@ pub(super) fn lower_path( collector: &mut ExprCollector<'_>, mut path: ast::Path, impl_trait_lower_fn: ImplTraitLowerFn<'_>, + lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> Option { let mut kind = PathKind::Plain; let mut type_anchor = None; @@ -99,13 +104,18 @@ pub(super) fn lower_path( let name = name_ref.as_name(); let args = segment .generic_arg_list() - .and_then(|it| collector.lower_generic_args(it, impl_trait_lower_fn)) + .and_then(|it| { + collector.lower_generic_args(it, impl_trait_lower_fn, lifetime_elision_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, + lifetime_elision_fn, + ) + }) }) .or_else(|| { segment.return_type_syntax().map(|_| GenericArgs::return_type_notation()) @@ -124,7 +134,7 @@ pub(super) fn lower_path( let type_ref = type_ref?; let self_type = collector.for_path_type_projection(|collector| { - collector.lower_type_ref(type_ref, impl_trait_lower_fn) + collector.lower_type_ref(type_ref, impl_trait_lower_fn, lifetime_elision_fn) }); match trait_ref { @@ -136,7 +146,11 @@ pub(super) fn lower_path( // >::Foo desugars to Trait::Foo Some(trait_ref) => { let path = collector.for_path_type_projection(|collector| { - collector.lower_path(trait_ref.path()?, impl_trait_lower_fn) + collector.lower_path( + trait_ref.path()?, + impl_trait_lower_fn, + lifetime_elision_fn, + ) })?; // FIXME: Unnecessary clone collector.alloc_type_ref( @@ -256,11 +270,49 @@ 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.elision_context.is_some() && !is_trait_assoc_item { + let args_in_source = generic_args.last().and_then(|g| g.as_ref()); + let merged_args_with_elided = collector.collect_path_elided_liftetimes( + resolved_module_def_id, + args_in_source, + lifetime_elision_fn, + ); + 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 { diff --git a/crates/hir-def/src/expr_store/lower/path/tests.rs b/crates/hir-def/src/expr_store/lower/path/tests.rs index b1d0ebb97d3a..bdd4a585689d 100644 --- a/crates/hir-def/src/expr_store/lower/path/tests.rs +++ b/crates/hir-def/src/expr_store/lower/path/tests.rs @@ -26,7 +26,11 @@ fn lower_path(path: ast::Path) -> (TestDB, ExpressionStore, Option) { file_id.into(), crate::LoweringMode::Analysis, ); - let lowered_path = ctx.lower_path(path, &mut ExprCollector::impl_trait_allocator); + let lowered_path = ctx.lower_path( + path, + &mut ExprCollector::impl_trait_allocator, + &mut ExprCollector::elided_lifetime_error_allocator, + ); let (store, _) = ctx.store.finish(); (db, store, lowered_path) } diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs index 1c70922467e1..d87e39a3a4b0 100644 --- a/crates/hir-def/src/expr_store/pretty.rs +++ b/crates/hir-def/src/expr_store/pretty.rs @@ -1267,6 +1267,7 @@ impl Printer<'_> { } LifetimeRef::Placeholder => w!(self, "'_"), LifetimeRef::Error => w!(self, "'{{error}}"), + LifetimeRef::HrtbParam(_) => w!(self, "'_"), // FIXME: properly handle it, currently do not have enough data to handle &LifetimeRef::Param(p) => self.print_lifetime_param(p), } } @@ -1324,7 +1325,9 @@ impl Printer<'_> { TypeRef::Fn(fn_) => { let ((_, return_type), args) = fn_.params.split_last().expect("TypeRef::Fn is missing return type"); - if let Some(binder) = &fn_.binder { + if let Some(binder) = &fn_.binder + && !binder.is_empty() + { w!( self, "for<{}> ", diff --git a/crates/hir-def/src/hir/generics.rs b/crates/hir-def/src/hir/generics.rs index 2e0b6f1ae1cd..14c759958309 100644 --- a/crates/hir-def/src/hir/generics.rs +++ b/crates/hir-def/src/hir/generics.rs @@ -35,6 +35,13 @@ pub struct TypeParamData { pub struct LifetimeParamData { pub name: Name, pub bound_type: LifetimeBoundType, + pub elided_source: Option, +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum ElidedSource { + Self_, + Param, } #[derive(Clone, PartialEq, Eq, Debug, Hash)] diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs index 8e29268c1c21..e493be65c7f2 100644 --- a/crates/hir-def/src/hir/type_ref.rs +++ b/crates/hir-def/src/hir/type_ref.rs @@ -7,7 +7,7 @@ use rustc_abi::ExternAbi; use thin_vec::ThinVec; use crate::{ - LifetimeParamId, TypeParamId, + HrtbLifetimeParamId, LifetimeParamId, TypeParamId, expr_store::{ExpressionStore, path::Path}, hir::{ExprId, PatId}, }; @@ -157,6 +157,7 @@ pub enum LifetimeRef { Static, Placeholder, Param(LifetimeParamId), + HrtbParam(HrtbLifetimeParamId), Error, } diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 0712a025b49c..159888277725 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -718,10 +718,7 @@ pub struct LifetimeParamId { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct HrtbLifetimeParamId { - pub scope: GenericDefId, - pub local_id: usize, -} +pub struct HrtbLifetimeParamId(pub usize); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] pub enum ItemContainerId { @@ -1420,6 +1417,21 @@ impl ModuleDefId { ModuleDefId::BuiltinType(_) => return None, }) } + + /// Converts this `ModuleDefId` into a `GenericDefId` if possible. + /// + /// Returns `None` for variants, modules, builtin types, and macros. + pub fn as_generic_def_id(self) -> Option { + match self { + ModuleDefId::FunctionId(id) => Some(id.into()), + ModuleDefId::AdtId(id) => Some(id.into()), + ModuleDefId::ConstId(id) => Some(id.into()), + ModuleDefId::StaticId(id) => Some(id.into()), + ModuleDefId::TraitId(id) => Some(id.into()), + ModuleDefId::TypeAliasId(id) => Some(id.into()), + _ => None, + } + } } /// Helper wrapper for `AstId` with `ModPath` #[derive(Clone, Debug, Eq, PartialEq)] diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 5b11f5ff8bbb..b907c221e5e2 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -571,6 +571,7 @@ impl<'db> Resolver<'db> { LifetimeRef::Param(lifetime_param_id) => { Some(LifetimeNs::LifetimeParam(*lifetime_param_id)) } + LifetimeRef::HrtbParam(_) => None, // this should be unreachable, should we panic? } } diff --git a/crates/hir-def/src/signatures.rs b/crates/hir-def/src/signatures.rs index b46d258686ad..e23e5b9a7620 100644 --- a/crates/hir-def/src/signatures.rs +++ b/crates/hir-def/src/signatures.rs @@ -1010,8 +1010,11 @@ fn lower_fields( has_fields = true; match AttrFlags::is_cfg_enabled_for(&field, cfg_options) { Ok(()) => { - let type_ref = - col.lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator); + let type_ref = col.lower_type_ref_opt( + ty, + &mut ExprCollector::impl_trait_error_allocator, + &mut ExprCollector::elided_lifetime_error_allocator, + ); let visibility = override_visibility.as_ref().map_or_else( || { visibility_from_ast(db, field.visibility(), &mut |range| { diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs index 7968adabbccf..e4dd6c8d95bc 100644 --- a/crates/hir-expand/src/name.rs +++ b/crates/hir-expand/src/name.rs @@ -112,6 +112,11 @@ impl Name { } } + #[inline] + pub fn anon_lifetime() -> Name { + Self::new_text("'_") + } + #[inline] pub fn new_symbol(symbol: Symbol, ctx: SyntaxContext) -> Self { debug_assert!(!symbol.as_str().starts_with("r#")); diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index dc20eb930e81..b6161894d3b1 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -2429,6 +2429,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for LifetimeRefId { LifetimeRef::Static => write!(f, "'static"), LifetimeRef::Placeholder => write!(f, "'_"), LifetimeRef::Error => write!(f, "'{{error}}"), + LifetimeRef::HrtbParam(_) => write!(f, "'_"), // FIXME: find a way to display HRTB param as well &LifetimeRef::Param(lifetime_param_id) => { let generic_params = GenericParams::of(f.db, lifetime_param_id.parent); write!( @@ -2521,7 +2522,9 @@ impl<'db> HirDisplayWithExpressionStore<'db> for TypeRefId { write!(f, "]")?; } TypeRef::Fn(fn_) => { - if let Some(binder) = &fn_.binder { + if let Some(binder) = &fn_.binder + && !binder.is_empty() + { let edition = f.edition(); write!( f, diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 5f7e6782fdd2..36788456eea3 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -46,8 +46,8 @@ use rustc_hash::FxHashSet; use rustc_type_ir::{ AliasTyKind, BoundRegion, BoundRegionKind, BoundTyKind, BoundVar, BoundVariableKind, DebruijnIndex, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, - Interner, OutlivesPredicate, TermKind, TyKind, TypeFoldable, TypeVisitableExt, Upcast, - UpcastFrom, elaborate, + INNERMOST, Interner, OutlivesPredicate, TermKind, TyKind, TypeFoldable, TypeVisitableExt, + Upcast, UpcastFrom, elaborate, inherent::{Clause as _, GenericArgs as _, IntoKind as _, Region as _, Ty as _}, }; use salsa::SalsaValue; @@ -1362,20 +1362,24 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { } fn find_and_lower_hrtb_lifetime(&mut self, lifetime: LifetimeRefId) -> Option> { - if let LifetimeRef::Named(lt_name) = &self.store[lifetime] { - self.bound_vars.iter().rev().enumerate().find_map(|(debruijn, (binder, _))| { - binder.iter().enumerate().find_map(|(index, l)| { - (l == lt_name).then(|| { - self.hrtb_region_param( - index as u32, - DebruijnIndex::from_usize(debruijn), - self.generic_def, - ) + match &self.store[lifetime] { + LifetimeRef::Named(lt_name) => { + self.bound_vars.iter().rev().enumerate().find_map(|(debruijn, (binder, _))| { + binder.iter().enumerate().find_map(|(index, l)| { + (l == lt_name).then(|| { + self.hrtb_region_param( + index as u32, + DebruijnIndex::from_usize(debruijn), + self.generic_def, + ) + }) }) }) - }) - } else { - None + } + LifetimeRef::HrtbParam(hrtb_param_id) => { + Some(self.hrtb_region_param(hrtb_param_id.0 as u32, INNERMOST, self.generic_def)) + } + _ => None, } } } diff --git a/crates/hir-ty/src/variance.rs b/crates/hir-ty/src/variance.rs index 269029728398..7d6baa56c21d 100644 --- a/crates/hir-ty/src/variance.rs +++ b/crates/hir-ty/src/variance.rs @@ -948,7 +948,7 @@ struct FixedPoint(&'static FixedPoint<(), T, U>, V); res, "{name}[{}]\n", generics(&db, def) - .iter(false) + .iter(true) .map(|(_, param)| match param { GenericParamDataRef::TypeParamData(type_param_data) => { type_param_data.name.as_ref().unwrap() diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 209091683a01..5fa32a038e1b 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -1286,11 +1286,18 @@ impl<'db> SourceAnalyzer<'db> { // FIXME: collectiong here shouldnt be necessary? let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id, LoweringMode::Ide); - let hir_path = - collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?; - let parent_hir_path = path - .parent_path() - .and_then(|p| collector.lower_path(p, &mut ExprCollector::impl_trait_error_allocator)); + let hir_path = collector.lower_path( + path.clone(), + &mut ExprCollector::impl_trait_error_allocator, + &mut ExprCollector::elided_lifetime_error_allocator, + )?; + let parent_hir_path = path.parent_path().and_then(|p| { + collector.lower_path( + p, + &mut ExprCollector::impl_trait_error_allocator, + &mut ExprCollector::elided_lifetime_error_allocator, + ) + }); let (store, _) = collector.store.finish(); // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are @@ -1492,8 +1499,11 @@ impl<'db> SourceAnalyzer<'db> { ) -> Option> { let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id, LoweringMode::Ide); - let hir_path = - collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?; + let hir_path = collector.lower_path( + path.clone(), + &mut ExprCollector::impl_trait_error_allocator, + &mut ExprCollector::elided_lifetime_error_allocator, + )?; let (store, _) = collector.store.finish(); Some(resolve_hir_path_( db, From 3018ecc13931e082b073f6f3dede5e28bad4fee5 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Tue, 21 Jul 2026 19:10:48 +0530 Subject: [PATCH 2/8] fix: tests updated for lifetime ellision --- .../src/expr_store/tests/signatures.rs | 10 +- crates/hir-ty/src/tests/macros.rs | 4 +- crates/hir-ty/src/tests/method_resolution.rs | 12 +- crates/hir-ty/src/tests/never_type.rs | 6 +- crates/hir-ty/src/tests/opaque_types.rs | 2 +- crates/hir-ty/src/tests/patterns.rs | 42 +- crates/hir-ty/src/tests/regression.rs | 68 ++-- .../hir-ty/src/tests/regression/new_solver.rs | 26 +- crates/hir-ty/src/tests/simple.rs | 116 +++--- crates/hir-ty/src/tests/traits.rs | 144 +++---- crates/hir-ty/src/variance.rs | 18 +- crates/hir/src/term_search/tactics.rs | 15 +- crates/ide-completion/src/completions/dot.rs | 204 +++++----- .../ide-completion/src/completions/postfix.rs | 2 +- crates/ide-completion/src/context/tests.rs | 2 +- crates/ide-completion/src/render.rs | 66 ++-- crates/ide-completion/src/render/function.rs | 2 +- crates/ide-completion/src/tests/expression.rs | 368 +++++++++--------- crates/ide-completion/src/tests/flyimport.rs | 20 +- .../ide-completion/src/tests/proc_macros.rs | 8 +- crates/ide-completion/src/tests/special.rs | 70 ++-- .../src/handlers/elided_lifetimes_in_path.rs | 2 + crates/ide/src/hover/tests.rs | 56 +-- crates/ide/src/rename.rs | 5 +- crates/ide/src/signature_help.rs | 34 +- crates/rust-analyzer/tests/slow-tests/cli.rs | 4 +- 26 files changed, 649 insertions(+), 657 deletions(-) diff --git a/crates/hir-def/src/expr_store/tests/signatures.rs b/crates/hir-def/src/expr_store/tests/signatures.rs index 460ab6418d92..14d6580cef7d 100644 --- a/crates/hir-def/src/expr_store/tests/signatures.rs +++ b/crates/hir-def/src/expr_store/tests/signatures.rs @@ -109,7 +109,7 @@ const async unsafe extern "C" fn a() {} fn ret_impl_trait() -> impl Trait {} "#, expect![[r#" - fn foo<'a, const C: usize = 314235, T = B>(&Struct, (), u32) -> &'a dyn Fn::<(), Output = i32> + fn foo<'a, '_, const C: usize = 314235, T = B>(&'_ Struct, (), u32) -> &'a dyn Fn::<(), Output = i32> where T: Trait::, (): Default @@ -169,15 +169,15 @@ fn allowed3(baz: impl Baz>) {} {...} fn not_allowed2(Param[0]) where - Param[0]: Fn::<(&{error}), Output = ()> + Param[0]: for<'_> Fn::<(&'_ {error}), Output = ()> {...} fn not_allowed3(Param[0]) where Param[0]: Bar::<{error}> {...} - fn not_allowed4(Param[0]) + fn not_allowed4<'_, Param[0]>(Param[0]) where - Param[0]: Bar::<&{error}> + Param[0]: Bar::<&'_ {error}> {...} fn allowed1(Param[1]) where @@ -207,7 +207,7 @@ type Alias<'a, 'b, T> = &'b T; fn f(_: Alias) {} "#, expect![[r#" - fn f(Alias::) {...} + fn f<'_, '_, T>(Alias::<'_, '_, T>) {...} "#]], ); } diff --git a/crates/hir-ty/src/tests/macros.rs b/crates/hir-ty/src/tests/macros.rs index c0da6cfd307d..d14bb1f2bf13 100644 --- a/crates/hir-ty/src/tests/macros.rs +++ b/crates/hir-ty/src/tests/macros.rs @@ -199,7 +199,7 @@ fn expr_macro_def_expanded_in_various_places() { 100..119 'for _ ...!() {}': ! 100..119 'for _ ...!() {}': {unknown} 100..119 'for _ ...!() {}': &'? mut {unknown} - 100..119 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> + 100..119 'for _ ...!() {}': fn next<{unknown}>(&'?0.0 mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 100..119 'for _ ...!() {}': Option<<{unknown} as Iterator>::Item> 100..119 'for _ ...!() {}': () 100..119 'for _ ...!() {}': () @@ -293,7 +293,7 @@ fn expr_macro_rules_expanded_in_various_places() { 114..133 'for _ ...!() {}': ! 114..133 'for _ ...!() {}': {unknown} 114..133 'for _ ...!() {}': &'? mut {unknown} - 114..133 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> + 114..133 'for _ ...!() {}': fn next<{unknown}>(&'?0.0 mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 114..133 'for _ ...!() {}': Option<<{unknown} as Iterator>::Item> 114..133 'for _ ...!() {}': () 114..133 'for _ ...!() {}': () diff --git a/crates/hir-ty/src/tests/method_resolution.rs b/crates/hir-ty/src/tests/method_resolution.rs index 985ecb6c5d3b..4204057960ff 100644 --- a/crates/hir-ty/src/tests/method_resolution.rs +++ b/crates/hir-ty/src/tests/method_resolution.rs @@ -660,7 +660,7 @@ fn infer_call_trait_method_on_generic_param_1() { } "#, expect![[r#" - 29..33 'self': &'? Self + 29..33 'self': &'_ Self 63..64 't': T 69..88 '{ ...d(); }': () 75..76 't': T @@ -681,7 +681,7 @@ fn infer_call_trait_method_on_generic_param_2() { } "#, expect![[r#" - 32..36 'self': &'? Self + 32..36 'self': &'_ Self 70..71 't': T 76..95 '{ ...d(); }': () 82..83 't': T @@ -1155,12 +1155,12 @@ fn dyn_trait_super_trait_not_in_scope() { } "#, expect![[r#" - 51..55 'self': &'? Self + 51..55 'self': &'_ Self 64..69 '{ 0 }': u32 66..67 '0': u32 - 176..177 'd': &'? (dyn Trait + 'static) + 176..177 'd': &'_ (dyn Trait + 'static) 191..207 '{ ...o(); }': () - 197..198 'd': &'? (dyn Trait + 'static) + 197..198 'd': &'_ (dyn Trait + 'static) 197..204 'd.foo()': u32 "#]], ); @@ -1187,7 +1187,7 @@ fn test() { } "#, expect![[r#" - 75..79 'self': &'? S + 75..79 'self': &'_ S 89..109 '{ ... }': bool 99..103 'true': bool 123..167 '{ ...o(); }': () diff --git a/crates/hir-ty/src/tests/never_type.rs b/crates/hir-ty/src/tests/never_type.rs index 5cc4156e2a4c..361f02db313b 100644 --- a/crates/hir-ty/src/tests/never_type.rs +++ b/crates/hir-ty/src/tests/never_type.rs @@ -364,7 +364,7 @@ fn diverging_expression_3_break() { 151..172 'for a ...eak; }': ! 151..172 'for a ...eak; }': {unknown} 151..172 'for a ...eak; }': &'? mut {unknown} - 151..172 'for a ...eak; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> + 151..172 'for a ...eak; }': fn next<{unknown}>(&'?0.0 mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 151..172 'for a ...eak; }': Option<<{unknown} as Iterator>::Item> 151..172 'for a ...eak; }': () 151..172 'for a ...eak; }': () @@ -381,7 +381,7 @@ fn diverging_expression_3_break() { 237..250 'for a in b {}': ! 237..250 'for a in b {}': {unknown} 237..250 'for a in b {}': &'? mut {unknown} - 237..250 'for a in b {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> + 237..250 'for a in b {}': fn next<{unknown}>(&'?0.0 mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 237..250 'for a in b {}': Option<<{unknown} as Iterator>::Item> 237..250 'for a in b {}': () 237..250 'for a in b {}': () @@ -397,7 +397,7 @@ fn diverging_expression_3_break() { 315..337 'for a ...urn; }': ! 315..337 'for a ...urn; }': {unknown} 315..337 'for a ...urn; }': &'? mut {unknown} - 315..337 'for a ...urn; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> + 315..337 'for a ...urn; }': fn next<{unknown}>(&'?0.0 mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 315..337 'for a ...urn; }': Option<<{unknown} as Iterator>::Item> 315..337 'for a ...urn; }': () 315..337 'for a ...urn; }': () diff --git a/crates/hir-ty/src/tests/opaque_types.rs b/crates/hir-ty/src/tests/opaque_types.rs index 21d830ed51e3..0503287c2023 100644 --- a/crates/hir-ty/src/tests/opaque_types.rs +++ b/crates/hir-ty/src/tests/opaque_types.rs @@ -204,7 +204,7 @@ impl Miku { 61..72 '{ loop {} }': Vec 63..70 'loop {}': ! 68..70 '{}': () - 133..137 'self': &'? Miku + 133..137 'self': &'_ Miku 152..220 '{ ... }': Miku 162..214 'Miku {... }': Miku 193..201 'Vec::new': fn new<{unknown}>() -> Vec<{unknown}> diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs index a6e864916f40..b9def8be8662 100644 --- a/crates/hir-ty/src/tests/patterns.rs +++ b/crates/hir-ty/src/tests/patterns.rs @@ -32,13 +32,13 @@ fn infer_pattern() { } "#, expect![[r#" - 8..9 'x': &'? i32 + 8..9 'x': &'_ i32 17..399 '{ ...o_x; }': () 27..28 'y': &'? i32 - 31..32 'x': &'? i32 + 31..32 'x': &'_ i32 42..44 '&z': &'? i32 43..44 'z': i32 - 47..48 'x': &'? i32 + 47..48 'x': &'_ i32 58..59 'a': i32 62..63 'z': i32 73..79 '(c, d)': (i32, &'? str) @@ -50,7 +50,7 @@ fn infer_pattern() { 101..150 'for (e... }': ! 101..150 'for (e... }': IntoIter<(i32, i32), 1> 101..150 'for (e... }': &'? mut IntoIter<(i32, i32), 1> - 101..150 'for (e... }': fn next>(&'? mut IntoIter<(i32, i32), 1>) -> Option< as Iterator>::Item> + 101..150 'for (e... }': fn next>(&'?0.0 mut IntoIter<(i32, i32), 1>) -> Option< as Iterator>::Item> 101..150 'for (e... }': Option<(i32, i32)> 101..150 'for (e... }': () 101..150 'for (e... }': () @@ -95,14 +95,14 @@ fn infer_pattern() { 276..281 'a + b': u64 280..281 'b': u64 283..284 'c': i32 - 297..309 'ref ref_to_x': &'? &'? i32 - 312..313 'x': &'? i32 + 297..309 'ref ref_to_x': &'? &'_ i32 + 312..313 'x': &'_ i32 323..332 'mut mut_x': &'? i32 - 335..336 'x': &'? i32 - 346..366 'ref mu...f_to_x': &'? mut &'? i32 - 369..370 'x': &'? i32 - 380..381 'k': &'? mut &'? i32 - 384..396 'mut_ref_to_x': &'? mut &'? i32 + 335..336 'x': &'_ i32 + 346..366 'ref mu...f_to_x': &'? mut &'_ i32 + 369..370 'x': &'_ i32 + 380..381 'k': &'? mut &'_ i32 + 384..396 'mut_ref_to_x': &'? mut &'_ i32 "#]], ); } @@ -127,7 +127,7 @@ fn infer_literal_pattern() { 17..28 '{ loop {} }': T 19..26 'loop {}': ! 24..26 '{}': () - 37..38 'x': &'? i32 + 37..38 'x': &'_ i32 46..263 '{ ...) {} }': () 52..75 'if let...y() {}': () 55..72 'let "f... any()': bool @@ -394,7 +394,7 @@ fn infer_pattern_match_byte_string_literal() { } "#, expect![[r#" - 105..109 'self': &'? [T; N] + 105..109 'self': &'_ [T; N] 111..116 'index': RangeFull 157..180 '{ ... }': &'? [u8] 167..174 'loop {}': ! @@ -705,7 +705,7 @@ fn main() { } "#, expect![[r#" - 27..31 'self': &'? S + 27..31 'self': &'_ S 41..50 '{ false }': bool 43..48 'false': bool 64..115 '{ ... } }': () @@ -777,10 +777,10 @@ fn slice_tail_pattern() { } "#, expect![[r#" - 7..13 'params': &'? [i32] + 7..13 'params': &'_ [i32] 23..92 '{ ... } }': () 29..90 'match ... }': () - 35..41 'params': &'? [i32] + 35..41 'params': &'_ [i32] 52..69 '[head,... @ ..]': [i32] 53..57 'head': &'? i32 59..68 'tail @ ..': &'? [i32] @@ -1338,23 +1338,23 @@ fn foo(v: &Box>) { } "#, expect![[r#" - 142..146 'self': &'? Box + 142..146 'self': &'_ Box 165..188 '{ ... }': &'? T 175..182 'loop {}': ! 180..182 '{}': () - 310..314 'self': &'? Foo + 310..314 'self': &'_ Foo 333..356 '{ ... }': &'? [T] 343..350 'loop {}': ! 348..350 '{}': () !0..20 'builti...inner)': Foo !0..28 'builti...nner))': Box> !14..19 'inner': &'? [i32] - 399..400 'v': &'? Box> + 399..400 'v': &'_ Box> 418..493 '{ ... } }': () 424..491 'match ... }': () - 430..431 'v': &'? Box> + 430..431 'v': &'_ Box> 467..469 '{}': () - 478..479 '_': &'? Box> + 478..479 '_': &'_ Box> 483..485 '{}': () "#]], ); diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index 6260722dd0f3..76321f7dec9c 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -303,7 +303,7 @@ fn infer_std_crash_5() { 32..320 'for co... }': ! 32..320 'for co... }': {unknown} 32..320 'for co... }': &'? mut {unknown} - 32..320 'for co... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> + 32..320 'for co... }': fn next<{unknown}>(&'?0.0 mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 32..320 'for co... }': Option<<{unknown} as Iterator>::Item> 32..320 'for co... }': () 32..320 'for co... }': () @@ -501,10 +501,10 @@ fn issue_3999_slice() { } "#, expect![[r#" - 7..13 'params': &'? [usize] + 7..13 'params': &'_ [usize] 25..80 '{ ... } }': () 31..78 'match ... }': () - 37..43 'params': &'? [usize] + 37..43 'params': &'_ [usize] 54..66 '[ps @ .., _]': [usize] 55..62 'ps @ ..': &'? [usize] 60..62 '..': [usize] @@ -559,7 +559,7 @@ fn issue_4235_name_conflicts() { "#, expect![[r#" 31..37 'FOO {}': FOO - 63..67 'self': &'? FOO + 63..67 'self': &'_ FOO 69..71 '{}': () 85..119 '{ ...o(); }': () 95..96 'a': &'? FOO @@ -751,12 +751,12 @@ fn issue_4885() { } "#, expect![[r#" - 70..73 'key': &'? K + 70..73 'key': &'_ K 132..148 '{ ...key) }': impl Future>::Bar> - 138..141 'bar': fn bar(&'? K) -> impl Future>::Bar> + 138..141 'bar': fn bar(&'?0.0 K) -> impl Future>::Bar> 138..146 'bar(key)': impl Future>::Bar> - 142..145 'key': &'? K - 162..165 'key': &'? K + 142..145 'key': &'_ K + 162..165 'key': &'_ K 224..227 '{ }': () "#]], ); @@ -807,11 +807,11 @@ fn issue_4800() { } "#, expect![[r#" - 379..383 'self': &'? mut PeerSet + 379..383 'self': &'_ mut PeerSet 401..424 '{ ... }': dyn Future + 'static 411..418 'loop {}': ! 416..418 '{}': () - 575..579 'self': &'? mut Self + 575..579 'self': &'_ mut Self "#]], ); } @@ -891,10 +891,10 @@ fn main() { } "#, expect![[r#" - 86..90 'self': &'? S + 86..90 'self': &'_ S 92..94 '_t': T 99..101 '{}': () - 127..131 'self': &'? S + 127..131 'self': &'_ S 133..135 '_f': F 140..142 '{}': () 155..217 '{ ...10); }': () @@ -938,13 +938,13 @@ fn flush(&self) { } "#, expect![[r#" - 129..133 'self': &'? Mutex + 129..133 'self': &'_ Mutex 156..158 '{}': MutexGuard<'?, T> - 242..246 'self': &'? MutexGuard<'a, T> + 242..246 'self': &'_ MutexGuard<'a, T> 265..276 '{ loop {} }': &'? T 267..274 'loop {}': ! 272..274 '{}': () - 289..293 'self': &'? {unknown} + 289..293 'self': &'_ {unknown} 295..345 '{ ...()); }': () 305..306 'w': &'? Mutex 331..342 '*(w.lock())': BufWriter @@ -1294,7 +1294,7 @@ fn test() { 16..66 'for _ ... }': ! 16..66 'for _ ... }': {unknown} 16..66 'for _ ... }': &'? mut {unknown} - 16..66 'for _ ... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> + 16..66 'for _ ... }': fn next<{unknown}>(&'?0.0 mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 16..66 'for _ ... }': Option<<{unknown} as Iterator>::Item> 16..66 'for _ ... }': () 16..66 'for _ ... }': () @@ -1689,7 +1689,7 @@ fn dyn_with_unresolved_trait() { r#" fn foo(a: &dyn DoesNotExist) { a.bar(); - //^&'? {unknown} + //^&'_ {unknown} } "#, ); @@ -2229,13 +2229,13 @@ impl<'a, T: Deref> Struct<'a, T> { } "#, expect![[r#" - 137..141 'self': &'? Struct<'a, T> + 137..141 'self': &'_ Struct<'a, T> 152..160 '{ self }': &'? Struct<'a, T> - 154..158 'self': &'? Struct<'a, T> - 174..178 'self': &'? Struct<'a, T> + 154..158 'self': &'_ Struct<'a, T> + 174..178 'self': &'_ Struct<'a, T> 180..215 '{ ... }': () 194..195 '_': &'? Struct<'?, T> - 198..202 'self': &'? Struct<'a, T> + 198..202 'self': &'_ Struct<'a, T> 198..208 'self.foo()': &'? Struct<'?, T> "#]], ); @@ -2301,8 +2301,8 @@ fn test(x: bool) { 69..80 '{ loop {} }': Map 71..78 'loop {}': ! 76..78 '{}': () - 93..97 'self': &'? Map - 99..100 '_': &'? T + 93..97 'self': &'_ Map + 99..100 '_': &'_ T 120..131 '{ loop {} }': Option<&'? U> 122..129 'loop {}': ! 127..129 '{}': () @@ -2768,24 +2768,24 @@ where } "#, expect![[r#" - 214..223 'filter_fn': dyn Fn(&'? T) -> bool + 'static + 214..223 'filter_fn': dyn Fn(&'_ T) -> bool + 'static 253..360 '{ ... }': Filter<'a, 'b, T> 263..354 'Self {... }': Filter<'a, 'b, T> - 293..302 'filter_fn': dyn Fn(&'? T) -> bool + 'static + 293..302 'filter_fn': dyn Fn(&'_ T) -> bool + 'static 319..323 'None': Option 340..343 '&()': &'? () 341..343 '()': () - 421..425 'self': &'? Self - 427..433 'filter': &'? Filter<'?, '?, T> - 580..584 'self': &'? [T; N] - 586..592 'filter': &'? Filter<'?, '?, T> + 421..425 'self': &'_ Self + 427..433 'filter': &'_ Filter<'_, '_, T> + 580..584 'self': &'_ [T; N] + 586..592 'filter': &'_ Filter<'_, '_, T> 622..704 '{ ... }': T - 636..637 '_': Filter, dyn Fn(&'? T) -> bool + '?> - 640..644 'self': &'? [T; N] + 636..637 '_': Filter, dyn Fn(&'_ T) -> bool + '?> + 640..644 'self': &'_ [T; N] 640..656 'self.i...iter()': Iter<'?, T> - 640..681 'self.i...er_fn)': Filter, dyn Fn(&'? T) -> bool + '?> - 664..670 'filter': &'? Filter<'?, '?, T> - 664..680 'filter...ter_fn': dyn Fn(&'? T) -> bool + 'static + 640..681 'self.i...er_fn)': Filter, dyn Fn(&'_ T) -> bool + '?> + 664..670 'filter': &'_ Filter<'_, '_, T> + 664..680 'filter...ter_fn': dyn Fn(&'_ T) -> bool + 'static 691..698 'loop {}': ! 696..698 '{}': () "#]], diff --git a/crates/hir-ty/src/tests/regression/new_solver.rs b/crates/hir-ty/src/tests/regression/new_solver.rs index 59563bdc33ea..33ca876ecbd1 100644 --- a/crates/hir-ty/src/tests/regression/new_solver.rs +++ b/crates/hir-ty/src/tests/regression/new_solver.rs @@ -140,7 +140,7 @@ fn test() -> i32 { 155..170 '{ loop {} }': *const T 161..168 'loop {}': ! 166..168 '{}': () - 195..199 'self': &'? Self + 195..199 'self': &'_ Self 208..231 '{ ... }': i32 218..225 'loop {}': ! 223..225 '{}': () @@ -578,7 +578,7 @@ fn test_at_most() { expect![[r#" 48..49 '0': usize 182..186 'self': Between - 188..192 '_sep': &'? str + 188..192 '_sep': &'_ str 200..206 '_other': Between 222..242 '{ ... }': Between 232..236 'self': Between @@ -740,10 +740,10 @@ where } "#, expect![[r#" - 43..47 'self': &'? Self - 168..172 'self': &'? F + 43..47 'self': &'_ Self + 168..172 'self': &'_ F 205..227 '{ ... }': >::CallRefFuture<'?> - 215..219 'self': &'? F + 215..219 'self': &'_ F 215..221 'self()': >::CallRefFuture<'?> "#]], ); @@ -860,12 +860,12 @@ fn main() { } "#, expect![[r#" - 164..168 'self': &'? mut Foo + 164..168 'self': &'_ mut Foo 192..224 '{ ... }': Option - 202..206 'self': &'? mut Foo + 202..206 'self': &'_ mut Foo 202..218 'self.n...spec()': Option - 278..282 'self': &'? mut Self - 380..384 'self': &'? mut Foo + 278..282 'self': &'_ mut Self + 380..384 'self': &'_ mut Foo 408..428 '{ ... }': Option 418..422 'None': Option 501..505 'iter': I @@ -924,10 +924,10 @@ fn test2(factory: T) { } "#, expect![[r#" - 39..43 'self': &'? Self - 101..105 'self': &'? Self - 198..202 'self': &'? Self - 239..243 'self': &'? Self + 39..43 'self': &'_ Self + 101..105 'self': &'_ Self + 198..202 'self': &'_ Self + 239..243 'self': &'_ Self 290..293 'foo': impl Foo + ?Sized 325..359 '{ ...z(); }': () 335..338 'baz': u8 diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs index 3cdfe4edcb90..3c463a8b825b 100644 --- a/crates/hir-ty/src/tests/simple.rs +++ b/crates/hir-ty/src/tests/simple.rs @@ -134,12 +134,12 @@ fn test(a: u32, b: isize, c: !, d: &str) { 8..9 'a': u32 16..17 'b': isize 26..27 'c': ! - 32..33 'd': &'? str + 32..33 'd': &'_ str 41..120 '{ ...f32; }': ! 47..48 'a': u32 54..55 'b': isize 61..62 'c': ! - 68..69 'd': &'? str + 68..69 'd': &'_ str 75..81 '1usize': usize 87..93 '1isize': isize 99..105 '"test"': &'static str @@ -363,23 +363,23 @@ fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) { } "#, expect![[r#" - 8..9 'a': &'? u32 - 17..18 'b': &'? mut u32 + 8..9 'a': &'_ u32 + 17..18 'b': &'_ mut u32 30..31 'c': *const u32 45..46 'd': *mut u32 58..149 '{ ... *d; }': () - 64..65 'a': &'? u32 + 64..65 'a': &'_ u32 71..73 '*a': u32 - 72..73 'a': &'? u32 - 79..81 '&a': &'? &'? u32 - 80..81 'a': &'? u32 - 87..93 '&mut a': &'? mut &'? u32 - 92..93 'a': &'? u32 - 99..100 'b': &'? mut u32 + 72..73 'a': &'_ u32 + 79..81 '&a': &'? &'_ u32 + 80..81 'a': &'_ u32 + 87..93 '&mut a': &'? mut &'_ u32 + 92..93 'a': &'_ u32 + 99..100 'b': &'_ mut u32 106..108 '*b': u32 - 107..108 'b': &'? mut u32 - 114..116 '&b': &'? &'? mut u32 - 115..116 'b': &'? mut u32 + 107..108 'b': &'_ mut u32 + 114..116 '&b': &'? &'_ mut u32 + 115..116 'b': &'_ mut u32 122..123 'c': *const u32 129..131 '*c': u32 130..131 'c': *const u32 @@ -602,12 +602,12 @@ impl S { } "#, expect![[r#" - 33..37 'self': &'? S + 33..37 'self': &'_ S 39..60 '{ ... }': () - 49..53 'self': &'? S - 74..78 'self': &'? S + 49..53 'self': &'_ S + 74..78 'self': &'_ S 87..108 '{ ... }': () - 97..101 'self': &'? S + 97..101 'self': &'_ S 132..152 '{ ... }': S 142..146 'S {}': S 176..199 '{ ... }': S @@ -870,19 +870,19 @@ fn test() { } "#, expect![[r#" - 66..70 'self': &'? A + 66..70 'self': &'_ A 78..101 '{ ... }': &'? T 88..95 '&self.0': &'? T - 89..93 'self': &'? A + 89..93 'self': &'_ A 89..95 'self.0': T - 182..186 'self': &'? B + 182..186 'self': &'_ B 205..228 '{ ... }': &'? T 215..222 '&self.0': &'? T - 216..220 'self': &'? B + 216..220 'self': &'_ B 216..222 'self.0': T 242..280 '{ ...))); }': () 252..253 't': &'? i32 - 256..262 'A::foo': fn foo(&'? A) -> &'? i32 + 256..262 'A::foo': fn foo(&'?0.0 A) -> &'? i32 256..277 'A::foo...42))))': &'? i32 263..276 '&&B(B(A(42)))': &'? &'? B>> 264..276 '&B(B(A(42)))': &'? B>> @@ -925,17 +925,17 @@ fn test(a: A) { } "#, expect![[r#" - 71..75 'self': &'? A - 77..78 'x': &'? A + 71..75 'self': &'_ A + 77..78 'x': &'_ A 93..114 '{ ... }': &'? T 103..108 '&*x.0': &'? T 104..108 '*x.0': T - 105..106 'x': &'? A + 105..106 'x': &'_ A 105..108 'x.0': *mut T - 195..199 'self': &'? B + 195..199 'self': &'_ B 218..241 '{ ... }': &'? T 228..235 '&self.0': &'? T - 229..233 'self': &'? B + 229..233 'self': &'_ B 229..235 'self.0': T 253..254 'a': A 264..310 '{ ...))); }': () @@ -1074,7 +1074,7 @@ fn infer_inherent_method() { 31..35 'self': A 37..38 'x': u32 52..54 '{}': i32 - 106..110 'self': &'? A + 106..110 'self': &'_ A 112..113 'x': u64 127..129 '{}': i64 147..148 'a': A @@ -1109,7 +1109,7 @@ fn test() { } "#, expect![[r#" - 67..71 'self': &'? str + 67..71 'self': &'_ str 80..82 '{}': i32 96..116 '{ ...o(); }': () 102..107 '"foo"': &'static str @@ -1132,7 +1132,7 @@ fn infer_tuple() { } "#, expect![[r#" - 8..9 'x': &'? str + 8..9 'x': &'_ str 17..18 'y': isize 27..169 '{ ...d"); }': () 37..38 'a': (u32, &'? str) @@ -1142,15 +1142,15 @@ fn infer_tuple() { 72..73 'b': ((u32, &'? str), &'? str) 76..82 '(a, x)': ((u32, &'? str), &'? str) 77..78 'a': (u32, &'? str) - 80..81 'x': &'? str + 80..81 'x': &'_ str 92..93 'c': (isize, &'? str) 96..102 '(y, x)': (isize, &'? str) 97..98 'y': isize - 100..101 'x': &'? str + 100..101 'x': &'_ str 112..113 'd': ((isize, &'? str), &'? str) 116..122 '(c, x)': ((isize, &'? str), &'? str) 117..118 'c': (isize, &'? str) - 120..121 'x': &'? str + 120..121 'x': &'_ str 132..133 'e': (i32, &'? str) 136..144 '(1, "e")': (i32, &'? str) 137..138 '1': i32 @@ -1187,12 +1187,12 @@ fn infer_array() { } "#, expect![[r#" - 8..9 'x': &'? str + 8..9 'x': &'_ str 17..18 'y': isize 27..326 '{ ...,4]; }': () 37..38 'a': [&'? str; 1] 41..44 '[x]': [&'? str; 1] - 42..43 'x': &'? str + 42..43 'x': &'_ str 54..55 'b': [[&'? str; 1]; 2] 58..64 '[a, a]': [[&'? str; 1]; 2] 59..60 'a': [&'? str; 1] @@ -1439,7 +1439,7 @@ fn infer_impl_generics_with_autoderef() { } "#, expect![[r#" - 77..81 'self': &'? Option + 77..81 'self': &'_ Option 97..99 '{}': Option<&'? T> 110..111 'o': Option 126..164 '{ ...f(); }': () @@ -1585,16 +1585,16 @@ fn infer_type_alias() { "#, expect![[r#" 115..116 'x': A - 123..124 'y': A<&'? str, u128> + 123..124 'y': A<&'_ str, u128> 137..138 'z': A 153..210 '{ ...z.y; }': () 159..160 'x': A 159..162 'x.x': u32 168..169 'x': A 168..171 'x.y': i128 - 177..178 'y': A<&'? str, u128> - 177..180 'y.x': &'? str - 186..187 'y': A<&'? str, u128> + 177..178 'y': A<&'_ str, u128> + 177..180 'y.x': &'_ str + 186..187 'y': A<&'_ str, u128> 186..189 'y.y': u128 195..196 'z': A 195..198 'z.x': u8 @@ -1652,10 +1652,10 @@ fn infer_type_param() { 9..10 'x': T 20..29 '{ x }': T 26..27 'x': T - 43..44 'x': &'? T + 43..44 'x': &'_ T 55..65 '{ *x }': T 61..63 '*x': T - 62..63 'x': &'? T + 62..63 'x': &'_ T 77..157 '{ ...(1); }': () 87..88 'y': u32 91..96 '10u32': u32 @@ -1663,7 +1663,7 @@ fn infer_type_param() { 102..107 'id(y)': u32 105..106 'y': u32 117..118 'x': bool - 127..132 'clone': fn clone(&'? bool) -> bool + 127..132 'clone': fn clone(&'?0.0 bool) -> bool 127..135 'clone(z)': bool 133..134 'z': &'? bool 141..151 'id::': fn id(i128) -> i128 @@ -2110,7 +2110,7 @@ fn test(mut cx: Context<'_>) { } "#, expect![[r#" - 91..97 'mut cx': Context<'?> + 91..97 'mut cx': Context<'_> 112..239 '{ ...cx); }': () 122..135 'mut generator': impl AsyncIterator 138..174 'async ... }': impl AsyncIterator @@ -2122,8 +2122,8 @@ fn test(mut cx: Context<'_>) { 193..236 'Pin::n...ut cx)': Poll> 202..216 '&mut generator': &'? mut impl AsyncIterator 207..216 'generator': impl AsyncIterator - 228..235 '&mut cx': &'? mut Context<'?> - 233..235 'cx': Context<'?> + 228..235 '&mut cx': &'? mut Context<'_> + 233..235 'cx': Context<'_> "#]], ); } @@ -2181,7 +2181,7 @@ fn test(mut cx: Context<'_>) { 103..120 '{ ... (); }': () 109..117 'yield ()': () 115..117 '()': () - 130..136 'mut cx': Context<'?> + 130..136 'mut cx': Context<'_> 151..248 '{ ...cx); }': () 161..174 'mut generator': impl AsyncIterator 177..181 'html': fn html() -> impl AsyncIterator @@ -2192,8 +2192,8 @@ fn test(mut cx: Context<'_>) { 202..245 'Pin::n...ut cx)': Poll> 211..225 '&mut generator': &'? mut impl AsyncIterator 216..225 'generator': impl AsyncIterator - 237..244 '&mut cx': &'? mut Context<'?> - 242..244 'cx': Context<'?> + 237..244 '&mut cx': &'? mut Context<'_> + 242..244 'cx': Context<'_> "#]], ); } @@ -3260,7 +3260,7 @@ fn main() { } "#, expect![[r#" - 104..108 'self': &'? Box + 104..108 'self': &'_ Box 188..192 'self': &'_ Box> 218..220 '{}': &'? T 242..246 'self': &'_ Box> @@ -3732,14 +3732,14 @@ fn f(t: Ark) { } "#, expect![[r#" - 47..51 'self': &'? Ark + 47..51 'self': &'_ Ark 65..88 '{ ... }': *const T 75..82 '&self.0': &'? T - 76..80 'self': &'? Ark + 76..80 'self': &'_ Ark 76..82 'self.0': T 99..100 't': Ark 110..144 '{ ... (); }': () - 116..124 'Ark::foo': fn foo(&'? Ark) -> *const T + 116..124 'Ark::foo': fn foo(&'?0.0 Ark) -> *const T 116..128 'Ark::foo(&t)': *const T 116..141 'Ark::f...nst ()': *const () 125..127 '&t': &'? Ark @@ -4099,13 +4099,13 @@ fn foo() { expect![[r#" 22..29 '{ 123 }': i32 24..27 '123': i32 - 37..38 's': &'? str + 37..38 's': &'_ str 46..48 '{}': () !0..68 'builti...");},)': () !40..43 'bar': fn bar() -> i32 !40..45 'bar()': i32 !51..66 '{baz("hello");}': () - !52..55 'baz': fn baz(&'? str) + !52..55 'baz': fn baz(&'?0.0 str) !52..64 'baz("hello")': () !56..63 '"hello"': &'static str 59..257 '{ ... } }': () @@ -4189,7 +4189,7 @@ fn foo() { 73..96 '{ ... }': LazyLock 83..90 'loop {}': ! 88..90 '{}': () - 111..115 'this': &'? LazyLock + 111..115 'this': &'_ LazyLock 130..153 '{ ... }': &'? T 140..147 'loop {}': ! 145..147 '{}': () @@ -4197,7 +4197,7 @@ fn foo() { 207..222 'LazyLock::new()': LazyLock<[u32; 0]> 234..285 '{ ...CK); }': () 244..245 '_': &'? [u32; 0] - 248..263 'LazyLock::force': fn force<[u32; 0]>(&'? LazyLock<[u32; 0]>) -> &'? [u32; 0] + 248..263 'LazyLock::force': fn force<[u32; 0]>(&'?0.0 LazyLock<[u32; 0]>) -> &'? [u32; 0] 248..282 'LazyLo..._LOCK)': &'? [u32; 0] 264..281 '&VALUE...Y_LOCK': &'? LazyLock<[u32; 0]> 265..281 'VALUES...Y_LOCK': LazyLock<[u32; 0]> diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index fad944589dab..779708e3bfdc 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -1022,15 +1022,15 @@ fn test(x: impl Trait, y: &impl Trait) { z.foo2(); }"#, expect![[r#" - 29..33 'self': &'? Self - 54..58 'self': &'? Self + 29..33 'self': &'_ Self + 54..58 'self': &'_ Self 77..78 'x': impl Trait 97..99 '{}': () 154..155 'x': impl Trait - 174..175 'y': &'? impl Trait + 174..175 'y': &'_ impl Trait 195..323 '{ ...2(); }': () 201..202 'x': impl Trait - 208..209 'y': &'? impl Trait + 208..209 'y': &'_ impl Trait 219..220 'z': S 223..224 'S': fn S(u16) -> S 223..227 'S(1)': S @@ -1040,13 +1040,13 @@ fn test(x: impl Trait, y: &impl Trait) { 237..238 'z': S 245..246 'x': impl Trait 245..252 'x.foo()': u64 - 258..259 'y': &'? impl Trait + 258..259 'y': &'_ impl Trait 258..265 'y.foo()': u32 271..272 'z': S 271..278 'z.foo()': u16 284..285 'x': impl Trait 284..292 'x.foo2()': i64 - 298..299 'y': &'? impl Trait + 298..299 'y': &'_ impl Trait 298..306 'y.foo2()': i64 312..313 'z': S 312..320 'z.foo2()': i64 @@ -1220,26 +1220,26 @@ fn test(x: impl Trait, y: &impl Trait) { z.foo2(); }"#, expect![[r#" - 29..33 'self': &'? Self - 54..58 'self': &'? Self + 29..33 'self': &'_ Self + 54..58 'self': &'_ Self 98..100 '{}': () 110..111 'x': impl Trait - 130..131 'y': &'? impl Trait + 130..131 'y': &'_ impl Trait 151..268 '{ ...2(); }': () 157..158 'x': impl Trait - 164..165 'y': &'? impl Trait + 164..165 'y': &'_ impl Trait 175..176 'z': impl Trait 179..182 'bar': fn bar() -> impl Trait 179..184 'bar()': impl Trait 190..191 'x': impl Trait 190..197 'x.foo()': u64 - 203..204 'y': &'? impl Trait + 203..204 'y': &'_ impl Trait 203..210 'y.foo()': u64 216..217 'z': impl Trait 216..223 'z.foo()': u64 229..230 'x': impl Trait 229..237 'x.foo2()': i64 - 243..244 'y': &'? impl Trait + 243..244 'y': &'_ impl Trait 243..251 'y.foo2()': i64 257..258 'z': impl Trait 257..265 'z.foo2()': i64 @@ -1344,7 +1344,7 @@ fn test() { a.foo(); }"#, expect![[r#" - 29..33 'self': &'? Self + 29..33 'self': &'_ Self 71..82 '{ loop {} }': ! 73..80 'loop {}': ! 78..80 '{}': () @@ -1382,8 +1382,8 @@ fn test() { d.foo(); }"#, expect![[r#" - 49..53 'self': &'? mut Self - 101..105 'self': &'? Self + 49..53 'self': &'_ mut Self + 101..105 'self': &'_ Self 184..195 '{ loop {} }': (impl Iterator>, impl Trait) 186..193 'loop {}': ! 191..193 '{}': () @@ -1488,26 +1488,26 @@ fn test(x: Box>, y: &dyn Trait) { z.foo2(); }"#, expect![[r#" - 29..33 'self': &'? Self - 54..58 'self': &'? Self + 29..33 'self': &'_ Self + 54..58 'self': &'_ Self 206..208 '{}': Box + '?> 218..219 'x': Box + 'static> - 242..243 'y': &'? (dyn Trait + 'static) + 242..243 'y': &'_ (dyn Trait + 'static) 262..379 '{ ...2(); }': () 268..269 'x': Box + 'static> - 275..276 'y': &'? (dyn Trait + 'static) + 275..276 'y': &'_ (dyn Trait + 'static) 286..287 'z': Box + '?> 290..293 'bar': fn bar() -> Box + 'static> 290..295 'bar()': Box + 'static> 301..302 'x': Box + 'static> 301..308 'x.foo()': u64 - 314..315 'y': &'? (dyn Trait + 'static) + 314..315 'y': &'_ (dyn Trait + 'static) 314..321 'y.foo()': u64 327..328 'z': Box + '?> 327..334 'z.foo()': u64 340..341 'x': Box + 'static> 340..348 'x.foo2()': i64 - 354..355 'y': &'? (dyn Trait + 'static) + 354..355 'y': &'_ (dyn Trait + 'static) 354..362 'y.foo2()': i64 368..369 'z': Box + '?> 368..376 'z.foo2()': i64 @@ -1536,12 +1536,12 @@ fn test(s: S) { s.bar().baz(); }"#, expect![[r#" - 32..36 'self': &'? Self - 106..110 'self': &'? S + 32..36 'self': &'_ Self + 106..110 'self': &'_ S 132..143 '{ loop {} }': &'? (dyn Trait + 'static) 134..141 'loop {}': ! 139..141 '{}': () - 179..183 'self': &'? Self + 179..183 'self': &'_ Self 255..256 's': S 271..293 '{ ...z(); }': () 277..278 's': S @@ -1570,19 +1570,19 @@ fn test(x: Trait, y: &Trait) -> u64 { z.foo(); }"#, expect![[r#" - 26..30 'self': &'? Self + 26..30 'self': &'_ Self 60..62 '{}': dyn Trait + '? 72..73 'x': dyn Trait + 'static - 82..83 'y': &'? (dyn Trait + 'static) + 82..83 'y': &'_ (dyn Trait + 'static) 100..175 '{ ...o(); }': u64 106..107 'x': dyn Trait + 'static - 113..114 'y': &'? (dyn Trait + 'static) + 113..114 'y': &'_ (dyn Trait + 'static) 124..125 'z': dyn Trait + '? 128..131 'bar': fn bar() -> dyn Trait + 'static 128..133 'bar()': dyn Trait + 'static 139..140 'x': dyn Trait + 'static 139..146 'x.foo()': u64 - 152..153 'y': &'? (dyn Trait + 'static) + 152..153 'y': &'_ (dyn Trait + 'static) 152..159 'y.foo()': u64 165..166 'z': dyn Trait + '? 165..172 'z.foo()': u64 @@ -1602,12 +1602,12 @@ fn main() { } "#, expect![[r#" - 31..35 'self': &'? S + 31..35 'self': &'_ S 37..39 '{}': () - 47..48 '_': &'? (dyn Fn(S) + 'static) + 47..48 '_': &'_ (dyn Fn(S) + 'static) 58..60 '{}': () 71..105 '{ ...()); }': () - 77..78 'f': fn f(&'? (dyn Fn(S) + 'static)) + 77..78 'f': fn f(&'?0.0 (dyn Fn(S) + 'static)) 77..102 'f(&|nu...foo())': () 79..101 '&|numb....foo()': &'? impl Fn(S) 80..101 '|numbe....foo()': impl Fn(S) @@ -1843,7 +1843,7 @@ fn test(x: T, y: U) { y.foo(); }"#, expect![[r#" - 53..57 'self': &'? Self + 53..57 'self': &'_ Self 66..68 '{}': u32 185..186 'x': T 191..192 'y': U @@ -1872,11 +1872,11 @@ fn test(x: &impl Trait1) { x.foo(); }"#, expect![[r#" - 53..57 'self': &'? Self + 53..57 'self': &'_ Self 66..68 '{}': u32 - 119..120 'x': &'? impl Trait1 + 119..120 'x': &'_ impl Trait1 136..152 '{ ...o(); }': () - 142..143 'x': &'? impl Trait1 + 142..143 'x': &'_ impl Trait1 142..149 'x.foo()': u32 "#]], ); @@ -1992,8 +1992,8 @@ fn test() { opt.map(f); }"#, expect![[r#" - 28..32 'self': &'? Self - 132..136 'self': &'? Bar + 28..32 'self': &'_ Self + 132..136 'self': &'_ Bar 149..160 '{ loop {} }': (A1, R) 151..158 'loop {}': ! 156..158 '{}': () @@ -2046,7 +2046,7 @@ fn make_foo_fn() -> Foo {} let r2 = lazy2.foo(); }"#, expect![[r#" - 36..40 'self': &'? Foo + 36..40 'self': &'_ Foo 51..53 '{}': usize 134..135 'f': F 154..156 '{}': Lazy @@ -2354,14 +2354,14 @@ impl Trait for S2 { fn f(&self, x: ::Item) { let y = x; } }"#, expect![[r#" - 40..44 'self': &'? Self + 40..44 'self': &'_ Self 46..47 'x': ::Item - 126..130 'self': &'? S + 126..130 'self': &'_ S 132..133 'x': u32 147..161 '{ let y = x; }': () 153..154 'y': u32 157..158 'x': u32 - 228..232 'self': &'? S2 + 228..232 'self': &'_ S2 234..235 'x': i32 251..265 '{ let y = x; }': () 257..258 'y': i32 @@ -2992,13 +2992,13 @@ fn test(x: &dyn Foo) { foo(x); }"#, expect![[r#" - 21..22 'x': &'? (dyn Foo + 'static) + 21..22 'x': &'_ (dyn Foo + 'static) 34..36 '{}': () - 46..47 'x': &'? (dyn Foo + 'static) + 46..47 'x': &'_ (dyn Foo + 'static) 59..74 '{ foo(x); }': () - 65..68 'foo': fn foo(&'? (dyn Foo + 'static)) + 65..68 'foo': fn foo(&'?0.0 (dyn Foo + 'static)) 65..71 'foo(x)': () - 69..70 'x': &'? (dyn Foo + 'static) + 69..70 'x': &'_ (dyn Foo + 'static) "#]], ); } @@ -3022,7 +3022,7 @@ fn test() { (IsCopy, NotCopy).test(); }"#, expect![[r#" - 78..82 'self': &'? Self + 78..82 'self': &'_ Self 134..235 '{ ...t(); }': () 140..146 'IsCopy': IsCopy 140..153 'IsCopy.test()': bool @@ -3064,7 +3064,7 @@ fn test() { 28..29 'T': {unknown} 36..38 '{}': T 36..38: expected T, got () - 113..117 'self': &'? Self + 113..117 'self': &'_ Self 169..249 '{ ...t(); }': () 175..178 'foo': fn foo() 175..185 'foo.test()': bool @@ -3092,7 +3092,7 @@ fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) { f3.test(); }"#, expect![[r#" - 22..26 'self': &'? Self + 22..26 'self': &'_ Self 76..78 'f1': fn() 86..88 'f2': fn(usize) -> u8 107..109 'f3': fn(u8, u8) -> &'? u8 @@ -3122,7 +3122,7 @@ fn test() { (1u8, *"foo").test(); // not Sized }"#, expect![[r#" - 22..26 'self': &'? Self + 22..26 'self': &'_ Self 79..194 '{ ...ized }': () 85..88 '1u8': u8 85..95 '1u8.test()': bool @@ -3265,12 +3265,12 @@ fn foo() { f(&s); }"#, expect![[r#" - 154..158 'self': &'? Box + 154..158 'self': &'_ Box 166..205 '{ ... }': &'? T 176..199 'unsafe...nner }': &'? T 185..197 '&*self.inner': &'? T 186..197 '*self.inner': T - 187..191 'self': &'? Box + 187..191 'self': &'_ Box 187..197 'self.inner': *mut T 218..324 '{ ...&s); }': () 228..229 's': Option @@ -3415,7 +3415,7 @@ fn f() { } }"#, expect![[r#" - 46..50 'self': &'? Self + 46..50 'self': &'_ Self 58..63 '{ 0 }': u8 60..61 '0': u8 115..185 '{ ... } }': () @@ -3779,11 +3779,11 @@ fn main() { } "#, expect![[r#" - 44..48 'self': &'? Self - 133..137 'self': &'? [u8; 4] + 44..48 'self': &'_ Self + 133..137 'self': &'_ [u8; 4] 155..172 '{ ... }': usize 165..166 '2': usize - 236..240 'self': &'? [u8; 2] + 236..240 'self': &'_ [u8; 2] 258..275 '{ ... }': u8 268..269 '2': u8 289..392 '{ ...g(); }': () @@ -3827,11 +3827,11 @@ fn main() { } "#, expect![[r#" - 44..48 'self': &'? Self - 151..155 'self': &'? [u8; L] + 44..48 'self': &'_ Self + 151..155 'self': &'_ [u8; L] 173..194 '{ ... }': [u8; L] 183..188 '*self': [u8; L] - 184..188 'self': &'? [u8; L] + 184..188 'self': &'_ [u8; L] 208..260 '{ ...g(); }': () 218..219 'v': [u8; 2] 222..230 '[0u8; 2]': [u8; 2] @@ -4151,13 +4151,13 @@ fn g(t: &(dyn Sync + T2 + T1 + Send)) { } "#, expect![[r#" - 68..69 't': &'? {unknown} + 68..69 't': &'_ {unknown} 101..103 '{}': () - 109..110 't': &'? {unknown} + 109..110 't': &'_ {unknown} 142..155 '{ f(t); }': () - 148..149 'f': fn f(&'? {unknown}) + 148..149 'f': fn f(&'?0.0 {unknown}) 148..152 'f(t)': () - 150..151 't': &'? {unknown} + 150..151 't': &'_ {unknown} "#]], ); @@ -4200,7 +4200,7 @@ trait Trait { } fn f(t: &dyn Trait) {} - //^&'? (dyn Trait + 'static) + //^&'_ (dyn Trait + 'static) "#, ); } @@ -4316,10 +4316,10 @@ fn f<'a>(v: &dyn Trait = &'a i32>) { } "#, expect![[r#" - 90..94 'self': &'? Self - 127..128 'v': &'? (dyn Trait = &'_ i32> + 'static) + 90..94 'self': &'_ Self + 127..128 'v': &'_ (dyn Trait = &'_ i32> + 'static) 164..195 '{ ...f(); }': () - 170..171 'v': &'? (dyn Trait = &'_ i32> + 'static) + 170..171 'v': &'_ (dyn Trait = &'_ i32> + 'static) 170..184 'v.get::()': <{unknown} as Trait>::Assoc 170..192 'v.get:...eref()': {unknown} "#]], @@ -4861,17 +4861,17 @@ fn allowed3(baz: impl Baz>) {} 184..185 'f': impl Fn({unknown}) 184..190 'f(foo)': () 186..189 'foo': S - 251..252 'f': impl Fn(&'? {unknown}) + 251..252 'f': impl Fn(&'?0.0 {unknown}) 274..307 '{ ...oo); }': () 284..287 'foo': S 290..291 'S': S - 297..298 'f': impl Fn(&'? {unknown}) + 297..298 'f': impl Fn(&'?0.0 {unknown}) 297..304 'f(&foo)': () 299..303 '&foo': &'? S 300..303 'foo': S 325..328 'bar': impl Bar<{unknown}> 350..352 '{}': () - 405..408 'bar': impl Bar<&'? {unknown}> + 405..408 'bar': impl Bar<&'?0.0 {unknown}> 431..433 '{}': () 447..450 'baz': impl Baz 480..482 '{}': () @@ -5068,7 +5068,7 @@ fn main() { } "#, expect![[r#" - 147..151 'self': &'? AnyhowError + 147..151 'self': &'_ AnyhowError 170..181 '{ loop {} }': &'? (dyn Error + Send + Sync + 'static) 172..179 'loop {}': ! 177..179 '{}': () @@ -5107,7 +5107,7 @@ fn main() { 290..291 '_': Box + '?> 294..298 'iter': Box + 'static> 294..310 'iter.i...iter()': Box + '?> - 152..156 'self': &'? mut Box + 152..156 'self': &'_ mut Box 177..208 '{ ... }': Option<::Item> 191..198 'loop {}': ! 196..198 '{}': () @@ -5372,7 +5372,7 @@ impl<'a, 'b> Trait<'a, 'b> for Foo {} fn run_dyn<'b>(val: &dyn for<'a> Trait<'a, 'b>) {} "#, expect![[r#" - 91..94 'val': &'? (dyn Trait<'_, '_> + 'static) + 91..94 'val': &'_ (dyn Trait<'_, '_> + 'static) 124..126 '{}': () "#]], ); diff --git a/crates/hir-ty/src/variance.rs b/crates/hir-ty/src/variance.rs index 7d6baa56c21d..2efdaa03cc60 100644 --- a/crates/hir-ty/src/variance.rs +++ b/crates/hir-ty/src/variance.rs @@ -592,8 +592,8 @@ struct TestBox+Setter> { //~ ERROR [U: *, T: +] } "#, expect![[r#" - get[Self: contravariant, T: covariant] - get[Self: contravariant, T: contravariant] + get[Self: contravariant, T: covariant, '_: invariant] + get[Self: contravariant, T: contravariant, '_: invariant] TestStruct[U: covariant, T: covariant] TestEnum[U: bivariant, T: covariant] TestContraStruct[U: bivariant, T: covariant] @@ -628,10 +628,10 @@ fn pick<'b, G>(get: &'b G, if_odd: &'b i32) -> i32 {} "#, expect![[r#" - get[Self: contravariant, T: covariant] + get[Self: contravariant, T: covariant, '_: invariant] Cloner[T: covariant] - get[T: invariant] - get['a: invariant, G: contravariant] + get[T: invariant, '_: invariant] + get['a: invariant, G: contravariant, '_: invariant] pick['b: contravariant, G: contravariant] "#]], ); @@ -653,7 +653,7 @@ struct TOption<'a> { //~ ERROR ['a: +] "#, expect![[r#" Option[T: covariant] - foo[Self: contravariant] + foo[Self: contravariant, '_: invariant] TOption['a: covariant] "#]], ); @@ -701,8 +701,8 @@ struct TestObject { //~ ERROR [A: o, R: o] TestMut[A: covariant, B: invariant] TestIndirect[A: covariant, B: invariant] TestIndirect2[A: invariant, B: invariant] - get[Self: contravariant, A: covariant] - set[Self: invariant, A: contravariant] + get[Self: contravariant, A: covariant, '_: invariant] + set[Self: invariant, A: contravariant, '_: invariant] TestObject[A: invariant, R: invariant] "#]], ); @@ -719,7 +719,7 @@ trait SomeTrait<'a> { fn foo(&self); } // OK on traits. expect![[r#" SomeStruct['a: bivariant] SomeEnum['a: bivariant] - foo[Self: contravariant, 'a: invariant] + foo[Self: contravariant, 'a: invariant, '_: invariant] "#]], ); } diff --git a/crates/hir/src/term_search/tactics.rs b/crates/hir/src/term_search/tactics.rs index b89921d8000c..8627eb4d49cc 100644 --- a/crates/hir/src/term_search/tactics.rs +++ b/crates/hir/src/term_search/tactics.rs @@ -287,11 +287,6 @@ pub(super) fn free_function<'a, 'lt, 'db, DB: HirDatabase>( .map(|it| it.as_type_param(db)) .collect::>>()?; - // Ignore lifetimes as we do not check them - if !generics.lifetime_params(db).is_empty() { - return None; - } - // Only account for stable type parameters for now, unstable params can be default // tho, for example in `Box` if type_params.iter().any(|it| it.is_unstable(db) && it.default(db).is_none()) { @@ -425,16 +420,8 @@ pub(super) fn impl_method<'a, 'lt, 'db, DB: HirDatabase>( _ => None, }) .filter(|_| should_continue()) - .filter_map(move |(imp, ty, it)| { + .filter_map(move |(_, ty, it)| { let fn_generics = GenericDef::from(it); - let imp_generics = GenericDef::from(imp); - - // Ignore all functions that have something to do with lifetimes as we don't check them - if !fn_generics.lifetime_params(db).is_empty() - || !imp_generics.lifetime_params(db).is_empty() - { - return None; - } // Ignore functions without self param if !it.has_self_param(db) { diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs index 774e14df4834..384075aaf1d0 100644 --- a/crates/ide-completion/src/completions/dot.rs +++ b/crates/ide-completion/src/completions/dot.rs @@ -320,8 +320,8 @@ impl S { fn foo(s: S) { s.$0 } "#, expect![[r#" - fd foo u32 - me bar() fn(&self) + fd foo u32 + me bar() fn(&'_ self) "#]], ); } @@ -358,7 +358,7 @@ impl S { } "#, expect![[r#" - me bar() fn(&self) + me bar() fn(&'_ self) "#]], ); } @@ -390,7 +390,7 @@ impl A { "#, expect![[r#" fd the_field (u32, i32) - me foo() fn(&self) + me foo() fn(&'_ self) "#]], ) } @@ -499,7 +499,7 @@ mod m { fn foo(a: lib::A) { a.$0 } "#, expect![[r#" - me pub_method() fn(&self) + me pub_method() fn(&'_ self) "#]], ); check_no_kw( @@ -517,7 +517,7 @@ mod m { fn foo(a: lib::A) { a.$0 } "#, expect![[r#" - me pub_method() fn(&self) + me pub_method() fn(&'_ self) "#]], ); } @@ -597,9 +597,9 @@ mod m { fn foo(a: lib::A) { a.$0 } "#, expect![[r#" - me crate_method() fn(&self) - me private_method() fn(&self) - me pub_method() fn(&self) + me crate_method() fn(&'_ self) + me private_method() fn(&'_ self) + me pub_method() fn(&'_ self) "#]], ); check_with_private_editable( @@ -617,7 +617,7 @@ mod m { fn foo(a: lib::A) { a.$0 } "#, expect![[r#" - me pub_method() fn(&self) + me pub_method() fn(&'_ self) "#]], ); } @@ -645,7 +645,7 @@ fn foo(a: A) { } "#, expect![[r#" - me pub_module_method() fn(&self) + me pub_module_method() fn(&'_ self) "#]], ); } @@ -671,8 +671,8 @@ impl A { } "#, expect![[r#" - fd pub_field u32 - me pub_method() fn(&self) + fd pub_field u32 + me pub_method() fn(&'_ self) "#]], ) } @@ -705,8 +705,8 @@ impl A { fn foo(a: A) { a.$0 } "#, expect![[r#" - fd 0 u32 - me the_method() fn(&self) + fd 0 u32 + me the_method() fn(&'_ self) "#]], ) } @@ -721,7 +721,7 @@ impl Trait for A {} fn foo(a: A) { a.$0 } "#, expect![[r#" - me the_method() (as Trait) fn(&self) + me the_method() (as Trait) fn(&'_ self) "#]], ); check_edit( @@ -751,7 +751,7 @@ impl Trait for T {} fn foo(a: &A) { a.$0 } ", expect![[r#" - me the_method() (as Trait) fn(&self) + me the_method() (as Trait) fn(&'_ self) "#]], ); } @@ -769,7 +769,7 @@ impl Trait for A {} fn foo(a: A) { a.$0 } ", expect![[r#" - me the_method() (as Trait) fn(&self) + me the_method() (as Trait) fn(&'_ self) "#]], ); } @@ -839,7 +839,7 @@ impl T { } "#, expect![[r#" - me blah() fn(&self) + me blah() fn(&'_ self) "#]], ); } @@ -860,9 +860,9 @@ fn test(a: A) { } "#, expect![[r#" - fd another u32 - fd field u8 - me deref() (use core::ops::Deref) fn(&self) -> &::Target + fd another u32 + fd field u8 + me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target "#]], ); } @@ -883,9 +883,9 @@ fn test(a: A) { } "#, expect![[r#" - fd 0 u8 - fd 1 u32 - me deref() (use core::ops::Deref) fn(&self) -> &::Target + fd 0 u8 + fd 1 u32 + me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target "#]], ); } @@ -905,9 +905,9 @@ fn test(a: A) { } "#, expect![[r#" - fd 0 u8 - fd 1 u32 - me deref() (use core::ops::Deref) fn(&self) -> &::Target + fd 0 u8 + fd 1 u32 + me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target "#]], ); } @@ -933,9 +933,9 @@ fn test(a: A) { } "#, expect![[r#" - me deref() (use core::ops::Deref) fn(&self) -> &::Target - me foo() fn(&self) -> u8 - me foo() (as Foo) fn(&self) -> u32 + me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target + me foo() fn(&'_ self) -> u8 + me foo() (as Foo) fn(&'_ self) -> u32 "#]], ); @@ -985,9 +985,9 @@ fn test(a: A) { } "#, expect![[r#" - me deref() (use core::ops::Deref) fn(&self) -> &::Target - me foo() fn(&self) -> u16 - me foo() (as Foo) fn(&self) -> u32 + me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target + me foo() fn(&'_ self) -> u16 + me foo() (as Foo) fn(&'_ self) -> u32 "#]], ); } @@ -1096,7 +1096,7 @@ fn foo() { } "#, expect![[r#" - me the_method() fn(&self) + me the_method() fn(&'_ self) "#]], ); } @@ -1111,7 +1111,7 @@ macro_rules! make_s { () => { S }; } fn main() { make_s!().f$0; } "#, expect![[r#" - me foo() fn(&self) + me foo() fn(&'_ self) "#]], ) } @@ -1139,7 +1139,7 @@ mod foo { } "#, expect![[r#" - me private() fn(&self) + me private() fn(&'_ self) "#]], ); } @@ -1166,7 +1166,7 @@ impl S { } "#, expect![[r#" - me foo() fn(&self) -> &[u8] + me foo() fn(&'_ self) -> &[u8] "#]], ); } @@ -1179,12 +1179,12 @@ struct Foo { field: i32 } impl Foo { fn foo(&self) { $0 } }"#, expect![[r#" - fd self.field i32 - me self.foo() fn(&self) - lc self &Foo - sp Self Foo - st Foo Foo - bt u32 u32 + fd self.field i32 + me self.foo() fn(&'_ self) + lc self &Foo + sp Self Foo + st Foo Foo + bt u32 u32 "#]], ); check_no_kw( @@ -1193,12 +1193,12 @@ struct Foo(i32); impl Foo { fn foo(&mut self) { $0 } }"#, expect![[r#" - fd self.0 i32 - me self.foo() fn(&mut self) - lc self &mut Foo - sp Self Foo - st Foo Foo - bt u32 u32 + fd self.0 i32 + me self.foo() fn(&'_ mut self) + lc self &mut Foo + sp Self Foo + st Foo Foo + bt u32 u32 "#]], ); } @@ -1212,17 +1212,17 @@ struct Foo { field: i32 } impl Foo { fn foo(&mut self) { let _: fn(&mut Self) = |this| { $0 } } }"#, expect![[r#" - fd this.field i32 - me this.foo() fn(&mut self) - lc self &mut Foo - lc this &mut Foo + fd this.field i32 + me this.foo() fn(&'_ mut self) + lc self &mut Foo + lc this &mut Foo md core:: - sp Self Foo - st Foo Foo + sp Self Foo + st Foo Foo tt Fn tt FnMut tt FnOnce - bt u32 u32 + bt u32 u32 "#]], ); } @@ -1236,17 +1236,17 @@ struct Foo { field: i32 } impl Foo { fn foo(&self) { let _: fn(&Self) = |foo| { $0 } } }"#, expect![[r#" - fd self.field i32 - me self.foo() fn(&self) - lc foo &Foo - lc self &Foo + fd self.field i32 + me self.foo() fn(&'_ self) + lc foo &Foo + lc self &Foo md core:: - sp Self Foo - st Foo Foo + sp Self Foo + st Foo Foo tt Fn tt FnMut tt FnOnce - bt u32 u32 + bt u32 u32 "#]], ); @@ -1257,16 +1257,16 @@ struct Foo { field: i32 } impl Foo { fn foo(&self) { let _: fn(&Self) = || { $0 } } }"#, expect![[r#" - fd self.field i32 - me self.foo() fn(&self) - lc self &Foo + fd self.field i32 + me self.foo() fn(&'_ self) + lc self &Foo md core:: - sp Self Foo - st Foo Foo + sp Self Foo + st Foo Foo tt Fn tt FnMut tt FnOnce - bt u32 u32 + bt u32 u32 "#]], ); @@ -1277,18 +1277,18 @@ struct Foo { field: i32 } impl Foo { fn foo(&self) { let _: fn(&Self, &Self) = |foo, other| { $0 } } }"#, expect![[r#" - fd self.field i32 - me self.foo() fn(&self) - lc foo &Foo - lc other &Foo - lc self &Foo + fd self.field i32 + me self.foo() fn(&'_ self) + lc foo &Foo + lc other &Foo + lc self &Foo md core:: - sp Self Foo - st Foo Foo + sp Self Foo + st Foo Foo tt Fn tt FnMut tt FnOnce - bt u32 u32 + bt u32 u32 "#]], ); } @@ -1313,7 +1313,7 @@ fn f() { } "#, expect![[r#" - me method() fn(&self) + me method() fn(&'_ self) "#]], ); } @@ -1411,8 +1411,8 @@ fn test(a: A) { } "#, expect![[r#" - fd 0 u8 - me deref() (use core::ops::Deref) fn(&self) -> &::Target + fd 0 u8 + me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target "#]], ); } @@ -1467,8 +1467,8 @@ impl> Foo { } "#, expect![[r#" - fd foo &u8 - me foobar() fn(&self) + fd foo &u8 + me foobar() fn(&'_ self) "#]], ); } @@ -1651,9 +1651,9 @@ fn baz() { } "#, expect![[r#" - me clone() (as Clone) fn(&self) -> Self - me fmt(…) (use core::fmt::Debug) fn(&self, &mut Formatter<'_>) -> Result<(), Error> - me into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me clone() (as Clone) fn(&'_ self) -> Self + me fmt(…) (use core::fmt::Debug) fn(&'_ self, &mut Formatter<'>) -> Result<(), Error> + me into_iter() (as IntoIterator) fn(self) -> ::IntoIter "#]], ); check_no_kw( @@ -1679,11 +1679,11 @@ fn foo() { } "#, expect![[r#" - me into_iter() (as IntoIterator) fn(self) -> ::IntoIter - me into_iter().by_ref() (as Iterator) fn(&mut self) -> &mut Self - me into_iter().into_iter() (as IntoIterator) fn(self) -> ::IntoIter - me into_iter().next() (as Iterator) fn(&mut self) -> Option<::Item> - me into_iter().nth(…) (as Iterator) fn(&mut self, usize) -> Option<::Item> + me into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me into_iter().by_ref() (as Iterator) fn(&'_ mut self) -> &mut Self + me into_iter().into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me into_iter().next() (as Iterator) fn(&'_ mut self) -> Option<::Item> + me into_iter().nth(…) (as Iterator) fn(&'_ mut self, usize) -> Option<::Item> "#]], ); check_no_kw( @@ -1711,13 +1711,13 @@ fn foo() { } "#, expect![[r#" - me deref() (use core::ops::Deref) fn(&self) -> &::Target - me into_iter() (as IntoIterator) fn(self) -> ::IntoIter - me iter() fn(&self) -> Iter - me iter().by_ref() (as Iterator) fn(&mut self) -> &mut Self - me iter().into_iter() (as IntoIterator) fn(self) -> ::IntoIter - me iter().next() (as Iterator) fn(&mut self) -> Option<::Item> - me iter().nth(…) (as Iterator) fn(&mut self, usize) -> Option<::Item> + me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target + me into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me iter() fn(&'_ self) -> Iter + me iter().by_ref() (as Iterator) fn(&'_ mut self) -> &mut Self + me iter().into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me iter().next() (as Iterator) fn(&'_ mut self) -> Option<::Item> + me iter().nth(…) (as Iterator) fn(&'_ mut self, usize) -> Option<::Item> "#]], ); } @@ -1821,10 +1821,10 @@ fn main() { } "#, expect![[r#" - me by_ref() (as Iterator) fn(&mut self) -> &mut Self - me into_iter() (as IntoIterator) fn(self) -> ::IntoIter - me next() (as Iterator) fn(&mut self) -> Option<::Item> - me nth(…) (as Iterator) fn(&mut self, usize) -> Option<::Item> + me by_ref() (as Iterator) fn(&'_ mut self) -> &mut Self + me into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me next() (as Iterator) fn(&'_ mut self) -> Option<::Item> + me nth(…) (as Iterator) fn(&'_ mut self, usize) -> Option<::Item> "#]], ); } diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs index 34b53e5e5bfe..7826a9b538a4 100644 --- a/crates/ide-completion/src/completions/postfix.rs +++ b/crates/ide-completion/src/completions/postfix.rs @@ -894,7 +894,7 @@ fn main() { "#, expect![[r#" me and(…) fn(self, Option) -> Option - me as_ref() const fn(&self) -> Option<&T> + me as_ref() const fn(&'_ self) -> Option<&T> me ok_or(…) const fn(self, E) -> Result me unwrap() const fn(self) -> T me unwrap_or(…) fn(self, T) -> T diff --git a/crates/ide-completion/src/context/tests.rs b/crates/ide-completion/src/context/tests.rs index c5fba82de480..4380ffc930ee 100644 --- a/crates/ide-completion/src/context/tests.rs +++ b/crates/ide-completion/src/context/tests.rs @@ -154,7 +154,7 @@ fn expected_type_fn_param_deref() { fn foo() { bar(*$0); } fn bar(x: &u32) {} "#, - expect!["ty: &'_ &'_ u32, name: x"], + expect!["ty: &'_ &' u32, name: x"], ); } diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index 43b2a53a7f7e..182953ac7e3f 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -931,7 +931,7 @@ fn main() { } "#, expect![[r#" - me my_method(…) fn(&self) [] + me my_method(…) fn(&'_ self) [] "#]], ); } @@ -1207,7 +1207,7 @@ fn main() { "#, expect![[r#" - me Function fn(&self, i32) -> bool [] + me Function(…) fn(&'_ self, i32) -> bool [] "#]], ); } @@ -1237,7 +1237,7 @@ fn func(input: Struct) { } ex Struct [type] lc self &Struct [local] fn func(…) fn(Struct) [] - me self.test() fn(&self) [] + me self.test() fn(&'_ self) [] "#]], ); } @@ -2382,7 +2382,7 @@ fn foo(s: S) { s.$0 } label: "the_method()", detail_left: None, detail_right: Some( - "fn(&self)", + "fn(&'_ self)", ), source_range: 81..81, delete: 81..81, @@ -2391,7 +2391,7 @@ fn foo(s: S) { s.$0 } Method, ), lookup: "the_method", - detail: "fn(&self)", + detail: "fn(&'_ self)", relevance: CompletionRelevance { exact_name_match: false, type_match: None, @@ -2672,8 +2672,8 @@ struct WorldSnapshot { _f: () }; fn go(world: &WorldSnapshot) { go(w$0) } "#, expect![[r#" - lc world &WorldSnapshot [type+name+local] - ex world [type] + lc world &WorldSnapshot [type_could_unify+name+local] + ex world [type_could_unify] st WorldSnapshot {…} WorldSnapshot { _f: () } [] st &WorldSnapshot {…} [type] st WorldSnapshot WorldSnapshot [] @@ -2871,7 +2871,7 @@ fn main() { label: "indent()", detail_left: None, detail_right: Some( - "fn(&self) -> i32", + "fn(&'_ self) -> i32", ), source_range: 144..145, delete: 144..145, @@ -2880,7 +2880,7 @@ fn main() { Method, ), lookup: "indent", - detail: "fn(&self) -> i32", + detail: "fn(&'_ self) -> i32", relevance: CompletionRelevance { exact_name_match: false, type_match: None, @@ -2992,9 +2992,9 @@ fn f() { } "#, expect![[r#" - me aaa() fn(&self) -> u32 [type+name] - me bbb() fn(&self) -> u32 [type] - me ccc() fn(&self) -> u64 [] + me aaa() fn(&'_ self) -> u32 [type+name] + me bbb() fn(&'_ self) -> u32 [type] + me ccc() fn(&'_ self) -> u64 [] "#]], ); } @@ -3013,7 +3013,7 @@ fn f() { } "#, expect![[r#" - me aaa() fn(&self) -> u64 [name] + me aaa() fn(&'_ self) -> u64 [name] "#]], ); } @@ -3509,8 +3509,8 @@ fn main() { "#, expect![[r#" fn new() fn() -> Foo [] - me eq(…) fn(&self, &Rhs) -> bool [op_method] - me ne(…) fn(&self, &Rhs) -> bool [op_method] + me eq(…) fn(&'_ self, &Rhs) -> bool [op_method] + me ne(…) fn(&'_ self, &Rhs) -> bool [op_method] "#]], ); } @@ -3568,7 +3568,7 @@ fn test() { expect![[r#" [ ( - "fn(&self, u32) -> Bar", + "fn(&'_ self, u32) -> Bar", Some( CompletionRelevanceFn { has_params: true, @@ -3578,7 +3578,7 @@ fn test() { ), ), ( - "fn(&self)", + "fn(&'_ self)", Some( CompletionRelevanceFn { has_params: true, @@ -3588,7 +3588,7 @@ fn test() { ), ), ( - "fn(&self) -> Foo", + "fn(&'_ self) -> Foo", Some( CompletionRelevanceFn { has_params: true, @@ -3598,7 +3598,7 @@ fn test() { ), ), ( - "fn(&self, u32) -> Foo", + "fn(&'_ self, u32) -> Foo", Some( CompletionRelevanceFn { has_params: true, @@ -3608,7 +3608,7 @@ fn test() { ), ), ( - "fn(&self) -> Option", + "fn(&'_ self) -> Option", Some( CompletionRelevanceFn { has_params: true, @@ -3618,7 +3618,7 @@ fn test() { ), ), ( - "fn(&self) -> Result", + "fn(&'_ self) -> Result", Some( CompletionRelevanceFn { has_params: true, @@ -3628,7 +3628,7 @@ fn test() { ), ), ( - "fn(&self) -> Result", + "fn(&'_ self) -> Result", Some( CompletionRelevanceFn { has_params: true, @@ -3638,7 +3638,7 @@ fn test() { ), ), ( - "fn(&self, u32) -> Option", + "fn(&'_ self, u32) -> Option", Some( CompletionRelevanceFn { has_params: true, @@ -3684,7 +3684,7 @@ fn test() { fn fn_ctr_with_args(…) fn(u32) -> Foo [type_could_unify] fn fn_builder() fn() -> FooBuilder [type_could_unify] fn fn_ctr() fn() -> Result [type_could_unify] - me fn_no_ret(…) fn(&self) [type_could_unify] + me fn_no_ret(…) fn(&'_ self) [type_could_unify] fn fn_other() fn() -> Result [type_could_unify] "#]], ); @@ -3722,7 +3722,7 @@ fn test() { fn fn_ctr_wrapped() fn() -> Option> [type_could_unify] fn fn_ctr_wrapped_2() fn() -> Result, u32> [type_could_unify] fn fn_other() fn() -> Option [type_could_unify] - me fn_returns_unit(…) fn(&self) [type_could_unify] + me fn_returns_unit(…) fn(&'_ self) [type_could_unify] "#]], ); } @@ -3757,7 +3757,7 @@ fn test() { fn fn_builder() fn() -> FooBuilder [type_could_unify] fn fn_ctr() fn() -> Option> [type_could_unify] fn fn_ctr2() fn() -> Result, u32> [type_could_unify] - me fn_no_ret(…) fn(&self) [type_could_unify] + me fn_no_ret(…) fn(&'_ self) [type_could_unify] fn fn_other() fn() -> Option [type_could_unify] "#]], ); @@ -3782,7 +3782,7 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 } label: "baz()", detail_left: None, detail_right: Some( - "fn(&self) -> u32", + "fn(&'_ self) -> u32", ), source_range: 109..110, delete: 109..110, @@ -3791,7 +3791,7 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 } Method, ), lookup: "baz", - detail: "fn(&self) -> u32", + detail: "fn(&'_ self) -> u32", relevance: CompletionRelevance { exact_name_match: false, type_match: None, @@ -4111,7 +4111,7 @@ fn main() { "#, &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)], expect![[r#" - me f() fn(&self) [] + me f() fn(&'_ self) [] sn box Box::new(expr) [] sn call function(expr) [] sn const const {} [] @@ -4426,7 +4426,7 @@ fn main() { "(as Write)", ), detail_right: Some( - "fn(&self)", + "fn(&'_ self)", ), source_range: 193..193, delete: 193..193, @@ -4435,7 +4435,7 @@ fn main() { Method, ), lookup: "flush", - detail: "fn(&self)", + detail: "fn(&'_ self)", relevance: CompletionRelevance { exact_name_match: false, type_match: None, @@ -4463,7 +4463,7 @@ fn main() { "(as Write)", ), detail_right: Some( - "fn(&self)", + "fn(&'_ self)", ), source_range: 193..193, delete: 193..193, @@ -4472,7 +4472,7 @@ fn main() { Method, ), lookup: "write", - detail: "fn(&self)", + detail: "fn(&'_ self)", relevance: CompletionRelevance { exact_name_match: false, type_match: None, diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs index 2fa8a9d4b08e..2dd4553024e3 100644 --- a/crates/ide-completion/src/render/function.rs +++ b/crates/ide-completion/src/render/function.rs @@ -508,7 +508,7 @@ struct S; impl S { fn foo(&self) {} } -fn main() { S::foo(${1:&self});$0 } +fn main() { S::foo(${1:&'_ self});$0 } "#, ); } diff --git a/crates/ide-completion/src/tests/expression.rs b/crates/ide-completion/src/tests/expression.rs index 0e558cf6a2b5..cbe3ffd30394 100644 --- a/crates/ide-completion/src/tests/expression.rs +++ b/crates/ide-completion/src/tests/expression.rs @@ -2482,7 +2482,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&self) + me foo() fn(&'_ self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -2509,7 +2509,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&self) + me foo() fn(&'_ self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -2540,7 +2540,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&self) + me foo() fn(&'_ self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -2567,7 +2567,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&self) + me foo() fn(&'_ self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -2594,7 +2594,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&self) + me foo() fn(&'_ self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -2621,7 +2621,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&self) + me foo() fn(&'_ self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -2735,20 +2735,20 @@ fn foo() { } "#, expect![[r#" - me inherent() fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me inherent() fn(&'_ self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -2774,22 +2774,22 @@ fn foo(v: &dyn ExcludedTrait) { } "#, expect![[r#" - me bar() (as ExcludedTrait) fn(&self) - me baz() (as ExcludedTrait) fn(&self) - me foo() (as ExcludedTrait) fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me bar() (as ExcludedTrait) fn(&'_ self) + me baz() (as ExcludedTrait) fn(&'_ self) + me foo() (as ExcludedTrait) fn(&'_ self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); check_with_config( @@ -2811,22 +2811,22 @@ fn foo(v: impl ExcludedTrait) { } "#, expect![[r#" - me bar() (as ExcludedTrait) fn(&self) - me baz() (as ExcludedTrait) fn(&self) - me foo() (as ExcludedTrait) fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me bar() (as ExcludedTrait) fn(&'_ self) + me baz() (as ExcludedTrait) fn(&'_ self) + me foo() (as ExcludedTrait) fn(&'_ self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); check_with_config( @@ -2848,22 +2848,22 @@ fn foo(v: T) { } "#, expect![[r#" - me bar() (as ExcludedTrait) fn(&self) - me baz() (as ExcludedTrait) fn(&self) - me foo() (as ExcludedTrait) fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me bar() (as ExcludedTrait) fn(&'_ self) + me baz() (as ExcludedTrait) fn(&'_ self) + me foo() (as ExcludedTrait) fn(&'_ self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -2896,20 +2896,20 @@ fn foo() { } "#, expect![[r#" - me inherent() fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me inherent() fn(&'_ self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -2945,20 +2945,20 @@ fn foo() { } "#, expect![[r#" - me inherent() fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me inherent() fn(&'_ self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -3137,7 +3137,7 @@ fn foo() { } "#, expect![[r#" - me inherent(…) fn(&self) + me inherent(…) fn(&'_ self) "#]], ); } @@ -3168,10 +3168,10 @@ fn foo() { } "#, expect![[r#" - me bar(…) (as ExcludedTrait) fn(&self) - me baz(…) (as ExcludedTrait) fn(&self) - me foo(…) (as ExcludedTrait) fn(&self) - "#]], + me bar(…) (as ExcludedTrait) fn(&'_ self) + me baz(…) (as ExcludedTrait) fn(&'_ self) + me foo(…) (as ExcludedTrait) fn(&'_ self) + "#]], ); check_with_config( CompletionConfig { @@ -3197,10 +3197,10 @@ fn foo() { } "#, expect![[r#" - me bar(…) (as ExcludedTrait) fn(&self) - me baz(…) (as ExcludedTrait) fn(&self) - me foo(…) (as ExcludedTrait) fn(&self) - "#]], + me bar(…) (as ExcludedTrait) fn(&'_ self) + me baz(…) (as ExcludedTrait) fn(&'_ self) + me foo(…) (as ExcludedTrait) fn(&'_ self) + "#]], ); } @@ -3225,9 +3225,9 @@ fn foo() { } "#, expect![[r#" - me bar(…) (as ExcludedTrait) fn(&self) - me baz(…) (as ExcludedTrait) fn(&self) - me foo(…) (as ExcludedTrait) fn(&self) + me bar(…) (as ExcludedTrait) fn(&'_ self) + me baz(…) (as ExcludedTrait) fn(&'_ self) + me foo(…) (as ExcludedTrait) fn(&'_ self) "#]], ); check_with_config( @@ -3249,9 +3249,9 @@ fn foo() { } "#, expect![[r#" - me bar(…) (as ExcludedTrait) fn(&self) - me baz(…) (as ExcludedTrait) fn(&self) - me foo(…) (as ExcludedTrait) fn(&self) + me bar(…) (as ExcludedTrait) fn(&'_ self) + me baz(…) (as ExcludedTrait) fn(&'_ self) + me foo(…) (as ExcludedTrait) fn(&'_ self) "#]], ); } @@ -3842,21 +3842,21 @@ fn field_in_previous_line_of_ambiguous_expr() { (2, 3) }"#, expect![[r#" - fd field i32 - me method() fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + fd field i32 + me method() fn(&'_ self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); @@ -3872,21 +3872,21 @@ fn field_in_previous_line_of_ambiguous_expr() { (2, 3) }"#, expect![[r#" - fd field i32 - me method() fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + fd field i32 + me method() fn(&'_ self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -3905,21 +3905,21 @@ fn fn_field_in_previous_line_of_ambiguous_expr() { (2, 3) }"#, expect![[r#" - fd field fn() - me method() fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + fd field fn() + me method() fn(&'_ self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); @@ -3970,20 +3970,20 @@ fn main() { } "#, expect![[r#" - me method() (as Trait) fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me method() (as Trait) fn(&'_ self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -4005,20 +4005,20 @@ fn baz(v: impl Bar) { } "#, expect![[r#" - me foo() (as Foo) fn(&self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me foo() (as Foo) fn(&'_ self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs index 8a5025caf901..67b19ae3498b 100644 --- a/crates/ide-completion/src/tests/flyimport.rs +++ b/crates/ide-completion/src/tests/flyimport.rs @@ -398,7 +398,7 @@ fn trait_method_fuzzy_completion() { check( fixture, expect![[r#" - me random_method() (use dep::test_mod::TestTrait) fn(&self) + me random_method() (use dep::test_mod::TestTrait) fn(&'_ self) "#]], ); @@ -443,7 +443,7 @@ fn main() { check( fixture, expect![[r#" - me some_method() (use foo::TestTrait) fn(&self) + me some_method() (use foo::TestTrait) fn(&'_ self) "#]], ); @@ -490,7 +490,7 @@ fn main() { check( fixture, expect![[r#" - me some_method() (use foo::TestTrait) fn(&self) + me some_method() (use foo::TestTrait) fn(&'_ self) "#]], ); @@ -538,7 +538,7 @@ fn completion(whatever: T) { check( fixture, expect![[r#" - me not_in_scope() (use foo::NotInScope) fn(&self) + me not_in_scope() (use foo::NotInScope) fn(&'_ self) "#]], ); @@ -779,7 +779,7 @@ fn main() { } "#, expect![[r#" - me random_method() (use dep::test_mod::TestTrait) fn(&self) DEPRECATED + me random_method() (use dep::test_mod::TestTrait) fn(&'_ self) DEPRECATED "#]], ); @@ -809,9 +809,9 @@ fn main() { } "#, expect![[r#" - ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8 DEPRECATED - fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED - me random_method(…) (use dep::test_mod::TestTrait) fn(&self) DEPRECATED + ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8 DEPRECATED + fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED + me random_method(…) (use dep::test_mod::TestTrait) fn(&'_ self) DEPRECATED "#]], ); } @@ -1775,7 +1775,7 @@ mod module { } "#, expect![[r#" - me choose (use module::SliceRandom) fn(&self) + me choose (use module::SliceRandom) fn(&'_ self) "#]], ); } @@ -2065,7 +2065,7 @@ fn trait_method_import_across_multiple_crates() { check( fixture, expect![[r#" - me test_function() (use test_trait::TestTrait) fn(&self) -> u32 + me test_function() (use test_trait::TestTrait) fn(&'_ self) -> u32 "#]], ); diff --git a/crates/ide-completion/src/tests/proc_macros.rs b/crates/ide-completion/src/tests/proc_macros.rs index 626d1677d555..e981de49f2f4 100644 --- a/crates/ide-completion/src/tests/proc_macros.rs +++ b/crates/ide-completion/src/tests/proc_macros.rs @@ -19,7 +19,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&self) + me foo() fn(&'_ self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -53,7 +53,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&self) + me foo() fn(&'_ self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -89,7 +89,7 @@ impl Foo { fn main() {} "#, expect![[r#" - me foo() fn(&self) + me foo() fn(&'_ self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -125,7 +125,7 @@ impl Foo { fn main() {} "#, expect![[r#" - me foo() fn(&self) + me foo() fn(&'_ self) sn box Box::new(expr) sn call function(expr) sn const const {} diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs index 6c2502a4eb67..5df4befb4e29 100644 --- a/crates/ide-completion/src/tests/special.rs +++ b/crates/ide-completion/src/tests/special.rs @@ -297,14 +297,14 @@ trait Sub: Super { fn foo() { T::$0 } "#, expect![[r#" - ct C2 (as Sub) const C2: () - ct CONST (as Super) const CONST: u8 - fn func() (as Super) fn() - fn subfunc() (as Sub) fn() - me method(…) (as Super) fn(&self) - me submethod(…) (as Sub) fn(&self) - ta SubTy (as Sub) type SubTy - ta Ty (as Super) type Ty + ct C2 (as Sub) const C2: () + ct CONST (as Super) const CONST: u8 + fn func() (as Super) fn() + fn subfunc() (as Sub) fn() + me method(…) (as Super) fn(&'_ self) + me submethod(…) (as Sub) fn(&'_ self) + ta SubTy (as Sub) type SubTy + ta Ty (as Super) type Ty "#]], ); } @@ -337,14 +337,14 @@ impl Sub for Wrap { } "#, expect![[r#" - ct C2 (as Sub) const C2: () - ct CONST (as Super) const CONST: u8 - fn func() (as Super) fn() - fn subfunc() (as Sub) fn() - me method(…) (as Super) fn(&self) - me submethod(…) (as Sub) fn(&self) - ta SubTy (as Sub) type SubTy - ta Ty (as Super) type Ty + ct C2 (as Sub) const C2: () + ct CONST (as Super) const CONST: u8 + fn func() (as Super) fn() + fn subfunc() (as Sub) fn() + me method(…) (as Super) fn(&'_ self) + me submethod(…) (as Sub) fn(&'_ self) + ta SubTy (as Sub) type SubTy + ta Ty (as Super) type Ty "#]], ); } @@ -981,8 +981,8 @@ fn main() { } "#, expect![[r#" - me by_macro() (as MyTrait) fn(&self) - me not_by_macro() (as MyTrait) fn(&self) + me by_macro() (as MyTrait) fn(&'_ self) + me not_by_macro() (as MyTrait) fn(&'_ self) "#]], ) } @@ -1021,8 +1021,8 @@ fn main() { } "#, expect![[r#" - me by_macro() (as MyTrait) fn(&self) - me not_by_macro() (as MyTrait) fn(&self) + me by_macro() (as MyTrait) fn(&'_ self) + me not_by_macro() (as MyTrait) fn(&'_ self) "#]], ) } @@ -1367,21 +1367,21 @@ fn here_we_go() { } "#, expect![[r#" - fd bar u8 - me baz() (alias qux) fn(&self) -> u8 - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + fd bar u8 + me baz() (alias qux) fn(&'_ self) -> u8 + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } diff --git a/crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs b/crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs index 8df99598590f..014ccc049b0c 100644 --- a/crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs +++ b/crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs @@ -30,6 +30,7 @@ mod tests { use crate::tests::check_diagnostics; #[test] + #[ignore = "lifetime elision shows the elided lifetimes being non-elided currently"] fn fn_() { check_diagnostics( r#" @@ -54,6 +55,7 @@ fn foo(_: Foo<'_>) -> Foo { loop {} } } #[test] + #[ignore = "lifetime elision shows the elided lifetimes being non-elided currently"] fn async_fn() { check_diagnostics( r#" diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 4fea4468c072..9bb500e45031 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -678,7 +678,7 @@ fn main() { } ``` ```rust - pub fn foo(_: &Path) + pub fn foo<'_>(_: &'_ Path) ``` --- @@ -711,7 +711,7 @@ fn main() { } ``` ```rust - pub fn foo(_: &Path) + pub fn foo<'_>(_: &'_ Path) ``` --- @@ -3431,7 +3431,7 @@ fn foo() { let bar = Bar; bar.fo$0o(); } ``` ```rust - fn foo(&self) + fn foo<'_>(&'_ self) ``` --- @@ -3469,7 +3469,7 @@ fn foo() { let bar = Bar; bar.fo$0o(); } ``` ```rust - fn foo(&self) + fn foo<'_>(&'_ self) ``` --- @@ -5911,7 +5911,7 @@ const FOO$0: &str = "bar"; ``` ```rust - const FOO: &str = "bar" + const FOO: &'static str = "bar" ``` --- @@ -6065,7 +6065,7 @@ const FOO$0: &i32 = &2; ``` ```rust - const FOO: &i32 = &2 + const FOO: &'static i32 = &2 ``` --- @@ -6240,7 +6240,7 @@ const FOO$0: Option<&i32> = Some(2).as_ref(); ``` ```rust - const FOO: Option<&i32> = Some(&2) + const FOO: Option<&'static i32> = Some(&2) ``` "#]], ); @@ -6263,7 +6263,7 @@ const FOO$0: &dyn Debug = &2i32; ``` ```rust - const FOO: &dyn Debug = &2 + const FOO: &'static dyn Debug = &2 ``` "#]], ); @@ -6284,7 +6284,7 @@ const FOO$0: &[i32] = &[1, 2, 3 + 4]; ``` ```rust - const FOO: &[i32] = &[1, 2, 7] + const FOO: &'static [i32] = &[1, 2, 7] ``` "#]], ); @@ -6301,7 +6301,7 @@ const FOO$0: &[i32; 5] = &[12; 5]; ``` ```rust - const FOO: &[i32; {const}] = &[12, 12, 12, 12, 12] + const FOO: &'static [i32; {const}] = &[12, 12, 12, 12, 12] ``` "#]], ); @@ -6322,7 +6322,7 @@ const FOO$0: (&i32, &[i32], &i32) = { ``` ```rust - const FOO: (&i32, &[i32], &i32) = (&1, &[1, 2, 3], &1) + const FOO: (&'static i32, &'static [i32], &'static i32) = (&1, &[1, 2, 3], &1) ``` "#]], ); @@ -6365,7 +6365,7 @@ const FOO$0: &S<[u8]> = core::mem::transmute::<&[u8], _>(&[1, 2, 3]); ``` ```rust - const FOO: &S<[u8]> = &S + const FOO: &'static S<[u8]> = &S ``` "#]], ); @@ -6385,7 +6385,7 @@ const FOO$0: &str = "foo"; ``` ```rust - const FOO: &str = "foo" + const FOO: &'static str = "foo" ``` "#]], ); @@ -6427,7 +6427,7 @@ const FOO$0: (&str, &str) = { ``` ```rust - const FOO: (&str, &str) = ("foo", "foo") + const FOO: (&'static str, &'static str) = ("foo", "foo") ``` "#]], ); @@ -6774,7 +6774,7 @@ fn main() { ``` ```rust - fn bar<'t, T>(s: &mut S<'t, T>, t: u32) -> *mut u32 + fn bar<'t, '_, T>(s: &'_ mut S<'t, T>, t: u32) -> *mut u32 where T: Clone + 't, 't: 't + 't, @@ -8165,7 +8165,7 @@ fn f() { ``` ```rust - fn deref(&self) -> &Self::Target + fn deref<'_>(&'_ self) -> &'_ Self::Target ``` "#]], ); @@ -8739,7 +8739,7 @@ fn main() { ``` ```rust - fn foo(&self, t: T) + fn foo<'_, T>(&'_ self, t: T) ``` "#]], ); @@ -9732,7 +9732,7 @@ fn test_hover_function_with_pat_param() { ``` ```rust - fn test_3(&(a, b): &(i32, i32)) + fn test_3<'_>(&(a, b): &'_ (i32, i32)) ``` "#]], ); @@ -9938,8 +9938,8 @@ fn fn_$0( ``` ```rust - fn fn_( - &self, + fn fn_<'_>( + &'_ self, attrs: impl IntoIterator, visibility: Option, fn_name: ast::Name, @@ -10525,7 +10525,7 @@ fn bar() { ```rust trait Trait - fn foo(&self, v: U) + fn foo<'_, U>(&'_ self, v: U) ``` --- @@ -10558,7 +10558,7 @@ fn bar() { ```rust impl<'a, T, const N: usize> Foo<'a, N, T> - fn foo<'b, const Z: u32, U>(&self, v: U) + fn foo<'b, '_, const Z: u32, U>(&'_ self, v: U) ``` --- @@ -11304,7 +11304,7 @@ fn bar(v: &Foo) { ```rust impl Foo - fn foo(&self, _u: U) + fn foo<'_, U>(&'_ self, _u: U) where U: Copy, // Bounds from impl: @@ -11495,7 +11495,7 @@ fn bar() { ```rust impl Foo<()> for T - fn foo(&self) + fn foo<'_>(&'_ self) ``` "#]], ); @@ -11520,7 +11520,7 @@ impl Foo for T { ```rust impl Foo for T - fn foo(&self) + fn foo<'_>(&'_ self) ``` "#]], ); @@ -11568,7 +11568,7 @@ pub trait MyTrait { ```rust pub trait MyTrait - pub fn do_something(&self) + pub fn do_something<'_>(&'_ self) ``` "#]], ); @@ -11588,7 +11588,7 @@ pub trait MyTrait { ```rust pub trait MyTrait - pub fn do_something(&self) + pub fn do_something<'_>(&'_ self) ``` --- @@ -11630,7 +11630,7 @@ fn foo() { let bar = Bar; bar.fo$0o(); } ``` ```rust - fn foo(&self) + fn foo<'_>(&'_ self) ``` --- diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs index 4a2cc5f551b6..b2229cfa044d 100644 --- a/crates/ide/src/rename.rs +++ b/crates/ide/src/rename.rs @@ -543,7 +543,10 @@ fn rename_to_self<'db>( }) }; - if ty != impl_ty { + let rebased_impl_ty = impl_ty.try_rebase_into(sema.db, &ty); + if let Some(impl_ty) = rebased_impl_ty + && !ty.could_unify_with(sema.db, &impl_ty) + { bail!("Parameter type differs from impl block type"); } diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs index 0022c1148a14..db8b8413ba88 100644 --- a/crates/ide/src/signature_help.rs +++ b/crates/ide/src/signature_help.rs @@ -921,7 +921,7 @@ fn bar() { } "#, expect![[r#" - fn do_it(&self) + fn do_it<'_>(&'_ self) "#]], ); } @@ -939,8 +939,8 @@ impl S { fn main() { S.foo($0); } "#, expect![[r#" - fn foo(&self, x: i32) - ^^^^^^ + fn foo<'_>(&'_ self, x: i32) + ^^^^^^ "#]], ); } @@ -958,8 +958,8 @@ impl S { fn main() { S(1u32).foo($0); } "#, expect![[r#" - fn foo(&self, x: u32) - ^^^^^^ + fn foo<'_>(&'_ self, x: u32) + ^^^^^^ "#]], ); } @@ -977,8 +977,8 @@ impl S { fn main() { S::foo($0); } "#, expect![[r#" - fn foo(self: &S, x: i32) - ^^^^^^^^ ------ + fn foo<'_>(self: &S, x: i32) + ^^^^^^^^ ------ "#]], ); } @@ -1116,8 +1116,8 @@ fn foo(mut r: impl WriteHandler<()>) { By default this method stops actor's `Context`. ------ - fn finished(&mut self, ctx: &mut as Actor>::Context) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + fn finished<'_, '_>(&'_ mut self, ctx: &mut as Actor>::Context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "#]], ); } @@ -1202,8 +1202,8 @@ fn main() { } "#, expect![[r#" - fn bar(&self, _: u32) - ^^^^^^ + fn bar<'_>(&'_ self, _: u32) + ^^^^^^ "#]], ); } @@ -1809,8 +1809,8 @@ fn f() { } "#, expect![[r#" - fn f - ^ + fn f<'_, T> + ^^ - "#]], ); } @@ -1829,8 +1829,8 @@ fn sup() { } "#, expect![[r#" - fn test(&mut self, val: V) - ^^^^^^ + fn test<'_, V>(&'_ mut self, val: V) + ^^^^^^ "#]], ); } @@ -2035,8 +2035,8 @@ fn f() { } "#, expect![[r#" - fn foo(self: &Self, other: Self) - ^^^^^^^^^^^ ----------- + fn foo<'_>(self: &Self, other: Self) + ^^^^^^^^^^^ ----------- "#]], ); } diff --git a/crates/rust-analyzer/tests/slow-tests/cli.rs b/crates/rust-analyzer/tests/slow-tests/cli.rs index 4ef930e9854e..4ad7320e8454 100644 --- a/crates/rust-analyzer/tests/slow-tests/cli.rs +++ b/crates/rust-analyzer/tests/slow-tests/cli.rs @@ -98,7 +98,7 @@ mod tests { {"id":56,"type":"edge","label":"textDocument/references","inV":55,"outV":11} {"id":57,"type":"edge","label":"item","document":1,"property":"definitions","inVs":[10],"outV":55} {"id":58,"type":"edge","label":"item","document":1,"property":"references","inVs":[13,23],"outV":55} - {"id":59,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nfoo\n```\n\n```rust\nconst REQ_001: &str = \"encoded_data\"\n```"}}} + {"id":59,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nfoo\n```\n\n```rust\nconst REQ_001: &'static str = \"encoded_data\"\n```"}}} {"id":60,"type":"edge","label":"textDocument/hover","inV":59,"outV":16} {"id":61,"type":"vertex","label":"moniker","scheme":"rust-analyzer","identifier":"foo::REQ_001","unique":"scheme","kind":"export"} {"id":62,"type":"edge","label":"packageInformation","inV":31,"outV":61} @@ -120,7 +120,7 @@ mod tests { {"id":78,"type":"vertex","label":"referenceResult"} {"id":79,"type":"edge","label":"textDocument/references","inV":78,"outV":19} {"id":80,"type":"edge","label":"item","document":1,"property":"definitions","inVs":[18],"outV":78} - {"id":81,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nfoo::tests\n```\n\n```rust\nconst REQ_002: &str = \"encoded_data\"\n```"}}} + {"id":81,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nfoo::tests\n```\n\n```rust\nconst REQ_002: &'static str = \"encoded_data\"\n```"}}} {"id":82,"type":"edge","label":"textDocument/hover","inV":81,"outV":26} {"id":83,"type":"vertex","label":"moniker","scheme":"rust-analyzer","identifier":"foo::tests::REQ_002","unique":"scheme","kind":"export"} {"id":84,"type":"edge","label":"packageInformation","inV":31,"outV":83} From 1fdad46be283fe7ac278a4ff657baf5e8b35528d Mon Sep 17 00:00:00 2001 From: dfireBird Date: Fri, 31 Jul 2026 14:56:38 +0530 Subject: [PATCH 3/8] fix: hide elided lifetimes in references and generic param list minor fixes related to review comments --- crates/hir-def/src/expr_store/lower.rs | 8 +- crates/hir-def/src/expr_store/pretty.rs | 12 +- .../src/expr_store/tests/signatures.rs | 10 +- crates/hir-def/src/hir/generics.rs | 4 + crates/hir-def/src/hir/type_ref.rs | 19 +- crates/hir-def/src/lib.rs | 7 +- crates/hir-def/src/resolver.rs | 5 +- crates/hir-expand/src/name.rs | 7 +- crates/hir-ty/src/display.rs | 10 +- crates/hir-ty/src/lower.rs | 2 +- crates/hir-ty/src/tests/closure_captures.rs | 62 ++- crates/hir/src/display.rs | 9 +- crates/hir/src/lib.rs | 4 + crates/ide-completion/src/completions/dot.rs | 204 +++++----- .../ide-completion/src/completions/postfix.rs | 2 +- crates/ide-completion/src/context/tests.rs | 2 +- crates/ide-completion/src/render.rs | 62 +-- crates/ide-completion/src/render/function.rs | 2 +- crates/ide-completion/src/tests/expression.rs | 364 +++++++++--------- crates/ide-completion/src/tests/flyimport.rs | 20 +- .../ide-completion/src/tests/proc_macros.rs | 8 +- crates/ide-completion/src/tests/special.rs | 70 ++-- crates/ide/src/hover/tests.rs | 36 +- crates/ide/src/signature_help.rs | 33 +- 24 files changed, 505 insertions(+), 457 deletions(-) diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index 6b0268421cda..b4caf41225f7 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -874,7 +874,11 @@ impl<'db> ExprCollector<'db> { let abi = inner.abi().map(lower_abi).unwrap_or(ExternAbi::Rust); params.push((None, ret_ty)); - let binder = self.for_type_binder.take().map(|(b, _)| b.into()); + let binder = self + .for_type_binder + .take() + .filter(|(b, _)| !b.is_empty()) + .map(|(b, _)| b.into()); self.for_type_binder = old_binder; self.elision_binder_source = old_elision_binder_source; @@ -1082,7 +1086,7 @@ impl<'db> ExprCollector<'db> { fn lower_elided_lifetime_for_binder(&mut self) -> LifetimeRefId { let name = Name::anon_lifetime(); let local_id = self.push_elided_lifetime_in_for_binder(name); - let param_id = HrtbLifetimeParamId(local_id); + let param_id = HrtbLifetimeParamId(local_id as u32); let lifetime_ref = LifetimeRef::HrtbParam(param_id); self.alloc_lifetime_ref_desugared(lifetime_ref) } diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs index d87e39a3a4b0..7406845fe3a1 100644 --- a/crates/hir-def/src/expr_store/pretty.rs +++ b/crates/hir-def/src/expr_store/pretty.rs @@ -374,6 +374,10 @@ fn print_generic_params( w!(p, "<"); let mut first = true; for (_i, param) in generic_params.iter_lt() { + if param.is_elided() { + continue; + } + if !first { w!(p, ", "); } @@ -1303,7 +1307,9 @@ impl Printer<'_> { Mutability::Mut => "mut ", }; w!(self, "&"); - if let Some(lt) = &ref_.lifetime { + if let Some(lt) = &ref_.lifetime + && !self.store[*lt].is_elided(self.db) + { self.print_lifetime_ref(*lt); w!(self, " "); } @@ -1325,9 +1331,7 @@ impl Printer<'_> { TypeRef::Fn(fn_) => { let ((_, return_type), args) = fn_.params.split_last().expect("TypeRef::Fn is missing return type"); - if let Some(binder) = &fn_.binder - && !binder.is_empty() - { + if let Some(binder) = &fn_.binder { w!( self, "for<{}> ", diff --git a/crates/hir-def/src/expr_store/tests/signatures.rs b/crates/hir-def/src/expr_store/tests/signatures.rs index 14d6580cef7d..5b08a6f7afe3 100644 --- a/crates/hir-def/src/expr_store/tests/signatures.rs +++ b/crates/hir-def/src/expr_store/tests/signatures.rs @@ -109,7 +109,7 @@ const async unsafe extern "C" fn a() {} fn ret_impl_trait() -> impl Trait {} "#, expect![[r#" - fn foo<'a, '_, const C: usize = 314235, T = B>(&'_ Struct, (), u32) -> &'a dyn Fn::<(), Output = i32> + fn foo<'a, const C: usize = 314235, T = B>(&Struct, (), u32) -> &'a dyn Fn::<(), Output = i32> where T: Trait::, (): Default @@ -169,15 +169,15 @@ fn allowed3(baz: impl Baz>) {} {...} fn not_allowed2(Param[0]) where - Param[0]: for<'_> Fn::<(&'_ {error}), Output = ()> + Param[0]: for<'_> Fn::<(&{error}), Output = ()> {...} fn not_allowed3(Param[0]) where Param[0]: Bar::<{error}> {...} - fn not_allowed4<'_, Param[0]>(Param[0]) + fn not_allowed4(Param[0]) where - Param[0]: Bar::<&'_ {error}> + Param[0]: Bar::<&{error}> {...} fn allowed1(Param[1]) where @@ -207,7 +207,7 @@ type Alias<'a, 'b, T> = &'b T; fn f(_: Alias) {} "#, expect![[r#" - fn f<'_, '_, T>(Alias::<'_, '_, T>) {...} + fn f(Alias::<'_, '_, T>) {...} "#]], ); } diff --git a/crates/hir-def/src/hir/generics.rs b/crates/hir-def/src/hir/generics.rs index 14c759958309..4c757704389f 100644 --- a/crates/hir-def/src/hir/generics.rs +++ b/crates/hir-def/src/hir/generics.rs @@ -51,6 +51,10 @@ pub enum LifetimeBoundType { } impl LifetimeParamData { + pub fn is_elided(&self) -> bool { + self.name.is_anon_lifetime() + } + pub fn is_late_bound(&self) -> bool { self.bound_type == LifetimeBoundType::LateBound } diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs index e493be65c7f2..edfabc5bda14 100644 --- a/crates/hir-def/src/hir/type_ref.rs +++ b/crates/hir-def/src/hir/type_ref.rs @@ -1,6 +1,7 @@ //! HIR for references to types. Paths in these are not yet resolved. They can //! be directly created from an ast::TypeRef, without further queries. +use base_db::SourceDatabase; use hir_expand::name::Name; use la_arena::Idx; use rustc_abi::ExternAbi; @@ -9,7 +10,7 @@ use thin_vec::ThinVec; use crate::{ HrtbLifetimeParamId, LifetimeParamId, TypeParamId, expr_store::{ExpressionStore, path::Path}, - hir::{ExprId, PatId}, + hir::{ExprId, PatId, generics::GenericParams}, }; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] @@ -203,6 +204,22 @@ impl TypeBound { } } +impl LifetimeRef { + pub fn is_elided(&self, db: &dyn SourceDatabase) -> bool { + match self { + LifetimeRef::HrtbParam(_) | LifetimeRef::Placeholder => true, + LifetimeRef::Named(name) => name.is_anon_lifetime(), // Ideally, should not be true if it's Named variant + LifetimeRef::Param(lifetime_param_id) => { + let generics = GenericParams::of(db, lifetime_param_id.parent); + let lt_param = &generics.lifetimes[lifetime_param_id.local_id]; + lt_param.name.is_anon_lifetime() + } + + LifetimeRef::Static | LifetimeRef::Error => false, + } + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct ConstRef { pub expr: ExprId, diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 159888277725..4cc3649fe95f 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -718,7 +718,7 @@ pub struct LifetimeParamId { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct HrtbLifetimeParamId(pub usize); +pub struct HrtbLifetimeParamId(pub u32); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)] pub enum ItemContainerId { @@ -1429,7 +1429,10 @@ impl ModuleDefId { ModuleDefId::StaticId(id) => Some(id.into()), ModuleDefId::TraitId(id) => Some(id.into()), ModuleDefId::TypeAliasId(id) => Some(id.into()), - _ => None, + ModuleDefId::ModuleId(_) => None, + ModuleDefId::EnumVariantId(_) => None, + ModuleDefId::BuiltinType(_) => None, + ModuleDefId::MacroId(_) => None, } } } diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index b907c221e5e2..28e0149a5cf8 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -571,7 +571,10 @@ impl<'db> Resolver<'db> { LifetimeRef::Param(lifetime_param_id) => { Some(LifetimeNs::LifetimeParam(*lifetime_param_id)) } - LifetimeRef::HrtbParam(_) => None, // this should be unreachable, should we panic? + LifetimeRef::HrtbParam(_) => { + stdx::never!(); + None + } } } diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs index e4dd6c8d95bc..5922830b7d8c 100644 --- a/crates/hir-expand/src/name.rs +++ b/crates/hir-expand/src/name.rs @@ -114,7 +114,7 @@ impl Name { #[inline] pub fn anon_lifetime() -> Name { - Self::new_text("'_") + Self::new_symbol_root(sym::tick_underscore) } #[inline] @@ -209,6 +209,11 @@ impl Name { pub fn is_generated(&self) -> bool { is_generated(self.as_str()) } + + #[inline] + pub fn is_anon_lifetime(&self) -> bool { + *self == sym::tick_underscore + } } #[inline] diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index b6161894d3b1..7ae0b319ba7a 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -2337,7 +2337,7 @@ impl<'db> HirDisplay<'db> for Region<'db> { write!(f, "'_") } } - RegionKind::ReErased => write!(f, "'"), + RegionKind::ReErased => write!(f, "'_"), RegionKind::RePlaceholder(_) => write!(f, "'"), RegionKind::ReLateParam(_) => write!(f, "'_"), } @@ -2502,7 +2502,9 @@ impl<'db> HirDisplayWithExpressionStore<'db> for TypeRefId { hir_def::type_ref::Mutability::Mut => "mut ", }; write!(f, "&")?; - if let Some(lifetime) = &ref_.lifetime { + if let Some(lifetime) = &ref_.lifetime + && !store[*lifetime].is_elided(f.db) + { lifetime.hir_fmt(f, owner, store)?; write!(f, " ")?; } @@ -2522,9 +2524,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for TypeRefId { write!(f, "]")?; } TypeRef::Fn(fn_) => { - if let Some(binder) = &fn_.binder - && !binder.is_empty() - { + if let Some(binder) = &fn_.binder { let edition = f.edition(); write!( f, diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 36788456eea3..9a96b86cac7a 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -1377,7 +1377,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { }) } LifetimeRef::HrtbParam(hrtb_param_id) => { - Some(self.hrtb_region_param(hrtb_param_id.0 as u32, INNERMOST, self.generic_def)) + Some(self.hrtb_region_param(hrtb_param_id.0, INNERMOST, self.generic_def)) } _ => None, } diff --git a/crates/hir-ty/src/tests/closure_captures.rs b/crates/hir-ty/src/tests/closure_captures.rs index c951a5481c46..29604e0ce5b9 100644 --- a/crates/hir-ty/src/tests/closure_captures.rs +++ b/crates/hir-ty/src/tests/closure_captures.rs @@ -175,7 +175,7 @@ fn main() { let closure = || { let b = *a; }; } "#, - expect!["53..71;20..21;66..68 ByRef(Immutable) *a &' bool"], + expect!["53..71;20..21;66..68 ByRef(Immutable) *a &'_ bool"], ); } @@ -189,7 +189,7 @@ fn main() { let closure = || { let &mut ref b = a; }; } "#, - expect!["53..79;20..21;62..72 ByRef(Immutable) *a &' bool"], + expect!["53..79;20..21;62..72 ByRef(Immutable) *a &'_ bool"], ); check_closure_captures( r#" @@ -199,7 +199,7 @@ fn main() { let closure = || { let &mut ref mut b = a; }; } "#, - expect!["53..83;20..21;62..76 ByRef(Mutable) *a &' mut bool"], + expect!["53..83;20..21;62..76 ByRef(Mutable) *a &'_ mut bool"], ); } @@ -213,7 +213,7 @@ fn main() { let closure = || { *a = false; }; } "#, - expect!["53..71;20..21;58..60 ByRef(Mutable) *a &' mut bool"], + expect!["53..71;20..21;58..60 ByRef(Mutable) *a &'_ mut bool"], ); } @@ -227,7 +227,7 @@ fn main() { let closure = || { let ref mut b = *a; }; } "#, - expect!["53..79;20..21;74..76 ByRef(Mutable) *a &' mut bool"], + expect!["53..79;20..21;74..76 ByRef(Mutable) *a &'_ mut bool"], ); } @@ -273,8 +273,8 @@ fn main() { } "#, expect![[r#" - 71..89;36..41;85..86 ByRef(Immutable) a &' NonCopy - 109..131;36..41;127..128 ByRef(Mutable) a &' mut NonCopy"#]], + 71..89;36..41;85..86 ByRef(Immutable) a &'_ NonCopy + 109..131;36..41;127..128 ByRef(Mutable) a &'_ mut NonCopy"#]], ); } @@ -289,7 +289,7 @@ fn main() { let closure = || { let b = a.a; }; } "#, - expect!["92..111;50..51;105..108 ByRef(Immutable) a.a &' i32"], + expect!["92..111;50..51;105..108 ByRef(Immutable) a.a &'_ i32"], ); } @@ -310,8 +310,8 @@ fn main() { } "#, expect![[r#" - 133..212;87..92;155..158 ByRef(Immutable) a.a &' i32 - 133..212;87..92;181..184 ByRef(Mutable) a.b &' mut i32 + 133..212;87..92;155..158 ByRef(Immutable) a.a &'_ i32 + 133..212;87..92;181..184 ByRef(Mutable) a.b &'_ mut i32 133..212;87..92;202..205 ByValue a.c NonCopy"#]], ); } @@ -333,8 +333,8 @@ fn main() { } "#, expect![[r#" - 123..133;92..97;126..127 ByRef(Immutable) a &' Foo - 153..164;92..97;156..157 ByRef(Mutable) a &' mut Foo"#]], + 123..133;92..97;126..127 ByRef(Immutable) a &'_ Foo + 153..164;92..97;156..157 ByRef(Mutable) a &'_ mut Foo"#]], ); } @@ -361,7 +361,7 @@ fn main() { } "#, expect![[r#" - 113..167;36..41;127..128,159..160 ByRef(Mutable) a &' mut &'? mut bool + 113..167;36..41;127..128,159..160 ByRef(Mutable) a &'_ mut &'? mut bool 231..304;196..201;252..253,276..277,296..297 ByValue a NonCopy"#]], ); } @@ -400,8 +400,8 @@ fn main() { } "#, expect![[r#" - 125..163;36..41;134..135 ByRef(Immutable) a &' NonCopy - 183..225;36..41;192..193 ByRef(Mutable) a &' mut NonCopy"#]], + 125..163;36..41;134..135 ByRef(Immutable) a &'_ NonCopy + 183..225;36..41;192..193 ByRef(Mutable) a &'_ mut NonCopy"#]], ); } @@ -415,7 +415,7 @@ fn main() { let mut closure = || { let (b | b) = a; }; } "#, - expect!["57..80;20..25;76..77 ByRef(Immutable) a &' bool"], + expect!["57..80;20..25;76..77 ByRef(Immutable) a &'_ bool"], ); } @@ -434,9 +434,7 @@ fn main() { }; } "#, - expect![ - "57..149;20..25;79..80,99..100,123..124,134..135 ByRef(Mutable) a &' mut bool" - ], + expect!["57..149;20..25;79..80,99..100,123..124,134..135 ByRef(Mutable) a &'_ mut bool"], ); } @@ -450,7 +448,7 @@ fn main() { let mut closure = || { let b = *&mut a; }; } "#, - expect!["57..80;20..25;76..77 ByRef(Mutable) a &' mut bool"], + expect!["57..80;20..25;76..77 ByRef(Mutable) a &'_ mut bool"], ); } @@ -469,10 +467,10 @@ fn main() { } "#, expect![[r#" - 54..72;20..25;68..69 ByRef(Immutable) a &' &'? bool - 92..114;20..25;110..111 ByRef(Mutable) a &' mut &'? bool - 158..176;124..125;172..173 ByRef(Immutable) a &' &'? mut bool - 196..218;124..125;214..215 ByRef(Mutable) a &' mut &'? mut bool"#]], + 54..72;20..25;68..69 ByRef(Immutable) a &'_ &'? bool + 92..114;20..25;110..111 ByRef(Mutable) a &'_ mut &'? bool + 158..176;124..125;172..173 ByRef(Immutable) a &'_ &'? mut bool + 196..218;124..125;214..215 ByRef(Mutable) a &'_ mut &'? mut bool"#]], ); } @@ -491,7 +489,7 @@ fn main() { closure(); } "#, - expect!["99..165;49..54;120..121,133..134 ByRef(Mutable) a &' mut A"], + expect!["99..165;49..54;120..121,133..134 ByRef(Mutable) a &'_ mut A"], ); } @@ -514,8 +512,8 @@ fn main() { } "#, expect![[r#" - 129..225;49..54;158..163 ByRef(Immutable) s_ref &' &'? mut S - 129..225;93..99;201..207 ByRef(Mutable) s_ref2 &' mut &'? mut S"#]], + 129..225;49..54;158..163 ByRef(Immutable) s_ref &'_ &'? mut S + 129..225;93..99;201..207 ByRef(Mutable) s_ref2 &'_ mut &'? mut S"#]], ); } @@ -559,7 +557,7 @@ fn main() { }; } "#, - expect!["220..257;174..175;245..250 ByRef(Immutable) c.b.x &' i32"], + expect!["220..257;174..175;245..250 ByRef(Immutable) c.b.x &'_ i32"], ); } @@ -578,8 +576,8 @@ fn f() { } "#, expect![[r#" - 44..113;17..18;92..93 ByRef(Immutable) a &' i32 - 73..106;17..18;92..93 ByRef(Immutable) a &' i32"#]], + 44..113;17..18;92..93 ByRef(Immutable) a &'_ i32 + 73..106;17..18;92..93 ByRef(Immutable) a &'_ i32"#]], ); } @@ -597,7 +595,7 @@ fn f() { }; } "#, - expect!["77..110;46..47;96..97 ByRef(Immutable) b &' i32"], + expect!["77..110;46..47;96..97 ByRef(Immutable) b &'_ i32"], ); } @@ -614,7 +612,7 @@ fn foo(foo: &Foo) { || { return foo.arr[0] }; } "#, - expect!["102..126;85..88;114..117 ByRef(Immutable) *foo &' Foo"], + expect!["102..126;85..88;114..117 ByRef(Immutable) *foo &'_ Foo"], ); } diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 61eda80fb487..c76b42caec79 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -327,7 +327,9 @@ impl<'db> HirDisplay<'db> for SelfParam { TypeRef::Reference(ref_) if matches!(&data.store[ref_.ty], TypeRef::Path(p) if p.is_self_type()) => { f.write_char('&')?; - if let Some(lifetime) = &ref_.lifetime { + if let Some(lifetime) = &ref_.lifetime + && !data.store[*lifetime].is_elided(f.db) + { lifetime.hir_fmt(f, owner, &data.store)?; f.write_char(' ')?; } @@ -704,7 +706,7 @@ fn write_generic_params_or_args<'db>( ) -> Result { let (params, store) = GenericParams::with_store(f.db, def); let owner = def.into(); - if params.iter_lt().next().is_none() + if params.iter_lt().all(|it| it.1.is_elided()) && params.iter_type_or_consts().all(|it| it.1.const_param().is_none()) && params .iter_type_or_consts() @@ -725,6 +727,9 @@ fn write_generic_params_or_args<'db>( } }; for (_, lifetime) in params.iter_lt() { + if lifetime.is_elided() { + continue; + } delim(f)?; write!(f, "{}", lifetime.name.display(f.db, f.edition()))?; } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 34d2a566ba81..abcd4a56a873 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -4436,6 +4436,10 @@ impl LifetimeParam { params[self.id.local_id].name.clone() } + pub fn is_elided(self, db: &dyn HirDatabase) -> bool { + self.name(db).is_anon_lifetime() + } + pub fn module(self, db: &dyn HirDatabase) -> Module { self.id.parent.module(db).into() } diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs index 384075aaf1d0..774e14df4834 100644 --- a/crates/ide-completion/src/completions/dot.rs +++ b/crates/ide-completion/src/completions/dot.rs @@ -320,8 +320,8 @@ impl S { fn foo(s: S) { s.$0 } "#, expect![[r#" - fd foo u32 - me bar() fn(&'_ self) + fd foo u32 + me bar() fn(&self) "#]], ); } @@ -358,7 +358,7 @@ impl S { } "#, expect![[r#" - me bar() fn(&'_ self) + me bar() fn(&self) "#]], ); } @@ -390,7 +390,7 @@ impl A { "#, expect![[r#" fd the_field (u32, i32) - me foo() fn(&'_ self) + me foo() fn(&self) "#]], ) } @@ -499,7 +499,7 @@ mod m { fn foo(a: lib::A) { a.$0 } "#, expect![[r#" - me pub_method() fn(&'_ self) + me pub_method() fn(&self) "#]], ); check_no_kw( @@ -517,7 +517,7 @@ mod m { fn foo(a: lib::A) { a.$0 } "#, expect![[r#" - me pub_method() fn(&'_ self) + me pub_method() fn(&self) "#]], ); } @@ -597,9 +597,9 @@ mod m { fn foo(a: lib::A) { a.$0 } "#, expect![[r#" - me crate_method() fn(&'_ self) - me private_method() fn(&'_ self) - me pub_method() fn(&'_ self) + me crate_method() fn(&self) + me private_method() fn(&self) + me pub_method() fn(&self) "#]], ); check_with_private_editable( @@ -617,7 +617,7 @@ mod m { fn foo(a: lib::A) { a.$0 } "#, expect![[r#" - me pub_method() fn(&'_ self) + me pub_method() fn(&self) "#]], ); } @@ -645,7 +645,7 @@ fn foo(a: A) { } "#, expect![[r#" - me pub_module_method() fn(&'_ self) + me pub_module_method() fn(&self) "#]], ); } @@ -671,8 +671,8 @@ impl A { } "#, expect![[r#" - fd pub_field u32 - me pub_method() fn(&'_ self) + fd pub_field u32 + me pub_method() fn(&self) "#]], ) } @@ -705,8 +705,8 @@ impl A { fn foo(a: A) { a.$0 } "#, expect![[r#" - fd 0 u32 - me the_method() fn(&'_ self) + fd 0 u32 + me the_method() fn(&self) "#]], ) } @@ -721,7 +721,7 @@ impl Trait for A {} fn foo(a: A) { a.$0 } "#, expect![[r#" - me the_method() (as Trait) fn(&'_ self) + me the_method() (as Trait) fn(&self) "#]], ); check_edit( @@ -751,7 +751,7 @@ impl Trait for T {} fn foo(a: &A) { a.$0 } ", expect![[r#" - me the_method() (as Trait) fn(&'_ self) + me the_method() (as Trait) fn(&self) "#]], ); } @@ -769,7 +769,7 @@ impl Trait for A {} fn foo(a: A) { a.$0 } ", expect![[r#" - me the_method() (as Trait) fn(&'_ self) + me the_method() (as Trait) fn(&self) "#]], ); } @@ -839,7 +839,7 @@ impl T { } "#, expect![[r#" - me blah() fn(&'_ self) + me blah() fn(&self) "#]], ); } @@ -860,9 +860,9 @@ fn test(a: A) { } "#, expect![[r#" - fd another u32 - fd field u8 - me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target + fd another u32 + fd field u8 + me deref() (use core::ops::Deref) fn(&self) -> &::Target "#]], ); } @@ -883,9 +883,9 @@ fn test(a: A) { } "#, expect![[r#" - fd 0 u8 - fd 1 u32 - me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target + fd 0 u8 + fd 1 u32 + me deref() (use core::ops::Deref) fn(&self) -> &::Target "#]], ); } @@ -905,9 +905,9 @@ fn test(a: A) { } "#, expect![[r#" - fd 0 u8 - fd 1 u32 - me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target + fd 0 u8 + fd 1 u32 + me deref() (use core::ops::Deref) fn(&self) -> &::Target "#]], ); } @@ -933,9 +933,9 @@ fn test(a: A) { } "#, expect![[r#" - me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target - me foo() fn(&'_ self) -> u8 - me foo() (as Foo) fn(&'_ self) -> u32 + me deref() (use core::ops::Deref) fn(&self) -> &::Target + me foo() fn(&self) -> u8 + me foo() (as Foo) fn(&self) -> u32 "#]], ); @@ -985,9 +985,9 @@ fn test(a: A) { } "#, expect![[r#" - me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target - me foo() fn(&'_ self) -> u16 - me foo() (as Foo) fn(&'_ self) -> u32 + me deref() (use core::ops::Deref) fn(&self) -> &::Target + me foo() fn(&self) -> u16 + me foo() (as Foo) fn(&self) -> u32 "#]], ); } @@ -1096,7 +1096,7 @@ fn foo() { } "#, expect![[r#" - me the_method() fn(&'_ self) + me the_method() fn(&self) "#]], ); } @@ -1111,7 +1111,7 @@ macro_rules! make_s { () => { S }; } fn main() { make_s!().f$0; } "#, expect![[r#" - me foo() fn(&'_ self) + me foo() fn(&self) "#]], ) } @@ -1139,7 +1139,7 @@ mod foo { } "#, expect![[r#" - me private() fn(&'_ self) + me private() fn(&self) "#]], ); } @@ -1166,7 +1166,7 @@ impl S { } "#, expect![[r#" - me foo() fn(&'_ self) -> &[u8] + me foo() fn(&self) -> &[u8] "#]], ); } @@ -1179,12 +1179,12 @@ struct Foo { field: i32 } impl Foo { fn foo(&self) { $0 } }"#, expect![[r#" - fd self.field i32 - me self.foo() fn(&'_ self) - lc self &Foo - sp Self Foo - st Foo Foo - bt u32 u32 + fd self.field i32 + me self.foo() fn(&self) + lc self &Foo + sp Self Foo + st Foo Foo + bt u32 u32 "#]], ); check_no_kw( @@ -1193,12 +1193,12 @@ struct Foo(i32); impl Foo { fn foo(&mut self) { $0 } }"#, expect![[r#" - fd self.0 i32 - me self.foo() fn(&'_ mut self) - lc self &mut Foo - sp Self Foo - st Foo Foo - bt u32 u32 + fd self.0 i32 + me self.foo() fn(&mut self) + lc self &mut Foo + sp Self Foo + st Foo Foo + bt u32 u32 "#]], ); } @@ -1212,17 +1212,17 @@ struct Foo { field: i32 } impl Foo { fn foo(&mut self) { let _: fn(&mut Self) = |this| { $0 } } }"#, expect![[r#" - fd this.field i32 - me this.foo() fn(&'_ mut self) - lc self &mut Foo - lc this &mut Foo + fd this.field i32 + me this.foo() fn(&mut self) + lc self &mut Foo + lc this &mut Foo md core:: - sp Self Foo - st Foo Foo + sp Self Foo + st Foo Foo tt Fn tt FnMut tt FnOnce - bt u32 u32 + bt u32 u32 "#]], ); } @@ -1236,17 +1236,17 @@ struct Foo { field: i32 } impl Foo { fn foo(&self) { let _: fn(&Self) = |foo| { $0 } } }"#, expect![[r#" - fd self.field i32 - me self.foo() fn(&'_ self) - lc foo &Foo - lc self &Foo + fd self.field i32 + me self.foo() fn(&self) + lc foo &Foo + lc self &Foo md core:: - sp Self Foo - st Foo Foo + sp Self Foo + st Foo Foo tt Fn tt FnMut tt FnOnce - bt u32 u32 + bt u32 u32 "#]], ); @@ -1257,16 +1257,16 @@ struct Foo { field: i32 } impl Foo { fn foo(&self) { let _: fn(&Self) = || { $0 } } }"#, expect![[r#" - fd self.field i32 - me self.foo() fn(&'_ self) - lc self &Foo + fd self.field i32 + me self.foo() fn(&self) + lc self &Foo md core:: - sp Self Foo - st Foo Foo + sp Self Foo + st Foo Foo tt Fn tt FnMut tt FnOnce - bt u32 u32 + bt u32 u32 "#]], ); @@ -1277,18 +1277,18 @@ struct Foo { field: i32 } impl Foo { fn foo(&self) { let _: fn(&Self, &Self) = |foo, other| { $0 } } }"#, expect![[r#" - fd self.field i32 - me self.foo() fn(&'_ self) - lc foo &Foo - lc other &Foo - lc self &Foo + fd self.field i32 + me self.foo() fn(&self) + lc foo &Foo + lc other &Foo + lc self &Foo md core:: - sp Self Foo - st Foo Foo + sp Self Foo + st Foo Foo tt Fn tt FnMut tt FnOnce - bt u32 u32 + bt u32 u32 "#]], ); } @@ -1313,7 +1313,7 @@ fn f() { } "#, expect![[r#" - me method() fn(&'_ self) + me method() fn(&self) "#]], ); } @@ -1411,8 +1411,8 @@ fn test(a: A) { } "#, expect![[r#" - fd 0 u8 - me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target + fd 0 u8 + me deref() (use core::ops::Deref) fn(&self) -> &::Target "#]], ); } @@ -1467,8 +1467,8 @@ impl> Foo { } "#, expect![[r#" - fd foo &u8 - me foobar() fn(&'_ self) + fd foo &u8 + me foobar() fn(&self) "#]], ); } @@ -1651,9 +1651,9 @@ fn baz() { } "#, expect![[r#" - me clone() (as Clone) fn(&'_ self) -> Self - me fmt(…) (use core::fmt::Debug) fn(&'_ self, &mut Formatter<'>) -> Result<(), Error> - me into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me clone() (as Clone) fn(&self) -> Self + me fmt(…) (use core::fmt::Debug) fn(&self, &mut Formatter<'_>) -> Result<(), Error> + me into_iter() (as IntoIterator) fn(self) -> ::IntoIter "#]], ); check_no_kw( @@ -1679,11 +1679,11 @@ fn foo() { } "#, expect![[r#" - me into_iter() (as IntoIterator) fn(self) -> ::IntoIter - me into_iter().by_ref() (as Iterator) fn(&'_ mut self) -> &mut Self - me into_iter().into_iter() (as IntoIterator) fn(self) -> ::IntoIter - me into_iter().next() (as Iterator) fn(&'_ mut self) -> Option<::Item> - me into_iter().nth(…) (as Iterator) fn(&'_ mut self, usize) -> Option<::Item> + me into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me into_iter().by_ref() (as Iterator) fn(&mut self) -> &mut Self + me into_iter().into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me into_iter().next() (as Iterator) fn(&mut self) -> Option<::Item> + me into_iter().nth(…) (as Iterator) fn(&mut self, usize) -> Option<::Item> "#]], ); check_no_kw( @@ -1711,13 +1711,13 @@ fn foo() { } "#, expect![[r#" - me deref() (use core::ops::Deref) fn(&'_ self) -> &::Target - me into_iter() (as IntoIterator) fn(self) -> ::IntoIter - me iter() fn(&'_ self) -> Iter - me iter().by_ref() (as Iterator) fn(&'_ mut self) -> &mut Self - me iter().into_iter() (as IntoIterator) fn(self) -> ::IntoIter - me iter().next() (as Iterator) fn(&'_ mut self) -> Option<::Item> - me iter().nth(…) (as Iterator) fn(&'_ mut self, usize) -> Option<::Item> + me deref() (use core::ops::Deref) fn(&self) -> &::Target + me into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me iter() fn(&self) -> Iter + me iter().by_ref() (as Iterator) fn(&mut self) -> &mut Self + me iter().into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me iter().next() (as Iterator) fn(&mut self) -> Option<::Item> + me iter().nth(…) (as Iterator) fn(&mut self, usize) -> Option<::Item> "#]], ); } @@ -1821,10 +1821,10 @@ fn main() { } "#, expect![[r#" - me by_ref() (as Iterator) fn(&'_ mut self) -> &mut Self - me into_iter() (as IntoIterator) fn(self) -> ::IntoIter - me next() (as Iterator) fn(&'_ mut self) -> Option<::Item> - me nth(…) (as Iterator) fn(&'_ mut self, usize) -> Option<::Item> + me by_ref() (as Iterator) fn(&mut self) -> &mut Self + me into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me next() (as Iterator) fn(&mut self) -> Option<::Item> + me nth(…) (as Iterator) fn(&mut self, usize) -> Option<::Item> "#]], ); } diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs index 7826a9b538a4..34b53e5e5bfe 100644 --- a/crates/ide-completion/src/completions/postfix.rs +++ b/crates/ide-completion/src/completions/postfix.rs @@ -894,7 +894,7 @@ fn main() { "#, expect![[r#" me and(…) fn(self, Option) -> Option - me as_ref() const fn(&'_ self) -> Option<&T> + me as_ref() const fn(&self) -> Option<&T> me ok_or(…) const fn(self, E) -> Result me unwrap() const fn(self) -> T me unwrap_or(…) fn(self, T) -> T diff --git a/crates/ide-completion/src/context/tests.rs b/crates/ide-completion/src/context/tests.rs index 4380ffc930ee..c5fba82de480 100644 --- a/crates/ide-completion/src/context/tests.rs +++ b/crates/ide-completion/src/context/tests.rs @@ -154,7 +154,7 @@ fn expected_type_fn_param_deref() { fn foo() { bar(*$0); } fn bar(x: &u32) {} "#, - expect!["ty: &'_ &' u32, name: x"], + expect!["ty: &'_ &'_ u32, name: x"], ); } diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index 182953ac7e3f..fe18f5042ccd 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -931,7 +931,7 @@ fn main() { } "#, expect![[r#" - me my_method(…) fn(&'_ self) [] + me my_method(…) fn(&self) [] "#]], ); } @@ -1207,7 +1207,7 @@ fn main() { "#, expect![[r#" - me Function(…) fn(&'_ self, i32) -> bool [] + me Function(…) fn(&self, i32) -> bool [] "#]], ); } @@ -1237,7 +1237,7 @@ fn func(input: Struct) { } ex Struct [type] lc self &Struct [local] fn func(…) fn(Struct) [] - me self.test() fn(&'_ self) [] + me self.test() fn(&self) [] "#]], ); } @@ -2382,7 +2382,7 @@ fn foo(s: S) { s.$0 } label: "the_method()", detail_left: None, detail_right: Some( - "fn(&'_ self)", + "fn(&self)", ), source_range: 81..81, delete: 81..81, @@ -2391,7 +2391,7 @@ fn foo(s: S) { s.$0 } Method, ), lookup: "the_method", - detail: "fn(&'_ self)", + detail: "fn(&self)", relevance: CompletionRelevance { exact_name_match: false, type_match: None, @@ -2871,7 +2871,7 @@ fn main() { label: "indent()", detail_left: None, detail_right: Some( - "fn(&'_ self) -> i32", + "fn(&self) -> i32", ), source_range: 144..145, delete: 144..145, @@ -2880,7 +2880,7 @@ fn main() { Method, ), lookup: "indent", - detail: "fn(&'_ self) -> i32", + detail: "fn(&self) -> i32", relevance: CompletionRelevance { exact_name_match: false, type_match: None, @@ -2992,9 +2992,9 @@ fn f() { } "#, expect![[r#" - me aaa() fn(&'_ self) -> u32 [type+name] - me bbb() fn(&'_ self) -> u32 [type] - me ccc() fn(&'_ self) -> u64 [] + me aaa() fn(&self) -> u32 [type+name] + me bbb() fn(&self) -> u32 [type] + me ccc() fn(&self) -> u64 [] "#]], ); } @@ -3013,7 +3013,7 @@ fn f() { } "#, expect![[r#" - me aaa() fn(&'_ self) -> u64 [name] + me aaa() fn(&self) -> u64 [name] "#]], ); } @@ -3509,8 +3509,8 @@ fn main() { "#, expect![[r#" fn new() fn() -> Foo [] - me eq(…) fn(&'_ self, &Rhs) -> bool [op_method] - me ne(…) fn(&'_ self, &Rhs) -> bool [op_method] + me eq(…) fn(&self, &Rhs) -> bool [op_method] + me ne(…) fn(&self, &Rhs) -> bool [op_method] "#]], ); } @@ -3568,7 +3568,7 @@ fn test() { expect![[r#" [ ( - "fn(&'_ self, u32) -> Bar", + "fn(&self, u32) -> Bar", Some( CompletionRelevanceFn { has_params: true, @@ -3578,7 +3578,7 @@ fn test() { ), ), ( - "fn(&'_ self)", + "fn(&self)", Some( CompletionRelevanceFn { has_params: true, @@ -3588,7 +3588,7 @@ fn test() { ), ), ( - "fn(&'_ self) -> Foo", + "fn(&self) -> Foo", Some( CompletionRelevanceFn { has_params: true, @@ -3598,7 +3598,7 @@ fn test() { ), ), ( - "fn(&'_ self, u32) -> Foo", + "fn(&self, u32) -> Foo", Some( CompletionRelevanceFn { has_params: true, @@ -3608,7 +3608,7 @@ fn test() { ), ), ( - "fn(&'_ self) -> Option", + "fn(&self) -> Option", Some( CompletionRelevanceFn { has_params: true, @@ -3618,7 +3618,7 @@ fn test() { ), ), ( - "fn(&'_ self) -> Result", + "fn(&self) -> Result", Some( CompletionRelevanceFn { has_params: true, @@ -3628,7 +3628,7 @@ fn test() { ), ), ( - "fn(&'_ self) -> Result", + "fn(&self) -> Result", Some( CompletionRelevanceFn { has_params: true, @@ -3638,7 +3638,7 @@ fn test() { ), ), ( - "fn(&'_ self, u32) -> Option", + "fn(&self, u32) -> Option", Some( CompletionRelevanceFn { has_params: true, @@ -3684,7 +3684,7 @@ fn test() { fn fn_ctr_with_args(…) fn(u32) -> Foo [type_could_unify] fn fn_builder() fn() -> FooBuilder [type_could_unify] fn fn_ctr() fn() -> Result [type_could_unify] - me fn_no_ret(…) fn(&'_ self) [type_could_unify] + me fn_no_ret(…) fn(&self) [type_could_unify] fn fn_other() fn() -> Result [type_could_unify] "#]], ); @@ -3722,7 +3722,7 @@ fn test() { fn fn_ctr_wrapped() fn() -> Option> [type_could_unify] fn fn_ctr_wrapped_2() fn() -> Result, u32> [type_could_unify] fn fn_other() fn() -> Option [type_could_unify] - me fn_returns_unit(…) fn(&'_ self) [type_could_unify] + me fn_returns_unit(…) fn(&self) [type_could_unify] "#]], ); } @@ -3757,7 +3757,7 @@ fn test() { fn fn_builder() fn() -> FooBuilder [type_could_unify] fn fn_ctr() fn() -> Option> [type_could_unify] fn fn_ctr2() fn() -> Result, u32> [type_could_unify] - me fn_no_ret(…) fn(&'_ self) [type_could_unify] + me fn_no_ret(…) fn(&self) [type_could_unify] fn fn_other() fn() -> Option [type_could_unify] "#]], ); @@ -3782,7 +3782,7 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 } label: "baz()", detail_left: None, detail_right: Some( - "fn(&'_ self) -> u32", + "fn(&self) -> u32", ), source_range: 109..110, delete: 109..110, @@ -3791,7 +3791,7 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 } Method, ), lookup: "baz", - detail: "fn(&'_ self) -> u32", + detail: "fn(&self) -> u32", relevance: CompletionRelevance { exact_name_match: false, type_match: None, @@ -4111,7 +4111,7 @@ fn main() { "#, &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)], expect![[r#" - me f() fn(&'_ self) [] + me f() fn(&self) [] sn box Box::new(expr) [] sn call function(expr) [] sn const const {} [] @@ -4426,7 +4426,7 @@ fn main() { "(as Write)", ), detail_right: Some( - "fn(&'_ self)", + "fn(&self)", ), source_range: 193..193, delete: 193..193, @@ -4435,7 +4435,7 @@ fn main() { Method, ), lookup: "flush", - detail: "fn(&'_ self)", + detail: "fn(&self)", relevance: CompletionRelevance { exact_name_match: false, type_match: None, @@ -4463,7 +4463,7 @@ fn main() { "(as Write)", ), detail_right: Some( - "fn(&'_ self)", + "fn(&self)", ), source_range: 193..193, delete: 193..193, @@ -4472,7 +4472,7 @@ fn main() { Method, ), lookup: "write", - detail: "fn(&'_ self)", + detail: "fn(&self)", relevance: CompletionRelevance { exact_name_match: false, type_match: None, diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs index 2dd4553024e3..2fa8a9d4b08e 100644 --- a/crates/ide-completion/src/render/function.rs +++ b/crates/ide-completion/src/render/function.rs @@ -508,7 +508,7 @@ struct S; impl S { fn foo(&self) {} } -fn main() { S::foo(${1:&'_ self});$0 } +fn main() { S::foo(${1:&self});$0 } "#, ); } diff --git a/crates/ide-completion/src/tests/expression.rs b/crates/ide-completion/src/tests/expression.rs index cbe3ffd30394..04331d48eaa8 100644 --- a/crates/ide-completion/src/tests/expression.rs +++ b/crates/ide-completion/src/tests/expression.rs @@ -2482,7 +2482,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&'_ self) + me foo() fn(&self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -2509,7 +2509,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&'_ self) + me foo() fn(&self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -2540,7 +2540,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&'_ self) + me foo() fn(&self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -2567,7 +2567,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&'_ self) + me foo() fn(&self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -2594,7 +2594,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&'_ self) + me foo() fn(&self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -2621,7 +2621,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&'_ self) + me foo() fn(&self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -2735,20 +2735,20 @@ fn foo() { } "#, expect![[r#" - me inherent() fn(&'_ self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me inherent() fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -2774,22 +2774,22 @@ fn foo(v: &dyn ExcludedTrait) { } "#, expect![[r#" - me bar() (as ExcludedTrait) fn(&'_ self) - me baz() (as ExcludedTrait) fn(&'_ self) - me foo() (as ExcludedTrait) fn(&'_ self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me bar() (as ExcludedTrait) fn(&self) + me baz() (as ExcludedTrait) fn(&self) + me foo() (as ExcludedTrait) fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); check_with_config( @@ -2811,22 +2811,22 @@ fn foo(v: impl ExcludedTrait) { } "#, expect![[r#" - me bar() (as ExcludedTrait) fn(&'_ self) - me baz() (as ExcludedTrait) fn(&'_ self) - me foo() (as ExcludedTrait) fn(&'_ self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me bar() (as ExcludedTrait) fn(&self) + me baz() (as ExcludedTrait) fn(&self) + me foo() (as ExcludedTrait) fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); check_with_config( @@ -2848,22 +2848,22 @@ fn foo(v: T) { } "#, expect![[r#" - me bar() (as ExcludedTrait) fn(&'_ self) - me baz() (as ExcludedTrait) fn(&'_ self) - me foo() (as ExcludedTrait) fn(&'_ self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me bar() (as ExcludedTrait) fn(&self) + me baz() (as ExcludedTrait) fn(&self) + me foo() (as ExcludedTrait) fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -2896,20 +2896,20 @@ fn foo() { } "#, expect![[r#" - me inherent() fn(&'_ self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me inherent() fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -2945,20 +2945,20 @@ fn foo() { } "#, expect![[r#" - me inherent() fn(&'_ self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me inherent() fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -3137,7 +3137,7 @@ fn foo() { } "#, expect![[r#" - me inherent(…) fn(&'_ self) + me inherent(…) fn(&self) "#]], ); } @@ -3168,9 +3168,9 @@ fn foo() { } "#, expect![[r#" - me bar(…) (as ExcludedTrait) fn(&'_ self) - me baz(…) (as ExcludedTrait) fn(&'_ self) - me foo(…) (as ExcludedTrait) fn(&'_ self) + me bar(…) (as ExcludedTrait) fn(&self) + me baz(…) (as ExcludedTrait) fn(&self) + me foo(…) (as ExcludedTrait) fn(&self) "#]], ); check_with_config( @@ -3197,9 +3197,9 @@ fn foo() { } "#, expect![[r#" - me bar(…) (as ExcludedTrait) fn(&'_ self) - me baz(…) (as ExcludedTrait) fn(&'_ self) - me foo(…) (as ExcludedTrait) fn(&'_ self) + me bar(…) (as ExcludedTrait) fn(&self) + me baz(…) (as ExcludedTrait) fn(&self) + me foo(…) (as ExcludedTrait) fn(&self) "#]], ); } @@ -3225,9 +3225,9 @@ fn foo() { } "#, expect![[r#" - me bar(…) (as ExcludedTrait) fn(&'_ self) - me baz(…) (as ExcludedTrait) fn(&'_ self) - me foo(…) (as ExcludedTrait) fn(&'_ self) + me bar(…) (as ExcludedTrait) fn(&self) + me baz(…) (as ExcludedTrait) fn(&self) + me foo(…) (as ExcludedTrait) fn(&self) "#]], ); check_with_config( @@ -3249,9 +3249,9 @@ fn foo() { } "#, expect![[r#" - me bar(…) (as ExcludedTrait) fn(&'_ self) - me baz(…) (as ExcludedTrait) fn(&'_ self) - me foo(…) (as ExcludedTrait) fn(&'_ self) + me bar(…) (as ExcludedTrait) fn(&self) + me baz(…) (as ExcludedTrait) fn(&self) + me foo(…) (as ExcludedTrait) fn(&self) "#]], ); } @@ -3842,21 +3842,21 @@ fn field_in_previous_line_of_ambiguous_expr() { (2, 3) }"#, expect![[r#" - fd field i32 - me method() fn(&'_ self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + fd field i32 + me method() fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); @@ -3872,21 +3872,21 @@ fn field_in_previous_line_of_ambiguous_expr() { (2, 3) }"#, expect![[r#" - fd field i32 - me method() fn(&'_ self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + fd field i32 + me method() fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -3905,21 +3905,21 @@ fn fn_field_in_previous_line_of_ambiguous_expr() { (2, 3) }"#, expect![[r#" - fd field fn() - me method() fn(&'_ self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + fd field fn() + me method() fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); @@ -3970,20 +3970,20 @@ fn main() { } "#, expect![[r#" - me method() (as Trait) fn(&'_ self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me method() (as Trait) fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } @@ -4005,20 +4005,20 @@ fn baz(v: impl Bar) { } "#, expect![[r#" - me foo() (as Foo) fn(&'_ self) - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + me foo() (as Foo) fn(&self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs index 67b19ae3498b..8a5025caf901 100644 --- a/crates/ide-completion/src/tests/flyimport.rs +++ b/crates/ide-completion/src/tests/flyimport.rs @@ -398,7 +398,7 @@ fn trait_method_fuzzy_completion() { check( fixture, expect![[r#" - me random_method() (use dep::test_mod::TestTrait) fn(&'_ self) + me random_method() (use dep::test_mod::TestTrait) fn(&self) "#]], ); @@ -443,7 +443,7 @@ fn main() { check( fixture, expect![[r#" - me some_method() (use foo::TestTrait) fn(&'_ self) + me some_method() (use foo::TestTrait) fn(&self) "#]], ); @@ -490,7 +490,7 @@ fn main() { check( fixture, expect![[r#" - me some_method() (use foo::TestTrait) fn(&'_ self) + me some_method() (use foo::TestTrait) fn(&self) "#]], ); @@ -538,7 +538,7 @@ fn completion(whatever: T) { check( fixture, expect![[r#" - me not_in_scope() (use foo::NotInScope) fn(&'_ self) + me not_in_scope() (use foo::NotInScope) fn(&self) "#]], ); @@ -779,7 +779,7 @@ fn main() { } "#, expect![[r#" - me random_method() (use dep::test_mod::TestTrait) fn(&'_ self) DEPRECATED + me random_method() (use dep::test_mod::TestTrait) fn(&self) DEPRECATED "#]], ); @@ -809,9 +809,9 @@ fn main() { } "#, expect![[r#" - ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8 DEPRECATED - fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED - me random_method(…) (use dep::test_mod::TestTrait) fn(&'_ self) DEPRECATED + ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8 DEPRECATED + fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED + me random_method(…) (use dep::test_mod::TestTrait) fn(&self) DEPRECATED "#]], ); } @@ -1775,7 +1775,7 @@ mod module { } "#, expect![[r#" - me choose (use module::SliceRandom) fn(&'_ self) + me choose (use module::SliceRandom) fn(&self) "#]], ); } @@ -2065,7 +2065,7 @@ fn trait_method_import_across_multiple_crates() { check( fixture, expect![[r#" - me test_function() (use test_trait::TestTrait) fn(&'_ self) -> u32 + me test_function() (use test_trait::TestTrait) fn(&self) -> u32 "#]], ); diff --git a/crates/ide-completion/src/tests/proc_macros.rs b/crates/ide-completion/src/tests/proc_macros.rs index e981de49f2f4..626d1677d555 100644 --- a/crates/ide-completion/src/tests/proc_macros.rs +++ b/crates/ide-completion/src/tests/proc_macros.rs @@ -19,7 +19,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&'_ self) + me foo() fn(&self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -53,7 +53,7 @@ fn main() { } "#, expect![[r#" - me foo() fn(&'_ self) + me foo() fn(&self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -89,7 +89,7 @@ impl Foo { fn main() {} "#, expect![[r#" - me foo() fn(&'_ self) + me foo() fn(&self) sn box Box::new(expr) sn call function(expr) sn const const {} @@ -125,7 +125,7 @@ impl Foo { fn main() {} "#, expect![[r#" - me foo() fn(&'_ self) + me foo() fn(&self) sn box Box::new(expr) sn call function(expr) sn const const {} diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs index 5df4befb4e29..6c2502a4eb67 100644 --- a/crates/ide-completion/src/tests/special.rs +++ b/crates/ide-completion/src/tests/special.rs @@ -297,14 +297,14 @@ trait Sub: Super { fn foo() { T::$0 } "#, expect![[r#" - ct C2 (as Sub) const C2: () - ct CONST (as Super) const CONST: u8 - fn func() (as Super) fn() - fn subfunc() (as Sub) fn() - me method(…) (as Super) fn(&'_ self) - me submethod(…) (as Sub) fn(&'_ self) - ta SubTy (as Sub) type SubTy - ta Ty (as Super) type Ty + ct C2 (as Sub) const C2: () + ct CONST (as Super) const CONST: u8 + fn func() (as Super) fn() + fn subfunc() (as Sub) fn() + me method(…) (as Super) fn(&self) + me submethod(…) (as Sub) fn(&self) + ta SubTy (as Sub) type SubTy + ta Ty (as Super) type Ty "#]], ); } @@ -337,14 +337,14 @@ impl Sub for Wrap { } "#, expect![[r#" - ct C2 (as Sub) const C2: () - ct CONST (as Super) const CONST: u8 - fn func() (as Super) fn() - fn subfunc() (as Sub) fn() - me method(…) (as Super) fn(&'_ self) - me submethod(…) (as Sub) fn(&'_ self) - ta SubTy (as Sub) type SubTy - ta Ty (as Super) type Ty + ct C2 (as Sub) const C2: () + ct CONST (as Super) const CONST: u8 + fn func() (as Super) fn() + fn subfunc() (as Sub) fn() + me method(…) (as Super) fn(&self) + me submethod(…) (as Sub) fn(&self) + ta SubTy (as Sub) type SubTy + ta Ty (as Super) type Ty "#]], ); } @@ -981,8 +981,8 @@ fn main() { } "#, expect![[r#" - me by_macro() (as MyTrait) fn(&'_ self) - me not_by_macro() (as MyTrait) fn(&'_ self) + me by_macro() (as MyTrait) fn(&self) + me not_by_macro() (as MyTrait) fn(&self) "#]], ) } @@ -1021,8 +1021,8 @@ fn main() { } "#, expect![[r#" - me by_macro() (as MyTrait) fn(&'_ self) - me not_by_macro() (as MyTrait) fn(&'_ self) + me by_macro() (as MyTrait) fn(&self) + me not_by_macro() (as MyTrait) fn(&self) "#]], ) } @@ -1367,21 +1367,21 @@ fn here_we_go() { } "#, expect![[r#" - fd bar u8 - me baz() (alias qux) fn(&'_ self) -> u8 - sn box Box::new(expr) - sn call function(expr) - sn const const {} - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn deref *expr - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr - sn return return expr - sn unsafe unsafe {} + fd bar u8 + me baz() (alias qux) fn(&self) -> u8 + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} "#]], ); } diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 9bb500e45031..6a7e6ae28a0a 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -678,7 +678,7 @@ fn main() { } ``` ```rust - pub fn foo<'_>(_: &'_ Path) + pub fn foo(_: &Path) ``` --- @@ -711,7 +711,7 @@ fn main() { } ``` ```rust - pub fn foo<'_>(_: &'_ Path) + pub fn foo(_: &Path) ``` --- @@ -3431,7 +3431,7 @@ fn foo() { let bar = Bar; bar.fo$0o(); } ``` ```rust - fn foo<'_>(&'_ self) + fn foo(&self) ``` --- @@ -3469,7 +3469,7 @@ fn foo() { let bar = Bar; bar.fo$0o(); } ``` ```rust - fn foo<'_>(&'_ self) + fn foo(&self) ``` --- @@ -6774,7 +6774,7 @@ fn main() { ``` ```rust - fn bar<'t, '_, T>(s: &'_ mut S<'t, T>, t: u32) -> *mut u32 + fn bar<'t, T>(s: &mut S<'t, T>, t: u32) -> *mut u32 where T: Clone + 't, 't: 't + 't, @@ -8165,7 +8165,7 @@ fn f() { ``` ```rust - fn deref<'_>(&'_ self) -> &'_ Self::Target + fn deref(&self) -> &Self::Target ``` "#]], ); @@ -8739,7 +8739,7 @@ fn main() { ``` ```rust - fn foo<'_, T>(&'_ self, t: T) + fn foo(&self, t: T) ``` "#]], ); @@ -9732,7 +9732,7 @@ fn test_hover_function_with_pat_param() { ``` ```rust - fn test_3<'_>(&(a, b): &'_ (i32, i32)) + fn test_3(&(a, b): &(i32, i32)) ``` "#]], ); @@ -9938,8 +9938,8 @@ fn fn_$0( ``` ```rust - fn fn_<'_>( - &'_ self, + fn fn_( + &self, attrs: impl IntoIterator, visibility: Option, fn_name: ast::Name, @@ -10525,7 +10525,7 @@ fn bar() { ```rust trait Trait - fn foo<'_, U>(&'_ self, v: U) + fn foo(&self, v: U) ``` --- @@ -10558,7 +10558,7 @@ fn bar() { ```rust impl<'a, T, const N: usize> Foo<'a, N, T> - fn foo<'b, '_, const Z: u32, U>(&'_ self, v: U) + fn foo<'b, const Z: u32, U>(&self, v: U) ``` --- @@ -11304,7 +11304,7 @@ fn bar(v: &Foo) { ```rust impl Foo - fn foo<'_, U>(&'_ self, _u: U) + fn foo(&self, _u: U) where U: Copy, // Bounds from impl: @@ -11495,7 +11495,7 @@ fn bar() { ```rust impl Foo<()> for T - fn foo<'_>(&'_ self) + fn foo(&self) ``` "#]], ); @@ -11520,7 +11520,7 @@ impl Foo for T { ```rust impl Foo for T - fn foo<'_>(&'_ self) + fn foo(&self) ``` "#]], ); @@ -11568,7 +11568,7 @@ pub trait MyTrait { ```rust pub trait MyTrait - pub fn do_something<'_>(&'_ self) + pub fn do_something(&self) ``` "#]], ); @@ -11588,7 +11588,7 @@ pub trait MyTrait { ```rust pub trait MyTrait - pub fn do_something<'_>(&'_ self) + pub fn do_something(&self) ``` --- @@ -11630,7 +11630,7 @@ fn foo() { let bar = Bar; bar.fo$0o(); } ``` ```rust - fn foo<'_>(&'_ self) + fn foo(&self) ``` --- diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs index db8b8413ba88..ce2da39e8ae4 100644 --- a/crates/ide/src/signature_help.rs +++ b/crates/ide/src/signature_help.rs @@ -190,7 +190,8 @@ fn signature_help_for_call( .iter() .filter(|param| match param { GenericParam::TypeParam(type_param) => !type_param.is_implicit(db), - GenericParam::ConstParam(_) | GenericParam::LifetimeParam(_) => true, + GenericParam::LifetimeParam(lt_param) => !lt_param.is_elided(db), + GenericParam::ConstParam(_) => true, }) .map(|param| param.display(db, display_target)) .join(", "); @@ -921,7 +922,7 @@ fn bar() { } "#, expect![[r#" - fn do_it<'_>(&'_ self) + fn do_it(&self) "#]], ); } @@ -939,8 +940,8 @@ impl S { fn main() { S.foo($0); } "#, expect![[r#" - fn foo<'_>(&'_ self, x: i32) - ^^^^^^ + fn foo(&self, x: i32) + ^^^^^^ "#]], ); } @@ -958,8 +959,8 @@ impl S { fn main() { S(1u32).foo($0); } "#, expect![[r#" - fn foo<'_>(&'_ self, x: u32) - ^^^^^^ + fn foo(&self, x: u32) + ^^^^^^ "#]], ); } @@ -977,8 +978,8 @@ impl S { fn main() { S::foo($0); } "#, expect![[r#" - fn foo<'_>(self: &S, x: i32) - ^^^^^^^^ ------ + fn foo(self: &S, x: i32) + ^^^^^^^^ ------ "#]], ); } @@ -1116,8 +1117,8 @@ fn foo(mut r: impl WriteHandler<()>) { By default this method stops actor's `Context`. ------ - fn finished<'_, '_>(&'_ mut self, ctx: &mut as Actor>::Context) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + fn finished(&mut self, ctx: &mut as Actor>::Context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "#]], ); } @@ -1202,8 +1203,8 @@ fn main() { } "#, expect![[r#" - fn bar<'_>(&'_ self, _: u32) - ^^^^^^ + fn bar(&self, _: u32) + ^^^^^^ "#]], ); } @@ -1829,8 +1830,8 @@ fn sup() { } "#, expect![[r#" - fn test<'_, V>(&'_ mut self, val: V) - ^^^^^^ + fn test(&mut self, val: V) + ^^^^^^ "#]], ); } @@ -2035,8 +2036,8 @@ fn f() { } "#, expect![[r#" - fn foo<'_>(self: &Self, other: Self) - ^^^^^^^^^^^ ----------- + fn foo(self: &Self, other: Self) + ^^^^^^^^^^^ ----------- "#]], ); } From 5ffb809f4790ce37e41dc0b86339851be729c198 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Mon, 27 Jul 2026 16:11:01 +0530 Subject: [PATCH 4/8] refactor: change elision callbacks to internal state --- crates/hir-def/src/expr_store/lower.rs | 673 +++++++++--------- crates/hir-def/src/expr_store/lower/asm.rs | 3 +- .../src/expr_store/lower/format_args.rs | 2 +- .../hir-def/src/expr_store/lower/generics.rs | 133 +--- crates/hir-def/src/expr_store/lower/path.rs | 27 +- .../src/expr_store/lower/path/tests.rs | 6 +- crates/hir-def/src/hir/generics.rs | 9 +- crates/hir-def/src/signatures.rs | 7 +- crates/hir-ty/src/tests/patterns.rs | 6 +- crates/hir-ty/src/tests/regression.rs | 8 +- crates/hir-ty/src/tests/simple.rs | 14 +- crates/hir-ty/src/tests/traits.rs | 8 +- crates/hir/src/source_analyzer.rs | 24 +- 13 files changed, 407 insertions(+), 513 deletions(-) diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index b4caf41225f7..b1b8932c1e46 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -11,7 +11,6 @@ use std::{cell::OnceCell, mem}; use base_db::{FxIndexSet, SourceDatabase}; use cfg::CfgOptions; use either::Either; -use generics::LifetimeElisionFn; use hir_expand::{ HirFileId, InFile, MacroDefId, mod_path::ModPath, @@ -20,6 +19,7 @@ use hir_expand::{ }; use intern::{Symbol, sym}; use itertools::Itertools; +use la_arena::Arena; use rustc_abi::ExternAbi; use rustc_hash::FxHashMap; use smallvec::SmallVec; @@ -37,8 +37,8 @@ use tt::TextRange; use crate::{ AdtId, BlockId, BlockIdLt, ConstId, DefWithBodyId, FunctionId, GenericDefId, - HrtbLifetimeParamId, ImplId, ItemContainerId, LoweringMode, MacroId, ModuleDefId, ModuleId, - TraitId, TypeAliasId, UnresolvedMacro, + HrtbLifetimeParamId, ImplId, ItemContainerId, LifetimeParamId, LoweringMode, MacroId, + ModuleDefId, ModuleId, TraitId, TypeAliasId, UnresolvedMacro, attrs::AttrFlags, expr_store::{ Body, BodySourceMap, ExprPtr, ExprRoot, ExpressionStore, ExpressionStoreBuilder, @@ -54,7 +54,7 @@ use crate::{ CoroutineKind, CoroutineSource, Expr, ExprId, Item, Label, LabelId, Literal, LoopSource, MatchArm, Movability, OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, RecordSpread, Statement, - generics::{ElidedSource, GenericParams}, + generics::{GenericParams, LifetimeBoundType, LifetimeParamData}, }, item_scope::BuiltinShadowMode, lang_item::{LangItemTarget, LangItems}, @@ -206,12 +206,10 @@ pub(crate) fn lower_type_ref( type_ref: InFile>, ) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId) { let mut expr_collector = - ExprCollector::new(db, module, type_ref.file_id, LoweringMode::Analysis); - let type_ref = expr_collector.lower_type_ref_opt( - type_ref.value, - &mut ExprCollector::impl_trait_allocator, - &mut ExprCollector::elided_lifetime_static_allocator, - ); + ExprCollector::new(db, module, type_ref.file_id, LoweringMode::Analysis) + .elide_static_lifetime(); + let type_ref = + expr_collector.lower_type_ref_opt(type_ref.value, &mut ExprCollector::impl_trait_allocator); let (store, source_map) = expr_collector.store.finish(); (store, source_map, type_ref) } @@ -247,23 +245,24 @@ pub(crate) fn lower_impl( impl_syntax.value.generic_param_list(), impl_syntax.value.where_clause(), ); - let self_ty = expr_collector.lower_type_ref_opt_disallow_impl_trait( - impl_syntax.value.self_ty(), - &mut collector.lower_elided_lifetime_in_impl_header(), + + expr_collector.elide_create_lifetime( + collector.lifetimes_mut(), + impl_id.into(), + LifetimeBoundType::EarlyBound, ); + let self_ty = + expr_collector.lower_type_ref_opt_disallow_impl_trait(impl_syntax.value.self_ty()); let trait_ = impl_syntax.value.trait_().and_then(|it| match &it { ast::Type::PathType(path_type) => { - let path = expr_collector.lower_path_type( - path_type, - &mut ExprCollector::impl_trait_allocator, - &mut collector.lower_elided_lifetime_in_impl_header(), - )?; + let path = expr_collector + .lower_path_type(path_type, &mut ExprCollector::impl_trait_allocator)?; Some(TraitRef { path: expr_collector.alloc_path(path, AstPtr::new(&it)) }) } _ => None, }); - let params = collector.finish(); let (store, source_map) = expr_collector.store.finish(); + let params = collector.finish(); (store, source_map, self_ty, trait_, params) } @@ -305,11 +304,7 @@ pub(crate) fn lower_type_alias( bounds .bounds() .map(|bound| { - expr_collector.lower_type_bound( - bound, - &mut ExprCollector::impl_trait_allocator, - &mut ExprCollector::elided_lifetime_error_allocator, - ) + expr_collector.lower_type_bound(bound, &mut ExprCollector::impl_trait_allocator) }) .collect() }) @@ -321,13 +316,10 @@ pub(crate) fn lower_type_alias( alias.value.where_clause(), ); let params = collector.finish(); - let type_ref = alias.value.ty().map(|ty| { - expr_collector.lower_type_ref( - ty, - &mut ExprCollector::impl_trait_allocator, - &mut ExprCollector::elided_lifetime_error_allocator, - ) - }); + let type_ref = alias + .value + .ty() + .map(|ty| expr_collector.lower_type_ref(ty, &mut ExprCollector::impl_trait_allocator)); let (store, source_map) = expr_collector.store.finish(); (store, source_map, params, bounds, type_ref) } @@ -352,102 +344,81 @@ pub(crate) fn lower_function( let mut params = vec![]; let mut has_self_param = false; let mut has_variadic = false; - collector.collect_impl_trait( - &mut expr_collector, - |collector, mut impl_trait_lower_fn, mut lifetime_elision_fn| { - collector.with_lifetime_bound_scope(LifetimeBoundScope::Argument, |collector| { - if let Some(param_list) = fn_.value.param_list() { - if let Some(param) = param_list.self_param() { - let enabled = collector.check_cfg(¶m); - if enabled { - has_self_param = true; - params.push(match param.ty() { - Some(ty) => collector.with_self_lt_elision(|this| { - this.lower_type_ref( - ty, - &mut impl_trait_lower_fn, - &mut lifetime_elision_fn, - ) - }), - None => { - let self_type = collector.alloc_type_ref_desugared( - TypeRef::Path(Name::new_symbol_root(sym::Self_).into()), - ); - let lifetime = collector.with_self_lt_elision(|this| { - param - .lifetime() - .map(|lifetime| { - this.lower_lifetime_ref( - lifetime, - lifetime_elision_fn, - ) - }) - .or_else(|| match param.kind() { - ast::SelfParamKind::Ref - | ast::SelfParamKind::MutRef => { - Some(lifetime_elision_fn(this)) - } - ast::SelfParamKind::Owned => None, - }) - }); - match param.kind() { - ast::SelfParamKind::Owned => self_type, - ast::SelfParamKind::Ref => collector - .alloc_type_ref_desugared(TypeRef::Reference( - Box::new(RefType { - ty: self_type, - lifetime, - mutability: Mutability::Shared, - }), - )), - ast::SelfParamKind::MutRef => collector - .alloc_type_ref_desugared(TypeRef::Reference( - Box::new(RefType { - ty: self_type, - lifetime, - mutability: Mutability::Mut, - }), - )), - } + collector.collect_impl_trait(&mut expr_collector, |collector, mut impl_trait_lower_fn| { + collector.with_lifetime_bound_scope(LifetimeBoundScope::Argument, |collector| { + if let Some(param_list) = fn_.value.param_list() { + if let Some(param) = param_list.self_param() { + let enabled = collector.check_cfg(¶m); + if enabled { + has_self_param = true; + params.push(match param.ty() { + Some(ty) => collector.with_self_lt_elision(|this| { + this.lower_type_ref(ty, &mut impl_trait_lower_fn) + }), + None => { + let self_type = collector.alloc_type_ref_desugared(TypeRef::Path( + Name::new_symbol_root(sym::Self_).into(), + )); + let lifetime = collector.with_self_lt_elision(|this| { + param + .lifetime() + .map(|lifetime| this.lower_lifetime_ref(lifetime)) + .or_else(|| match param.kind() { + ast::SelfParamKind::Ref + | ast::SelfParamKind::MutRef => { + Some(this.lower_elided_lifetime()) + } + ast::SelfParamKind::Owned => None, + }) + }); + match param.kind() { + ast::SelfParamKind::Owned => self_type, + ast::SelfParamKind::Ref => collector.alloc_type_ref_desugared( + TypeRef::Reference(Box::new(RefType { + ty: self_type, + lifetime, + mutability: Mutability::Shared, + })), + ), + ast::SelfParamKind::MutRef => collector + .alloc_type_ref_desugared(TypeRef::Reference(Box::new( + RefType { + ty: self_type, + lifetime, + mutability: Mutability::Mut, + }, + ))), } - }); - } + } + }); } - let p = param_list - .params() - .filter(|param| collector.check_cfg(param)) - .filter(|param| { - let is_variadic = param.dotdotdot_token().is_some(); - has_variadic |= is_variadic; - !is_variadic - }) - .map(|param| param.ty()) - // FIXME - .collect::>(); - collector.with_param_lt_elision(|this| { - for p in p { - params.push(this.lower_type_ref_opt( - p, - &mut impl_trait_lower_fn, - &mut lifetime_elision_fn, - )); - } - }) } - }) - }, - ); + let p = param_list + .params() + .filter(|param| collector.check_cfg(param)) + .filter(|param| { + let is_variadic = param.dotdotdot_token().is_some(); + has_variadic |= is_variadic; + !is_variadic + }) + .map(|param| param.ty()) + // FIXME + .collect::>(); + collector.with_param_lt_elision(|this| { + for p in p { + params.push(this.lower_type_ref_opt(p, &mut impl_trait_lower_fn)); + } + }) + } + }) + }); + expr_collector.elide_return_lifetime(); let return_type = fn_.value.ret_type().map(|ret_type| { expr_collector.with_lifetime_bound_scope(LifetimeBoundScope::Return, |this| { - this.lower_type_ref_opt( - ret_type.ty(), - &mut ExprCollector::impl_trait_allocator, - &mut ExprCollector::elided_lifetime_placeholder_allocator, - ) + this.lower_type_ref_opt(ret_type.ty(), &mut ExprCollector::impl_trait_allocator) }) }); - collector.update_to_late_bound_lifetimes(&expr_collector.named_lifetime_store); - let generics = collector.finish(); + expr_collector.update_to_late_bound_lifetimes(); let return_type = if fn_.value.async_token().is_some() || fn_.value.gen_token().is_some() { let (path, assoc_name) = @@ -486,6 +457,7 @@ pub(crate) fn lower_function( return_type }; let (store, source_map) = expr_collector.store.finish(); + let generics = collector.finish(); ( store, source_map, @@ -497,7 +469,7 @@ pub(crate) fn lower_function( ) } -pub struct ExprCollector<'db> { +pub struct ExprCollector<'db, 'a> { db: &'db dyn SourceDatabase, cfg_options: &'db CfgOptions, expander: Expander<'db>, @@ -515,7 +487,9 @@ pub struct ExprCollector<'db> { is_lowering_coroutine: bool, - elision_context: Option, + lifetime_arena: Option<&'a mut Arena>, + lifetime_elision_kind: LifetimeElisionKind, + argument_elision_context: Option, elision_binder_source: ElisionBinderSource, for_type_binder: Option<(ThinVec, ForBinderSource)>, @@ -587,7 +561,7 @@ struct BindingList { impl BindingList { fn find( &mut self, - ec: &mut ExprCollector<'_>, + ec: &mut ExprCollector<'_, '_>, name: Name, hygiene: HygieneId, mode: BindingAnnotation, @@ -603,7 +577,7 @@ impl BindingList { id } - fn check_is_used(&mut self, ec: &mut ExprCollector<'_>, id: BindingId) { + fn check_is_used(&mut self, ec: &mut ExprCollector<'_, '_>, id: BindingId) { match self.is_used.get(&id) { None => { if self.reject_new { @@ -674,13 +648,32 @@ impl NamedLifetimeStore { } } -impl<'db> ExprCollector<'db> { +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum ArgumentElisionContext { + Self_, + Param, +} + +#[derive(Debug)] +pub enum LifetimeElisionKind { + NewLifetimeParam { + bound_type: LifetimeBoundType, + parent: Option, + return_lt: Option<(Either, ArgumentElisionContext)>, + total_created: u32, + }, + Lifetime(Option>), + Static, + Error, +} + +impl<'db, 'a> ExprCollector<'db, 'a> { pub fn new( - db: &dyn SourceDatabase, + db: &'db dyn SourceDatabase, module: ModuleId, current_file_id: HirFileId, lowering_mode: LoweringMode, - ) -> ExprCollector<'_> { + ) -> ExprCollector<'db, 'a> { let (def_map, local_def_map) = module.local_def_map(db); let expander = Expander::new(db, current_file_id, def_map); let krate = module.krate(db); @@ -705,7 +698,9 @@ impl<'db> ExprCollector<'db> { name_generator_index: 0, named_lifetime_store: NamedLifetimeStore::default(), for_type_binder: None, - elision_context: None, + lifetime_arena: None, + lifetime_elision_kind: LifetimeElisionKind::Error, + argument_elision_context: None, elision_binder_source: ElisionBinderSource::Parent, }; result.store.inference_roots = Some(SmallVec::new()); @@ -718,6 +713,79 @@ impl<'db> ExprCollector<'db> { Name::generate_new_name(index) } + fn elide_static_lifetime(mut self) -> Self { + self.lifetime_elision_kind = LifetimeElisionKind::Static; + self + } + + fn elide_lifetime_for_binder(&mut self) -> LifetimeElisionKind { + mem::replace( + &mut self.lifetime_elision_kind, + LifetimeElisionKind::NewLifetimeParam { + bound_type: LifetimeBoundType::LateBound, + parent: None, + return_lt: None, + total_created: 0, + }, + ) + } + + fn elide_create_lifetime( + &mut self, + lifetimes: &'a mut Arena, + parent: GenericDefId, + bound_type: LifetimeBoundType, + ) { + self.lifetime_arena = Some(lifetimes); + self.lifetime_elision_kind = LifetimeElisionKind::NewLifetimeParam { + bound_type, + parent: Some(parent), + return_lt: None, + total_created: 0, + }; + } + + fn elide_return_lifetime(&mut self) { + let old_elision_kind = + mem::replace(&mut self.lifetime_elision_kind, LifetimeElisionKind::Error); + + let new_elision_kind = + if let LifetimeElisionKind::NewLifetimeParam { return_lt, total_created, .. } = + old_elision_kind + { + let lifetime_param_id = + return_lt.and_then(|(lifetime_param_id, elided_source)| match elided_source { + ArgumentElisionContext::Self_ => Some(lifetime_param_id), + ArgumentElisionContext::Param if total_created == 1 => { + Some(lifetime_param_id) + } + ArgumentElisionContext::Param => None, + }); + LifetimeElisionKind::Lifetime(lifetime_param_id) + } else { + unreachable!("Method should not be called with other lifetime_elision_kind") + }; + self.lifetime_elision_kind = new_elision_kind; + } + + pub(crate) fn update_to_late_bound_lifetimes(&mut self) { + let lifetimes = self.lifetime_arena.as_mut().unwrap(); // Should never call with None + for (_param_id, lifetime) in lifetimes.iter_mut() { + let lifetime_name = &lifetime.name; + if self.named_lifetime_store.lifetimes_in_where_clause.contains(lifetime_name) { + continue; + } + + if !self.named_lifetime_store.lifetimes_constrained_by_input.contains(lifetime_name) + && self.named_lifetime_store.lifetimes_in_output.contains(lifetime_name) + { + continue; + } + + lifetime.bound_type = LifetimeBoundType::LateBound + } + } + #[inline] pub(crate) fn lang_items(&self) -> &'db LangItems { self.lang_items.get_or_init(|| crate::lang_item::lang_items(self.db, self.def_map.krate())) @@ -731,14 +799,12 @@ impl<'db> ExprCollector<'db> { pub(in crate::expr_store) fn lower_lifetime_ref( &mut self, lifetime: ast::Lifetime, - lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> LifetimeRefId { // FIXME: Keyword check? let lifetime_ref = match lifetime.text() { "" | "'" => LifetimeRef::Error, "'static" => LifetimeRef::Static, - "'_" if self.elision_context.is_some() => return lifetime_elision_fn(self), - "'_" => LifetimeRef::Placeholder, + "'_" => return self.lower_elided_lifetime(), text => LifetimeRef::Named(Name::new_lifetime(text)), }; self.alloc_lifetime_ref(lifetime_ref, AstPtr::new(&lifetime)) @@ -747,10 +813,9 @@ impl<'db> ExprCollector<'db> { pub(in crate::expr_store) fn lower_lifetime_ref_opt( &mut self, lifetime: Option, - lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> LifetimeRefId { match lifetime { - Some(lifetime) => self.lower_lifetime_ref(lifetime, lifetime_elision_fn), + Some(lifetime) => self.lower_lifetime_ref(lifetime), None => self.alloc_lifetime_ref_desugared(LifetimeRef::Placeholder), } } @@ -760,56 +825,41 @@ impl<'db> ExprCollector<'db> { &mut self, node: ast::Type, impl_trait_lower_fn: ImplTraitLowerFn<'_>, - lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> TypeRefId { let ty = match &node { ast::Type::ParenType(inner) => { - return self.lower_type_ref_opt( - inner.ty(), - impl_trait_lower_fn, - lifetime_elision_fn, - ); + return self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn); } ast::Type::TupleType(inner) => TypeRef::Tuple(ThinVec::from_iter(Vec::from_iter( - inner - .fields() - .map(|it| self.lower_type_ref(it, impl_trait_lower_fn, lifetime_elision_fn)), + inner.fields().map(|it| self.lower_type_ref(it, impl_trait_lower_fn)), ))), ast::Type::NeverType(..) => TypeRef::Never, ast::Type::PathType(inner) => inner .path() - .and_then(|it| self.lower_path(it, impl_trait_lower_fn, lifetime_elision_fn)) + .and_then(|it| self.lower_path(it, impl_trait_lower_fn)) .map(TypeRef::Path) .unwrap_or(TypeRef::Error), ast::Type::PtrType(inner) => { - let inner_ty = - self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn, lifetime_elision_fn); + let inner_ty = self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn); let mutability = Mutability::from_mutable(inner.mut_token().is_some()); TypeRef::RawPtr(inner_ty, mutability) } ast::Type::ArrayType(inner) => { let len = self.lower_const_arg_opt(inner.const_arg()); TypeRef::Array(ArrayType { - ty: self.lower_type_ref_opt( - inner.ty(), - impl_trait_lower_fn, - lifetime_elision_fn, - ), + ty: self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn), len, }) } - ast::Type::SliceType(inner) => TypeRef::Slice(self.lower_type_ref_opt( - inner.ty(), - impl_trait_lower_fn, - lifetime_elision_fn, - )), + ast::Type::SliceType(inner) => { + TypeRef::Slice(self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn)) + } ast::Type::RefType(inner) => { - let inner_ty = - self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn, lifetime_elision_fn); + let inner_ty = self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn); let lifetime = if let Some(lt) = inner.lifetime() { - Some(self.lower_lifetime_ref(lt, lifetime_elision_fn)) + Some(self.lower_lifetime_ref(lt)) } else { - Some(lifetime_elision_fn(self)) + Some(self.lower_elided_lifetime()) }; let mutability = Mutability::from_mutable(inner.mut_token().is_some()); TypeRef::Reference(Box::new(RefType { ty: inner_ty, lifetime, mutability })) @@ -825,20 +875,8 @@ impl<'db> ExprCollector<'db> { let old_elision_binder_source = mem::replace(&mut self.elision_binder_source, ElisionBinderSource::ForBinder); - let mut for_binder_elision_fn = - |ec: &mut ExprCollector<'_>| ec.lower_elided_lifetime_for_binder(); + let old_elision_kind = self.elide_lifetime_for_binder(); - let ret_ty = inner - .ret_type() - .and_then(|rt| rt.ty()) - .map(|it| { - self.lower_type_ref( - it, - impl_trait_lower_fn, - &mut Self::elided_lifetime_placeholder_allocator, - ) - }) - .unwrap_or_else(|| self.alloc_type_ref_desugared(TypeRef::unit())); let mut is_varargs = false; let mut params = if let Some(pl) = inner.param_list() { if let Some(param) = pl.params().last() { @@ -848,11 +886,9 @@ impl<'db> ExprCollector<'db> { pl.params() .filter(|it| it.dotdotdot_token().is_none()) .map(|it| { - let type_ref = self.lower_type_ref_opt( - it.ty(), - impl_trait_lower_fn, - &mut for_binder_elision_fn, - ); + let type_ref = self.with_param_lt_elision(|this| { + this.lower_type_ref_opt(it.ty(), impl_trait_lower_fn) + }); let name = match it.pat() { Some(ast::Pat::IdentPat(it)) => Some( it.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing), @@ -865,6 +901,14 @@ impl<'db> ExprCollector<'db> { } else { Vec::with_capacity(1) }; + self.elide_return_lifetime(); + let ret_ty = inner + .ret_type() + .and_then(|rt| rt.ty()) + .map(|it| self.lower_type_ref(it, impl_trait_lower_fn)) + .unwrap_or_else(|| self.alloc_type_ref_desugared(TypeRef::unit())); + params.push((None, ret_ty)); + fn lower_abi(abi: ast::Abi) -> ExternAbi { abi.abi_string() .and_then(|abi| abi.text_without_quotes().parse().ok()) @@ -872,7 +916,6 @@ impl<'db> ExprCollector<'db> { } let abi = inner.abi().map(lower_abi).unwrap_or(ExternAbi::Rust); - params.push((None, ret_ty)); let binder = self .for_type_binder @@ -882,6 +925,7 @@ impl<'db> ExprCollector<'db> { self.for_type_binder = old_binder; self.elision_binder_source = old_elision_binder_source; + self.lifetime_elision_kind = old_elision_kind; TypeRef::Fn(Box::new(FnType { is_varargs, is_unsafe: inner.unsafe_token().is_some(), @@ -894,7 +938,7 @@ impl<'db> ExprCollector<'db> { ast::Type::ForType(inner) => { let binder = self.lower_for_binder_opt(inner.for_binder()); let ty = self.with_for_binder(binder, ForBinderSource::ForType, |ec| { - ec.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn, lifetime_elision_fn) + ec.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn) }); return ty; } @@ -903,7 +947,7 @@ impl<'db> ExprCollector<'db> { // Disallow nested impl traits TypeRef::Error } else { - let old_elision_context = self.elision_context.take(); + let old_elision_context = self.argument_elision_context.take(); let result = self.with_outer_impl_trait_scope(true, |this| { let is_argument_scope = this.is_argument_lt_bound_scope(); let type_bounds = this.with_lifetime_bound_scope( @@ -912,23 +956,20 @@ impl<'db> ExprCollector<'db> { this.type_bounds_from_ast( inner.type_bound_list(), impl_trait_lower_fn, - lifetime_elision_fn, ) }, ); impl_trait_lower_fn(this, AstPtr::new(&node), type_bounds) }); - self.elision_context = old_elision_context; + self.argument_elision_context = old_elision_context; return result; } } - ast::Type::DynTraitType(inner) => TypeRef::DynTrait(self.type_bounds_from_ast( - inner.type_bound_list(), - impl_trait_lower_fn, - lifetime_elision_fn, - )), + ast::Type::DynTraitType(inner) => TypeRef::DynTrait( + self.type_bounds_from_ast(inner.type_bound_list(), impl_trait_lower_fn), + ), ast::Type::PatternType(inner) => TypeRef::PatternType( - self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn, lifetime_elision_fn), + self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn), self.collect_ty_pat_opt(inner.pat()), ), ast::Type::MacroType(mt) => match mt.macro_call() { @@ -936,7 +977,7 @@ impl<'db> ExprCollector<'db> { let macro_ptr = AstPtr::new(&mcall); let src = self.expander.in_file(AstPtr::new(&node)); let id = self.collect_macro_call(mcall, macro_ptr, true, |this, expansion| { - this.lower_type_ref_opt(expansion, impl_trait_lower_fn, lifetime_elision_fn) + this.lower_type_ref_opt(expansion, impl_trait_lower_fn) }); self.store.types_map.insert(src, id); return id; @@ -947,22 +988,17 @@ impl<'db> ExprCollector<'db> { self.alloc_type_ref(ty, AstPtr::new(&node)) } - pub(crate) fn lower_type_ref_disallow_impl_trait( - &mut self, - node: ast::Type, - lifetime_elision_fn: LifetimeElisionFn<'_>, - ) -> TypeRefId { - self.lower_type_ref(node, &mut Self::impl_trait_error_allocator, lifetime_elision_fn) + pub(crate) fn lower_type_ref_disallow_impl_trait(&mut self, node: ast::Type) -> TypeRefId { + self.lower_type_ref(node, &mut Self::impl_trait_error_allocator) } pub(crate) fn lower_type_ref_opt( &mut self, node: Option, impl_trait_lower_fn: ImplTraitLowerFn<'_>, - lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> TypeRefId { match node { - Some(node) => self.lower_type_ref(node, impl_trait_lower_fn, lifetime_elision_fn), + Some(node) => self.lower_type_ref(node, impl_trait_lower_fn), None => self.alloc_error_type(), } } @@ -970,9 +1006,8 @@ impl<'db> ExprCollector<'db> { pub(crate) fn lower_type_ref_opt_disallow_impl_trait( &mut self, node: Option, - lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> TypeRefId { - self.lower_type_ref_opt(node, &mut Self::impl_trait_error_allocator, lifetime_elision_fn) + self.lower_type_ref_opt(node, &mut Self::impl_trait_error_allocator) } fn alloc_type_ref(&mut self, type_ref: TypeRef, node: TypePtr) -> TypeRefId { @@ -1022,9 +1057,8 @@ impl<'db> ExprCollector<'db> { &mut self, ast: ast::Path, impl_trait_lower_fn: ImplTraitLowerFn<'_>, - lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> Option { - super::lower::path::lower_path(self, ast, impl_trait_lower_fn, lifetime_elision_fn) + super::lower::path::lower_path(self, ast, impl_trait_lower_fn) } fn with_outer_impl_trait_scope( @@ -1050,21 +1084,21 @@ impl<'db> ExprCollector<'db> { } fn with_self_lt_elision(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { - self.with_elision_context(ElidedSource::Self_, f) + self.with_elision_context(ArgumentElisionContext::Self_, f) } fn with_param_lt_elision(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { - self.with_elision_context(ElidedSource::Param, f) + self.with_elision_context(ArgumentElisionContext::Param, f) } fn with_elision_context( &mut self, - elision_context: ElidedSource, + elision_context: ArgumentElisionContext, f: impl FnOnce(&mut Self) -> R, ) -> R { - let old = self.elision_context.replace(elision_context); + let old = self.argument_elision_context.replace(elision_context); let result = f(self); - self.elision_context = old; + self.argument_elision_context = old; result } @@ -1083,28 +1117,51 @@ impl<'db> ExprCollector<'db> { result } - fn lower_elided_lifetime_for_binder(&mut self) -> LifetimeRefId { - let name = Name::anon_lifetime(); - let local_id = self.push_elided_lifetime_in_for_binder(name); - let param_id = HrtbLifetimeParamId(local_id as u32); - let lifetime_ref = LifetimeRef::HrtbParam(param_id); - self.alloc_lifetime_ref_desugared(lifetime_ref) - } + fn lower_elided_lifetime(&mut self) -> LifetimeRefId { + let mut lifetime_param_id = None; + let lifetime_ref = match &self.lifetime_elision_kind { + &LifetimeElisionKind::NewLifetimeParam { bound_type, parent, .. } => { + let name = Name::anon_lifetime(); + if matches!(self.elision_binder_source, ElisionBinderSource::ForBinder) { + let local_id = self.push_elided_lifetime_in_for_binder(name); + let param_id = HrtbLifetimeParamId(local_id as u32); + lifetime_param_id = Some(Either::Left(param_id)); - pub fn elided_lifetime_error_allocator(ec: &mut ExprCollector<'_>) -> LifetimeRefId { - ec.alloc_lifetime_ref_desugared(LifetimeRef::Error) - } + LifetimeRef::HrtbParam(param_id) + } else { + let lifetimes = self.lifetime_arena.as_mut().unwrap(); + let parent = parent.unwrap(); + let lifetime = LifetimeParamData { name, bound_type }; + let param_id = LifetimeParamId { parent, local_id: lifetimes.alloc(lifetime) }; + lifetime_param_id = Some(Either::Right(param_id)); - pub fn elided_lifetime_placeholder_allocator(ec: &mut ExprCollector<'_>) -> LifetimeRefId { - ec.alloc_lifetime_ref_desugared(LifetimeRef::Placeholder) - } + LifetimeRef::Param(param_id) + } + } + &LifetimeElisionKind::Lifetime(Some(lifetime_param_id)) => match lifetime_param_id { + Either::Left(hrtb_param_id) => LifetimeRef::HrtbParam(hrtb_param_id), + Either::Right(lifetime_param_id) => LifetimeRef::Param(lifetime_param_id), + }, + LifetimeElisionKind::Static => LifetimeRef::Static, + LifetimeElisionKind::Error | LifetimeElisionKind::Lifetime(None) => LifetimeRef::Error, + }; - pub fn elided_lifetime_static_allocator(ec: &mut ExprCollector<'_>) -> LifetimeRefId { - ec.alloc_lifetime_ref_desugared(LifetimeRef::Static) + if let Some(lifetime_param_id) = lifetime_param_id + && let Some(elided_source) = &self.argument_elision_context + && let LifetimeElisionKind::NewLifetimeParam { return_lt, total_created, .. } = + &mut self.lifetime_elision_kind + { + *total_created += 1; + if return_lt.is_none() { + *return_lt = Some((lifetime_param_id, elided_source.clone())); + } + } + + self.alloc_lifetime_ref_desugared(lifetime_ref) } pub fn impl_trait_error_allocator( - ec: &mut ExprCollector<'_>, + ec: &mut ExprCollector<'_, '_>, ptr: TypePtr, _: ThinVec, ) -> TypeRefId { @@ -1112,7 +1169,7 @@ impl<'db> ExprCollector<'db> { } fn impl_trait_allocator( - ec: &mut ExprCollector<'_>, + ec: &mut ExprCollector<'_, '_>, ptr: TypePtr, bounds: ThinVec, ) -> TypeRefId { @@ -1130,21 +1187,18 @@ impl<'db> ExprCollector<'db> { args: Option, ret_type: Option, impl_trait_lower_fn: ImplTraitLowerFn<'_>, - lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> Option { let params = args?; let mut param_types = Vec::new(); for param in params.type_args() { - let type_ref = - self.lower_type_ref_opt(param.ty(), impl_trait_lower_fn, lifetime_elision_fn); + let type_ref = self.lower_type_ref_opt(param.ty(), impl_trait_lower_fn); param_types.push(type_ref); } let args = Box::new([GenericArg::Type( self.alloc_type_ref_desugared(TypeRef::Tuple(ThinVec::from_iter(param_types))), )]); let bindings = if let Some(ret_type) = ret_type { - let type_ref = - self.lower_type_ref_opt(ret_type.ty(), impl_trait_lower_fn, lifetime_elision_fn); + let type_ref = self.lower_type_ref_opt(ret_type.ty(), impl_trait_lower_fn); Box::new([AssociatedTypeBinding { name: Name::new_symbol_root(sym::Output), args: None, @@ -1173,7 +1227,6 @@ impl<'db> ExprCollector<'db> { &mut self, node: ast::GenericArgList, impl_trait_lower_fn: ImplTraitLowerFn<'_>, - lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> Option { // This needs to be kept in sync with `hir_generic_arg_to_ast()`. let mut args = Vec::new(); @@ -1181,11 +1234,7 @@ impl<'db> ExprCollector<'db> { for generic_arg in node.generic_args() { match generic_arg { ast::GenericArg::TypeArg(type_arg) => { - let type_ref = self.lower_type_ref_opt( - type_arg.ty(), - impl_trait_lower_fn, - lifetime_elision_fn, - ); + let type_ref = self.lower_type_ref_opt(type_arg.ty(), impl_trait_lower_fn); args.push(GenericArg::Type(type_ref)); } ast::GenericArg::AssocTypeArg(assoc_type_arg) => { @@ -1200,30 +1249,18 @@ impl<'db> ExprCollector<'db> { let name = name_ref.as_name(); let args = assoc_type_arg .generic_arg_list() - .and_then(|args| { - this.lower_generic_args( - args, - impl_trait_lower_fn, - lifetime_elision_fn, - ) - }) + .and_then(|args| this.lower_generic_args(args, impl_trait_lower_fn)) .or_else(|| { assoc_type_arg .return_type_syntax() .map(|_| GenericArgs::return_type_notation()) }); - let type_ref = assoc_type_arg.ty().map(|it| { - this.lower_type_ref(it, impl_trait_lower_fn, lifetime_elision_fn) - }); + let type_ref = assoc_type_arg + .ty() + .map(|it| this.lower_type_ref(it, impl_trait_lower_fn)); let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { l.bounds() - .map(|it| { - this.lower_type_bound( - it, - impl_trait_lower_fn, - lifetime_elision_fn, - ) - }) + .map(|it| this.lower_type_bound(it, impl_trait_lower_fn)) .collect() } else { Box::default() @@ -1234,7 +1271,7 @@ impl<'db> ExprCollector<'db> { } ast::GenericArg::LifetimeArg(lifetime_arg) => { if let Some(lifetime) = lifetime_arg.lifetime() { - let lifetime_ref = self.lower_lifetime_ref(lifetime, lifetime_elision_fn); + let lifetime_ref = self.lower_lifetime_ref(lifetime); args.push(GenericArg::Lifetime(lifetime_ref)) } } @@ -1475,13 +1512,10 @@ impl<'db> ExprCollector<'db> { &mut self, type_bounds_opt: Option, impl_trait_lower_fn: ImplTraitLowerFn<'_>, - lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> ThinVec { if let Some(type_bounds) = type_bounds_opt { ThinVec::from_iter(Vec::from_iter( - type_bounds - .bounds() - .map(|it| self.lower_type_bound(it, impl_trait_lower_fn, lifetime_elision_fn)), + type_bounds.bounds().map(|it| self.lower_type_bound(it, impl_trait_lower_fn)), )) } else { ThinVec::from_iter([]) @@ -1492,9 +1526,8 @@ impl<'db> ExprCollector<'db> { &mut self, path_type: &ast::PathType, impl_trait_lower_fn: ImplTraitLowerFn<'_>, - lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> Option { - let path = self.lower_path(path_type.path()?, impl_trait_lower_fn, lifetime_elision_fn)?; + let path = self.lower_path(path_type.path()?, impl_trait_lower_fn)?; Some(path) } @@ -1502,7 +1535,6 @@ impl<'db> ExprCollector<'db> { &mut self, node: ast::TypeBound, impl_trait_lower_fn: ImplTraitLowerFn<'_>, - lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> TypeBound { let Some(kind) = node.kind() else { return TypeBound::Error }; match kind { @@ -1513,7 +1545,7 @@ impl<'db> ExprCollector<'db> { None => TraitBoundModifier::None, }; self.with_for_binder(Some(binder), ForBinderSource::ForBound, |ec| { - ec.lower_path_type(&path_type, impl_trait_lower_fn, lifetime_elision_fn) + ec.lower_path_type(&path_type, impl_trait_lower_fn) .map(|p| { let path = ec.alloc_path(p, AstPtr::new(&path_type).upcast()); let binder = ec.for_type_binder.take(); @@ -1532,14 +1564,14 @@ impl<'db> ExprCollector<'db> { gal.use_bound_generic_args() .map(|p| match p { ast::UseBoundGenericArg::Lifetime(l) => { - UseArgRef::Lifetime(self.lower_lifetime_ref(l, lifetime_elision_fn)) + UseArgRef::Lifetime(self.lower_lifetime_ref(l)) } ast::UseBoundGenericArg::NameRef(n) => UseArgRef::Name(n.as_name()), }) .collect(), ), ast::TypeBoundKind::Lifetime(lifetime) => { - TypeBound::Lifetime(self.lower_lifetime_ref(lifetime, lifetime_elision_fn)) + TypeBound::Lifetime(self.lower_lifetime_ref(lifetime)) } } } @@ -1736,7 +1768,7 @@ impl<'db> ExprCollector<'db> { let generic_args = e .generic_arg_list() .and_then(|it| { - self.lower_generic_args(it, &mut Self::impl_trait_error_allocator, &mut Self::elided_lifetime_error_allocator) + self.lower_generic_args(it, &mut Self::impl_trait_error_allocator) }) .map(Box::new); self.alloc_expr( @@ -1822,7 +1854,7 @@ impl<'db> ExprCollector<'db> { ast::Expr::RecordExpr(e) => { let path = e .path() - .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator, &mut Self::elided_lifetime_placeholder_allocator)); + .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); let Some(path) = path else { return Some(self.missing_expr()); }; @@ -1880,7 +1912,7 @@ impl<'db> ExprCollector<'db> { ast::Expr::TryExpr(e) => self.collect_try_operator(syntax_ptr, e), ast::Expr::CastExpr(e) => { let expr = self.collect_expr_opt(e.expr()); - let type_ref = self.lower_type_ref_opt_disallow_impl_trait(e.ty(), &mut Self::elided_lifetime_placeholder_allocator); + let type_ref = self.lower_type_ref_opt_disallow_impl_trait(e.ty()); self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) } ast::Expr::RefExpr(e) => { @@ -1908,6 +1940,7 @@ impl<'db> ExprCollector<'db> { let mut arg_types = Vec::new(); // For coroutine closures, the body, aka. the coroutine is the bindings owner, and not the closure. if let Some(pl) = e.param_list() { + // Should we elide in closure? let num_params = pl.params().count(); args.reserve_exact(num_params); arg_types.reserve_exact(num_params); @@ -1919,7 +1952,7 @@ impl<'db> ExprCollector<'db> { let pat = this.collect_pat_top(param.pat()); let type_ref = // FIXME: should closures elide if so how? - param.ty().map(|it| this.lower_type_ref_disallow_impl_trait(it, &mut Self::elided_lifetime_placeholder_allocator)); + param.ty().map(|it| this.lower_type_ref_disallow_impl_trait(it)); args.push(pat); arg_types.push(type_ref); } @@ -1927,7 +1960,7 @@ impl<'db> ExprCollector<'db> { let ret_type = e .ret_type() .and_then(|r| r.ty()) - .map(|it| this.lower_type_ref_disallow_impl_trait(it, &mut Self::elided_lifetime_placeholder_allocator)); + .map(|it| this.lower_type_ref_disallow_impl_trait(it)); let prev_is_lowering_coroutine = mem::take(&mut this.is_lowering_coroutine); let prev_try_block = this.current_try_block.take(); @@ -2097,7 +2130,7 @@ impl<'db> ExprCollector<'db> { ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr), ast::Expr::AsmExpr(e) => self.lower_inline_asm(e, syntax_ptr), ast::Expr::OffsetOfExpr(e) => { - let container = self.lower_type_ref_opt_disallow_impl_trait(e.ty(), &mut Self::elided_lifetime_placeholder_allocator); + let container = self.lower_type_ref_opt_disallow_impl_trait(e.ty()); let fields = e.fields().map(|it| it.as_name()).collect(); self.alloc_expr(Expr::OffsetOf(OffsetOf { container, fields }), syntax_ptr) } @@ -2108,11 +2141,7 @@ impl<'db> ExprCollector<'db> { fn collect_expr_path(&mut self, e: ast::PathExpr) -> Option<(Path, HygieneId)> { e.path().and_then(|path| { - let path = self.lower_path( - path, - &mut Self::impl_trait_error_allocator, - &mut Self::elided_lifetime_placeholder_allocator, - )?; + let path = self.lower_path(path, &mut Self::impl_trait_error_allocator)?; // Need to enable `mod_path.len() < 1` for `self`. let may_be_variable = matches!(&path, Path::BarePath(mod_path) if mod_path.len() <= 1); let hygiene = if may_be_variable { @@ -2220,13 +2249,9 @@ impl<'db> ExprCollector<'db> { } ast::Expr::CallExpr(e) => { let path = collect_path(self, e.expr()?)?; - let path = path.path().and_then(|path| { - self.lower_path( - path, - &mut Self::impl_trait_error_allocator, - &mut Self::elided_lifetime_placeholder_allocator, - ) - }); + let path = path + .path() + .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); let Some(path) = path else { return Some(self.missing_pat()); }; @@ -2257,13 +2282,9 @@ impl<'db> ExprCollector<'db> { id } ast::Expr::RecordExpr(e) => { - let path = e.path().and_then(|path| { - self.lower_path( - path, - &mut Self::impl_trait_error_allocator, - &mut Self::elided_lifetime_placeholder_allocator, - ) - }); + let path = e + .path() + .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); let Some(path) = path else { return Some(self.missing_pat()); }; @@ -2296,7 +2317,10 @@ impl<'db> ExprCollector<'db> { }; return Some(result); - fn collect_path(this: &mut ExprCollector<'_>, expr: ast::Expr) -> Option { + fn collect_path( + this: &mut ExprCollector<'_, '_>, + expr: ast::Expr, + ) -> Option { match expr { ast::Expr::PathExpr(e) => Some(e), ast::Expr::MacroExpr(mac) => { @@ -2313,7 +2337,7 @@ impl<'db> ExprCollector<'db> { } fn collect_possibly_rest( - this: &mut ExprCollector<'_>, + this: &mut ExprCollector<'_, '_>, expr: ast::Expr, ) -> Either { match &expr { @@ -2346,7 +2370,7 @@ impl<'db> ExprCollector<'db> { } fn collect_tuple( - this: &mut ExprCollector<'_>, + this: &mut ExprCollector<'_, '_>, fields: ast::AstChildren, ) -> (Option, Box<[la_arena::Idx]>) { let mut ellipsis = None; @@ -2443,10 +2467,7 @@ impl<'db> ExprCollector<'db> { Some(ty) => { // `{ let : = ; }` let name = self.generate_new_name(); - let type_ref = self.lower_type_ref_disallow_impl_trait( - ty, - &mut Self::elided_lifetime_placeholder_allocator, - ); + let type_ref = self.lower_type_ref_disallow_impl_trait(ty); let binding = self.alloc_binding( name.clone(), BindingAnnotation::Unannotated, @@ -2825,12 +2846,7 @@ impl<'db> ExprCollector<'db> { return; } let pat = self.collect_pat_top(stmt.pat()); - let type_ref = stmt.ty().map(|it| { - self.lower_type_ref_disallow_impl_trait( - it, - &mut Self::elided_lifetime_placeholder_allocator, - ) - }); + let type_ref = stmt.ty().map(|it| self.lower_type_ref_disallow_impl_trait(it)); let initializer = stmt.initializer().map(|e| self.collect_expr(e)); let else_branch = stmt .let_else() @@ -3067,13 +3083,9 @@ impl<'db> ExprCollector<'db> { return pat; } ast::Pat::TupleStructPat(p) => { - let path = p.path().and_then(|path| { - self.lower_path( - path, - &mut Self::impl_trait_error_allocator, - &mut Self::elided_lifetime_error_allocator, - ) - }); + let path = p + .path() + .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); let Some(path) = path else { return self.missing_pat(); }; @@ -3090,13 +3102,9 @@ impl<'db> ExprCollector<'db> { Pat::Ref { pat, mutability } } ast::Pat::PathPat(p) => { - let path = p.path().and_then(|path| { - self.lower_path( - path, - &mut Self::impl_trait_error_allocator, - &mut Self::elided_lifetime_error_allocator, - ) - }); + let path = p + .path() + .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); path.map(Pat::Path).unwrap_or(Pat::Missing) } ast::Pat::OrPat(p) => 'b: { @@ -3143,13 +3151,9 @@ impl<'db> ExprCollector<'db> { } ast::Pat::WildcardPat(_) => Pat::Wild, ast::Pat::RecordPat(p) => { - let path = p.path().and_then(|path| { - self.lower_path( - path, - &mut Self::impl_trait_error_allocator, - &mut Self::elided_lifetime_error_allocator, - ) - }); + let path = p + .path() + .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); let Some(path) = path else { return self.missing_pat(); }; @@ -3242,11 +3246,7 @@ impl<'db> ExprCollector<'db> { ast::Pat::PathPat(p) => p .path() .and_then(|path| { - self.lower_path( - path, - &mut Self::impl_trait_error_allocator, - &mut Self::elided_lifetime_error_allocator, - ) + self.lower_path(path, &mut Self::impl_trait_error_allocator) }) .map(|parsed| self.alloc_expr_from_pat(Expr::Path(parsed), ptr)), // We only need to handle literal, ident (if bare) and path patterns here, @@ -3400,13 +3400,9 @@ impl<'db> ExprCollector<'db> { } } ast::Pat::PathPat(it) => { - let path = it.path().and_then(|path| { - self.lower_path( - path, - &mut Self::impl_trait_error_allocator, - &mut Self::elided_lifetime_error_allocator, - ) - }); + let path = it + .path() + .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator)); self.alloc_expr_from_pat(path.map(Expr::Path).unwrap_or(Expr::Missing), ptr) } ast::Pat::IdentPat(it) if it.is_simple_ident() => { @@ -3629,7 +3625,7 @@ fn pat_literal_to_hir(lit: &ast::LiteralPat) -> Option<(Literal, ast::Literal)> Some((hir_lit, ast_lit)) } -impl<'db> ExprCollector<'db> { +impl<'db, 'a> ExprCollector<'db, 'a> { fn with_fresh_binding_expr_root(&mut self, f: impl FnOnce(&mut Self) -> ExprId) -> ExprId { self.with_expr_root(|this| this.with_binding_owner(f)) } @@ -3784,11 +3780,11 @@ impl<'db> ExprCollector<'db> { matches!(self.named_lifetime_store.lifetime_bound_scope, Some(LifetimeBoundScope::Argument)) } - fn get_constrained_lifetimes_if_type_alias<'a>( + fn get_constrained_lifetimes_if_type_alias<'g>( &mut self, module_def_id: Option, - generic_args: Option<&'a GenericArgs>, - ) -> Option + use<'a, 'db>> { + generic_args: Option<&'g GenericArgs>, + ) -> Option + use<'g, 'db>> { let generic_args = generic_args?; let ModuleDefId::TypeAliasId(id) = module_def_id? else { return None }; @@ -3863,7 +3859,6 @@ impl<'db> ExprCollector<'db> { &mut self, module_def_id: Option, args: Option<&GenericArgs>, - lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> Option { let num_lifetime_args = args .as_ref() @@ -3882,7 +3877,7 @@ impl<'db> ExprCollector<'db> { // lifetime args does not exist in source // call elided function for all lifetime params for _ in 0..num_lifetime_params { - let lt_id = lifetime_elision_fn(self); + let lt_id = self.lower_elided_lifetime(); elided_args.push(GenericArg::Lifetime(lt_id)); } } diff --git a/crates/hir-def/src/expr_store/lower/asm.rs b/crates/hir-def/src/expr_store/lower/asm.rs index b80b52e6f416..b4813cbf5192 100644 --- a/crates/hir-def/src/expr_store/lower/asm.rs +++ b/crates/hir-def/src/expr_store/lower/asm.rs @@ -13,7 +13,7 @@ use crate::{ hir::{AsmOperand, AsmOptions, Expr, ExprId, InlineAsm, InlineAsmKind, InlineAsmRegOrRegClass}, }; -impl ExprCollector<'_> { +impl ExprCollector<'_, '_> { pub(super) fn lower_inline_asm( &mut self, asm: ast::AsmExpr, @@ -166,7 +166,6 @@ impl ExprCollector<'_> { self.lower_path( p, &mut ExprCollector::impl_trait_error_allocator, - &mut ExprCollector::elided_lifetime_error_allocator, ) }) else { continue; diff --git a/crates/hir-def/src/expr_store/lower/format_args.rs b/crates/hir-def/src/expr_store/lower/format_args.rs index ad548c6758c1..0c7d33628cdd 100644 --- a/crates/hir-def/src/expr_store/lower/format_args.rs +++ b/crates/hir-def/src/expr_store/lower/format_args.rs @@ -22,7 +22,7 @@ use crate::{ type_ref::{Mutability, Rawness}, }; -impl<'db> ExprCollector<'db> { +impl<'db> ExprCollector<'db, '_> { pub(super) fn collect_format_args( &mut self, f: ast::FormatArgsExpr, diff --git a/crates/hir-def/src/expr_store/lower/generics.rs b/crates/hir-def/src/expr_store/lower/generics.rs index 06b6632fe290..5bff54610f22 100644 --- a/crates/hir-def/src/expr_store/lower/generics.rs +++ b/crates/hir-def/src/expr_store/lower/generics.rs @@ -11,10 +11,10 @@ use syntax::ast::{self, HasName, HasTypeBounds}; use thin_vec::ThinVec; use crate::{ - GenericDefId, LifetimeParamId, TypeOrConstParamId, TypeParamId, + GenericDefId, TypeOrConstParamId, TypeParamId, expr_store::{ TypePtr, - lower::{ExprCollector, LifetimeBoundScope, NamedLifetimeStore}, + lower::{ExprCollector, LifetimeBoundScope}, }, hir::generics::{ ConstParamData, GenericParams, LifetimeBoundType, LifetimeParamData, TypeOrConstParamData, @@ -23,15 +23,12 @@ use crate::{ type_ref::{LifetimeRef, LifetimeRefId, TypeBound, TypeRef, TypeRefId}, }; -pub(crate) type ImplTraitLowerFn<'l> = &'l mut dyn for<'ec, 'db> FnMut( - &'ec mut ExprCollector<'db>, +pub(crate) type ImplTraitLowerFn<'l> = &'l mut dyn for<'ec, 'db, 'a> FnMut( + &'ec mut ExprCollector<'db, 'a>, TypePtr, ThinVec, ) -> TypeRefId; -pub(crate) type LifetimeElisionFn<'l> = - &'l mut dyn for<'ec, 'db> FnMut(&'ec mut ExprCollector<'db>) -> LifetimeRefId; - pub(crate) struct GenericParamsCollector { type_or_consts: Arena, lifetimes: Arena, @@ -49,7 +46,7 @@ impl GenericParamsCollector { } } pub(crate) fn with_self_param( - ec: &mut ExprCollector<'_>, + ec: &mut ExprCollector<'_, '_>, parent: GenericDefId, bounds: Option, ) -> Self { @@ -60,7 +57,7 @@ impl GenericParamsCollector { pub(crate) fn lower( &mut self, - ec: &mut ExprCollector<'_>, + ec: &mut ExprCollector<'_, '_>, generic_param_list: Option, where_clause: Option, ) { @@ -72,11 +69,12 @@ impl GenericParamsCollector { } } - pub(crate) fn collect_impl_trait( - &mut self, - ec: &mut ExprCollector<'_>, - cb: impl FnOnce(&mut ExprCollector<'_>, ImplTraitLowerFn<'_>, LifetimeElisionFn<'_>) -> R, + pub(crate) fn collect_impl_trait<'a, R>( + &'a mut self, + ec: &mut ExprCollector<'_, 'a>, + cb: impl FnOnce(&mut ExprCollector<'_, '_>, ImplTraitLowerFn<'_>) -> R, ) -> R { + ec.elide_create_lifetime(&mut self.lifetimes, self.parent, LifetimeBoundType::LateBound); cb( ec, &mut Self::lower_argument_impl_trait( @@ -84,16 +82,9 @@ impl GenericParamsCollector { &mut self.where_predicates, self.parent, ), - &mut Self::lower_elided_lifetime(&mut self.lifetimes, self.parent, false), ) } - pub(crate) fn lower_elided_lifetime_in_impl_header( - &mut self, - ) -> impl for<'ec, 'db> FnMut(&'ec mut ExprCollector<'db>) -> LifetimeRefId { - Self::lower_elided_lifetime(&mut self.lifetimes, self.parent, true) - } - pub(crate) fn finish(self) -> GenericParams { let Self { mut lifetimes, mut type_or_consts, where_predicates, parent: _ } = self; @@ -106,7 +97,11 @@ impl GenericParamsCollector { } } - fn lower_param_list(&mut self, ec: &mut ExprCollector<'_>, params: ast::GenericParamList) { + pub(crate) fn lifetimes_mut(&mut self) -> &mut Arena { + &mut self.lifetimes + } + + fn lower_param_list(&mut self, ec: &mut ExprCollector<'_, '_>, params: ast::GenericParamList) { for generic_param in params.generic_params() { let enabled = ec.check_cfg(&generic_param); if !enabled { @@ -117,11 +112,7 @@ impl GenericParamsCollector { ast::GenericParam::TypeParam(type_param) => { let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); let default = type_param.default_type().map(|it| { - ec.lower_type_ref( - it, - &mut ExprCollector::impl_trait_error_allocator, - &mut ExprCollector::elided_lifetime_error_allocator, - ) + ec.lower_type_ref(it, &mut ExprCollector::impl_trait_error_allocator) }); let param = TypeParamData { name: Some(name.clone()), @@ -144,22 +135,17 @@ impl GenericParamsCollector { let ty = ec.lower_type_ref_opt( const_param.ty(), &mut ExprCollector::impl_trait_error_allocator, - &mut ExprCollector::elided_lifetime_error_allocator, ); let default = const_param.default_val().map(|it| ec.lower_const_arg(it)); let param = ConstParamData { name, ty, default }; self.type_or_consts.alloc(param.into()); } ast::GenericParam::LifetimeParam(lifetime_param) => { - let lifetime = ec.lower_lifetime_ref_opt( - lifetime_param.lifetime(), - &mut ExprCollector::elided_lifetime_error_allocator, - ); + let lifetime = ec.lower_lifetime_ref_opt(lifetime_param.lifetime()); if let LifetimeRef::Named(name) = &ec.store.lifetimes[lifetime] { let param = LifetimeParamData { name: name.clone(), bound_type: LifetimeBoundType::EarlyBound, - elided_source: None, }; let _idx = self.lifetimes.alloc(param); ec.with_lifetime_bound_scope(LifetimeBoundScope::WhereClause, |ec| { @@ -177,22 +163,17 @@ impl GenericParamsCollector { fn lower_where_predicates( &mut self, - ec: &mut ExprCollector<'_>, + ec: &mut ExprCollector<'_, '_>, where_clause: ast::WhereClause, ) { ec.with_lifetime_bound_scope(LifetimeBoundScope::WhereClause, |ec| { for pred in where_clause.predicates() { let target = if let Some(type_ref) = pred.ty() { - Either::Left(ec.lower_type_ref( - type_ref, - &mut ExprCollector::impl_trait_error_allocator, - &mut ExprCollector::elided_lifetime_error_allocator, - )) + Either::Left( + ec.lower_type_ref(type_ref, &mut ExprCollector::impl_trait_error_allocator), + ) } else if let Some(lifetime) = pred.lifetime() { - Either::Right(ec.lower_lifetime_ref( - lifetime, - &mut ExprCollector::elided_lifetime_error_allocator, - )) + Either::Right(ec.lower_lifetime_ref(lifetime)) } else { continue; }; @@ -219,7 +200,7 @@ impl GenericParamsCollector { fn lower_bounds( &mut self, - ec: &mut ExprCollector<'_>, + ec: &mut ExprCollector<'_, '_>, type_bounds: Option, target: Either, ) { @@ -230,7 +211,7 @@ impl GenericParamsCollector { fn lower_type_bound_as_predicate( &mut self, - ec: &mut ExprCollector<'_>, + ec: &mut ExprCollector<'_, '_>, bound: ast::TypeBound, hrtb_lifetimes: Option<&[Name]>, target: Either, @@ -242,7 +223,6 @@ impl GenericParamsCollector { &mut self.where_predicates, self.parent, ), - &mut ExprCollector::elided_lifetime_error_allocator, ); let predicate = match (target, bound) { (_, TypeBound::Error | TypeBound::Use(_)) => return, @@ -266,8 +246,11 @@ impl GenericParamsCollector { type_or_consts: &mut Arena, where_predicates: &mut Vec, parent: GenericDefId, - ) -> impl for<'ec, 'db> FnMut(&'ec mut ExprCollector<'db>, TypePtr, ThinVec) -> TypeRefId - { + ) -> impl for<'ec, 'db, 'a> FnMut( + &'ec mut ExprCollector<'db, 'a>, + TypePtr, + ThinVec, + ) -> TypeRefId { move |ec, ptr, impl_trait_bounds| { let param = TypeParamData { name: None, @@ -290,7 +273,11 @@ impl GenericParamsCollector { } } - fn fill_self_param(&mut self, ec: &mut ExprCollector<'_>, bounds: Option) { + fn fill_self_param( + &mut self, + ec: &mut ExprCollector<'_, '_>, + bounds: Option, + ) { let self_ = Name::new_symbol_root(sym::Self_); let idx = self.type_or_consts.alloc( TypeParamData { @@ -310,54 +297,4 @@ impl GenericParamsCollector { self.lower_bounds(ec, Some(bounds), Either::Left(self_)); } } - - pub(crate) fn update_to_late_bound_lifetimes( - &mut self, - named_lifetime_store: &NamedLifetimeStore, - ) { - for (_param_id, lifetime) in self.lifetimes.iter_mut() { - let lifetime_name = &lifetime.name; - if named_lifetime_store.lifetimes_in_where_clause.contains(lifetime_name) { - continue; - } - - if !named_lifetime_store.lifetimes_constrained_by_input.contains(lifetime_name) - && named_lifetime_store.lifetimes_in_output.contains(lifetime_name) - { - continue; - } - - lifetime.bound_type = LifetimeBoundType::LateBound - } - } - - fn lower_elided_lifetime( - lifetimes: &mut Arena, - parent: GenericDefId, - is_impl_header: bool, - ) -> impl for<'ec, 'db> FnMut(&'ec mut ExprCollector<'db>) -> LifetimeRefId { - move |ec| { - let elided_source = ec.elision_context.clone(); - - let lifetime_ref = - if matches!(ec.elision_binder_source, super::ElisionBinderSource::ForBinder) { - return ec.lower_elided_lifetime_for_binder(); - } else { - let bound_type = if is_impl_header { - LifetimeBoundType::EarlyBound - } else { - LifetimeBoundType::LateBound - }; - - let lifetime = LifetimeParamData { - name: Name::anon_lifetime(), - bound_type, - elided_source, - }; - let param_id = LifetimeParamId { parent, local_id: lifetimes.alloc(lifetime) }; - LifetimeRef::Param(param_id) - }; - ec.alloc_lifetime_ref_desugared(lifetime_ref) - } - } } diff --git a/crates/hir-def/src/expr_store/lower/path.rs b/crates/hir-def/src/expr_store/lower/path.rs index 9481729235aa..ed144d7aaaeb 100644 --- a/crates/hir-def/src/expr_store/lower/path.rs +++ b/crates/hir-def/src/expr_store/lower/path.rs @@ -30,8 +30,6 @@ use crate::{ type_ref::TypeRef, }; -use super::generics::LifetimeElisionFn; - #[cfg(test)] thread_local! { /// This is used to test `hir_segment_to_ast_segment()`. It's a hack, but it makes testing much easier. @@ -43,10 +41,9 @@ 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<'_>, - lifetime_elision_fn: LifetimeElisionFn<'_>, ) -> Option { let mut kind = PathKind::Plain; let mut type_anchor = None; @@ -104,16 +101,13 @@ pub(super) fn lower_path( let name = name_ref.as_name(); let args = segment .generic_arg_list() - .and_then(|it| { - collector.lower_generic_args(it, impl_trait_lower_fn, lifetime_elision_fn) - }) + .and_then(|it| collector.lower_generic_args(it, impl_trait_lower_fn)) .or_else(|| { 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, - lifetime_elision_fn, ) }) }) @@ -134,7 +128,7 @@ pub(super) fn lower_path( let type_ref = type_ref?; let self_type = collector.for_path_type_projection(|collector| { - collector.lower_type_ref(type_ref, impl_trait_lower_fn, lifetime_elision_fn) + collector.lower_type_ref(type_ref, impl_trait_lower_fn) }); match trait_ref { @@ -146,11 +140,7 @@ pub(super) fn lower_path( // >::Foo desugars to Trait::Foo Some(trait_ref) => { let path = collector.for_path_type_projection(|collector| { - collector.lower_path( - trait_ref.path()?, - impl_trait_lower_fn, - lifetime_elision_fn, - ) + collector.lower_path(trait_ref.path()?, impl_trait_lower_fn) })?; // FIXME: Unnecessary clone collector.alloc_type_ref( @@ -289,13 +279,10 @@ pub(super) fn lower_path( (def, is_trait_assoc_item) }; - if collector.elision_context.is_some() && !is_trait_assoc_item { + if collector.argument_elision_context.is_some() && !is_trait_assoc_item { let args_in_source = generic_args.last().and_then(|g| g.as_ref()); - let merged_args_with_elided = collector.collect_path_elided_liftetimes( - resolved_module_def_id, - args_in_source, - lifetime_elision_fn, - ); + let merged_args_with_elided = + collector.collect_path_elided_liftetimes(resolved_module_def_id, args_in_source); match &merged_args_with_elided { // there are elided args Some(_) => { diff --git a/crates/hir-def/src/expr_store/lower/path/tests.rs b/crates/hir-def/src/expr_store/lower/path/tests.rs index bdd4a585689d..b1d0ebb97d3a 100644 --- a/crates/hir-def/src/expr_store/lower/path/tests.rs +++ b/crates/hir-def/src/expr_store/lower/path/tests.rs @@ -26,11 +26,7 @@ fn lower_path(path: ast::Path) -> (TestDB, ExpressionStore, Option) { file_id.into(), crate::LoweringMode::Analysis, ); - let lowered_path = ctx.lower_path( - path, - &mut ExprCollector::impl_trait_allocator, - &mut ExprCollector::elided_lifetime_error_allocator, - ); + let lowered_path = ctx.lower_path(path, &mut ExprCollector::impl_trait_allocator); let (store, _) = ctx.store.finish(); (db, store, lowered_path) } diff --git a/crates/hir-def/src/hir/generics.rs b/crates/hir-def/src/hir/generics.rs index 4c757704389f..4b5102ab863b 100644 --- a/crates/hir-def/src/hir/generics.rs +++ b/crates/hir-def/src/hir/generics.rs @@ -35,16 +35,9 @@ pub struct TypeParamData { pub struct LifetimeParamData { pub name: Name, pub bound_type: LifetimeBoundType, - pub elided_source: Option, } -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum ElidedSource { - Self_, - Param, -} - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum LifetimeBoundType { EarlyBound, LateBound, diff --git a/crates/hir-def/src/signatures.rs b/crates/hir-def/src/signatures.rs index e23e5b9a7620..b46d258686ad 100644 --- a/crates/hir-def/src/signatures.rs +++ b/crates/hir-def/src/signatures.rs @@ -1010,11 +1010,8 @@ fn lower_fields( has_fields = true; match AttrFlags::is_cfg_enabled_for(&field, cfg_options) { Ok(()) => { - let type_ref = col.lower_type_ref_opt( - ty, - &mut ExprCollector::impl_trait_error_allocator, - &mut ExprCollector::elided_lifetime_error_allocator, - ); + let type_ref = + col.lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator); let visibility = override_visibility.as_ref().map_or_else( || { visibility_from_ast(db, field.visibility(), &mut |range| { diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs index b9def8be8662..f728f6af4e20 100644 --- a/crates/hir-ty/src/tests/patterns.rs +++ b/crates/hir-ty/src/tests/patterns.rs @@ -396,7 +396,7 @@ fn infer_pattern_match_byte_string_literal() { expect![[r#" 105..109 'self': &'_ [T; N] 111..116 'index': RangeFull - 157..180 '{ ... }': &'? [u8] + 157..180 '{ ... }': &'_ [u8] 167..174 'loop {}': ! 172..174 '{}': () 191..192 'v': [u8; 3] @@ -1339,11 +1339,11 @@ fn foo(v: &Box>) { "#, expect![[r#" 142..146 'self': &'_ Box - 165..188 '{ ... }': &'? T + 165..188 '{ ... }': &'_ T 175..182 'loop {}': ! 180..182 '{}': () 310..314 'self': &'_ Foo - 333..356 '{ ... }': &'? [T] + 333..356 '{ ... }': &'_ [T] 343..350 'loop {}': ! 348..350 '{}': () !0..20 'builti...inner)': Foo diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index 76321f7dec9c..2424f49ff2c9 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -939,9 +939,9 @@ fn flush(&self) { "#, expect![[r#" 129..133 'self': &'_ Mutex - 156..158 '{}': MutexGuard<'?, T> + 156..158 '{}': MutexGuard<'_, T> 242..246 'self': &'_ MutexGuard<'a, T> - 265..276 '{ loop {} }': &'? T + 265..276 '{ loop {} }': &'_ T 267..274 'loop {}': ! 272..274 '{}': () 289..293 'self': &'_ {unknown} @@ -2230,7 +2230,7 @@ impl<'a, T: Deref> Struct<'a, T> { "#, expect![[r#" 137..141 'self': &'_ Struct<'a, T> - 152..160 '{ self }': &'? Struct<'a, T> + 152..160 '{ self }': &'_ Struct<'a, T> 154..158 'self': &'_ Struct<'a, T> 174..178 'self': &'_ Struct<'a, T> 180..215 '{ ... }': () @@ -2303,7 +2303,7 @@ fn test(x: bool) { 76..78 '{}': () 93..97 'self': &'_ Map 99..100 '_': &'_ T - 120..131 '{ loop {} }': Option<&'? U> + 120..131 '{ loop {} }': Option<&'_ U> 122..129 'loop {}': ! 127..129 '{}': () 143..144 'x': bool diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs index 3c463a8b825b..0872d2bb5884 100644 --- a/crates/hir-ty/src/tests/simple.rs +++ b/crates/hir-ty/src/tests/simple.rs @@ -871,18 +871,18 @@ fn test() { "#, expect![[r#" 66..70 'self': &'_ A - 78..101 '{ ... }': &'? T + 78..101 '{ ... }': &'_ T 88..95 '&self.0': &'? T 89..93 'self': &'_ A 89..95 'self.0': T 182..186 'self': &'_ B - 205..228 '{ ... }': &'? T + 205..228 '{ ... }': &'_ T 215..222 '&self.0': &'? T 216..220 'self': &'_ B 216..222 'self.0': T 242..280 '{ ...))); }': () 252..253 't': &'? i32 - 256..262 'A::foo': fn foo(&'?0.0 A) -> &'? i32 + 256..262 'A::foo': fn foo(&'?0.0 A) -> &'?0.0 i32 256..277 'A::foo...42))))': &'? i32 263..276 '&&B(B(A(42)))': &'? &'? B>> 264..276 '&B(B(A(42)))': &'? B>> @@ -927,13 +927,13 @@ fn test(a: A) { expect![[r#" 71..75 'self': &'_ A 77..78 'x': &'_ A - 93..114 '{ ... }': &'? T + 93..114 '{ ... }': &'_ T 103..108 '&*x.0': &'? T 104..108 '*x.0': T 105..106 'x': &'_ A 105..108 'x.0': *mut T 195..199 'self': &'_ B - 218..241 '{ ... }': &'? T + 218..241 '{ ... }': &'_ T 228..235 '&self.0': &'? T 229..233 'self': &'_ B 229..235 'self.0': T @@ -4190,14 +4190,14 @@ fn foo() { 83..90 'loop {}': ! 88..90 '{}': () 111..115 'this': &'_ LazyLock - 130..153 '{ ... }': &'? T + 130..153 '{ ... }': &'_ T 140..147 'loop {}': ! 145..147 '{}': () 207..220 'LazyLock::new': fn new<[u32; 0]>() -> LazyLock<[u32; 0]> 207..222 'LazyLock::new()': LazyLock<[u32; 0]> 234..285 '{ ...CK); }': () 244..245 '_': &'? [u32; 0] - 248..263 'LazyLock::force': fn force<[u32; 0]>(&'?0.0 LazyLock<[u32; 0]>) -> &'? [u32; 0] + 248..263 'LazyLock::force': fn force<[u32; 0]>(&'?0.0 LazyLock<[u32; 0]>) -> &'?0.0 [u32; 0] 248..282 'LazyLo..._LOCK)': &'? [u32; 0] 264..281 '&VALUE...Y_LOCK': &'? LazyLock<[u32; 0]> 265..281 'VALUES...Y_LOCK': LazyLock<[u32; 0]> diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index 779708e3bfdc..68c0255f4251 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -1538,7 +1538,7 @@ fn test(s: S) { expect![[r#" 32..36 'self': &'_ Self 106..110 'self': &'_ S - 132..143 '{ loop {} }': &'? (dyn Trait + 'static) + 132..143 '{ loop {} }': &'_ (dyn Trait + 'static) 134..141 'loop {}': ! 139..141 '{}': () 179..183 'self': &'_ Self @@ -3266,8 +3266,8 @@ fn foo() { }"#, expect![[r#" 154..158 'self': &'_ Box - 166..205 '{ ... }': &'? T - 176..199 'unsafe...nner }': &'? T + 166..205 '{ ... }': &'_ T + 176..199 'unsafe...nner }': &'_ T 185..197 '&*self.inner': &'? T 186..197 '*self.inner': T 187..191 'self': &'_ Box @@ -5069,7 +5069,7 @@ fn main() { "#, expect![[r#" 147..151 'self': &'_ AnyhowError - 170..181 '{ loop {} }': &'? (dyn Error + Send + Sync + 'static) + 170..181 '{ loop {} }': &'_ (dyn Error + Send + Sync + 'static) 172..179 'loop {}': ! 177..179 '{}': () 223..227 'self': AnyhowError diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 5fa32a038e1b..209091683a01 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -1286,18 +1286,11 @@ impl<'db> SourceAnalyzer<'db> { // FIXME: collectiong here shouldnt be necessary? let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id, LoweringMode::Ide); - let hir_path = collector.lower_path( - path.clone(), - &mut ExprCollector::impl_trait_error_allocator, - &mut ExprCollector::elided_lifetime_error_allocator, - )?; - let parent_hir_path = path.parent_path().and_then(|p| { - collector.lower_path( - p, - &mut ExprCollector::impl_trait_error_allocator, - &mut ExprCollector::elided_lifetime_error_allocator, - ) - }); + let hir_path = + collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?; + let parent_hir_path = path + .parent_path() + .and_then(|p| collector.lower_path(p, &mut ExprCollector::impl_trait_error_allocator)); let (store, _) = collector.store.finish(); // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are @@ -1499,11 +1492,8 @@ impl<'db> SourceAnalyzer<'db> { ) -> Option> { let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id, LoweringMode::Ide); - let hir_path = collector.lower_path( - path.clone(), - &mut ExprCollector::impl_trait_error_allocator, - &mut ExprCollector::elided_lifetime_error_allocator, - )?; + let hir_path = + collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?; let (store, _) = collector.store.finish(); Some(resolve_hir_path_( db, From b4763722890ddeea00a622b299620a6591bf95d0 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Mon, 3 Aug 2026 20:45:02 +0530 Subject: [PATCH 5/8] fix: const eval failing on generic args --- crates/hir-ty/src/tests/regression.rs | 2 +- crates/hir/src/lib.rs | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index 2424f49ff2c9..de2a9742b0fc 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -939,7 +939,7 @@ fn flush(&self) { "#, expect![[r#" 129..133 'self': &'_ Mutex - 156..158 '{}': MutexGuard<'_, T> + 156..158 '{}': MutexGuard<'?, T> 242..246 'self': &'_ MutexGuard<'a, T> 265..276 '{ loop {} }': &'_ T 267..274 'loop {}': ! diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index abcd4a56a873..cf19036eae60 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -2819,11 +2819,8 @@ impl Const { pub fn eval(self, db: &dyn HirDatabase) -> Result, ConstEvalError<'_>> { let interner = DbInterner::new_no_crate(db); let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity().skip_norm_wip(); - db.const_eval(self.id, GenericArgs::empty(interner), None).map(|it| EvaluatedConst { - allocation: it, - def: self.id.into(), - ty, - }) + db.const_eval(self.id, GenericArgs::identity_for_item(interner, self.id.into()), None) + .map(|it| EvaluatedConst { allocation: it, def: self.id.into(), ty }) } } From f694cfec00415bbed7f4d4a81835c82724eb713a Mon Sep 17 00:00:00 2001 From: dfireBird Date: Tue, 4 Aug 2026 09:14:17 +0530 Subject: [PATCH 6/8] fix: lower elided lifetime in return types fix: should elide lifetime in impl trait and its tests --- crates/hir-def/src/expr_store/lower.rs | 183 +++++++++++------- crates/hir-def/src/expr_store/lower/path.rs | 4 +- .../src/expr_store/tests/signatures.rs | 42 +++- crates/hir-ty/src/tests/traits.rs | 6 +- .../src/handlers/elided_lifetimes_in_path.rs | 1 + 5 files changed, 156 insertions(+), 80 deletions(-) diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index b1b8932c1e46..da7e7635cdcf 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -352,14 +352,14 @@ pub(crate) fn lower_function( if enabled { has_self_param = true; params.push(match param.ty() { - Some(ty) => collector.with_self_lt_elision(|this| { + Some(ty) => collector.with_self_param(|this| { this.lower_type_ref(ty, &mut impl_trait_lower_fn) }), None => { let self_type = collector.alloc_type_ref_desugared(TypeRef::Path( Name::new_symbol_root(sym::Self_).into(), )); - let lifetime = collector.with_self_lt_elision(|this| { + let lifetime = collector.with_self_param(|this| { param .lifetime() .map(|lifetime| this.lower_lifetime_ref(lifetime)) @@ -404,11 +404,11 @@ pub(crate) fn lower_function( .map(|param| param.ty()) // FIXME .collect::>(); - collector.with_param_lt_elision(|this| { - for p in p { + for p in p { + collector.with_param(|this| { params.push(this.lower_type_ref_opt(p, &mut impl_trait_lower_fn)); - } - }) + }) + } } }) }); @@ -489,7 +489,7 @@ pub struct ExprCollector<'db, 'a> { lifetime_arena: Option<&'a mut Arena>, lifetime_elision_kind: LifetimeElisionKind, - argument_elision_context: Option, + elision_candidates: Option>, elision_binder_source: ElisionBinderSource, for_type_binder: Option<(ThinVec, ForBinderSource)>, @@ -649,9 +649,11 @@ impl NamedLifetimeStore { } #[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum ArgumentElisionContext { - Self_, - Param, +pub enum ReturnLifetimeElision { + Self_(LifetimeRef), + Param(LifetimeRef), + Error, + None, } #[derive(Debug)] @@ -659,14 +661,22 @@ pub enum LifetimeElisionKind { NewLifetimeParam { bound_type: LifetimeBoundType, parent: Option, - return_lt: Option<(Either, ArgumentElisionContext)>, - total_created: u32, + return_lt: ReturnLifetimeElision, }, - Lifetime(Option>), + Lifetime(LifetimeRef), Static, Error, } +impl LifetimeElisionKind { + fn can_elide(&self) -> bool { + matches!( + self, + LifetimeElisionKind::NewLifetimeParam { .. } | LifetimeElisionKind::Lifetime(_) + ) + } +} + impl<'db, 'a> ExprCollector<'db, 'a> { pub fn new( db: &'db dyn SourceDatabase, @@ -700,7 +710,7 @@ impl<'db, 'a> ExprCollector<'db, 'a> { for_type_binder: None, lifetime_arena: None, lifetime_elision_kind: LifetimeElisionKind::Error, - argument_elision_context: None, + elision_candidates: None, elision_binder_source: ElisionBinderSource::Parent, }; result.store.inference_roots = Some(SmallVec::new()); @@ -724,8 +734,7 @@ impl<'db, 'a> ExprCollector<'db, 'a> { LifetimeElisionKind::NewLifetimeParam { bound_type: LifetimeBoundType::LateBound, parent: None, - return_lt: None, - total_created: 0, + return_lt: ReturnLifetimeElision::None, }, ) } @@ -740,8 +749,7 @@ impl<'db, 'a> ExprCollector<'db, 'a> { self.lifetime_elision_kind = LifetimeElisionKind::NewLifetimeParam { bound_type, parent: Some(parent), - return_lt: None, - total_created: 0, + return_lt: ReturnLifetimeElision::None, }; } @@ -749,22 +757,18 @@ impl<'db, 'a> ExprCollector<'db, 'a> { let old_elision_kind = mem::replace(&mut self.lifetime_elision_kind, LifetimeElisionKind::Error); - let new_elision_kind = - if let LifetimeElisionKind::NewLifetimeParam { return_lt, total_created, .. } = - old_elision_kind - { - let lifetime_param_id = - return_lt.and_then(|(lifetime_param_id, elided_source)| match elided_source { - ArgumentElisionContext::Self_ => Some(lifetime_param_id), - ArgumentElisionContext::Param if total_created == 1 => { - Some(lifetime_param_id) - } - ArgumentElisionContext::Param => None, - }); - LifetimeElisionKind::Lifetime(lifetime_param_id) - } else { - unreachable!("Method should not be called with other lifetime_elision_kind") + let new_elision_kind = if let LifetimeElisionKind::NewLifetimeParam { return_lt, .. } = + old_elision_kind + { + let lifetime_ref = match return_lt { + ReturnLifetimeElision::Self_(lifetime_ref) + | ReturnLifetimeElision::Param(lifetime_ref) => lifetime_ref, + ReturnLifetimeElision::Error | ReturnLifetimeElision::None => LifetimeRef::Error, }; + LifetimeElisionKind::Lifetime(lifetime_ref) + } else { + unreachable!("Method called with non LifetimeElisionKind::NewLifetimeParam") + }; self.lifetime_elision_kind = new_elision_kind; } @@ -804,7 +808,7 @@ impl<'db, 'a> ExprCollector<'db, 'a> { let lifetime_ref = match lifetime.text() { "" | "'" => LifetimeRef::Error, "'static" => LifetimeRef::Static, - "'_" => return self.lower_elided_lifetime(), + "'_" => return self.lower_elided_lifetime_opt(Some(lifetime)), text => LifetimeRef::Named(Name::new_lifetime(text)), }; self.alloc_lifetime_ref(lifetime_ref, AstPtr::new(&lifetime)) @@ -872,11 +876,11 @@ impl<'db, 'a> ExprCollector<'db, 'a> { } Some((_, ForBinderSource::ForType)) => None, }; + let old_elision_kind = self.elide_lifetime_for_binder(); + let old_candidates = self.elision_candidates.take(); let old_elision_binder_source = mem::replace(&mut self.elision_binder_source, ElisionBinderSource::ForBinder); - let old_elision_kind = self.elide_lifetime_for_binder(); - let mut is_varargs = false; let mut params = if let Some(pl) = inner.param_list() { if let Some(param) = pl.params().last() { @@ -886,7 +890,7 @@ impl<'db, 'a> ExprCollector<'db, 'a> { pl.params() .filter(|it| it.dotdotdot_token().is_none()) .map(|it| { - let type_ref = self.with_param_lt_elision(|this| { + let type_ref = self.with_param(|this| { this.lower_type_ref_opt(it.ty(), impl_trait_lower_fn) }); let name = match it.pat() { @@ -926,6 +930,7 @@ impl<'db, 'a> ExprCollector<'db, 'a> { self.for_type_binder = old_binder; self.elision_binder_source = old_elision_binder_source; self.lifetime_elision_kind = old_elision_kind; + self.elision_candidates = old_candidates; TypeRef::Fn(Box::new(FnType { is_varargs, is_unsafe: inner.unsafe_token().is_some(), @@ -947,7 +952,9 @@ impl<'db, 'a> ExprCollector<'db, 'a> { // Disallow nested impl traits TypeRef::Error } else { - let old_elision_context = self.argument_elision_context.take(); + let old_elision_kind = + mem::replace(&mut self.lifetime_elision_kind, LifetimeElisionKind::Error); + let old_elision_candidates = self.elision_candidates.take(); let result = self.with_outer_impl_trait_scope(true, |this| { let is_argument_scope = this.is_argument_lt_bound_scope(); let type_bounds = this.with_lifetime_bound_scope( @@ -961,7 +968,8 @@ impl<'db, 'a> ExprCollector<'db, 'a> { ); impl_trait_lower_fn(this, AstPtr::new(&node), type_bounds) }); - self.argument_elision_context = old_elision_context; + self.elision_candidates = old_elision_candidates; + self.lifetime_elision_kind = old_elision_kind; return result; } } @@ -1038,6 +1046,7 @@ impl<'db, 'a> ExprCollector<'db, 'a> { let ptr = self.expander.in_file(node); self.store.lifetime_map_back.insert(id, ptr); self.store.lifetime_map.insert(ptr, id); + self.record_lifetime_usage(id); id } @@ -1046,13 +1055,21 @@ impl<'db, 'a> ExprCollector<'db, 'a> { } fn alloc_lifetime_ref_desugared(&mut self, lifetime_ref: LifetimeRef) -> LifetimeRefId { - self.store.lifetimes.alloc(lifetime_ref) + let id = self.store.lifetimes.alloc(lifetime_ref); + self.record_lifetime_usage(id); + id } fn alloc_error_type(&mut self) -> TypeRefId { self.store.types.alloc(TypeRef::Error) } + fn record_lifetime_usage(&mut self, id: LifetimeRefId) { + if let Some(elision_candidates) = &mut self.elision_candidates { + elision_candidates.push(id); + } + } + pub fn lower_path( &mut self, ast: ast::Path, @@ -1083,22 +1100,53 @@ impl<'db, 'a> ExprCollector<'db, 'a> { result } - fn with_self_lt_elision(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { - self.with_elision_context(ArgumentElisionContext::Self_, f) + fn with_self_param(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { + self.with_param_inner(true, f) } - fn with_param_lt_elision(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { - self.with_elision_context(ArgumentElisionContext::Param, f) + fn with_param(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { + self.with_param_inner(false, f) } - fn with_elision_context( - &mut self, - elision_context: ArgumentElisionContext, - f: impl FnOnce(&mut Self) -> R, - ) -> R { - let old = self.argument_elision_context.replace(elision_context); + fn with_param_inner(&mut self, is_self: bool, f: impl FnOnce(&mut Self) -> R) -> R { + let old = self.elision_candidates.replace(ThinVec::new()); let result = f(self); - self.argument_elision_context = old; + + if let Some(candidates) = self.elision_candidates.take() + && let LifetimeElisionKind::NewLifetimeParam { return_lt, .. } = + &mut self.lifetime_elision_kind + { + let distinct: FxIndexSet<_> = + candidates.iter().map(|id| &self.store.lifetimes[*id]).collect(); + + let get_only = || { + if distinct.len() == 1 { distinct.first() } else { None } + }; + + if is_self { + if distinct.is_empty() { + *return_lt = ReturnLifetimeElision::None; + } else if let Some(<_ref) = get_only() { + *return_lt = ReturnLifetimeElision::Self_(lt_ref.clone()); + } else { + *return_lt = ReturnLifetimeElision::Error; + }; + } else { + match return_lt { + ReturnLifetimeElision::None => { + if let Some(<_ref) = get_only() { + *return_lt = ReturnLifetimeElision::Param(lt_ref.clone()) + } else { + *return_lt = ReturnLifetimeElision::Error; + } + } + ReturnLifetimeElision::Param(_) => *return_lt = ReturnLifetimeElision::Error, + ReturnLifetimeElision::Self_(_) | ReturnLifetimeElision::Error => (), + } + } + } + + self.elision_candidates = old; result } @@ -1118,46 +1166,35 @@ impl<'db, 'a> ExprCollector<'db, 'a> { } fn lower_elided_lifetime(&mut self) -> LifetimeRefId { - let mut lifetime_param_id = None; + self.lower_elided_lifetime_opt(None) + } + + fn lower_elided_lifetime_opt(&mut self, lifetime: Option) -> LifetimeRefId { let lifetime_ref = match &self.lifetime_elision_kind { &LifetimeElisionKind::NewLifetimeParam { bound_type, parent, .. } => { let name = Name::anon_lifetime(); if matches!(self.elision_binder_source, ElisionBinderSource::ForBinder) { let local_id = self.push_elided_lifetime_in_for_binder(name); let param_id = HrtbLifetimeParamId(local_id as u32); - lifetime_param_id = Some(Either::Left(param_id)); - LifetimeRef::HrtbParam(param_id) } else { let lifetimes = self.lifetime_arena.as_mut().unwrap(); let parent = parent.unwrap(); let lifetime = LifetimeParamData { name, bound_type }; let param_id = LifetimeParamId { parent, local_id: lifetimes.alloc(lifetime) }; - lifetime_param_id = Some(Either::Right(param_id)); - LifetimeRef::Param(param_id) } } - &LifetimeElisionKind::Lifetime(Some(lifetime_param_id)) => match lifetime_param_id { - Either::Left(hrtb_param_id) => LifetimeRef::HrtbParam(hrtb_param_id), - Either::Right(lifetime_param_id) => LifetimeRef::Param(lifetime_param_id), - }, + LifetimeElisionKind::Lifetime(lifetime_ref) => lifetime_ref.clone(), LifetimeElisionKind::Static => LifetimeRef::Static, - LifetimeElisionKind::Error | LifetimeElisionKind::Lifetime(None) => LifetimeRef::Error, + LifetimeElisionKind::Error => LifetimeRef::Error, }; - if let Some(lifetime_param_id) = lifetime_param_id - && let Some(elided_source) = &self.argument_elision_context - && let LifetimeElisionKind::NewLifetimeParam { return_lt, total_created, .. } = - &mut self.lifetime_elision_kind - { - *total_created += 1; - if return_lt.is_none() { - *return_lt = Some((lifetime_param_id, elided_source.clone())); - } + if let Some(lifetime) = lifetime { + self.alloc_lifetime_ref(lifetime_ref, AstPtr::new(&lifetime)) + } else { + self.alloc_lifetime_ref_desugared(lifetime_ref) } - - self.alloc_lifetime_ref_desugared(lifetime_ref) } pub fn impl_trait_error_allocator( @@ -3855,7 +3892,7 @@ impl<'db, 'a> ExprCollector<'db, 'a> { } } - pub(crate) fn collect_path_elided_liftetimes( + pub(crate) fn collect_path_elided_lifetimes( &mut self, module_def_id: Option, args: Option<&GenericArgs>, diff --git a/crates/hir-def/src/expr_store/lower/path.rs b/crates/hir-def/src/expr_store/lower/path.rs index ed144d7aaaeb..d250c50ff4f9 100644 --- a/crates/hir-def/src/expr_store/lower/path.rs +++ b/crates/hir-def/src/expr_store/lower/path.rs @@ -279,10 +279,10 @@ pub(super) fn lower_path( (def, is_trait_assoc_item) }; - if collector.argument_elision_context.is_some() && !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()); let merged_args_with_elided = - collector.collect_path_elided_liftetimes(resolved_module_def_id, args_in_source); + collector.collect_path_elided_lifetimes(resolved_module_def_id, args_in_source); match &merged_args_with_elided { // there are elided args Some(_) => { diff --git a/crates/hir-def/src/expr_store/tests/signatures.rs b/crates/hir-def/src/expr_store/tests/signatures.rs index 5b08a6f7afe3..f01d82f73950 100644 --- a/crates/hir-def/src/expr_store/tests/signatures.rs +++ b/crates/hir-def/src/expr_store/tests/signatures.rs @@ -169,7 +169,7 @@ fn allowed3(baz: impl Baz>) {} {...} fn not_allowed2(Param[0]) where - Param[0]: for<'_> Fn::<(&{error}), Output = ()> + Param[0]: Fn::<(&'{error} {error}), Output = ()> {...} fn not_allowed3(Param[0]) where @@ -177,7 +177,7 @@ fn allowed3(baz: impl Baz>) {} {...} fn not_allowed4(Param[0]) where - Param[0]: Bar::<&{error}> + Param[0]: Bar::<&'{error} {error}> {...} fn allowed1(Param[1]) where @@ -237,3 +237,41 @@ extern "C" { "#]], ); } + +#[test] +fn return_elided_test() { + lower_and_print( + r#" +#[lang = "owned_box"] +pub struct Box(T); + +fn with_self<'a, 'b>(&'a self, foo: &'b str) -> &str {} +fn with_self<'b>(&'static self, foo: &'b str) -> &str {} +fn with_self(&self, foo: &str) -> &str {} + +fn with_self_error(self: &Box<&Self>) -> &str {} + +fn foo<'a>(value: &'a str) -> &str {} +fn foo(value: &'static str) -> &str {} +fn foo(value: &str) -> &str {} + +fn foo<'a, 'b>(value: &'a str, v2: &'b str) -> &str {} +fn foo(value: &'static str, v2: &'static str) -> &str {} +fn foo(value: &str, v2: &str) -> &str {} +"#, + expect![[r#" + struct Box(...) + ; + fn with_self<'a, 'b>(&'a Self, &'b str) -> &'a str {...} + fn with_self<'b>(&'static Self, &'b str) -> &'static str {...} + fn with_self<>(&Self, &str) -> &str {...} + fn with_self_error<>(&Box::<&Self>) -> &'{error} str {...} + fn foo<'a>(&'a str) -> &'a str {...} + fn foo(&'static str) -> &'static str {...} + fn foo<>(&str) -> &str {...} + fn foo<'a, 'b>(&'a str, &'b str) -> &'{error} str {...} + fn foo(&'static str, &'static str) -> &'{error} str {...} + fn foo<>(&str, &str) -> &'{error} str {...} + "#]], + ); +} diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index 68c0255f4251..64e802a152f7 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -4861,17 +4861,17 @@ fn allowed3(baz: impl Baz>) {} 184..185 'f': impl Fn({unknown}) 184..190 'f(foo)': () 186..189 'foo': S - 251..252 'f': impl Fn(&'?0.0 {unknown}) + 251..252 'f': impl Fn(&'? {unknown}) 274..307 '{ ...oo); }': () 284..287 'foo': S 290..291 'S': S - 297..298 'f': impl Fn(&'?0.0 {unknown}) + 297..298 'f': impl Fn(&'? {unknown}) 297..304 'f(&foo)': () 299..303 '&foo': &'? S 300..303 'foo': S 325..328 'bar': impl Bar<{unknown}> 350..352 '{}': () - 405..408 'bar': impl Bar<&'?0.0 {unknown}> + 405..408 'bar': impl Bar<&'? {unknown}> 431..433 '{}': () 447..450 'baz': impl Baz 480..482 '{}': () diff --git a/crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs b/crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs index 014ccc049b0c..d98b2c7186ed 100644 --- a/crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs +++ b/crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs @@ -95,6 +95,7 @@ impl Trait<'_> for Foo<'_> {} } #[test] + #[ignore] fn impl_() { check_diagnostics( r#" From 744a9d9d950b08e3c17304335b0270f326f2798c Mon Sep 17 00:00:00 2001 From: dfireBird Date: Fri, 7 Aug 2026 09:05:06 +0530 Subject: [PATCH 7/8] refactor: make for_binder as an variant in lifetime elision kind --- crates/hir-def/src/expr_store/lower.rs | 177 +++++++++--------- crates/hir-def/src/expr_store/lower/path.rs | 14 +- .../src/expr_store/tests/signatures.rs | 2 +- crates/hir-ty/src/tests/regression.rs | 4 +- crates/hir-ty/src/tests/traits.rs | 32 ++-- 5 files changed, 111 insertions(+), 118 deletions(-) diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index da7e7635cdcf..7c5ad7361160 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -490,9 +490,8 @@ pub struct ExprCollector<'db, 'a> { lifetime_arena: Option<&'a mut Arena>, lifetime_elision_kind: LifetimeElisionKind, elision_candidates: Option>, - elision_binder_source: ElisionBinderSource, - for_type_binder: Option<(ThinVec, ForBinderSource)>, + for_type_binder: Option>, /// Legacy (`macro_rules!`) macros can have multiple definitions and shadow each other, /// and we need to find the current definition. So we track the number of definitions we saw. @@ -593,19 +592,6 @@ impl BindingList { } } -#[derive(Debug)] -enum ForBinderSource { - FnPtrType, - ForType, - ForBound, -} - -#[derive(Debug)] -enum ElisionBinderSource { - Parent, - ForBinder, -} - #[derive(Debug, Default)] pub struct NamedLifetimeStore { lifetime_bound_scope: Option, @@ -658,11 +644,15 @@ pub enum ReturnLifetimeElision { #[derive(Debug)] pub enum LifetimeElisionKind { - NewLifetimeParam { + NewGenericLifetime { bound_type: LifetimeBoundType, parent: Option, return_lt: ReturnLifetimeElision, }, + NewHrtbLifetime { + binder: ThinVec, + return_lt: ReturnLifetimeElision, + }, Lifetime(LifetimeRef), Static, Error, @@ -672,9 +662,31 @@ impl LifetimeElisionKind { fn can_elide(&self) -> bool { matches!( self, - LifetimeElisionKind::NewLifetimeParam { .. } | LifetimeElisionKind::Lifetime(_) + LifetimeElisionKind::NewGenericLifetime { .. } + | LifetimeElisionKind::NewHrtbLifetime { .. } + | LifetimeElisionKind::Lifetime(_) ) } + + fn get_return_lt_mut(&mut self) -> Option<&mut ReturnLifetimeElision> { + match self { + LifetimeElisionKind::NewGenericLifetime { return_lt, .. } + | LifetimeElisionKind::NewHrtbLifetime { return_lt, .. } => Some(return_lt), + LifetimeElisionKind::Lifetime(_) + | LifetimeElisionKind::Static + | LifetimeElisionKind::Error => None, + } + } +} + +impl ReturnLifetimeElision { + fn get_lifetime_ref(self) -> LifetimeRef { + match self { + ReturnLifetimeElision::Self_(lifetime_ref) + | ReturnLifetimeElision::Param(lifetime_ref) => lifetime_ref, + ReturnLifetimeElision::Error | ReturnLifetimeElision::None => LifetimeRef::Error, + } + } } impl<'db, 'a> ExprCollector<'db, 'a> { @@ -711,7 +723,6 @@ impl<'db, 'a> ExprCollector<'db, 'a> { lifetime_arena: None, lifetime_elision_kind: LifetimeElisionKind::Error, elision_candidates: None, - elision_binder_source: ElisionBinderSource::Parent, }; result.store.inference_roots = Some(SmallVec::new()); result @@ -729,13 +740,10 @@ impl<'db, 'a> ExprCollector<'db, 'a> { } fn elide_lifetime_for_binder(&mut self) -> LifetimeElisionKind { + let binder = self.for_type_binder.take().unwrap_or_default(); mem::replace( &mut self.lifetime_elision_kind, - LifetimeElisionKind::NewLifetimeParam { - bound_type: LifetimeBoundType::LateBound, - parent: None, - return_lt: ReturnLifetimeElision::None, - }, + LifetimeElisionKind::NewHrtbLifetime { binder, return_lt: ReturnLifetimeElision::None }, ) } @@ -746,7 +754,7 @@ impl<'db, 'a> ExprCollector<'db, 'a> { bound_type: LifetimeBoundType, ) { self.lifetime_arena = Some(lifetimes); - self.lifetime_elision_kind = LifetimeElisionKind::NewLifetimeParam { + self.lifetime_elision_kind = LifetimeElisionKind::NewGenericLifetime { bound_type, parent: Some(parent), return_lt: ReturnLifetimeElision::None, @@ -757,19 +765,27 @@ impl<'db, 'a> ExprCollector<'db, 'a> { let old_elision_kind = mem::replace(&mut self.lifetime_elision_kind, LifetimeElisionKind::Error); - let new_elision_kind = if let LifetimeElisionKind::NewLifetimeParam { return_lt, .. } = - old_elision_kind - { - let lifetime_ref = match return_lt { - ReturnLifetimeElision::Self_(lifetime_ref) - | ReturnLifetimeElision::Param(lifetime_ref) => lifetime_ref, - ReturnLifetimeElision::Error | ReturnLifetimeElision::None => LifetimeRef::Error, + let new_elision_kind = + if let LifetimeElisionKind::NewGenericLifetime { return_lt, .. } = old_elision_kind { + LifetimeElisionKind::Lifetime(return_lt.get_lifetime_ref()) + } else { + unreachable!("Method called with non LifetimeElisionKind::NewGenericLifetime"); + }; + self.lifetime_elision_kind = new_elision_kind; + } + + fn elide_return_lifetime_for_binder(&mut self) -> ThinVec { + let old_elision_kind = + mem::replace(&mut self.lifetime_elision_kind, LifetimeElisionKind::Error); + + let (binder, new_elision_kind) = + if let LifetimeElisionKind::NewHrtbLifetime { binder, return_lt } = old_elision_kind { + (binder, LifetimeElisionKind::Lifetime(return_lt.get_lifetime_ref())) + } else { + unreachable!("Method called with non LifetimeElisionKind::NewHrtbLifetime"); }; - LifetimeElisionKind::Lifetime(lifetime_ref) - } else { - unreachable!("Method called with non LifetimeElisionKind::NewLifetimeParam") - }; self.lifetime_elision_kind = new_elision_kind; + binder } pub(crate) fn update_to_late_bound_lifetimes(&mut self) { @@ -870,16 +886,8 @@ impl<'db, 'a> ExprCollector<'db, 'a> { } ast::Type::InferType(_inner) => TypeRef::Placeholder, ast::Type::FnPtrType(inner) => { - let old_binder = match self.for_type_binder { - None | Some((_, ForBinderSource::FnPtrType | ForBinderSource::ForBound)) => { - self.for_type_binder.replace((ThinVec::new(), ForBinderSource::FnPtrType)) - } - Some((_, ForBinderSource::ForType)) => None, - }; let old_elision_kind = self.elide_lifetime_for_binder(); let old_candidates = self.elision_candidates.take(); - let old_elision_binder_source = - mem::replace(&mut self.elision_binder_source, ElisionBinderSource::ForBinder); let mut is_varargs = false; let mut params = if let Some(pl) = inner.param_list() { @@ -905,7 +913,7 @@ impl<'db, 'a> ExprCollector<'db, 'a> { } else { Vec::with_capacity(1) }; - self.elide_return_lifetime(); + let elided_for_binder = self.elide_return_lifetime_for_binder(); let ret_ty = inner .ret_type() .and_then(|rt| rt.ty()) @@ -921,14 +929,8 @@ impl<'db, 'a> ExprCollector<'db, 'a> { let abi = inner.abi().map(lower_abi).unwrap_or(ExternAbi::Rust); - let binder = self - .for_type_binder - .take() - .filter(|(b, _)| !b.is_empty()) - .map(|(b, _)| b.into()); + let binder = (!elided_for_binder.is_empty()).then_some(elided_for_binder.into()); - self.for_type_binder = old_binder; - self.elision_binder_source = old_elision_binder_source; self.lifetime_elision_kind = old_elision_kind; self.elision_candidates = old_candidates; TypeRef::Fn(Box::new(FnType { @@ -942,7 +944,7 @@ impl<'db, 'a> ExprCollector<'db, 'a> { // for types are close enough for our purposes to the inner type for now... ast::Type::ForType(inner) => { let binder = self.lower_for_binder_opt(inner.for_binder()); - let ty = self.with_for_binder(binder, ForBinderSource::ForType, |ec| { + let ty = self.with_for_binder(binder, |ec| { ec.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn) }); return ty; @@ -1026,13 +1028,6 @@ impl<'db, 'a> ExprCollector<'db, 'a> { id } - fn push_elided_lifetime_in_for_binder(&mut self, name: Name) -> usize { - let (binder, _) = self.for_type_binder.as_mut().unwrap(); // Should not call this method without a for binder - let idx = binder.len(); - binder.push(name); - idx - } - fn alloc_lifetime_ref( &mut self, lifetime_ref: LifetimeRef, @@ -1089,17 +1084,6 @@ impl<'db, 'a> ExprCollector<'db, 'a> { result } - fn with_type_bound_source( - &mut self, - source: ElisionBinderSource, - f: impl FnOnce(&mut Self) -> R, - ) -> R { - let old = mem::replace(&mut self.elision_binder_source, source); - let result = f(self); - self.elision_binder_source = old; - result - } - fn with_self_param(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { self.with_param_inner(true, f) } @@ -1112,9 +1096,10 @@ impl<'db, 'a> ExprCollector<'db, 'a> { let old = self.elision_candidates.replace(ThinVec::new()); let result = f(self); + let return_lt = self.lifetime_elision_kind.get_return_lt_mut(); + if let Some(candidates) = self.elision_candidates.take() - && let LifetimeElisionKind::NewLifetimeParam { return_lt, .. } = - &mut self.lifetime_elision_kind + && let Some(return_lt) = return_lt { let distinct: FxIndexSet<_> = candidates.iter().map(|id| &self.store.lifetimes[*id]).collect(); @@ -1153,12 +1138,11 @@ impl<'db, 'a> ExprCollector<'db, 'a> { fn with_for_binder( &mut self, binder: Option>, - source: ForBinderSource, f: impl FnOnce(&mut Self) -> R, ) -> R { let old = match binder { - Some(binder) => self.for_type_binder.replace((binder, source)), - None => return f(self), + Some(binder) => self.for_type_binder.replace(binder), + None => self.for_type_binder.take(), }; let result = f(self); self.for_type_binder = old; @@ -1170,20 +1154,21 @@ impl<'db, 'a> ExprCollector<'db, 'a> { } fn lower_elided_lifetime_opt(&mut self, lifetime: Option) -> LifetimeRefId { - let lifetime_ref = match &self.lifetime_elision_kind { - &LifetimeElisionKind::NewLifetimeParam { bound_type, parent, .. } => { + let lifetime_ref = match &mut self.lifetime_elision_kind { + &mut LifetimeElisionKind::NewGenericLifetime { bound_type, parent, .. } => { let name = Name::anon_lifetime(); - if matches!(self.elision_binder_source, ElisionBinderSource::ForBinder) { - let local_id = self.push_elided_lifetime_in_for_binder(name); - let param_id = HrtbLifetimeParamId(local_id as u32); - LifetimeRef::HrtbParam(param_id) - } else { - let lifetimes = self.lifetime_arena.as_mut().unwrap(); - let parent = parent.unwrap(); - let lifetime = LifetimeParamData { name, bound_type }; - let param_id = LifetimeParamId { parent, local_id: lifetimes.alloc(lifetime) }; - LifetimeRef::Param(param_id) - } + let lifetimes = self.lifetime_arena.as_mut().unwrap(); + let parent = parent.unwrap(); + let lifetime = LifetimeParamData { name, bound_type }; + let param_id = LifetimeParamId { parent, local_id: lifetimes.alloc(lifetime) }; + LifetimeRef::Param(param_id) + } + LifetimeElisionKind::NewHrtbLifetime { binder, .. } => { + let name = Name::anon_lifetime(); + let local_id = binder.len(); + binder.push(name); + let param_id = HrtbLifetimeParamId(local_id as u32); + LifetimeRef::HrtbParam(param_id) } LifetimeElisionKind::Lifetime(lifetime_ref) => lifetime_ref.clone(), LifetimeElisionKind::Static => LifetimeRef::Static, @@ -1226,6 +1211,9 @@ impl<'db, 'a> ExprCollector<'db, 'a> { impl_trait_lower_fn: ImplTraitLowerFn<'_>, ) -> Option { let params = args?; + let old_elision_kind = self.elide_lifetime_for_binder(); + let old_candidates = self.elision_candidates.take(); + let mut param_types = Vec::new(); for param in params.type_args() { let type_ref = self.lower_type_ref_opt(param.ty(), impl_trait_lower_fn); @@ -1234,6 +1222,10 @@ impl<'db, 'a> ExprCollector<'db, 'a> { let args = Box::new([GenericArg::Type( self.alloc_type_ref_desugared(TypeRef::Tuple(ThinVec::from_iter(param_types))), )]); + + let elided_for_binder = self.elide_return_lifetime_for_binder(); + self.for_type_binder = Some(elided_for_binder); + let bindings = if let Some(ret_type) = ret_type { let type_ref = self.lower_type_ref_opt(ret_type.ty(), impl_trait_lower_fn); Box::new([AssociatedTypeBinding { @@ -1252,6 +1244,9 @@ impl<'db, 'a> ExprCollector<'db, 'a> { bounds: Box::default(), }]) }; + + self.lifetime_elision_kind = old_elision_kind; + self.elision_candidates = old_candidates; Some(GenericArgs { args, has_self_type: false, @@ -1576,17 +1571,17 @@ impl<'db, 'a> ExprCollector<'db, 'a> { let Some(kind) = node.kind() else { return TypeBound::Error }; match kind { ast::TypeBoundKind::PathType(binder, path_type) => { - let binder = self.lower_for_binder_opt(binder).unwrap_or_default(); + let binder = self.lower_for_binder_opt(binder); let m = match node.question_mark_token() { Some(_) => TraitBoundModifier::Maybe, None => TraitBoundModifier::None, }; - self.with_for_binder(Some(binder), ForBinderSource::ForBound, |ec| { + self.with_for_binder(binder, |ec| { ec.lower_path_type(&path_type, impl_trait_lower_fn) .map(|p| { let path = ec.alloc_path(p, AstPtr::new(&path_type).upcast()); let binder = ec.for_type_binder.take(); - if let Some((binder, _)) = binder + if let Some(binder) = binder && !binder.is_empty() { TypeBound::ForLifetime(binder, path) diff --git a/crates/hir-def/src/expr_store/lower/path.rs b/crates/hir-def/src/expr_store/lower/path.rs index d250c50ff4f9..63cca00ec20f 100644 --- a/crates/hir-def/src/expr_store/lower/path.rs +++ b/crates/hir-def/src/expr_store/lower/path.rs @@ -8,7 +8,7 @@ use std::iter; use crate::{ ModuleDefId, expr_store::{ - lower::{ElisionBinderSource, ExprCollector, generics::ImplTraitLowerFn}, + lower::{ExprCollector, generics::ImplTraitLowerFn}, path::NormalPath, }, item_scope::BuiltinShadowMode, @@ -103,13 +103,11 @@ pub(super) fn lower_path( .generic_arg_list() .and_then(|it| collector.lower_generic_args(it, impl_trait_lower_fn)) .or_else(|| { - 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, - ) - }) + collector.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()) diff --git a/crates/hir-def/src/expr_store/tests/signatures.rs b/crates/hir-def/src/expr_store/tests/signatures.rs index f01d82f73950..29bda53461cb 100644 --- a/crates/hir-def/src/expr_store/tests/signatures.rs +++ b/crates/hir-def/src/expr_store/tests/signatures.rs @@ -169,7 +169,7 @@ fn allowed3(baz: impl Baz>) {} {...} fn not_allowed2(Param[0]) where - Param[0]: Fn::<(&'{error} {error}), Output = ()> + Param[0]: for<'_> Fn::<(&{error}), Output = ()> {...} fn not_allowed3(Param[0]) where diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index de2a9742b0fc..18cce33c9cfe 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -904,8 +904,8 @@ fn main() { 171..182 'PhantomData': PhantomData 189..190 's': S 189..201 's.g(|_x| {})': () - 193..200 '|_x| {}': impl FnOnce(&'? i32) - 194..196 '_x': &'? i32 + 193..200 '|_x| {}': impl FnOnce(&'?0.0 i32) + 194..196 '_x': &'_ i32 198..200 '{}': () 207..208 's': S 207..214 's.f(10)': () diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index 64e802a152f7..6f124bfa7fbb 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -1430,10 +1430,10 @@ fn foo() -> (impl FnOnce(&str, T), impl Trait) { } "#, expect![[r#" - 134..165 '{ ...(C)) }': (impl FnOnce(&'? str, T), impl Trait) - 140..163 '(|inpu...ar(C))': (impl FnOnce(&'? str, T), Bar) - 141..154 '|input, t| {}': impl FnOnce(&'? str, T) - 142..147 'input': &'? str + 134..165 '{ ...(C)) }': (impl FnOnce(&'?0.0 str, T), impl Trait) + 140..163 '(|inpu...ar(C))': (impl FnOnce(&'?0.0 str, T), Bar) + 141..154 '|input, t| {}': impl FnOnce(&'?0.0 str, T) + 142..147 'input': &'_ str 149..150 't': T 152..154 '{}': () 156..159 'Bar': fn Bar(u8) -> Bar @@ -2738,12 +2738,12 @@ fn main() { 72..74 '_v': F 117..120 '{ }': () 132..163 '{ ... }); }': () - 138..148 'f::<(), _>': fn f<(), impl FnOnce(&'? ())>(impl FnOnce(&'? ())) + 138..148 'f::<(), _>': fn f<(), impl FnOnce(&'?0.0 ())>(impl FnOnce(&'?0.0 ())) 138..160 'f::<()... z; })': () - 149..159 '|z| { z; }': impl FnOnce(&'? ()) - 150..151 'z': &'? () + 149..159 '|z| { z; }': impl FnOnce(&'?0.0 ()) + 150..151 'z': &'_ () 153..159 '{ z; }': () - 155..156 'z': &'? () + 155..156 'z': &'_ () "#]], ); } @@ -3275,13 +3275,13 @@ fn foo() { 218..324 '{ ...&s); }': () 228..229 's': Option 232..236 'None': Option - 246..247 'f': Box) + 'static> - 281..310 'Box { ... {}) }': Box) + 'static> - 294..308 '&mut (|ps| {})': &'? mut impl FnOnce(&'? Option) - 300..307 '|ps| {}': impl FnOnce(&'? Option) - 301..303 'ps': &'? Option + 246..247 'f': Box) + 'static> + 281..310 'Box { ... {}) }': Box) + 'static> + 294..308 '&mut (|ps| {})': &'? mut impl FnOnce(&'_ Option) + 300..307 '|ps| {}': impl FnOnce(&'_ Option) + 301..303 'ps': &'_ Option 305..307 '{}': () - 316..317 'f': Box) + 'static> + 316..317 'f': Box) + 'static> 316..321 'f(&s)': () 318..320 '&s': &'? Option 319..320 's': Option @@ -4861,11 +4861,11 @@ fn allowed3(baz: impl Baz>) {} 184..185 'f': impl Fn({unknown}) 184..190 'f(foo)': () 186..189 'foo': S - 251..252 'f': impl Fn(&'? {unknown}) + 251..252 'f': impl Fn(&'?0.0 {unknown}) 274..307 '{ ...oo); }': () 284..287 'foo': S 290..291 'S': S - 297..298 'f': impl Fn(&'? {unknown}) + 297..298 'f': impl Fn(&'?0.0 {unknown}) 297..304 'f(&foo)': () 299..303 '&foo': &'? S 300..303 'foo': S From 232fe69c590e83b634d1801de60adf78774fe088 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Sun, 9 Aug 2026 20:56:12 +0530 Subject: [PATCH 8/8] chore: merge TypeBound::ForLifetimes into TypeBound::Path --- crates/hir-def/src/expr_store.rs | 3 +-- crates/hir-def/src/expr_store/lower.rs | 13 +++------- .../hir-def/src/expr_store/lower/generics.rs | 2 +- crates/hir-def/src/expr_store/pretty.rs | 25 +++++++++---------- crates/hir-def/src/hir/type_ref.rs | 6 ++--- crates/hir-ty/src/display.rs | 19 +++++++------- crates/hir-ty/src/lower.rs | 18 ++++++------- crates/hir/src/display.rs | 2 +- 8 files changed, 37 insertions(+), 51 deletions(-) diff --git a/crates/hir-def/src/expr_store.rs b/crates/hir-def/src/expr_store.rs index 5e6633d1cec1..2afd94aea757 100644 --- a/crates/hir-def/src/expr_store.rs +++ b/crates/hir-def/src/expr_store.rs @@ -994,8 +994,7 @@ impl StoreVisitor for &mut V { pub trait StoreVisitorExt: StoreVisitor { fn on_type_bound(&mut self, bound: &TypeBound) { match bound { - TypeBound::Path(path_id, _) => self.on_type(path_id.type_ref()), - TypeBound::ForLifetime(_, path_id) => self.on_type(path_id.type_ref()), + TypeBound::Path(_, path_id, _) => self.on_type(path_id.type_ref()), TypeBound::Lifetime(lifetime) => self.on_lifetime(*lifetime), TypeBound::Use(args) => { for arg in args { diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index 7c5ad7361160..254b3701b44d 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -448,7 +448,7 @@ pub(crate) fn lower_function( let path = PathId::from_type_ref_unchecked( expr_collector.alloc_type_ref_desugared(TypeRef::Path(path)), ); - let ty_bound = TypeBound::Path(path, TraitBoundModifier::None); + let ty_bound = TypeBound::Path(None, path, TraitBoundModifier::None); Some( expr_collector .alloc_type_ref_desugared(TypeRef::ImplTrait(ThinVec::from_iter([ty_bound]))), @@ -1580,14 +1580,9 @@ impl<'db, 'a> ExprCollector<'db, 'a> { ec.lower_path_type(&path_type, impl_trait_lower_fn) .map(|p| { let path = ec.alloc_path(p, AstPtr::new(&path_type).upcast()); - let binder = ec.for_type_binder.take(); - if let Some(binder) = binder - && !binder.is_empty() - { - TypeBound::ForLifetime(binder, path) - } else { - TypeBound::Path(path, m) - } + let binder = ec.for_type_binder.take().filter(|b| !b.is_empty()); + let m = if binder.is_some() { TraitBoundModifier::None } else { m }; + TypeBound::Path(binder, path, m) }) .unwrap_or(TypeBound::Error) }) diff --git a/crates/hir-def/src/expr_store/lower/generics.rs b/crates/hir-def/src/expr_store/lower/generics.rs index 5bff54610f22..3267833b02d0 100644 --- a/crates/hir-def/src/expr_store/lower/generics.rs +++ b/crates/hir-def/src/expr_store/lower/generics.rs @@ -234,7 +234,7 @@ impl GenericParamsCollector { (Either::Right(lifetime), TypeBound::Lifetime(bound)) => { WherePredicate::Lifetime { target: lifetime, bound } } - (Either::Right(_), TypeBound::ForLifetime(..) | TypeBound::Path(..)) => return, + (Either::Right(_), TypeBound::Path(..)) => return, }; if let WherePredicate::Lifetime { target, .. } = predicate { ec.push_named_target_lifetime(target); diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs index 7406845fe3a1..b7ca0b3d1063 100644 --- a/crates/hir-def/src/expr_store/pretty.rs +++ b/crates/hir-def/src/expr_store/pretty.rs @@ -1390,25 +1390,24 @@ impl Printer<'_> { } match bound { - TypeBound::Path(path, modifier) => { + TypeBound::Path(binder, path, modifier) => { + if let Some(lifetimes) = binder { + w!( + self, + "for<{}> ", + lifetimes + .iter() + .map(|it| it.display(self.db, self.edition)) + .format(", ") + .to_string() + ); + } match modifier { TraitBoundModifier::None => (), TraitBoundModifier::Maybe => w!(self, "?"), } self.print_path(&self.store[*path]); } - TypeBound::ForLifetime(lifetimes, path) => { - w!( - self, - "for<{}> ", - lifetimes - .iter() - .map(|it| it.display(self.db, self.edition)) - .format(", ") - .to_string() - ); - self.print_path(&self.store[*path]); - } TypeBound::Lifetime(lt) => self.print_lifetime_ref(*lt), TypeBound::Use(args) => { w!(self, "use<"); diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs index edfabc5bda14..c80dbc4877c0 100644 --- a/crates/hir-def/src/hir/type_ref.rs +++ b/crates/hir-def/src/hir/type_ref.rs @@ -164,8 +164,7 @@ pub enum LifetimeRef { #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub enum TypeBound { - Path(PathId, TraitBoundModifier), - ForLifetime(ThinVec, PathId), + Path(Option>, PathId, TraitBoundModifier), Lifetime(LifetimeRefId), Use(ThinVec), Error, @@ -197,8 +196,7 @@ impl TypeRef { impl TypeBound { pub fn as_path<'a>(&self, map: &'a ExpressionStore) -> Option<(&'a Path, TraitBoundModifier)> { match self { - &TypeBound::Path(p, m) => Some((&map[p], m)), - &TypeBound::ForLifetime(_, p) => Some((&map[p], TraitBoundModifier::None)), + &TypeBound::Path(_, p, m) => Some((&map[p], m)), TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => None, } } diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 7ae0b319ba7a..8a7dc0e11cb6 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -2637,7 +2637,15 @@ impl<'db> HirDisplayWithExpressionStore<'db> for TypeBound { store: &ExpressionStore, ) -> Result { match self { - &TypeBound::Path(path, modifier) => { + &TypeBound::Path(ref binder, path, modifier) => { + if let Some(lifetimes) = binder { + let edition = f.edition(); + write!( + f, + "for<{}> ", + lifetimes.iter().map(|it| it.display(f.db, edition)).format(", ") + )?; + } match modifier { TraitBoundModifier::None => (), TraitBoundModifier::Maybe => write!(f, "?")?, @@ -2645,15 +2653,6 @@ impl<'db> HirDisplayWithExpressionStore<'db> for TypeBound { store[path].hir_fmt(f, owner, store) } TypeBound::Lifetime(lifetime) => lifetime.hir_fmt(f, owner, store), - TypeBound::ForLifetime(lifetimes, path) => { - let edition = f.edition(); - write!( - f, - "for<{}> ", - lifetimes.iter().map(|it| it.display(f.db, edition)).format(", ") - )?; - store[*path].hir_fmt(f, owner, store) - } TypeBound::Use(args) => { write!(f, "use<")?; let edition = f.edition(); diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 9a96b86cac7a..1215e73b26d7 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -853,7 +853,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() { // trait object type without dyn - let bound = TypeBound::Path(path_id, TraitBoundModifier::None); + let bound = TypeBound::Path(None, path_id, TraitBoundModifier::None); let ty = self.lower_dyn_trait(&[bound]); return (ty, None); } @@ -974,11 +974,11 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { }; match bound { - &TypeBound::ForLifetime(ref binder, path) => { + &TypeBound::Path(Some(ref binder), path, _) => { self.with_shifted_in(binder, |ctx| lower_path_bound(ctx, path)).0 } - &TypeBound::Path(path, TraitBoundModifier::None) => lower_path_bound(self, path), - &TypeBound::Path(path, TraitBoundModifier::Maybe) => { + &TypeBound::Path(None, path, TraitBoundModifier::None) => lower_path_bound(self, path), + &TypeBound::Path(None, path, TraitBoundModifier::Maybe) => { let sized_trait = self.lang_items.Sized; // Don't lower associated type bindings as the only possible relaxed trait bound // `?Sized` has no of them. @@ -1031,7 +1031,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { for b in bounds { let db = self.db; match b { - TypeBound::Path(_, TraitBoundModifier::None) => { + TypeBound::Path(None, _, TraitBoundModifier::None) => { // `dyn Trait<'a>` is an existential predicate that introduces a binder. self.with_shifted_in(&[], |ctx| { ctx.lower_type_bound(b, dummy_self_ty, false) @@ -2033,9 +2033,7 @@ impl SupertraitsInfo { let WherePredicate::TypeBound { lifetimes: _, target, bound } = pred else { continue; }; - let (TypeBound::Path(bounded_trait, TraitBoundModifier::None) - | TypeBound::ForLifetime(_, bounded_trait)) = *bound - else { + let TypeBound::Path(_, bounded_trait, TraitBoundModifier::None) = *bound else { continue; }; let target = &signature.store[*target]; @@ -2149,9 +2147,7 @@ fn resolve_type_param_assoc_type_shorthand( let WherePredicate::TypeBound { lifetimes: _, target, bound } = pred else { continue; }; - let (TypeBound::Path(bounded_trait_path, TraitBoundModifier::None) - | TypeBound::ForLifetime(_, bounded_trait_path)) = *bound - else { + let TypeBound::Path(_, bounded_trait_path, TraitBoundModifier::None) = *bound else { continue; }; let Some(target) = ctx.lower_ty_only_param(*target) else { continue }; diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index c76b42caec79..27a95f1ce122 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -246,7 +246,7 @@ fn write_function<'db>(f: &mut HirFormatter<'_, 'db>, func_id: FunctionId) -> Re } else if let Some(ret_type) = data.ret_type { match &data.store[ret_type] { TypeRef::ImplTrait(bounds) => match &bounds[0] { - &TypeBound::Path(path, _) => Some( + &TypeBound::Path(_, path, _) => Some( *data.store[path] .segments() .iter()