mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 03:54:42 +00:00 
			
		
		
		
	Test unsafeness is respected when manual impling derives
This commit is contained in:
		
							parent
							
								
									824df43d2d
								
							
						
					
					
						commit
						1afbcc06f3
					
				
					 1 changed files with 45 additions and 5 deletions
				
			
		|  | @ -131,7 +131,7 @@ fn add_assist( | ||||||
|         target, |         target, | ||||||
|         |builder| { |         |builder| { | ||||||
|             let insert_after = ted::Position::after(builder.make_mut(adt.clone()).syntax()); |             let insert_after = ted::Position::after(builder.make_mut(adt.clone()).syntax()); | ||||||
| 
 |             let impl_is_unsafe = trait_.map(|s| s.is_unsafe(ctx.db())).unwrap_or(false); | ||||||
|             let impl_def_with_items = |             let impl_def_with_items = | ||||||
|                 impl_def_from_trait(&ctx.sema, adt, &annotated_name, trait_, replace_trait_path); |                 impl_def_from_trait(&ctx.sema, adt, &annotated_name, trait_, replace_trait_path); | ||||||
|             update_attribute(builder, old_derives, old_tree, old_trait_path, attr); |             update_attribute(builder, old_derives, old_tree, old_trait_path, attr); | ||||||
|  | @ -141,6 +141,12 @@ fn add_assist( | ||||||
|             match (ctx.config.snippet_cap, impl_def_with_items) { |             match (ctx.config.snippet_cap, impl_def_with_items) { | ||||||
|                 (None, None) => { |                 (None, None) => { | ||||||
|                     let impl_def = generate_trait_impl(adt, trait_path); |                     let impl_def = generate_trait_impl(adt, trait_path); | ||||||
|  |                     if impl_is_unsafe { | ||||||
|  |                         ted::insert( | ||||||
|  |                             Position::first_child_of(impl_def.syntax()), | ||||||
|  |                             make::token(T![unsafe]), | ||||||
|  |                         ); | ||||||
|  |                     } | ||||||
| 
 | 
 | ||||||
|                     ted::insert_all( |                     ted::insert_all( | ||||||
|                         insert_after, |                         insert_after, | ||||||
|  | @ -148,6 +154,12 @@ fn add_assist( | ||||||
|                     ); |                     ); | ||||||
|                 } |                 } | ||||||
|                 (None, Some((impl_def, _))) => { |                 (None, Some((impl_def, _))) => { | ||||||
|  |                     if impl_is_unsafe { | ||||||
|  |                         ted::insert( | ||||||
|  |                             Position::first_child_of(impl_def.syntax()), | ||||||
|  |                             make::token(T![unsafe]), | ||||||
|  |                         ); | ||||||
|  |                     } | ||||||
|                     ted::insert_all( |                     ted::insert_all( | ||||||
|                         insert_after, |                         insert_after, | ||||||
|                         vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()], |                         vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()], | ||||||
|  | @ -156,6 +168,13 @@ fn add_assist( | ||||||
|                 (Some(cap), None) => { |                 (Some(cap), None) => { | ||||||
|                     let impl_def = generate_trait_impl(adt, trait_path); |                     let impl_def = generate_trait_impl(adt, trait_path); | ||||||
| 
 | 
 | ||||||
|  |                     if impl_is_unsafe { | ||||||
|  |                         ted::insert( | ||||||
|  |                             Position::first_child_of(impl_def.syntax()), | ||||||
|  |                             make::token(T![unsafe]), | ||||||
|  |                         ); | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|                     if let Some(l_curly) = |                     if let Some(l_curly) = | ||||||
|                         impl_def.assoc_item_list().and_then(|it| it.l_curly_token()) |                         impl_def.assoc_item_list().and_then(|it| it.l_curly_token()) | ||||||
|                     { |                     { | ||||||
|  | @ -169,6 +188,14 @@ fn add_assist( | ||||||
|                 } |                 } | ||||||
|                 (Some(cap), Some((impl_def, first_assoc_item))) => { |                 (Some(cap), Some((impl_def, first_assoc_item))) => { | ||||||
|                     let mut added_snippet = false; |                     let mut added_snippet = false; | ||||||
|  | 
 | ||||||
|  |                     if impl_is_unsafe { | ||||||
|  |                         ted::insert( | ||||||
|  |                             Position::first_child_of(impl_def.syntax()), | ||||||
|  |                             make::token(T![unsafe]), | ||||||
|  |                         ); | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|                     if let ast::AssocItem::Fn(ref func) = first_assoc_item { |                     if let ast::AssocItem::Fn(ref func) = first_assoc_item { | ||||||
|                         if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast) |                         if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast) | ||||||
|                         { |                         { | ||||||
|  | @ -223,10 +250,6 @@ fn impl_def_from_trait( | ||||||
|     let first_assoc_item = |     let first_assoc_item = | ||||||
|         add_trait_assoc_items_to_impl(sema, &trait_items, trait_, &impl_def, &target_scope); |         add_trait_assoc_items_to_impl(sema, &trait_items, trait_, &impl_def, &target_scope); | ||||||
| 
 | 
 | ||||||
|     if trait_.is_unsafe(sema.db) { |  | ||||||
|         ted::insert(Position::first_child_of(impl_def.syntax()), make::token(T![unsafe])); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Generate a default `impl` function body for the derived trait.
 |     // Generate a default `impl` function body for the derived trait.
 | ||||||
|     if let ast::AssocItem::Fn(ref func) = first_assoc_item { |     if let ast::AssocItem::Fn(ref func) = first_assoc_item { | ||||||
|         let _ = gen_trait_fn_body(func, trait_path, adt, None); |         let _ = gen_trait_fn_body(func, trait_path, adt, None); | ||||||
|  | @ -1406,6 +1429,23 @@ impl core::fmt::Debug for Foo { | ||||||
|         f.debug_struct("Foo").finish() |         f.debug_struct("Foo").finish() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | "#,
 | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn unsafeness_of_a_trait_observed() { | ||||||
|  |         check_assist( | ||||||
|  |             replace_derive_with_manual_impl, | ||||||
|  |             r#" | ||||||
|  | //- minicore: send, derive
 | ||||||
|  | #[derive(Sen$0d)] | ||||||
|  | pub struct Foo; | ||||||
|  | "#,
 | ||||||
|  |             r#" | ||||||
|  | pub struct Foo; | ||||||
|  | 
 | ||||||
|  | unsafe impl Send for Foo {$0} | ||||||
| "#,
 | "#,
 | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Ali Bektas
						Ali Bektas