@@ -157,7 +157,7 @@ fn complete_trait_impl(
157157 add_function_impl ( acc, ctx, replacement_range, func, hir_impl)
158158 }
159159 ( hir:: AssocItem :: TypeAlias ( type_alias) , All | TypeAlias ) => {
160- add_type_alias_impl ( acc, ctx, replacement_range, type_alias)
160+ add_type_alias_impl ( acc, ctx, replacement_range, type_alias, hir_impl )
161161 }
162162 ( hir:: AssocItem :: Const ( const_) , All | Const ) => {
163163 add_const_impl ( acc, ctx, replacement_range, const_, hir_impl)
@@ -247,24 +247,50 @@ fn add_type_alias_impl(
247247 ctx : & CompletionContext < ' _ > ,
248248 replacement_range : TextRange ,
249249 type_alias : hir:: TypeAlias ,
250+ impl_def : hir:: Impl ,
250251) {
251- let alias_name = type_alias. name ( ctx. db ) ;
252- let ( alias_name, escaped_name) =
253- ( alias_name. unescaped ( ) . to_smol_str ( ) , alias_name. to_smol_str ( ) ) ;
252+ let alias_name = type_alias. name ( ctx. db ) . unescaped ( ) . to_smol_str ( ) ;
254253
255254 let label = format ! ( "type {} =" , alias_name) ;
256- let replacement = format ! ( "type {} = " , escaped_name) ;
257255
258256 let mut item = CompletionItem :: new ( SymbolKind :: TypeAlias , replacement_range, label) ;
259257 item. lookup_by ( format ! ( "type {}" , alias_name) )
260258 . set_documentation ( type_alias. docs ( ctx. db ) )
261259 . set_relevance ( CompletionRelevance { is_item_from_trait : true , ..Default :: default ( ) } ) ;
262- match ctx. config . snippet_cap {
263- Some ( cap) => item
264- . snippet_edit ( cap, TextEdit :: replace ( replacement_range, format ! ( "{}$0;" , replacement) ) ) ,
265- None => item. text_edit ( TextEdit :: replace ( replacement_range, replacement) ) ,
266- } ;
267- item. add_to ( acc) ;
260+
261+ if let Some ( source) = ctx. sema . source ( type_alias) {
262+ let assoc_item = ast:: AssocItem :: TypeAlias ( source. value ) ;
263+ if let Some ( transformed_item) = get_transformed_assoc_item ( ctx, assoc_item, impl_def) {
264+ let transformed_ty = match transformed_item {
265+ ast:: AssocItem :: TypeAlias ( ty) => ty,
266+ _ => unreachable ! ( ) ,
267+ } ;
268+
269+ let start = transformed_ty. syntax ( ) . text_range ( ) . start ( ) ;
270+ let Some ( end) = transformed_ty
271+ . eq_token ( )
272+ . map ( |tok| tok. text_range ( ) . start ( ) )
273+ . or ( transformed_ty. semicolon_token ( ) . map ( |tok| tok. text_range ( ) . start ( ) ) ) else { return } ;
274+
275+ let len = end - start;
276+ let mut decl = transformed_ty. syntax ( ) . text ( ) . slice ( ..len) . to_string ( ) ;
277+ if !decl. ends_with ( ' ' ) {
278+ decl. push ( ' ' ) ;
279+ }
280+ decl. push_str ( "= " ) ;
281+
282+ match ctx. config . snippet_cap {
283+ Some ( cap) => {
284+ let snippet = format ! ( "{}$0;" , decl) ;
285+ item. snippet_edit ( cap, TextEdit :: replace ( replacement_range, snippet) ) ;
286+ }
287+ None => {
288+ item. text_edit ( TextEdit :: replace ( replacement_range, decl) ) ;
289+ }
290+ } ;
291+ item. add_to ( acc) ;
292+ }
293+ }
268294}
269295
270296fn add_const_impl (
@@ -350,9 +376,7 @@ fn function_declaration(node: &ast::Fn, needs_whitespace: bool) -> String {
350376 . map_or ( end, |f| f. text_range ( ) . start ( ) ) ;
351377
352378 let len = end - start;
353- let range = TextRange :: new ( 0 . into ( ) , len) ;
354-
355- let syntax = node. text ( ) . slice ( range) . to_string ( ) ;
379+ let syntax = node. text ( ) . slice ( ..len) . to_string ( ) ;
356380
357381 syntax. trim_end ( ) . to_owned ( )
358382}
@@ -1160,6 +1184,31 @@ impl Foo for Test {
11601184 $0
11611185}
11621186}
1187+ "# ,
1188+ ) ;
1189+ }
1190+
1191+ #[ test]
1192+ fn includes_gat_generics ( ) {
1193+ check_edit (
1194+ "type Ty" ,
1195+ r#"
1196+ trait Tr<'b> {
1197+ type Ty<'a: 'b, T: Copy, const C: usize>;
1198+ }
1199+
1200+ impl<'b> Tr<'b> for () {
1201+ $0
1202+ }
1203+ "# ,
1204+ r#"
1205+ trait Tr<'b> {
1206+ type Ty<'a: 'b, T: Copy, const C: usize>;
1207+ }
1208+
1209+ impl<'b> Tr<'b> for () {
1210+ type Ty<'a: 'b, T: Copy, const C: usize> = $0;
1211+ }
11631212"# ,
11641213 ) ;
11651214 }
0 commit comments