1
1
use either:: Either ;
2
2
use hir:: {
3
3
db:: { AstDatabase , HirDatabase } ,
4
- known, HirDisplay , InFile , SemanticsScope , Type ,
4
+ known, AssocItem , HirDisplay , InFile , Type ,
5
5
} ;
6
6
use ide_db:: { assists:: Assist , helpers:: FamousDefs , source_change:: SourceChange } ;
7
7
use rustc_hash:: FxHashMap ;
@@ -74,8 +74,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
74
74
let generate_fill_expr = |ty : & Type | match ctx. config . expr_fill_default {
75
75
crate :: ExprFillDefaultMode :: Todo => Some ( make:: ext:: expr_todo ( ) ) ,
76
76
crate :: ExprFillDefaultMode :: DefaultImpl => {
77
- let scope = ctx. sema . scope ( & root) ;
78
- let default_constr = get_default_constructor ( ctx, d, & scope, ty) ;
77
+ let default_constr = get_default_constructor ( ctx, d, ty) ;
79
78
match default_constr {
80
79
Some ( default_constr) => Some ( default_constr) ,
81
80
_ => Some ( make:: ext:: expr_todo ( ) ) ,
@@ -134,7 +133,6 @@ fn make_ty(ty: &hir::Type, db: &dyn HirDatabase, module: hir::Module) -> ast::Ty
134
133
fn get_default_constructor (
135
134
ctx : & DiagnosticsContext < ' _ > ,
136
135
d : & hir:: MissingFields ,
137
- scope : & SemanticsScope ,
138
136
ty : & Type ,
139
137
) -> Option < ast:: Expr > {
140
138
if let Some ( builtin_ty) = ty. as_builtin ( ) {
@@ -151,33 +149,35 @@ fn get_default_constructor(
151
149
return Some ( make:: ext:: empty_str ( ) ) ;
152
150
}
153
151
}
152
+
154
153
let krate = ctx. sema . to_module_def ( d. file . original_file ( ctx. sema . db ) ) ?. krate ( ) ;
155
154
let module = krate. root_module ( ctx. sema . db ) ;
156
- let default_trait = FamousDefs ( & ctx. sema , Some ( krate) ) . core_default_Default ( ) ?;
157
- let traits_in_scope = scope. visible_traits ( ) ;
158
155
159
- // Look for a ::new() method
160
- // FIXME: doesn't work for now
161
- let has_new_method = ty
162
- . iterate_method_candidates (
163
- ctx. sema . db ,
164
- krate,
165
- & traits_in_scope,
166
- Some ( & known:: new) ,
167
- |_, func| {
168
- if func. assoc_fn_params ( ctx. sema . db ) . is_empty ( )
156
+ // Look for a ::new() associated function
157
+ let has_new_func = ty
158
+ . iterate_assoc_items ( ctx. sema . db , krate, |assoc_item| {
159
+ if let AssocItem :: Function ( func) = assoc_item {
160
+ if func. name ( ctx. sema . db ) == known:: new
161
+ && func. assoc_fn_params ( ctx. sema . db ) . is_empty ( )
169
162
&& func. self_param ( ctx. sema . db ) . is_none ( )
170
163
{
171
164
return Some ( ( ) ) ;
172
165
}
173
- None
174
- } ,
175
- )
166
+ }
167
+
168
+ None
169
+ } )
176
170
. is_some ( ) ;
177
171
178
- if has_new_method {
172
+ if has_new_func {
179
173
Some ( make:: ext:: expr_ty_new ( & make_ty ( ty, ctx. sema . db , module) ) )
180
- } else if !ty. is_array ( ) && ty. impls_trait ( ctx. sema . db , default_trait, & [ ] ) {
174
+ } else if !ty. is_array ( )
175
+ && ty. impls_trait (
176
+ ctx. sema . db ,
177
+ FamousDefs ( & ctx. sema , Some ( krate) ) . core_default_Default ( ) ?,
178
+ & [ ] ,
179
+ )
180
+ {
181
181
Some ( make:: ext:: expr_ty_default ( & make_ty ( ty, ctx. sema . db , module) ) )
182
182
} else {
183
183
None
@@ -264,7 +264,7 @@ fn here() {}
264
264
macro_rules! id { ($($tt:tt)*) => { $($tt)*}; }
265
265
266
266
fn main() {
267
- let _x = id![Foo {a:42, b: todo!() }];
267
+ let _x = id![Foo {a:42, b: 0 }];
268
268
}
269
269
270
270
pub struct Foo { pub a: i32, pub b: i32 }
@@ -286,7 +286,7 @@ fn test_fn() {
286
286
struct TestStruct { one: i32, two: i64 }
287
287
288
288
fn test_fn() {
289
- let s = TestStruct { one: todo!() , two: todo!() };
289
+ let s = TestStruct { one: 0 , two: 0 };
290
290
}
291
291
"# ,
292
292
) ;
@@ -306,7 +306,7 @@ impl TestStruct {
306
306
struct TestStruct { one: i32 }
307
307
308
308
impl TestStruct {
309
- fn test_fn() { let s = Self { one: todo!() }; }
309
+ fn test_fn() { let s = Self { one: 0 }; }
310
310
}
311
311
"# ,
312
312
) ;
@@ -354,7 +354,72 @@ fn test_fn() {
354
354
struct TestStruct { one: i32, two: i64 }
355
355
356
356
fn test_fn() {
357
- let s = TestStruct{ two: 2, one: todo!() };
357
+ let s = TestStruct{ two: 2, one: 0 };
358
+ }
359
+ " ,
360
+ ) ;
361
+ }
362
+
363
+ #[ test]
364
+ fn test_fill_struct_fields_new ( ) {
365
+ check_fix (
366
+ r#"
367
+ struct TestWithNew(usize);
368
+ impl TestWithNew {
369
+ pub fn new() -> Self {
370
+ Self(0)
371
+ }
372
+ }
373
+ struct TestStruct { one: i32, two: TestWithNew }
374
+
375
+ fn test_fn() {
376
+ let s = TestStruct{ $0 };
377
+ }
378
+ "# ,
379
+ r"
380
+ struct TestWithNew(usize);
381
+ impl TestWithNew {
382
+ pub fn new() -> Self {
383
+ Self(0)
384
+ }
385
+ }
386
+ struct TestStruct { one: i32, two: TestWithNew }
387
+
388
+ fn test_fn() {
389
+ let s = TestStruct{ one: 0, two: TestWithNew::new() };
390
+ }
391
+ " ,
392
+ ) ;
393
+ }
394
+
395
+ #[ test]
396
+ fn test_fill_struct_fields_default ( ) {
397
+ check_fix (
398
+ r#"
399
+ //- minicore: default
400
+ struct TestWithDefault(usize);
401
+ impl Default for TestWithDefault {
402
+ pub fn default() -> Self {
403
+ Self(0)
404
+ }
405
+ }
406
+ struct TestStruct { one: i32, two: TestWithDefault }
407
+
408
+ fn test_fn() {
409
+ let s = TestStruct{ $0 };
410
+ }
411
+ "# ,
412
+ r"
413
+ struct TestWithDefault(usize);
414
+ impl Default for TestWithDefault {
415
+ pub fn default() -> Self {
416
+ Self(0)
417
+ }
418
+ }
419
+ struct TestStruct { one: i32, two: TestWithDefault }
420
+
421
+ fn test_fn() {
422
+ let s = TestStruct{ one: 0, two: TestWithDefault::default() };
358
423
}
359
424
" ,
360
425
) ;
@@ -374,7 +439,7 @@ fn test_fn() {
374
439
struct TestStruct { r#type: u8 }
375
440
376
441
fn test_fn() {
377
- TestStruct { r#type: todo!() };
442
+ TestStruct { r#type: 0 };
378
443
}
379
444
" ,
380
445
) ;
@@ -485,7 +550,7 @@ fn f() {
485
550
let b = 1usize;
486
551
S {
487
552
a,
488
- b: todo!() ,
553
+ b: 0 ,
489
554
};
490
555
}
491
556
"# ,
0 commit comments