@@ -5,7 +5,7 @@ use hir_def::{
5
5
layout:: { Layout , LayoutError } ,
6
6
} ;
7
7
8
- use crate :: { test_db:: TestDB , Interner , Substitution } ;
8
+ use crate :: { db :: HirDatabase , test_db:: TestDB , Interner , Substitution } ;
9
9
10
10
use super :: layout_of_ty;
11
11
@@ -45,13 +45,64 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Layout, LayoutError> {
45
45
layout_of_ty ( & db, & goal_ty, module_id. krate ( ) )
46
46
}
47
47
48
+ /// A version of `eval_goal` for types that can not be expressed in ADTs, like closures and `impl Trait`
49
+ fn eval_expr ( ra_fixture : & str , minicore : & str ) -> Result < Layout , LayoutError > {
50
+ // using unstable cargo features failed, fall back to using plain rustc
51
+ let mut cmd = std:: process:: Command :: new ( "rustc" ) ;
52
+ cmd. args ( [ "-Z" , "unstable-options" , "--print" , "target-spec-json" ] ) . env ( "RUSTC_BOOTSTRAP" , "1" ) ;
53
+ let output = cmd. output ( ) . unwrap ( ) ;
54
+ assert ! ( output. status. success( ) , "{}" , output. status) ;
55
+ let stdout = String :: from_utf8 ( output. stdout ) . unwrap ( ) ;
56
+ let target_data_layout =
57
+ stdout. split_once ( r#""data-layout": ""# ) . unwrap ( ) . 1 . split_once ( '"' ) . unwrap ( ) . 0 . to_owned ( ) ;
58
+
59
+ let ra_fixture = format ! (
60
+ "{minicore}//- /main.rs crate:test target_data_layout:{target_data_layout}\n fn main(){{let goal = {{{ra_fixture}}};}}" ,
61
+ ) ;
62
+
63
+ let ( db, file_id) = TestDB :: with_single_file ( & ra_fixture) ;
64
+ let module_id = db. module_for_file ( file_id) ;
65
+ let def_map = module_id. def_map ( & db) ;
66
+ let scope = & def_map[ module_id. local_id ] . scope ;
67
+ let adt_id = scope
68
+ . declarations ( )
69
+ . find_map ( |x| match x {
70
+ hir_def:: ModuleDefId :: FunctionId ( x) => {
71
+ let name = db. function_data ( x) . name . to_smol_str ( ) ;
72
+ ( name == "main" ) . then_some ( x)
73
+ }
74
+ _ => None ,
75
+ } )
76
+ . unwrap ( ) ;
77
+ let hir_body = db. body ( adt_id. into ( ) ) ;
78
+ let pat = hir_body
79
+ . pats
80
+ . iter ( )
81
+ . find ( |x| match x. 1 {
82
+ hir_def:: expr:: Pat :: Bind { name, .. } => name. to_smol_str ( ) == "goal" ,
83
+ _ => false ,
84
+ } )
85
+ . unwrap ( )
86
+ . 0 ;
87
+ let infer = db. infer ( adt_id. into ( ) ) ;
88
+ let goal_ty = infer. type_of_pat [ pat] . clone ( ) ;
89
+ layout_of_ty ( & db, & goal_ty, module_id. krate ( ) )
90
+ }
91
+
48
92
#[ track_caller]
49
93
fn check_size_and_align ( ra_fixture : & str , minicore : & str , size : u64 , align : u64 ) {
50
94
let l = eval_goal ( ra_fixture, minicore) . unwrap ( ) ;
51
95
assert_eq ! ( l. size. bytes( ) , size) ;
52
96
assert_eq ! ( l. align. abi. bytes( ) , align) ;
53
97
}
54
98
99
+ #[ track_caller]
100
+ fn check_size_and_align_expr ( ra_fixture : & str , minicore : & str , size : u64 , align : u64 ) {
101
+ let l = eval_expr ( ra_fixture, minicore) . unwrap ( ) ;
102
+ assert_eq ! ( l. size. bytes( ) , size) ;
103
+ assert_eq ! ( l. align. abi. bytes( ) , align) ;
104
+ }
105
+
55
106
#[ track_caller]
56
107
fn check_fail ( ra_fixture : & str , e : LayoutError ) {
57
108
let r = eval_goal ( ra_fixture, "" ) ;
@@ -85,11 +136,31 @@ macro_rules! size_and_align {
85
136
} ;
86
137
}
87
138
139
+ macro_rules! size_and_align_expr {
140
+ ( $( $t: tt) * ) => {
141
+ {
142
+ #[ allow( dead_code) ]
143
+ {
144
+ let val = { $( $t) * } ;
145
+ check_size_and_align_expr(
146
+ stringify!( $( $t) * ) ,
147
+ "" ,
148
+ :: std:: mem:: size_of_val( & val) as u64 ,
149
+ :: std:: mem:: align_of_val( & val) as u64 ,
150
+ ) ;
151
+ }
152
+ }
153
+ } ;
154
+ }
155
+
88
156
#[ test]
89
157
fn hello_world ( ) {
90
158
size_and_align ! {
91
159
struct Goal ( i32 ) ;
92
160
}
161
+ size_and_align_expr ! {
162
+ 2i32
163
+ }
93
164
}
94
165
95
166
#[ test]
@@ -143,6 +214,40 @@ fn generic() {
143
214
}
144
215
}
145
216
217
+ #[ test]
218
+ fn return_position_impl_trait ( ) {
219
+ size_and_align_expr ! {
220
+ trait T { }
221
+ impl T for i32 { }
222
+ impl T for i64 { }
223
+ fn foo( ) -> impl T { 2i64 }
224
+ foo( )
225
+ }
226
+ size_and_align_expr ! {
227
+ trait T { }
228
+ impl T for i32 { }
229
+ impl T for i64 { }
230
+ fn foo( ) -> ( impl T , impl T , impl T ) { ( 2i64 , 5i32 , 7i32 ) }
231
+ foo( )
232
+ }
233
+ size_and_align_expr ! {
234
+ struct Foo <T >( T , T , ( T , T ) ) ;
235
+ trait T { }
236
+ impl T for Foo <i32 > { }
237
+ impl T for Foo <i64 > { }
238
+
239
+ fn foo( ) -> Foo <impl T > { Foo (
240
+ Foo ( 1i64 , 2 , ( 3 , 4 ) ) ,
241
+ Foo ( 5 , 6 , ( 7 , 8 ) ) ,
242
+ (
243
+ Foo ( 1i64 , 2 , ( 3 , 4 ) ) ,
244
+ Foo ( 5 , 6 , ( 7 , 8 ) ) ,
245
+ ) ,
246
+ ) }
247
+ foo( )
248
+ }
249
+ }
250
+
146
251
#[ test]
147
252
fn enums ( ) {
148
253
size_and_align ! {
0 commit comments