@@ -5,7 +5,7 @@ use hir_def::{
55 layout:: { Layout , LayoutError } ,
66} ;
77
8- use crate :: { test_db:: TestDB , Interner , Substitution } ;
8+ use crate :: { db :: HirDatabase , test_db:: TestDB , Interner , Substitution } ;
99
1010use super :: layout_of_ty;
1111
@@ -45,13 +45,64 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Layout, LayoutError> {
4545 layout_of_ty ( & db, & goal_ty, module_id. krate ( ) )
4646}
4747
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+
4892#[ track_caller]
4993fn check_size_and_align ( ra_fixture : & str , minicore : & str , size : u64 , align : u64 ) {
5094 let l = eval_goal ( ra_fixture, minicore) . unwrap ( ) ;
5195 assert_eq ! ( l. size. bytes( ) , size) ;
5296 assert_eq ! ( l. align. abi. bytes( ) , align) ;
5397}
5498
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+
55106#[ track_caller]
56107fn check_fail ( ra_fixture : & str , e : LayoutError ) {
57108 let r = eval_goal ( ra_fixture, "" ) ;
@@ -85,11 +136,31 @@ macro_rules! size_and_align {
85136 } ;
86137}
87138
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+
88156#[ test]
89157fn hello_world ( ) {
90158 size_and_align ! {
91159 struct Goal ( i32 ) ;
92160 }
161+ size_and_align_expr ! {
162+ 2i32
163+ }
93164}
94165
95166#[ test]
@@ -143,6 +214,40 @@ fn generic() {
143214 }
144215}
145216
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+
146251#[ test]
147252fn enums ( ) {
148253 size_and_align ! {
0 commit comments