2019-12-03 12:38:54 +00:00
use insta ::assert_snapshot ;
use ra_db ::fixture ::WithFixture ;
2020-05-20 10:59:20 +00:00
use test_utils ::mark ;
2019-12-15 20:06:08 +00:00
use crate ::test_db ::TestDB ;
2019-12-03 12:38:54 +00:00
2020-05-20 10:59:20 +00:00
use super ::{ infer , infer_with_mismatches , type_at , type_at_pos } ;
2019-12-03 12:38:54 +00:00
#[ test ]
fn infer_await ( ) {
let ( db , pos ) = TestDB ::with_position (
r #"
2020-06-11 14:22:31 +00:00
//- /main.rs crate:main deps:core
2019-12-03 12:38:54 +00:00
struct IntFuture ;
impl Future for IntFuture {
type Output = u64 ;
}
fn test ( ) {
let r = IntFuture ;
let v = r . await ;
v < | > ;
}
2020-06-11 14:22:31 +00:00
//- /core.rs crate:core
2019-12-03 12:38:54 +00:00
#[ prelude_import ] use future ::* ;
mod future {
2019-12-29 16:39:31 +00:00
#[ lang = " future_trait " ]
2019-12-03 12:38:54 +00:00
trait Future {
type Output ;
}
}
" #,
) ;
assert_eq! ( " u64 " , type_at_pos ( & db , pos ) ) ;
}
2019-12-24 11:45:28 +00:00
#[ test ]
fn infer_async ( ) {
let ( db , pos ) = TestDB ::with_position (
r #"
2020-06-11 14:22:31 +00:00
//- /main.rs crate:main deps:core
2019-12-24 11:45:28 +00:00
async fn foo ( ) -> u64 {
128
}
fn test ( ) {
let r = foo ( ) ;
let v = r . await ;
v < | > ;
}
2020-06-11 14:22:31 +00:00
//- /core.rs crate:core
2019-12-24 11:45:28 +00:00
#[ prelude_import ] use future ::* ;
mod future {
2019-12-29 16:39:31 +00:00
#[ lang = " future_trait " ]
2019-12-24 11:45:28 +00:00
trait Future {
type Output ;
}
}
" #,
) ;
assert_eq! ( " u64 " , type_at_pos ( & db , pos ) ) ;
}
#[ test ]
fn infer_desugar_async ( ) {
let ( db , pos ) = TestDB ::with_position (
r #"
2020-06-11 14:22:31 +00:00
//- /main.rs crate:main deps:core
2019-12-24 11:45:28 +00:00
async fn foo ( ) -> u64 {
128
}
fn test ( ) {
let r = foo ( ) ;
r < | > ;
}
2020-06-11 14:22:31 +00:00
//- /core.rs crate:core
2019-12-24 11:45:28 +00:00
#[ prelude_import ] use future ::* ;
mod future {
trait Future {
type Output ;
}
}
" #,
) ;
assert_eq! ( " impl Future<Output = u64> " , type_at_pos ( & db , pos ) ) ;
}
2019-12-03 12:38:54 +00:00
#[ test ]
fn infer_try ( ) {
let ( db , pos ) = TestDB ::with_position (
r #"
2020-06-11 14:22:31 +00:00
//- /main.rs crate:main deps:core
2019-12-03 12:38:54 +00:00
fn test ( ) {
let r : Result < i32 , u64 > = Result ::Ok ( 1 ) ;
let v = r ? ;
v < | > ;
}
2020-06-11 14:22:31 +00:00
//- /core.rs crate:core
2019-12-03 12:38:54 +00:00
#[ prelude_import ] use ops ::* ;
mod ops {
trait Try {
type Ok ;
type Error ;
}
}
#[ prelude_import ] use result ::* ;
mod result {
enum Result < O , E > {
Ok ( O ) ,
Err ( E )
}
impl < O , E > crate ::ops ::Try for Result < O , E > {
type Ok = O ;
type Error = E ;
}
}
" #,
) ;
assert_eq! ( " i32 " , type_at_pos ( & db , pos ) ) ;
}
#[ test ]
fn infer_for_loop ( ) {
let ( db , pos ) = TestDB ::with_position (
r #"
2020-06-11 14:22:31 +00:00
//- /main.rs crate:main deps:core,alloc
2019-12-03 12:38:54 +00:00
2020-06-11 14:22:31 +00:00
use alloc ::collections ::Vec ;
2019-12-03 12:38:54 +00:00
fn test ( ) {
let v = Vec ::new ( ) ;
v . push ( " foo " ) ;
for x in v {
x < | > ;
}
}
2020-06-11 14:22:31 +00:00
//- /core.rs crate:core
2019-12-03 12:38:54 +00:00
#[ prelude_import ] use iter ::* ;
mod iter {
trait IntoIterator {
type Item ;
}
}
2020-06-11 14:22:31 +00:00
//- /alloc.rs crate:alloc deps:core
2019-12-03 12:38:54 +00:00
mod collections {
struct Vec < T > { }
impl < T > Vec < T > {
fn new ( ) -> Self { Vec { } }
fn push ( & mut self , t : T ) { }
}
2020-06-11 14:22:31 +00:00
impl < T > IntoIterator for Vec < T > {
2019-12-03 12:38:54 +00:00
type Item = T ;
}
}
" #,
) ;
assert_eq! ( " &str " , type_at_pos ( & db , pos ) ) ;
}
2019-12-13 11:44:42 +00:00
#[ test ]
fn infer_ops_neg ( ) {
let ( db , pos ) = TestDB ::with_position (
r #"
//- /main.rs crate:main deps:std
struct Bar ;
struct Foo ;
impl std ::ops ::Neg for Bar {
type Output = Foo ;
}
fn test ( ) {
let a = Bar ;
let b = - a ;
b < | > ;
}
//- /std.rs crate:std
#[ prelude_import ] use ops ::* ;
mod ops {
2019-12-29 16:39:31 +00:00
#[ lang = " neg " ]
2019-12-13 11:44:42 +00:00
pub trait Neg {
type Output ;
}
}
" #,
) ;
assert_eq! ( " Foo " , type_at_pos ( & db , pos ) ) ;
}
#[ test ]
fn infer_ops_not ( ) {
let ( db , pos ) = TestDB ::with_position (
r #"
//- /main.rs crate:main deps:std
struct Bar ;
struct Foo ;
impl std ::ops ::Not for Bar {
type Output = Foo ;
}
fn test ( ) {
let a = Bar ;
let b = ! a ;
b < | > ;
}
//- /std.rs crate:std
#[ prelude_import ] use ops ::* ;
mod ops {
2019-12-29 16:39:31 +00:00
#[ lang = " not " ]
2019-12-13 11:44:42 +00:00
pub trait Not {
type Output ;
}
}
" #,
) ;
assert_eq! ( " Foo " , type_at_pos ( & db , pos ) ) ;
}
2019-12-03 12:38:54 +00:00
#[ test ]
fn infer_from_bound_1 ( ) {
assert_snapshot! (
infer ( r #"
trait Trait < T > { }
struct S < T > ( T ) ;
impl < U > Trait < U > for S < U > { }
fn foo < T : Trait < u32 > > ( t : T ) { }
fn test ( ) {
let s = S ( unknown ) ;
foo ( s ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
86 .. 87 't' : T
92 .. 94 ' { } ' : ( )
105 .. 144 ' { .. . ( s ) ; } ' : ( )
115 .. 116 's' : S < u32 >
119 .. 120 'S' : S < u32 > ( u32 ) -> S < u32 >
119 .. 129 ' S ( unknown ) ' : S < u32 >
121 .. 128 ' unknown ' : u32
135 .. 138 ' foo ' : fn foo < S < u32 > > ( S < u32 > )
135 .. 141 ' foo ( s ) ' : ( )
139 .. 140 's' : S < u32 >
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn infer_from_bound_2 ( ) {
assert_snapshot! (
infer ( r #"
trait Trait < T > { }
struct S < T > ( T ) ;
impl < U > Trait < U > for S < U > { }
fn foo < U , T : Trait < U > > ( t : T ) -> U { }
fn test ( ) {
let s = S ( unknown ) ;
let x : u32 = foo ( s ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
87 .. 88 't' : T
98 .. 100 ' { } ' : ( )
111 .. 163 ' { .. . ( s ) ; } ' : ( )
121 .. 122 's' : S < u32 >
125 .. 126 'S' : S < u32 > ( u32 ) -> S < u32 >
125 .. 135 ' S ( unknown ) ' : S < u32 >
127 .. 134 ' unknown ' : u32
145 .. 146 'x' : u32
154 .. 157 ' foo ' : fn foo < u32 , S < u32 > > ( S < u32 > ) -> u32
154 .. 160 ' foo ( s ) ' : u32
158 .. 159 's' : S < u32 >
2019-12-03 12:38:54 +00:00
" ###
) ;
2020-02-14 18:16:42 +00:00
}
#[ test ]
fn trait_default_method_self_bound_implements_trait ( ) {
2020-05-20 10:59:20 +00:00
mark ::check! ( trait_self_implements_self ) ;
2020-02-14 18:16:42 +00:00
assert_snapshot! (
infer ( r #"
trait Trait {
fn foo ( & self ) -> i64 ;
fn bar ( & self ) -> {
let x = self . foo ( ) ;
}
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
27 .. 31 ' self ' : & Self
53 .. 57 ' self ' : & Self
62 .. 97 ' { .. . } ' : ( )
76 .. 77 'x' : i64
80 .. 84 ' self ' : & Self
80 .. 90 ' self . foo ( ) ' : i64
2020-02-14 18:16:42 +00:00
" ###
) ;
}
#[ test ]
fn trait_default_method_self_bound_implements_super_trait ( ) {
assert_snapshot! (
infer ( r #"
trait SuperTrait {
fn foo ( & self ) -> i64 ;
}
trait Trait : SuperTrait {
fn bar ( & self ) -> {
let x = self . foo ( ) ;
}
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
32 .. 36 ' self ' : & Self
86 .. 90 ' self ' : & Self
95 .. 130 ' { .. . } ' : ( )
109 .. 110 'x' : i64
113 .. 117 ' self ' : & Self
113 .. 123 ' self . foo ( ) ' : i64
2020-02-14 18:16:42 +00:00
" ###
) ;
2019-12-03 12:38:54 +00:00
}
#[ test ]
fn infer_project_associated_type ( ) {
assert_snapshot! (
infer ( r #"
trait Iterable {
type Item ;
}
struct S ;
impl Iterable for S { type Item = u32 ; }
fn test < T : Iterable > ( ) {
let x : < S as Iterable > ::Item = 1 ;
let y : < T as Iterable > ::Item = no_matter ;
let z : T ::Item = no_matter ;
let a : < T > ::Item = no_matter ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
108 .. 261 ' { .. . ter ; } ' : ( )
118 .. 119 'x' : u32
145 .. 146 '1' : u32
156 .. 157 'y' : Iterable ::Item < T >
183 .. 192 ' no_matter ' : Iterable ::Item < T >
202 .. 203 'z' : Iterable ::Item < T >
215 .. 224 ' no_matter ' : Iterable ::Item < T >
234 .. 235 'a' : Iterable ::Item < T >
249 .. 258 ' no_matter ' : Iterable ::Item < T >
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn infer_return_associated_type ( ) {
assert_snapshot! (
infer ( r #"
trait Iterable {
type Item ;
}
struct S ;
impl Iterable for S { type Item = u32 ; }
fn foo1 < T : Iterable > ( t : T ) -> T ::Item { }
fn foo2 < T : Iterable > ( t : T ) -> < T as Iterable > ::Item { }
fn foo3 < T : Iterable > ( t : T ) -> < T > ::Item { }
fn test ( ) {
let x = foo1 ( S ) ;
let y = foo2 ( S ) ;
let z = foo3 ( S ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
106 .. 107 't' : T
123 .. 125 ' { } ' : ( )
147 .. 148 't' : T
178 .. 180 ' { } ' : ( )
202 .. 203 't' : T
221 .. 223 ' { } ' : ( )
234 .. 300 ' { .. . ( S ) ; } ' : ( )
244 .. 245 'x' : u32
248 .. 252 ' foo1 ' : fn foo1 < S > ( S ) -> < S as Iterable > ::Item
248 .. 255 ' foo1 ( S ) ' : u32
253 .. 254 'S' : S
265 .. 266 'y' : u32
269 .. 273 ' foo2 ' : fn foo2 < S > ( S ) -> < S as Iterable > ::Item
269 .. 276 ' foo2 ( S ) ' : u32
274 .. 275 'S' : S
286 .. 287 'z' : u32
290 .. 294 ' foo3 ' : fn foo3 < S > ( S ) -> < S as Iterable > ::Item
290 .. 297 ' foo3 ( S ) ' : u32
295 .. 296 'S' : S
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn infer_associated_type_bound ( ) {
assert_snapshot! (
infer ( r #"
trait Iterable {
type Item ;
}
fn test < T : Iterable < Item = u32 > > ( ) {
let y : T ::Item = unknown ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
67 .. 100 ' { .. . own ; } ' : ( )
77 .. 78 'y' : u32
90 .. 97 ' unknown ' : u32
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn infer_const_body ( ) {
assert_snapshot! (
infer ( r #"
const A : u32 = 1 + 1 ;
static B : u64 = { let x = 1 ; x } ;
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
16 .. 17 '1' : u32
16 .. 21 ' 1 + 1 ' : u32
20 .. 21 '1' : u32
39 .. 55 ' { let .. . 1 ; x } ' : u64
45 .. 46 'x' : u64
49 .. 50 '1' : u64
52 .. 53 'x' : u64
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn tuple_struct_fields ( ) {
assert_snapshot! (
infer ( r #"
struct S ( i32 , u64 ) ;
fn test ( ) -> u64 {
let a = S ( 4 , 6 ) ;
let b = a . 0 ;
a . 1
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
38 .. 87 ' { .. . a . 1 } ' : u64
48 .. 49 'a' : S
52 .. 53 'S' : S ( i32 , u64 ) -> S
52 .. 59 ' S ( 4 , 6 ) ' : S
54 .. 55 '4' : i32
57 .. 58 '6' : u64
69 .. 70 'b' : i32
73 .. 74 'a' : S
73 .. 76 ' a . 0 ' : i32
82 .. 83 'a' : S
82 .. 85 ' a . 1 ' : u64
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn tuple_struct_with_fn ( ) {
assert_snapshot! (
infer ( r #"
struct S ( fn ( u32 ) -> u64 ) ;
fn test ( ) -> u64 {
let a = S ( | i | 2 * i ) ;
let b = a . 0 ( 4 ) ;
a . 0 ( 2 )
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
44 .. 102 ' { .. . 0 ( 2 ) } ' : u64
54 .. 55 'a' : S
58 .. 59 'S' : S ( fn ( u32 ) -> u64 ) -> S
58 .. 68 ' S ( | i | 2 * i ) ' : S
60 .. 67 ' | i | 2 * i ' : | u32 | -> u64
61 .. 62 'i' : u32
64 .. 65 '2' : u32
64 .. 67 ' 2 * i ' : u32
66 .. 67 'i' : u32
78 .. 79 'b' : u64
82 .. 83 'a' : S
82 .. 85 ' a . 0 ' : fn ( u32 ) -> u64
82 .. 88 ' a . 0 ( 4 ) ' : u64
86 .. 87 '4' : u32
94 .. 95 'a' : S
94 .. 97 ' a . 0 ' : fn ( u32 ) -> u64
94 .. 100 ' a . 0 ( 2 ) ' : u64
98 .. 99 '2' : u32
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn indexing_arrays ( ) {
assert_snapshot! (
infer ( " fn main() { &mut [9][2]; } " ) ,
@ r ###"
2020-04-24 21:51:02 +00:00
10 .. 26 ' { & mut .. . [ 2 ] ; } ' : ( )
12 .. 23 ' & mut [ 9 ] [ 2 ] ' : & mut { unknown }
17 .. 20 ' [ 9 ] ' : [ i32 ; _ ]
17 .. 23 ' [ 9 ] [ 2 ] ' : { unknown }
18 .. 19 '9' : i32
21 .. 22 '2' : i32
2019-12-03 12:38:54 +00:00
" ###
)
}
2019-12-19 04:45:07 +00:00
#[ test ]
fn infer_ops_index ( ) {
let ( db , pos ) = TestDB ::with_position (
r #"
//- /main.rs crate:main deps:std
struct Bar ;
struct Foo ;
impl std ::ops ::Index < u32 > for Bar {
type Output = Foo ;
}
fn test ( ) {
let a = Bar ;
2020-04-10 15:44:43 +00:00
let b = a [ 1 u32 ] ;
2019-12-19 04:45:07 +00:00
b < | > ;
}
//- /std.rs crate:std
#[ prelude_import ] use ops ::* ;
mod ops {
2019-12-29 16:39:31 +00:00
#[ lang = " index " ]
2019-12-19 04:45:07 +00:00
pub trait Index < Idx > {
type Output ;
}
}
" #,
) ;
assert_eq! ( " Foo " , type_at_pos ( & db , pos ) ) ;
}
2020-02-29 21:48:23 +00:00
#[ test ]
fn infer_ops_index_autoderef ( ) {
let ( db , pos ) = TestDB ::with_position (
r #"
//- /main.rs crate:main deps:std
fn test ( ) {
let a = & [ 1 u32 , 2 , 3 ] ;
2020-04-10 15:44:43 +00:00
let b = a [ 1 u32 ] ;
2020-02-29 21:48:23 +00:00
b < | > ;
}
//- /std.rs crate:std
impl < T > ops ::Index < u32 > for [ T ] {
type Output = T ;
}
#[ prelude_import ] use ops ::* ;
mod ops {
#[ lang = " index " ]
pub trait Index < Idx > {
type Output ;
}
}
" #,
) ;
assert_eq! ( " u32 " , type_at_pos ( & db , pos ) ) ;
}
2019-12-03 12:38:54 +00:00
#[ test ]
fn deref_trait ( ) {
let t = type_at (
r #"
//- /main.rs
#[ lang = " deref " ]
trait Deref {
type Target ;
fn deref ( & self ) -> & Self ::Target ;
}
struct Arc < T > ;
impl < T > Deref for Arc < T > {
type Target = T ;
}
struct S ;
impl S {
fn foo ( & self ) -> u128 { }
}
fn test ( s : Arc < S > ) {
( * s , s . foo ( ) ) < | > ;
}
" #,
) ;
assert_eq! ( t , " (S, u128) " ) ;
}
#[ test ]
fn deref_trait_with_inference_var ( ) {
let t = type_at (
r #"
//- /main.rs
#[ lang = " deref " ]
trait Deref {
type Target ;
fn deref ( & self ) -> & Self ::Target ;
}
struct Arc < T > ;
fn new_arc < T > ( ) -> Arc < T > { }
impl < T > Deref for Arc < T > {
type Target = T ;
}
struct S ;
fn foo ( a : Arc < S > ) { }
fn test ( ) {
let a = new_arc ( ) ;
let b = ( * a ) < | > ;
foo ( a ) ;
}
" #,
) ;
assert_eq! ( t , " S " ) ;
}
#[ test ]
fn deref_trait_infinite_recursion ( ) {
let t = type_at (
r #"
//- /main.rs
#[ lang = " deref " ]
trait Deref {
type Target ;
fn deref ( & self ) -> & Self ::Target ;
}
struct S ;
impl Deref for S {
type Target = S ;
}
fn test ( s : S ) {
s . foo ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " {unknown} " ) ;
}
#[ test ]
fn deref_trait_with_question_mark_size ( ) {
let t = type_at (
r #"
//- /main.rs
#[ lang = " deref " ]
trait Deref {
type Target ;
fn deref ( & self ) -> & Self ::Target ;
}
struct Arc < T > ;
impl < T > Deref for Arc < T > {
type Target = T ;
}
struct S ;
impl S {
fn foo ( & self ) -> u128 { }
}
fn test ( s : Arc < S > ) {
( * s , s . foo ( ) ) < | > ;
}
" #,
) ;
assert_eq! ( t , " (S, u128) " ) ;
}
#[ test ]
fn obligation_from_function_clause ( ) {
let t = type_at (
r #"
//- /main.rs
struct S ;
trait Trait < T > { }
impl Trait < u32 > for S { }
fn foo < T : Trait < U > , U > ( t : T ) -> U { }
fn test ( s : S ) {
foo ( s ) < | > ;
}
" #,
) ;
assert_eq! ( t , " u32 " ) ;
}
#[ test ]
fn obligation_from_method_clause ( ) {
let t = type_at (
r #"
//- /main.rs
struct S ;
trait Trait < T > { }
impl Trait < isize > for S { }
struct O ;
impl O {
fn foo < T : Trait < U > , U > ( & self , t : T ) -> U { }
}
fn test ( ) {
O . foo ( S ) < | > ;
}
" #,
) ;
assert_eq! ( t , " isize " ) ;
}
#[ test ]
fn obligation_from_self_method_clause ( ) {
let t = type_at (
r #"
//- /main.rs
struct S ;
trait Trait < T > { }
impl Trait < i64 > for S { }
impl S {
fn foo < U > ( & self ) -> U where Self : Trait < U > { }
}
fn test ( ) {
S . foo ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " i64 " ) ;
}
#[ test ]
fn obligation_from_impl_clause ( ) {
let t = type_at (
r #"
//- /main.rs
struct S ;
trait Trait < T > { }
impl Trait < & str > for S { }
struct O < T > ;
impl < U , T : Trait < U > > O < T > {
fn foo ( & self ) -> U { }
}
fn test ( o : O < S > ) {
o . foo ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " &str " ) ;
}
#[ test ]
fn generic_param_env_1 ( ) {
let t = type_at (
r #"
//- /main.rs
trait Clone { }
trait Trait { fn foo ( self ) -> u128 ; }
struct S ;
impl Clone for S { }
impl < T > Trait for T where T : Clone { }
fn test < T : Clone > ( t : T ) { t . foo ( ) < | > ; }
" #,
) ;
assert_eq! ( t , " u128 " ) ;
}
#[ test ]
fn generic_param_env_1_not_met ( ) {
let t = type_at (
r #"
//- /main.rs
trait Clone { }
trait Trait { fn foo ( self ) -> u128 ; }
struct S ;
impl Clone for S { }
impl < T > Trait for T where T : Clone { }
fn test < T > ( t : T ) { t . foo ( ) < | > ; }
" #,
) ;
assert_eq! ( t , " {unknown} " ) ;
}
#[ test ]
fn generic_param_env_2 ( ) {
let t = type_at (
r #"
//- /main.rs
trait Trait { fn foo ( self ) -> u128 ; }
struct S ;
impl Trait for S { }
fn test < T : Trait > ( t : T ) { t . foo ( ) < | > ; }
" #,
) ;
assert_eq! ( t , " u128 " ) ;
}
#[ test ]
fn generic_param_env_2_not_met ( ) {
let t = type_at (
r #"
//- /main.rs
trait Trait { fn foo ( self ) -> u128 ; }
struct S ;
impl Trait for S { }
fn test < T > ( t : T ) { t . foo ( ) < | > ; }
" #,
) ;
assert_eq! ( t , " {unknown} " ) ;
}
#[ test ]
fn generic_param_env_deref ( ) {
let t = type_at (
r #"
//- /main.rs
#[ lang = " deref " ]
trait Deref {
type Target ;
}
trait Trait { }
impl < T > Deref for T where T : Trait {
type Target = i128 ;
}
fn test < T : Trait > ( t : T ) { ( * t ) < | > ; }
" #,
) ;
assert_eq! ( t , " i128 " ) ;
}
#[ test ]
fn associated_type_placeholder ( ) {
let t = type_at (
r #"
//- /main.rs
pub trait ApplyL {
type Out ;
}
pub struct RefMutL < T > ;
impl < T > ApplyL for RefMutL < T > {
type Out = < T as ApplyL > ::Out ;
}
fn test < T : ApplyL > ( ) {
let y : < RefMutL < T > as ApplyL > ::Out = no_matter ;
y < | > ;
}
" #,
) ;
// inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types].
2020-01-31 15:52:43 +00:00
assert_eq! ( t , " ApplyL::Out<T> " ) ;
2019-12-03 12:38:54 +00:00
}
#[ test ]
fn associated_type_placeholder_2 ( ) {
let t = type_at (
r #"
//- /main.rs
pub trait ApplyL {
type Out ;
}
fn foo < T : ApplyL > ( t : T ) -> < T as ApplyL > ::Out ;
fn test < T : ApplyL > ( t : T ) {
let y = foo ( t ) ;
y < | > ;
}
" #,
) ;
2020-04-10 15:44:43 +00:00
assert_eq! ( t , " ApplyL::Out<T> " ) ;
2019-12-03 12:38:54 +00:00
}
2020-01-31 15:05:58 +00:00
#[ test ]
fn argument_impl_trait ( ) {
assert_snapshot! (
infer_with_mismatches ( r #"
trait Trait < T > {
fn foo ( & self ) -> T ;
fn foo2 ( & self ) -> i64 ;
}
2020-02-02 12:04:22 +00:00
fn bar ( x : impl Trait < u16 > ) { }
2020-01-31 15:05:58 +00:00
struct S < T > ( T ) ;
impl < T > Trait < T > for S < T > { }
2020-02-02 12:04:22 +00:00
fn test ( x : impl Trait < u64 > , y : & impl Trait < u32 > ) {
2020-01-31 15:05:58 +00:00
x ;
y ;
let z = S ( 1 ) ;
bar ( z ) ;
x . foo ( ) ;
y . foo ( ) ;
z . foo ( ) ;
x . foo2 ( ) ;
y . foo2 ( ) ;
z . foo2 ( ) ;
}
" #, true),
@ r ###"
2020-04-24 21:51:02 +00:00
30 .. 34 ' self ' : & Self
55 .. 59 ' self ' : & Self
78 .. 79 'x' : impl Trait < u16 >
98 .. 100 ' { } ' : ( )
155 .. 156 'x' : impl Trait < u64 >
175 .. 176 'y' : & impl Trait < u32 >
196 .. 324 ' { .. . 2 ( ) ; } ' : ( )
202 .. 203 'x' : impl Trait < u64 >
209 .. 210 'y' : & impl Trait < u32 >
220 .. 221 'z' : S < u16 >
224 .. 225 'S' : S < u16 > ( u16 ) -> S < u16 >
224 .. 228 ' S ( 1 ) ' : S < u16 >
226 .. 227 '1' : u16
234 .. 237 ' bar ' : fn bar ( S < u16 > )
234 .. 240 ' bar ( z ) ' : ( )
238 .. 239 'z' : S < u16 >
246 .. 247 'x' : impl Trait < u64 >
246 .. 253 ' x . foo ( ) ' : u64
259 .. 260 'y' : & impl Trait < u32 >
259 .. 266 ' y . foo ( ) ' : u32
272 .. 273 'z' : S < u16 >
272 .. 279 ' z . foo ( ) ' : u16
285 .. 286 'x' : impl Trait < u64 >
285 .. 293 ' x . foo2 ( ) ' : i64
299 .. 300 'y' : & impl Trait < u32 >
299 .. 307 ' y . foo2 ( ) ' : i64
313 .. 314 'z' : S < u16 >
313 .. 321 ' z . foo2 ( ) ' : i64
2020-01-31 15:05:58 +00:00
" ###
) ;
}
2020-02-07 15:24:09 +00:00
#[ test ]
fn argument_impl_trait_type_args_1 ( ) {
assert_snapshot! (
infer_with_mismatches ( r #"
trait Trait { }
trait Foo {
// this function has an implicit Self param, an explicit type param,
// and an implicit impl Trait param!
fn bar < T > ( x : impl Trait ) -> T { loop { } }
}
fn foo < T > ( x : impl Trait ) -> T { loop { } }
struct S ;
impl Trait for S { }
struct F ;
impl Foo for F { }
fn test ( ) {
Foo ::bar ( S ) ;
< F as Foo > ::bar ( S ) ;
F ::bar ( S ) ;
Foo ::bar ::< u32 > ( S ) ;
< F as Foo > ::bar ::< u32 > ( S ) ;
foo ( S ) ;
foo ::< u32 > ( S ) ;
foo ::< u32 , i32 > ( S ) ; // we should ignore the extraneous i32
}
" #, true),
@ r ###"
2020-04-24 21:51:02 +00:00
156 .. 157 'x' : impl Trait
176 .. 187 ' { loop { } } ' : T
178 .. 185 ' loop { } ' : !
183 .. 185 ' { } ' : ( )
200 .. 201 'x' : impl Trait
220 .. 231 ' { loop { } } ' : T
222 .. 229 ' loop { } ' : !
227 .. 229 ' { } ' : ( )
301 .. 510 ' { .. . i32 } ' : ( )
307 .. 315 ' Foo ::bar ' : fn bar < { unknown } , { unknown } > ( S ) -> { unknown }
307 .. 318 ' Foo ::bar ( S ) ' : { unknown }
316 .. 317 'S' : S
324 .. 339 ' < F as Foo > ::bar ' : fn bar < F , { unknown } > ( S ) -> { unknown }
324 .. 342 ' < F as .. . bar ( S ) ' : { unknown }
340 .. 341 'S' : S
348 .. 354 ' F ::bar ' : fn bar < F , { unknown } > ( S ) -> { unknown }
348 .. 357 ' F ::bar ( S ) ' : { unknown }
355 .. 356 'S' : S
363 .. 378 ' Foo ::bar ::< u32 > ' : fn bar < { unknown } , u32 > ( S ) -> u32
363 .. 381 ' Foo ::b .. . 32 > ( S ) ' : u32
379 .. 380 'S' : S
387 .. 409 ' < F as .. . :< u32 > ' : fn bar < F , u32 > ( S ) -> u32
387 .. 412 ' < F as .. . 32 > ( S ) ' : u32
410 .. 411 'S' : S
419 .. 422 ' foo ' : fn foo < { unknown } > ( S ) -> { unknown }
419 .. 425 ' foo ( S ) ' : { unknown }
423 .. 424 'S' : S
431 .. 441 ' foo ::< u32 > ' : fn foo < u32 > ( S ) -> u32
431 .. 444 ' foo ::< u32 > ( S ) ' : u32
442 .. 443 'S' : S
450 .. 465 ' foo ::< u32 , i32 > ' : fn foo < u32 > ( S ) -> u32
450 .. 468 ' foo ::< .. . 32 > ( S ) ' : u32
466 .. 467 'S' : S
2020-02-07 15:24:09 +00:00
" ###
) ;
}
#[ test ]
fn argument_impl_trait_type_args_2 ( ) {
assert_snapshot! (
infer_with_mismatches ( r #"
trait Trait { }
struct S ;
impl Trait for S { }
struct F < T > ;
impl < T > F < T > {
fn foo < U > ( self , x : impl Trait ) -> ( T , U ) { loop { } }
}
fn test ( ) {
F . foo ( S ) ;
F ::< u32 > . foo ( S ) ;
F ::< u32 > . foo ::< i32 > ( S ) ;
F ::< u32 > . foo ::< i32 , u32 > ( S ) ; // extraneous argument should be ignored
}
" #, true),
@ r ###"
2020-04-24 21:51:02 +00:00
88 .. 92 ' self ' : F < T >
94 .. 95 'x' : impl Trait
119 .. 130 ' { loop { } } ' : ( T , U )
121 .. 128 ' loop { } ' : !
126 .. 128 ' { } ' : ( )
144 .. 284 ' { .. . ored } ' : ( )
150 .. 151 'F' : F < { unknown } >
150 .. 158 ' F . foo ( S ) ' : ( { unknown } , { unknown } )
156 .. 157 'S' : S
164 .. 172 ' F ::< u32 > ' : F < u32 >
164 .. 179 ' F ::< u32 > . foo ( S ) ' : ( u32 , { unknown } )
177 .. 178 'S' : S
185 .. 193 ' F ::< u32 > ' : F < u32 >
185 .. 207 ' F ::< u3 .. . 32 > ( S ) ' : ( u32 , i32 )
205 .. 206 'S' : S
213 .. 221 ' F ::< u32 > ' : F < u32 >
213 .. 240 ' F ::< u3 .. . 32 > ( S ) ' : ( u32 , i32 )
238 .. 239 'S' : S
2020-02-07 15:24:09 +00:00
" ###
) ;
}
2020-02-07 17:27:54 +00:00
#[ test ]
fn argument_impl_trait_to_fn_pointer ( ) {
assert_snapshot! (
infer_with_mismatches ( r #"
trait Trait { }
fn foo ( x : impl Trait ) { loop { } }
struct S ;
impl Trait for S { }
fn test ( ) {
let f : fn ( S ) -> ( ) = foo ;
}
" #, true),
@ r ###"
2020-04-24 21:51:02 +00:00
23 .. 24 'x' : impl Trait
38 .. 49 ' { loop { } } ' : ( )
40 .. 47 ' loop { } ' : !
45 .. 47 ' { } ' : ( )
91 .. 124 ' { .. . foo ; } ' : ( )
101 .. 102 'f' : fn ( S )
118 .. 121 ' foo ' : fn foo ( S )
2020-02-07 17:27:54 +00:00
" ###
) ;
}
2019-12-03 12:38:54 +00:00
#[ test ]
fn impl_trait ( ) {
assert_snapshot! (
infer ( r #"
trait Trait < T > {
fn foo ( & self ) -> T ;
fn foo2 ( & self ) -> i64 ;
}
fn bar ( ) -> impl Trait < u64 > { }
fn test ( x : impl Trait < u64 > , y : & impl Trait < u64 > ) {
x ;
y ;
let z = bar ( ) ;
x . foo ( ) ;
y . foo ( ) ;
z . foo ( ) ;
x . foo2 ( ) ;
y . foo2 ( ) ;
z . foo2 ( ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
30 .. 34 ' self ' : & Self
55 .. 59 ' self ' : & Self
99 .. 101 ' { } ' : ( )
111 .. 112 'x' : impl Trait < u64 >
131 .. 132 'y' : & impl Trait < u64 >
152 .. 269 ' { .. . 2 ( ) ; } ' : ( )
158 .. 159 'x' : impl Trait < u64 >
165 .. 166 'y' : & impl Trait < u64 >
176 .. 177 'z' : impl Trait < u64 >
180 .. 183 ' bar ' : fn bar ( ) -> impl Trait < u64 >
180 .. 185 ' bar ( ) ' : impl Trait < u64 >
191 .. 192 'x' : impl Trait < u64 >
191 .. 198 ' x . foo ( ) ' : u64
204 .. 205 'y' : & impl Trait < u64 >
204 .. 211 ' y . foo ( ) ' : u64
217 .. 218 'z' : impl Trait < u64 >
217 .. 224 ' z . foo ( ) ' : u64
230 .. 231 'x' : impl Trait < u64 >
230 .. 238 ' x . foo2 ( ) ' : i64
244 .. 245 'y' : & impl Trait < u64 >
244 .. 252 ' y . foo2 ( ) ' : i64
258 .. 259 'z' : impl Trait < u64 >
258 .. 266 ' z . foo2 ( ) ' : i64
2019-12-03 12:38:54 +00:00
" ###
) ;
}
2020-03-04 22:00:44 +00:00
#[ test ]
2020-06-05 15:41:58 +00:00
fn simple_return_pos_impl_trait ( ) {
mark ::check! ( lower_rpit ) ;
assert_snapshot! (
infer ( r #"
trait Trait < T > {
fn foo ( & self ) -> T ;
}
fn bar ( ) -> impl Trait < u64 > { loop { } }
fn test ( ) {
let a = bar ( ) ;
a . foo ( ) ;
}
" #),
@ r ###"
30 .. 34 ' self ' : & Self
72 .. 83 ' { loop { } } ' : !
74 .. 81 ' loop { } ' : !
79 .. 81 ' { } ' : ( )
95 .. 130 ' { .. . o ( ) ; } ' : ( )
105 .. 106 'a' : impl Trait < u64 >
109 .. 112 ' bar ' : fn bar ( ) -> impl Trait < u64 >
109 .. 114 ' bar ( ) ' : impl Trait < u64 >
120 .. 121 'a' : impl Trait < u64 >
120 .. 127 ' a . foo ( ) ' : u64
" ###
) ;
}
#[ test ]
fn more_return_pos_impl_trait ( ) {
2020-03-04 22:00:44 +00:00
assert_snapshot! (
infer ( r #"
trait Iterator {
type Item ;
fn next ( & mut self ) -> Self ::Item ;
}
trait Trait < T > {
fn foo ( & self ) -> T ;
}
fn bar ( ) -> ( impl Iterator < Item = impl Trait < u32 > > , impl Trait < u64 > ) { loop { } }
fn baz < T > ( t : T ) -> ( impl Iterator < Item = impl Trait < T > > , impl Trait < T > ) { loop { } }
fn test ( ) {
2020-06-05 15:41:58 +00:00
let ( a , b ) = bar ( ) ;
a . next ( ) . foo ( ) ;
b . foo ( ) ;
2020-03-04 22:00:44 +00:00
let ( c , d ) = baz ( 1 u128 ) ;
2020-06-05 15:41:58 +00:00
c . next ( ) . foo ( ) ;
d . foo ( ) ;
2020-03-04 22:00:44 +00:00
}
" #),
@ r ###"
50 .. 54 ' self ' : & mut Self
102 .. 106 ' self ' : & Self
185 .. 196 ' { loop { } } ' : ( { unknown } , { unknown } )
187 .. 194 ' loop { } ' : !
192 .. 194 ' { } ' : ( )
207 .. 208 't' : T
269 .. 280 ' { loop { } } ' : ( { unknown } , { unknown } )
271 .. 278 ' loop { } ' : !
276 .. 278 ' { } ' : ( )
2020-06-05 15:41:58 +00:00
292 .. 414 ' { .. . o ( ) ; } ' : ( )
302 .. 308 ' ( a , b ) ' : ( impl Iterator < Item = impl Trait < u32 > > , impl Trait < u64 > )
303 .. 304 'a' : impl Iterator < Item = impl Trait < u32 > >
306 .. 307 'b' : impl Trait < u64 >
311 .. 314 ' bar ' : fn bar ( ) -> ( impl Iterator < Item = impl Trait < u32 > > , impl Trait < u64 > )
311 .. 316 ' bar ( ) ' : ( impl Iterator < Item = impl Trait < u32 > > , impl Trait < u64 > )
322 .. 323 'a' : impl Iterator < Item = impl Trait < u32 > >
322 .. 330 ' a . next ( ) ' : impl Trait < u32 >
322 .. 336 ' a . next ( ) . foo ( ) ' : u32
342 .. 343 'b' : impl Trait < u64 >
342 .. 349 ' b . foo ( ) ' : u64
359 .. 365 ' ( c , d ) ' : ( impl Iterator < Item = impl Trait < u128 > > , impl Trait < u128 > )
360 .. 361 'c' : impl Iterator < Item = impl Trait < u128 > >
363 .. 364 'd' : impl Trait < u128 >
368 .. 371 ' baz ' : fn baz < u128 > ( u128 ) -> ( impl Iterator < Item = impl Trait < u128 > > , impl Trait < u128 > )
368 .. 378 ' baz ( 1 u128 ) ' : ( impl Iterator < Item = impl Trait < u128 > > , impl Trait < u128 > )
372 .. 377 ' 1 u128 ' : u128
384 .. 385 'c' : impl Iterator < Item = impl Trait < u128 > >
384 .. 392 ' c . next ( ) ' : impl Trait < u128 >
384 .. 398 ' c . next ( ) . foo ( ) ' : u128
404 .. 405 'd' : impl Trait < u128 >
404 .. 411 ' d . foo ( ) ' : u128
2020-03-04 22:00:44 +00:00
" ###
) ;
}
2019-12-03 12:38:54 +00:00
#[ test ]
fn dyn_trait ( ) {
assert_snapshot! (
infer ( r #"
trait Trait < T > {
fn foo ( & self ) -> T ;
fn foo2 ( & self ) -> i64 ;
}
fn bar ( ) -> dyn Trait < u64 > { }
fn test ( x : dyn Trait < u64 > , y : & dyn Trait < u64 > ) {
x ;
y ;
let z = bar ( ) ;
x . foo ( ) ;
y . foo ( ) ;
z . foo ( ) ;
x . foo2 ( ) ;
y . foo2 ( ) ;
z . foo2 ( ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
30 .. 34 ' self ' : & Self
55 .. 59 ' self ' : & Self
98 .. 100 ' { } ' : ( )
110 .. 111 'x' : dyn Trait < u64 >
129 .. 130 'y' : & dyn Trait < u64 >
149 .. 266 ' { .. . 2 ( ) ; } ' : ( )
155 .. 156 'x' : dyn Trait < u64 >
162 .. 163 'y' : & dyn Trait < u64 >
173 .. 174 'z' : dyn Trait < u64 >
177 .. 180 ' bar ' : fn bar ( ) -> dyn Trait < u64 >
177 .. 182 ' bar ( ) ' : dyn Trait < u64 >
188 .. 189 'x' : dyn Trait < u64 >
188 .. 195 ' x . foo ( ) ' : u64
201 .. 202 'y' : & dyn Trait < u64 >
201 .. 208 ' y . foo ( ) ' : u64
214 .. 215 'z' : dyn Trait < u64 >
214 .. 221 ' z . foo ( ) ' : u64
227 .. 228 'x' : dyn Trait < u64 >
227 .. 235 ' x . foo2 ( ) ' : i64
241 .. 242 'y' : & dyn Trait < u64 >
241 .. 249 ' y . foo2 ( ) ' : i64
255 .. 256 'z' : dyn Trait < u64 >
255 .. 263 ' z . foo2 ( ) ' : i64
2019-12-03 12:38:54 +00:00
" ###
) ;
}
2020-04-17 20:48:29 +00:00
#[ test ]
fn dyn_trait_in_impl ( ) {
assert_snapshot! (
infer ( r #"
trait Trait < T , U > {
fn foo ( & self ) -> ( T , U ) ;
}
struct S < T , U > { }
impl < T , U > S < T , U > {
fn bar ( & self ) -> & dyn Trait < T , U > { loop { } }
}
trait Trait2 < T , U > {
fn baz ( & self ) -> ( T , U ) ;
}
impl < T , U > Trait2 < T , U > for dyn Trait < T , U > { }
fn test ( s : S < u32 , i32 > ) {
s . bar ( ) . baz ( ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
33 .. 37 ' self ' : & Self
103 .. 107 ' self ' : & S < T , U >
129 .. 140 ' { loop { } } ' : & dyn Trait < T , U >
131 .. 138 ' loop { } ' : !
136 .. 138 ' { } ' : ( )
176 .. 180 ' self ' : & Self
252 .. 253 's' : S < u32 , i32 >
268 .. 290 ' { .. . z ( ) ; } ' : ( )
274 .. 275 's' : S < u32 , i32 >
274 .. 281 ' s . bar ( ) ' : & dyn Trait < u32 , i32 >
274 .. 287 ' s . bar ( ) . baz ( ) ' : ( u32 , i32 )
2020-04-17 20:48:29 +00:00
" ###
) ;
}
2019-12-03 12:38:54 +00:00
#[ test ]
fn dyn_trait_bare ( ) {
assert_snapshot! (
infer ( r #"
trait Trait {
fn foo ( & self ) -> u64 ;
}
fn bar ( ) -> Trait { }
fn test ( x : Trait , y : & Trait ) -> u64 {
x ;
y ;
let z = bar ( ) ;
x . foo ( ) ;
y . foo ( ) ;
z . foo ( ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
27 .. 31 ' self ' : & Self
61 .. 63 ' { } ' : ( )
73 .. 74 'x' : dyn Trait
83 .. 84 'y' : & dyn Trait
101 .. 176 ' { .. . o ( ) ; } ' : ( )
107 .. 108 'x' : dyn Trait
114 .. 115 'y' : & dyn Trait
125 .. 126 'z' : dyn Trait
129 .. 132 ' bar ' : fn bar ( ) -> dyn Trait
129 .. 134 ' bar ( ) ' : dyn Trait
140 .. 141 'x' : dyn Trait
140 .. 147 ' x . foo ( ) ' : u64
153 .. 154 'y' : & dyn Trait
153 .. 160 ' y . foo ( ) ' : u64
166 .. 167 'z' : dyn Trait
166 .. 173 ' z . foo ( ) ' : u64
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn weird_bounds ( ) {
assert_snapshot! (
infer ( r #"
trait Trait { }
2020-01-24 15:46:43 +00:00
fn test ( a : impl Trait + ' lifetime , b : impl ' lifetime , c : impl ( Trait ) , d : impl ( ' lifetime ) , e : impl ? Sized , f : impl Trait + ? Sized ) {
2019-12-03 12:38:54 +00:00
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
24 .. 25 'a' : impl Trait + { error }
51 .. 52 'b' : impl { error }
70 .. 71 'c' : impl Trait
87 .. 88 'd' : impl { error }
108 .. 109 'e' : impl { error }
124 .. 125 'f' : impl Trait + { error }
148 .. 151 ' { } ' : ( )
2019-12-03 12:38:54 +00:00
" ###
) ;
}
2019-12-21 18:15:06 +00:00
#[ test ]
2020-01-27 20:38:10 +00:00
#[ ignore ]
2019-12-21 18:15:06 +00:00
fn error_bound_chalk ( ) {
let t = type_at (
r #"
//- /main.rs
trait Trait {
fn foo ( & self ) -> u32 { }
}
fn test ( x : ( impl Trait + UnknownTrait ) ) {
x . foo ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " u32 " ) ;
}
2019-12-03 12:38:54 +00:00
#[ test ]
fn assoc_type_bindings ( ) {
assert_snapshot! (
infer ( r #"
trait Trait {
type Type ;
}
fn get < T : Trait > ( t : T ) -> < T as Trait > ::Type { }
fn get2 < U , T : Trait < Type = U > > ( t : T ) -> U { }
fn set < T : Trait < Type = u64 > > ( t : T ) -> T { t }
struct S < T > ;
impl < T > Trait for S < T > { type Type = T ; }
fn test < T : Trait < Type = u32 > > ( x : T , y : impl Trait < Type = i64 > ) {
get ( x ) ;
get2 ( x ) ;
get ( y ) ;
get2 ( y ) ;
get ( set ( S ) ) ;
get2 ( set ( S ) ) ;
get2 ( S ::< str > ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
50 .. 51 't' : T
78 .. 80 ' { } ' : ( )
112 .. 113 't' : T
123 .. 125 ' { } ' : ( )
155 .. 156 't' : T
166 .. 169 ' { t } ' : T
167 .. 168 't' : T
257 .. 258 'x' : T
263 .. 264 'y' : impl Trait < Type = i64 >
290 .. 398 ' { .. . r > ) ; } ' : ( )
296 .. 299 ' get ' : fn get < T > ( T ) -> < T as Trait > ::Type
296 .. 302 ' get ( x ) ' : u32
300 .. 301 'x' : T
308 .. 312 ' get2 ' : fn get2 < u32 , T > ( T ) -> u32
308 .. 315 ' get2 ( x ) ' : u32
313 .. 314 'x' : T
321 .. 324 ' get ' : fn get < impl Trait < Type = i64 > > ( impl Trait < Type = i64 > ) -> < impl Trait < Type = i64 > as Trait > ::Type
321 .. 327 ' get ( y ) ' : i64
325 .. 326 'y' : impl Trait < Type = i64 >
333 .. 337 ' get2 ' : fn get2 < i64 , impl Trait < Type = i64 > > ( impl Trait < Type = i64 > ) -> i64
333 .. 340 ' get2 ( y ) ' : i64
338 .. 339 'y' : impl Trait < Type = i64 >
346 .. 349 ' get ' : fn get < S < u64 > > ( S < u64 > ) -> < S < u64 > as Trait > ::Type
346 .. 357 ' get ( set ( S ) ) ' : u64
350 .. 353 ' set ' : fn set < S < u64 > > ( S < u64 > ) -> S < u64 >
350 .. 356 ' set ( S ) ' : S < u64 >
354 .. 355 'S' : S < u64 >
363 .. 367 ' get2 ' : fn get2 < u64 , S < u64 > > ( S < u64 > ) -> u64
363 .. 375 ' get2 ( set ( S ) ) ' : u64
368 .. 371 ' set ' : fn set < S < u64 > > ( S < u64 > ) -> S < u64 >
368 .. 374 ' set ( S ) ' : S < u64 >
372 .. 373 'S' : S < u64 >
381 .. 385 ' get2 ' : fn get2 < str , S < str > > ( S < str > ) -> str
381 .. 395 ' get2 ( S ::< str > ) ' : str
386 .. 394 ' S ::< str > ' : S < str >
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn impl_trait_assoc_binding_projection_bug ( ) {
let ( db , pos ) = TestDB ::with_position (
r #"
//- /main.rs crate:main deps:std
pub trait Language {
type Kind ;
}
pub enum RustLanguage { }
impl Language for RustLanguage {
type Kind = SyntaxKind ;
}
struct SyntaxNode < L > { }
fn foo ( ) -> impl Iterator < Item = SyntaxNode < RustLanguage > > { }
trait Clone {
fn clone ( & self ) -> Self ;
}
fn api_walkthrough ( ) {
for node in foo ( ) {
node . clone ( ) < | > ;
}
}
//- /std.rs crate:std
#[ prelude_import ] use iter ::* ;
mod iter {
trait IntoIterator {
type Item ;
}
trait Iterator {
type Item ;
}
impl < T : Iterator > IntoIterator for T {
type Item = < T as Iterator > ::Item ;
}
}
" #,
) ;
assert_eq! ( " {unknown} " , type_at_pos ( & db , pos ) ) ;
}
#[ test ]
fn projection_eq_within_chalk ( ) {
assert_snapshot! (
infer ( r #"
trait Trait1 {
type Type ;
}
trait Trait2 < T > {
fn foo ( self ) -> T ;
}
impl < T , U > Trait2 < T > for U where U : Trait1 < Type = T > { }
fn test < T : Trait1 < Type = u32 > > ( x : T ) {
x . foo ( ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
62 .. 66 ' self ' : Self
164 .. 165 'x' : T
170 .. 186 ' { .. . o ( ) ; } ' : ( )
176 .. 177 'x' : T
176 .. 183 ' x . foo ( ) ' : u32
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn where_clause_trait_in_scope_for_method_resolution ( ) {
let t = type_at (
r #"
//- /main.rs
mod foo {
trait Trait {
fn foo ( & self ) -> u32 { }
}
}
fn test < T : foo ::Trait > ( x : T ) {
x . foo ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " u32 " ) ;
}
#[ test ]
fn super_trait_method_resolution ( ) {
assert_snapshot! (
infer ( r #"
mod foo {
trait SuperTrait {
fn foo ( & self ) -> u32 { }
}
}
trait Trait1 : foo ::SuperTrait { }
trait Trait2 where Self : foo ::SuperTrait { }
fn test < T : Trait1 , U : Trait2 > ( x : T , y : U ) {
x . foo ( ) ;
y . foo ( ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
50 .. 54 ' self ' : & Self
63 .. 65 ' { } ' : ( )
182 .. 183 'x' : T
188 .. 189 'y' : U
194 .. 223 ' { .. . o ( ) ; } ' : ( )
200 .. 201 'x' : T
200 .. 207 ' x . foo ( ) ' : u32
213 .. 214 'y' : U
213 .. 220 ' y . foo ( ) ' : u32
2019-12-03 12:38:54 +00:00
" ###
) ;
}
2020-02-07 17:27:54 +00:00
#[ test ]
fn super_trait_impl_trait_method_resolution ( ) {
assert_snapshot! (
infer ( r #"
mod foo {
trait SuperTrait {
fn foo ( & self ) -> u32 { }
}
}
trait Trait1 : foo ::SuperTrait { }
fn test ( x : & impl Trait1 ) {
x . foo ( ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
50 .. 54 ' self ' : & Self
63 .. 65 ' { } ' : ( )
116 .. 117 'x' : & impl Trait1
133 .. 149 ' { .. . o ( ) ; } ' : ( )
139 .. 140 'x' : & impl Trait1
139 .. 146 ' x . foo ( ) ' : u32
2020-02-07 17:27:54 +00:00
" ###
) ;
}
2019-12-03 12:38:54 +00:00
#[ test ]
fn super_trait_cycle ( ) {
// This just needs to not crash
assert_snapshot! (
infer ( r #"
trait A : B { }
trait B : A { }
fn test < T : A > ( x : T ) {
x . foo ( ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
44 .. 45 'x' : T
50 .. 66 ' { .. . o ( ) ; } ' : ( )
56 .. 57 'x' : T
56 .. 63 ' x . foo ( ) ' : { unknown }
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn super_trait_assoc_type_bounds ( ) {
assert_snapshot! (
infer ( r #"
trait SuperTrait { type Type ; }
trait Trait where Self : SuperTrait { }
fn get2 < U , T : Trait < Type = U > > ( t : T ) -> U { }
fn set < T : Trait < Type = u64 > > ( t : T ) -> T { t }
struct S < T > ;
impl < T > SuperTrait for S < T > { type Type = T ; }
impl < T > Trait for S < T > { }
fn test ( ) {
get2 ( set ( S ) ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
103 .. 104 't' : T
114 .. 116 ' { } ' : ( )
146 .. 147 't' : T
157 .. 160 ' { t } ' : T
158 .. 159 't' : T
259 .. 280 ' { .. . S ) ) ; } ' : ( )
265 .. 269 ' get2 ' : fn get2 < u64 , S < u64 > > ( S < u64 > ) -> u64
265 .. 277 ' get2 ( set ( S ) ) ' : u64
270 .. 273 ' set ' : fn set < S < u64 > > ( S < u64 > ) -> S < u64 >
270 .. 276 ' set ( S ) ' : S < u64 >
274 .. 275 'S' : S < u64 >
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn fn_trait ( ) {
assert_snapshot! (
infer ( r #"
trait FnOnce < Args > {
type Output ;
fn call_once ( self , args : Args ) -> < Self as FnOnce < Args > > ::Output ;
}
fn test < F : FnOnce ( u32 , u64 ) -> u128 > ( f : F ) {
f . call_once ( ( 1 , 2 ) ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
57 .. 61 ' self ' : Self
63 .. 67 ' args ' : Args
150 .. 151 'f' : F
156 .. 184 ' { .. . 2 ) ) ; } ' : ( )
162 .. 163 'f' : F
162 .. 181 ' f . call .. . 1 , 2 ) ) ' : u128
174 .. 180 ' ( 1 , 2 ) ' : ( u32 , u64 )
175 .. 176 '1' : u32
178 .. 179 '2' : u64
2019-12-03 12:38:54 +00:00
" ###
) ;
}
2020-05-18 06:07:31 +00:00
#[ test ]
fn fn_ptr_and_item ( ) {
assert_snapshot! (
infer ( r #"
#[ lang= " fn_once " ]
trait FnOnce < Args > {
type Output ;
fn call_once ( self , args : Args ) -> Self ::Output ;
}
trait Foo < T > {
fn foo ( & self ) -> T ;
}
struct Bar < T > ( T ) ;
impl < A1 , R , F : FnOnce ( A1 ) -> R > Foo < ( A1 , R ) > for Bar < F > {
fn foo ( & self ) -> ( A1 , R ) { }
}
enum Opt < T > { None , Some ( T ) }
impl < T > Opt < T > {
fn map < U , F : FnOnce ( T ) -> U > ( self , f : F ) -> Opt < U > { }
}
fn test ( ) {
let bar : Bar < fn ( u8 ) -> u32 > ;
bar . foo ( ) ;
let opt : Opt < u8 > ;
let f : fn ( u8 ) -> u32 ;
opt . map ( f ) ;
}
" #),
@ r ###"
75 .. 79 ' self ' : Self
81 .. 85 ' args ' : Args
140 .. 144 ' self ' : & Self
244 .. 248 ' self ' : & Bar < F >
261 .. 263 ' { } ' : ( )
347 .. 351 ' self ' : Opt < T >
353 .. 354 'f' : F
369 .. 371 ' { } ' : ( )
385 .. 501 ' { .. . ( f ) ; } ' : ( )
395 .. 398 ' bar ' : Bar < fn ( u8 ) -> u32 >
424 .. 427 ' bar ' : Bar < fn ( u8 ) -> u32 >
424 .. 433 ' bar . foo ( ) ' : { unknown }
444 .. 447 ' opt ' : Opt < u8 >
466 .. 467 'f' : fn ( u8 ) -> u32
488 .. 491 ' opt ' : Opt < u8 >
488 .. 498 ' opt . map ( f ) ' : Opt < FnOnce ::Output < fn ( u8 ) -> u32 , ( u8 , ) > >
496 .. 497 'f' : fn ( u8 ) -> u32
" ###
) ;
}
#[ test ]
fn fn_trait_deref_with_ty_default ( ) {
assert_snapshot! (
infer ( r #"
#[ lang = " deref " ]
trait Deref {
type Target ;
fn deref ( & self ) -> & Self ::Target ;
}
#[ lang= " fn_once " ]
trait FnOnce < Args > {
type Output ;
fn call_once ( self , args : Args ) -> Self ::Output ;
}
struct Foo ;
impl Foo {
fn foo ( & self ) -> usize { }
}
struct Lazy < T , F = fn ( ) -> T > ( F ) ;
impl < T , F > Lazy < T , F > {
pub fn new ( f : F ) -> Lazy < T , F > { }
}
impl < T , F : FnOnce ( ) -> T > Deref for Lazy < T , F > {
type Target = T ;
}
fn test ( ) {
let lazy1 : Lazy < Foo , _ > = Lazy ::new ( | | Foo ) ;
let r1 = lazy1 . foo ( ) ;
fn make_foo_fn ( ) -> Foo { }
let make_foo_fn_ptr : fn ( ) -> Foo = make_foo_fn ;
let lazy2 : Lazy < Foo , _ > = Lazy ::new ( make_foo_fn_ptr ) ;
let r2 = lazy2 . foo ( ) ;
}
" #),
@ r ###"
2020-05-29 17:14:04 +00:00
65 .. 69 ' self ' : & Self
166 .. 170 ' self ' : Self
172 .. 176 ' args ' : Args
240 .. 244 ' self ' : & Foo
255 .. 257 ' { } ' : ( )
335 .. 336 'f' : F
355 .. 357 ' { } ' : ( )
444 .. 690 ' { .. . o ( ) ; } ' : ( )
454 .. 459 ' lazy1 ' : Lazy < Foo , | | -> Foo >
476 .. 485 ' Lazy ::new ' : fn new < Foo , | | -> Foo > ( | | -> Foo ) -> Lazy < Foo , | | -> Foo >
476 .. 493 ' Lazy ::.. . | Foo ) ' : Lazy < Foo , | | -> Foo >
486 .. 492 ' | | Foo ' : | | -> Foo
489 .. 492 ' Foo ' : Foo
503 .. 505 ' r1 ' : usize
508 .. 513 ' lazy1 ' : Lazy < Foo , | | -> Foo >
508 .. 519 ' lazy1 . foo ( ) ' : usize
561 .. 576 ' make_foo_fn_ptr ' : fn ( ) -> Foo
592 .. 603 ' make_foo_fn ' : fn make_foo_fn ( ) -> Foo
613 .. 618 ' lazy2 ' : Lazy < Foo , fn ( ) -> Foo >
635 .. 644 ' Lazy ::new ' : fn new < Foo , fn ( ) -> Foo > ( fn ( ) -> Foo ) -> Lazy < Foo , fn ( ) -> Foo >
635 .. 661 ' Lazy ::.. . n_ptr ) ' : Lazy < Foo , fn ( ) -> Foo >
645 .. 660 ' make_foo_fn_ptr ' : fn ( ) -> Foo
671 .. 673 ' r2 ' : { unknown }
676 .. 681 ' lazy2 ' : Lazy < Foo , fn ( ) -> Foo >
676 .. 687 ' lazy2 . foo ( ) ' : { unknown }
550 .. 552 ' { } ' : ( )
" ###
2020-05-18 06:07:31 +00:00
) ;
}
2019-12-03 12:38:54 +00:00
#[ test ]
fn closure_1 ( ) {
assert_snapshot! (
infer ( r #"
#[ lang = " fn_once " ]
trait FnOnce < Args > {
type Output ;
}
enum Option < T > { Some ( T ) , None }
impl < T > Option < T > {
fn map < U , F : FnOnce ( T ) -> U > ( self , f : F ) -> Option < U > { }
}
fn test ( ) {
let x = Option ::Some ( 1 u32 ) ;
x . map ( | v | v + 1 ) ;
x . map ( | _v | 1 u64 ) ;
let y : Option < i64 > = x . map ( | _v | 1 ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
148 .. 152 ' self ' : Option < T >
154 .. 155 'f' : F
173 .. 175 ' { } ' : ( )
189 .. 308 ' { .. . 1 ) ; } ' : ( )
199 .. 200 'x' : Option < u32 >
203 .. 215 ' Option ::Some ' : Some < u32 > ( u32 ) -> Option < u32 >
203 .. 221 ' Option .. . ( 1 u32 ) ' : Option < u32 >
216 .. 220 ' 1 u32 ' : u32
227 .. 228 'x' : Option < u32 >
227 .. 243 ' x . map ( .. . v + 1 ) ' : Option < u32 >
233 .. 242 ' | v | v + 1 ' : | u32 | -> u32
234 .. 235 'v' : u32
237 .. 238 'v' : u32
237 .. 242 ' v + 1 ' : u32
241 .. 242 '1' : u32
249 .. 250 'x' : Option < u32 >
249 .. 265 ' x . map ( .. . 1 u64 ) ' : Option < u64 >
255 .. 264 ' | _v | 1 u64 ' : | u32 | -> u64
256 .. 258 '_ v ' : u32
260 .. 264 ' 1 u64 ' : u64
275 .. 276 'y' : Option < i64 >
292 .. 293 'x' : Option < u32 >
292 .. 305 ' x . map ( | _v | 1 ) ' : Option < i64 >
298 .. 304 ' | _v | 1 ' : | u32 | -> i64
299 .. 301 '_ v ' : u32
303 .. 304 '1' : i64
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn closure_2 ( ) {
assert_snapshot! (
infer ( r #"
trait FnOnce < Args > {
type Output ;
}
fn test < F : FnOnce ( u32 ) -> u64 > ( f : F ) {
f ( 1 ) ;
let g = | v | v + 1 ;
g ( 1 u64 ) ;
let h = | v | 1 u128 + v ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
73 .. 74 'f' : F
79 .. 155 ' { .. . + v ; } ' : ( )
85 .. 86 'f' : F
85 .. 89 ' f ( 1 ) ' : { unknown }
87 .. 88 '1' : i32
99 .. 100 'g' : | u64 | -> i32
103 .. 112 ' | v | v + 1 ' : | u64 | -> i32
104 .. 105 'v' : u64
107 .. 108 'v' : u64
107 .. 112 ' v + 1 ' : i32
111 .. 112 '1' : i32
118 .. 119 'g' : | u64 | -> i32
118 .. 125 ' g ( 1 u64 ) ' : i32
120 .. 124 ' 1 u64 ' : u64
135 .. 136 'h' : | u128 | -> u128
139 .. 152 ' | v | 1 u128 + v ' : | u128 | -> u128
140 .. 141 'v' : u128
143 .. 148 ' 1 u128 ' : u128
143 .. 152 ' 1 u128 + v ' : u128
151 .. 152 'v' : u128
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn closure_as_argument_inference_order ( ) {
assert_snapshot! (
infer ( r #"
#[ lang = " fn_once " ]
trait FnOnce < Args > {
type Output ;
}
fn foo1 < T , U , F : FnOnce ( T ) -> U > ( x : T , f : F ) -> U { }
fn foo2 < T , U , F : FnOnce ( T ) -> U > ( f : F , x : T ) -> U { }
struct S ;
impl S {
fn method ( self ) -> u64 ;
fn foo1 < T , U , F : FnOnce ( T ) -> U > ( self , x : T , f : F ) -> U { }
fn foo2 < T , U , F : FnOnce ( T ) -> U > ( self , f : F , x : T ) -> U { }
}
fn test ( ) {
let x1 = foo1 ( S , | s | s . method ( ) ) ;
let x2 = foo2 ( | s | s . method ( ) , S ) ;
let x3 = S . foo1 ( S , | s | s . method ( ) ) ;
let x4 = S . foo2 ( | s | s . method ( ) , S ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
95 .. 96 'x' : T
101 .. 102 'f' : F
112 .. 114 ' { } ' : ( )
148 .. 149 'f' : F
154 .. 155 'x' : T
165 .. 167 ' { } ' : ( )
202 .. 206 ' self ' : S
254 .. 258 ' self ' : S
260 .. 261 'x' : T
266 .. 267 'f' : F
277 .. 279 ' { } ' : ( )
317 .. 321 ' self ' : S
323 .. 324 'f' : F
329 .. 330 'x' : T
340 .. 342 ' { } ' : ( )
356 .. 515 ' { .. . S ) ; } ' : ( )
366 .. 368 ' x1 ' : u64
371 .. 375 ' foo1 ' : fn foo1 < S , u64 , | S | -> u64 > ( S , | S | -> u64 ) -> u64
371 .. 394 ' foo1 ( S .. . hod ( ) ) ' : u64
376 .. 377 'S' : S
379 .. 393 ' | s | s . method ( ) ' : | S | -> u64
380 .. 381 's' : S
383 .. 384 's' : S
383 .. 393 ' s . method ( ) ' : u64
404 .. 406 ' x2 ' : u64
409 .. 413 ' foo2 ' : fn foo2 < S , u64 , | S | -> u64 > ( | S | -> u64 , S ) -> u64
409 .. 432 ' foo2 ( | .. . ( ) , S ) ' : u64
414 .. 428 ' | s | s . method ( ) ' : | S | -> u64
415 .. 416 's' : S
418 .. 419 's' : S
418 .. 428 ' s . method ( ) ' : u64
430 .. 431 'S' : S
442 .. 444 ' x3 ' : u64
447 .. 448 'S' : S
447 .. 472 ' S . foo1 .. . hod ( ) ) ' : u64
454 .. 455 'S' : S
457 .. 471 ' | s | s . method ( ) ' : | S | -> u64
458 .. 459 's' : S
461 .. 462 's' : S
461 .. 471 ' s . method ( ) ' : u64
482 .. 484 ' x4 ' : u64
487 .. 488 'S' : S
487 .. 512 ' S . foo2 .. . ( ) , S ) ' : u64
494 .. 508 ' | s | s . method ( ) ' : | S | -> u64
495 .. 496 's' : S
498 .. 499 's' : S
498 .. 508 ' s . method ( ) ' : u64
510 .. 511 'S' : S
2019-12-03 12:38:54 +00:00
" ###
) ;
}
#[ test ]
fn unselected_projection_in_trait_env_1 ( ) {
let t = type_at (
r #"
//- /main.rs
trait Trait {
type Item ;
}
trait Trait2 {
fn foo ( & self ) -> u32 ;
}
fn test < T : Trait > ( ) where T ::Item : Trait2 {
let x : T ::Item = no_matter ;
x . foo ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " u32 " ) ;
}
#[ test ]
fn unselected_projection_in_trait_env_2 ( ) {
let t = type_at (
r #"
//- /main.rs
trait Trait < T > {
type Item ;
}
trait Trait2 {
fn foo ( & self ) -> u32 ;
}
fn test < T , U > ( ) where T ::Item : Trait2 , T : Trait < U ::Item > , U : Trait < ( ) > {
let x : T ::Item = no_matter ;
x . foo ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " u32 " ) ;
}
2020-03-06 17:08:10 +00:00
#[ test ]
2020-04-12 10:29:03 +00:00
fn unselected_projection_on_impl_self ( ) {
2020-03-06 17:08:10 +00:00
assert_snapshot! ( infer (
r #"
//- /main.rs
trait Trait {
type Item ;
fn f ( & self , x : Self ::Item ) ;
}
struct S ;
impl Trait for S {
type Item = u32 ;
fn f ( & self , x : Self ::Item ) { let y = x ; }
}
struct S2 ;
impl Trait for S2 {
type Item = i32 ;
fn f ( & self , x : < Self > ::Item ) { let y = x ; }
}
" #,
) , @ r ###"
2020-04-24 21:51:02 +00:00
54 .. 58 ' self ' : & Self
60 .. 61 'x' : Trait ::Item < Self >
140 .. 144 ' self ' : & S
146 .. 147 'x' : u32
161 .. 175 ' { let y = x ; } ' : ( )
167 .. 168 'y' : u32
171 .. 172 'x' : u32
242 .. 246 ' self ' : & S2
248 .. 249 'x' : i32
265 .. 279 ' { let y = x ; } ' : ( )
271 .. 272 'y' : i32
275 .. 276 'x' : i32
2020-03-06 17:08:10 +00:00
" ###);
}
2020-04-12 10:29:03 +00:00
#[ test ]
fn unselected_projection_on_trait_self ( ) {
let t = type_at (
r #"
//- /main.rs
trait Trait {
type Item ;
fn f ( & self ) -> Self ::Item { loop { } }
}
struct S ;
impl Trait for S {
type Item = u32 ;
}
fn test ( ) {
S . f ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " u32 " ) ;
}
2020-04-26 14:56:25 +00:00
#[ test ]
fn unselected_projection_chalk_fold ( ) {
let t = type_at (
r #"
//- /main.rs
trait Interner { }
trait Fold < I : Interner , TI = I > {
type Result ;
}
struct Ty < I : Interner > { }
impl < I : Interner , TI : Interner > Fold < I , TI > for Ty < I > {
type Result = Ty < TI > ;
}
fn fold < I : Interner , T > ( interner : & I , t : T ) -> T ::Result
where
T : Fold < I , I > ,
{
loop { }
}
fn foo < I : Interner > ( interner : & I , t : Ty < I > ) {
fold ( interner , t ) < | > ;
}
" #,
) ;
assert_eq! ( t , " Ty<I> " ) ;
}
2019-12-03 12:38:54 +00:00
#[ test ]
fn trait_impl_self_ty ( ) {
let t = type_at (
r #"
//- /main.rs
trait Trait < T > {
fn foo ( & self ) ;
}
struct S ;
impl Trait < Self > for S { }
fn test ( ) {
S . foo ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " () " ) ;
}
#[ test ]
fn trait_impl_self_ty_cycle ( ) {
let t = type_at (
r #"
//- /main.rs
trait Trait {
fn foo ( & self ) ;
}
struct S < T > ;
impl Trait for S < Self > { }
fn test ( ) {
S . foo ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " {unknown} " ) ;
}
#[ test ]
fn unselected_projection_in_trait_env_cycle_1 ( ) {
let t = type_at (
r #"
//- /main.rs
trait Trait {
type Item ;
}
trait Trait2 < T > { }
fn test < T : Trait > ( ) where T : Trait2 < T ::Item > {
let x : T ::Item = no_matter < | > ;
}
" #,
) ;
// this is a legitimate cycle
assert_eq! ( t , " {unknown} " ) ;
}
#[ test ]
fn unselected_projection_in_trait_env_cycle_2 ( ) {
let t = type_at (
r #"
//- /main.rs
trait Trait < T > {
type Item ;
}
fn test < T , U > ( ) where T : Trait < U ::Item > , U : Trait < T ::Item > {
let x : T ::Item = no_matter < | > ;
}
" #,
) ;
// this is a legitimate cycle
assert_eq! ( t , " {unknown} " ) ;
}
2019-12-06 11:45:00 +00:00
2020-04-10 20:05:46 +00:00
#[ test ]
fn inline_assoc_type_bounds_1 ( ) {
let t = type_at (
r #"
//- /main.rs
trait Iterator {
type Item ;
}
trait OtherTrait < T > {
fn foo ( & self ) -> T ;
}
// workaround for Chalk assoc type normalization problems
pub struct S < T > ;
impl < T : Iterator > Iterator for S < T > {
type Item = < T as Iterator > ::Item ;
}
fn test < I : Iterator < Item : OtherTrait < u32 > > > ( ) {
let x : < S < I > as Iterator > ::Item ;
x . foo ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " u32 " ) ;
}
#[ test ]
fn inline_assoc_type_bounds_2 ( ) {
let t = type_at (
r #"
//- /main.rs
trait Iterator {
type Item ;
}
fn test < I : Iterator < Item : Iterator < Item = u32 > > > ( ) {
let x : < < I as Iterator > ::Item as Iterator > ::Item ;
x < | > ;
}
" #,
) ;
2020-04-10 15:44:43 +00:00
assert_eq! ( t , " u32 " ) ;
2020-04-10 20:05:46 +00:00
}
2020-04-13 09:55:34 +00:00
#[ test ]
fn proc_macro_server_types ( ) {
assert_snapshot! (
2020-05-03 14:08:39 +00:00
infer ( r #"
2020-04-13 09:55:34 +00:00
macro_rules ! with_api {
( $S :ident , $self :ident , $m :ident ) = > {
$m ! {
TokenStream {
fn new ( ) -> $S ::TokenStream ;
} ,
Group {
} ,
}
} ;
}
macro_rules ! associated_item {
( type TokenStream ) = >
2020-05-03 14:08:39 +00:00
( type TokenStream : 'static ; ) ;
2020-04-13 09:55:34 +00:00
( type Group ) = >
2020-05-03 14:08:39 +00:00
( type Group : 'static ; ) ;
2020-04-13 09:55:34 +00:00
( $( $item :tt ) * ) = > ( $( $item ) * ; )
}
macro_rules ! declare_server_traits {
( $( $name :ident {
$( fn $method :ident ( $( $arg :ident : $arg_ty :ty ) , * $(, ) ? ) $( -> $ret_ty :ty ) ? ; ) *
} ) , * $(, ) ? ) = > {
pub trait Types {
$( associated_item! ( type $name ) ; ) *
}
$( pub trait $name : Types {
2020-05-03 14:08:39 +00:00
$( associated_item! ( fn $method ( $( $arg : $arg_ty ) , * ) $( -> $ret_ty ) ? ) ; ) *
2020-04-13 09:55:34 +00:00
} ) *
pub trait Server : Types $( + $name ) * { }
impl < S : Types $( + $name ) * > Server for S { }
}
}
2020-05-03 14:08:39 +00:00
2020-04-13 09:55:34 +00:00
with_api! ( Self , self_ , declare_server_traits ) ;
2020-05-03 14:08:39 +00:00
struct G { }
struct T { }
2020-04-13 09:55:34 +00:00
struct Rustc ;
impl Types for Rustc {
2020-05-03 14:08:39 +00:00
type TokenStream = T ;
type Group = G ;
2020-04-13 09:55:34 +00:00
}
2020-05-03 14:08:39 +00:00
2020-04-13 09:55:34 +00:00
fn make < T > ( ) -> T { loop { } }
impl TokenStream for Rustc {
fn new ( ) -> Self ::TokenStream {
let group : Self ::Group = make ( ) ;
make ( )
}
2020-05-03 14:15:07 +00:00
}
2020-05-03 14:08:39 +00:00
" #),
2020-04-13 09:55:34 +00:00
@ r ###"
2020-05-03 14:08:39 +00:00
1062 .. 1073 ' { loop { } } ' : T
1064 .. 1071 ' loop { } ' : !
1069 .. 1071 ' { } ' : ( )
1137 .. 1200 ' { .. . } ' : T
1151 .. 1156 ' group ' : G
1172 .. 1176 ' make ' : fn make < G > ( ) -> G
1172 .. 1178 ' make ( ) ' : G
1188 .. 1192 ' make ' : fn make < T > ( ) -> T
1188 .. 1194 ' make ( ) ' : T
2020-04-13 09:55:34 +00:00
" ###
) ;
}
2019-12-06 11:45:00 +00:00
#[ test ]
fn unify_impl_trait ( ) {
assert_snapshot! (
infer_with_mismatches ( r #"
trait Trait < T > { }
fn foo ( x : impl Trait < u32 > ) { loop { } }
fn bar < T > ( x : impl Trait < T > ) -> T { loop { } }
struct S < T > ( T ) ;
impl < T > Trait < T > for S < T > { }
fn default < T > ( ) -> T { loop { } }
fn test ( ) -> impl Trait < i32 > {
let s1 = S ( default ( ) ) ;
foo ( s1 ) ;
let x : i32 = bar ( S ( default ( ) ) ) ;
S ( default ( ) )
}
" #, true),
@ r ###"
2020-04-24 21:51:02 +00:00
27 .. 28 'x' : impl Trait < u32 >
47 .. 58 ' { loop { } } ' : ( )
49 .. 56 ' loop { } ' : !
54 .. 56 ' { } ' : ( )
69 .. 70 'x' : impl Trait < T >
92 .. 103 ' { loop { } } ' : T
94 .. 101 ' loop { } ' : !
99 .. 101 ' { } ' : ( )
172 .. 183 ' { loop { } } ' : T
174 .. 181 ' loop { } ' : !
179 .. 181 ' { } ' : ( )
214 .. 310 ' { .. . t ( ) ) } ' : S < { unknown } >
224 .. 226 ' s1 ' : S < u32 >
229 .. 230 'S' : S < u32 > ( u32 ) -> S < u32 >
229 .. 241 ' S ( default ( ) ) ' : S < u32 >
231 .. 238 ' default ' : fn default < u32 > ( ) -> u32
231 .. 240 ' default ( ) ' : u32
247 .. 250 ' foo ' : fn foo ( S < u32 > )
247 .. 254 ' foo ( s1 ) ' : ( )
251 .. 253 ' s1 ' : S < u32 >
264 .. 265 'x' : i32
273 .. 276 ' bar ' : fn bar < i32 > ( S < i32 > ) -> i32
273 .. 290 ' bar ( S ( .. . lt ( ) ) ) ' : i32
277 .. 278 'S' : S < i32 > ( i32 ) -> S < i32 >
277 .. 289 ' S ( default ( ) ) ' : S < i32 >
279 .. 286 ' default ' : fn default < i32 > ( ) -> i32
279 .. 288 ' default ( ) ' : i32
296 .. 297 'S' : S < { unknown } > ( { unknown } ) -> S < { unknown } >
296 .. 308 ' S ( default ( ) ) ' : S < { unknown } >
298 .. 305 ' default ' : fn default < { unknown } > ( ) -> { unknown }
298 .. 307 ' default ( ) ' : { unknown }
2019-12-06 11:45:00 +00:00
" ###
) ;
}
2020-02-21 12:47:49 +00:00
#[ test ]
fn assoc_types_from_bounds ( ) {
assert_snapshot! (
infer ( r #"
//- /main.rs
#[ lang = " fn_once " ]
trait FnOnce < Args > {
type Output ;
}
trait T {
type O ;
}
impl T for ( ) {
type O = ( ) ;
}
fn f < X , F > ( _v : F )
where
X : T ,
F : FnOnce ( & X ::O ) ,
{ }
fn main ( ) {
f ::< ( ) , _ > ( | z | { z ; } ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
147 .. 149 '_ v ' : F
192 .. 195 ' { } ' : ( )
207 .. 238 ' { .. . } ) ; } ' : ( )
213 .. 223 ' f ::< ( ) , _ > ' : fn f < ( ) , | & ( ) | -> ( ) > ( | & ( ) | -> ( ) )
213 .. 235 ' f ::< ( ) .. . z ; } ) ' : ( )
224 .. 234 ' | z | { z ; } ' : | & ( ) | -> ( )
225 .. 226 'z' : & ( )
228 .. 234 ' { z ; } ' : ( )
230 .. 231 'z' : & ( )
2020-02-21 12:47:49 +00:00
" ###
) ;
}
2020-04-06 15:24:08 +00:00
2020-04-12 10:28:24 +00:00
#[ test ]
fn associated_type_bound ( ) {
let t = type_at (
r #"
//- /main.rs
pub trait Trait {
type Item : OtherTrait < u32 > ;
}
pub trait OtherTrait < T > {
fn foo ( & self ) -> T ;
}
// this is just a workaround for chalk#234
pub struct S < T > ;
impl < T : Trait > Trait for S < T > {
type Item = < T as Trait > ::Item ;
}
fn test < T : Trait > ( ) {
let y : < S < T > as Trait > ::Item = no_matter ;
y . foo ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " u32 " ) ;
}
2020-04-06 15:24:08 +00:00
#[ test ]
fn dyn_trait_through_chalk ( ) {
let t = type_at (
r #"
//- /main.rs
struct Box < T > { }
#[ lang = " deref " ]
trait Deref {
type Target ;
}
impl < T > Deref for Box < T > {
type Target = T ;
}
trait Trait {
fn foo ( & self ) ;
}
fn test ( x : Box < dyn Trait > ) {
x . foo ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " () " ) ;
}
2020-04-17 16:27:20 +00:00
#[ test ]
fn string_to_owned ( ) {
let t = type_at (
r #"
//- /main.rs
struct String { }
pub trait ToOwned {
type Owned ;
fn to_owned ( & self ) -> Self ::Owned ;
}
impl ToOwned for str {
type Owned = String ;
}
fn test ( ) {
" foo " . to_owned ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " String " ) ;
}
#[ test ]
fn iterator_chain ( ) {
assert_snapshot! (
infer ( r #"
//- /main.rs
#[ lang = " fn_once " ]
trait FnOnce < Args > {
type Output ;
}
#[ lang = " fn_mut " ]
trait FnMut < Args > : FnOnce < Args > { }
enum Option < T > { Some ( T ) , None }
use Option ::* ;
pub trait Iterator {
type Item ;
fn filter_map < B , F > ( self , f : F ) -> FilterMap < Self , F >
where
F : FnMut ( Self ::Item ) -> Option < B > ,
{ loop { } }
fn for_each < F > ( self , f : F )
where
F : FnMut ( Self ::Item ) ,
{ loop { } }
}
pub trait IntoIterator {
type Item ;
type IntoIter : Iterator < Item = Self ::Item > ;
fn into_iter ( self ) -> Self ::IntoIter ;
}
pub struct FilterMap < I , F > { }
impl < B , I : Iterator , F > Iterator for FilterMap < I , F >
where
F : FnMut ( I ::Item ) -> Option < B > ,
{
type Item = B ;
}
#[ stable(feature = " rust1 " , since = " 1.0.0 " ) ]
impl < I : Iterator > IntoIterator for I {
type Item = I ::Item ;
type IntoIter = I ;
fn into_iter ( self ) -> I {
self
}
}
struct Vec < T > { }
impl < T > Vec < T > {
fn new ( ) -> Self { loop { } }
}
impl < T > IntoIterator for Vec < T > {
type Item = T ;
type IntoIter = IntoIter < T > ;
}
pub struct IntoIter < T > { }
impl < T > Iterator for IntoIter < T > {
type Item = T ;
}
fn main ( ) {
Vec ::< i32 > ::new ( ) . into_iter ( )
. filter_map ( | x | if x > 0 { Some ( x as u32 ) } else { None } )
. for_each ( | y | { y ; } ) ;
}
" #),
@ r ###"
2020-04-24 21:51:02 +00:00
240 .. 244 ' self ' : Self
246 .. 247 'f' : F
331 .. 342 ' { loop { } } ' : FilterMap < Self , F >
333 .. 340 ' loop { } ' : !
338 .. 340 ' { } ' : ( )
363 .. 367 ' self ' : Self
369 .. 370 'f' : F
419 .. 430 ' { loop { } } ' : ( )
421 .. 428 ' loop { } ' : !
426 .. 428 ' { } ' : ( )
539 .. 543 ' self ' : Self
868 .. 872 ' self ' : I
879 .. 899 ' { .. . } ' : I
889 .. 893 ' self ' : I
958 .. 969 ' { loop { } } ' : Vec < T >
960 .. 967 ' loop { } ' : !
965 .. 967 ' { } ' : ( )
1156 .. 1287 ' { .. . } ) ; } ' : ( )
1162 .. 1177 ' Vec ::< i32 > ::new ' : fn new < i32 > ( ) -> Vec < i32 >
1162 .. 1179 ' Vec ::< .. . :new ( ) ' : Vec < i32 >
1162 .. 1191 ' Vec ::< .. . iter ( ) ' : IntoIter < i32 >
1162 .. 1256 ' Vec ::< .. . one } ) ' : FilterMap < IntoIter < i32 > , | i32 | -> Option < u32 > >
1162 .. 1284 ' Vec ::< .. . y ; } ) ' : ( )
1210 .. 1255 ' | x | if .. . None } ' : | i32 | -> Option < u32 >
1211 .. 1212 'x' : i32
1214 .. 1255 ' if x > .. . None } ' : Option < u32 >
1217 .. 1218 'x' : i32
1217 .. 1222 ' x > 0 ' : bool
1221 .. 1222 '0' : i32
1223 .. 1241 ' { Some .. . u32 ) } ' : Option < u32 >
1225 .. 1229 ' Some ' : Some < u32 > ( u32 ) -> Option < u32 >
1225 .. 1239 ' Some ( x as u32 ) ' : Option < u32 >
1230 .. 1231 'x' : i32
1230 .. 1238 ' x as u32 ' : u32
1247 .. 1255 ' { None } ' : Option < u32 >
1249 .. 1253 ' None ' : Option < u32 >
1273 .. 1283 ' | y | { y ; } ' : | u32 | -> ( )
1274 .. 1275 'y' : u32
1277 .. 1283 ' { y ; } ' : ( )
1279 .. 1280 'y' : u32
2020-04-17 16:27:20 +00:00
" ###
) ;
}
#[ test ]
fn nested_assoc ( ) {
let t = type_at (
r #"
//- /main.rs
struct Bar ;
struct Foo ;
trait A {
type OutputA ;
}
impl A for Bar {
type OutputA = Foo ;
}
trait B {
type Output ;
fn foo ( ) -> Self ::Output ;
}
impl < T :A > B for T {
type Output = T ::OutputA ;
fn foo ( ) -> Self ::Output { loop { } }
}
fn main ( ) {
Bar ::foo ( ) < | > ;
}
" #,
) ;
assert_eq! ( t , " Foo " ) ;
}
2020-04-17 17:41:37 +00:00
#[ test ]
fn trait_object_no_coercion ( ) {
assert_snapshot! (
infer_with_mismatches ( r #"
trait Foo { }
fn foo ( x : & dyn Foo ) { }
fn test ( x : & dyn Foo ) {
foo ( x ) ;
}
" #, true),
@ r ###"
2020-04-24 21:51:02 +00:00
22 .. 23 'x' : & dyn Foo
35 .. 37 ' { } ' : ( )
47 .. 48 'x' : & dyn Foo
60 .. 75 ' { foo ( x ) ; } ' : ( )
66 .. 69 ' foo ' : fn foo ( & dyn Foo )
66 .. 72 ' foo ( x ) ' : ( )
70 .. 71 'x' : & dyn Foo
2020-04-17 17:41:37 +00:00
" ###
) ;
}
2020-05-22 16:52:07 +00:00
#[ test ]
fn builtin_copy ( ) {
assert_snapshot! (
infer_with_mismatches ( r #"
#[ lang = " copy " ]
trait Copy { }
struct IsCopy ;
impl Copy for IsCopy { }
struct NotCopy ;
trait Test { fn test ( & self ) -> bool ; }
impl < T : Copy > Test for T { }
fn test ( ) {
IsCopy . test ( ) ;
NotCopy . test ( ) ;
( IsCopy , IsCopy ) . test ( ) ;
( IsCopy , NotCopy ) . test ( ) ;
}
" #, true),
@ r ###"
111 .. 115 ' self ' : & Self
167 .. 268 ' { .. . t ( ) ; } ' : ( )
173 .. 179 ' IsCopy ' : IsCopy
173 .. 186 ' IsCopy . test ( ) ' : bool
192 .. 199 ' NotCopy ' : NotCopy
192 .. 206 ' NotCopy . test ( ) ' : { unknown }
212 .. 228 ' ( IsCop .. . sCopy ) ' : ( IsCopy , IsCopy )
212 .. 235 ' ( IsCop .. . test ( ) ' : bool
213 .. 219 ' IsCopy ' : IsCopy
221 .. 227 ' IsCopy ' : IsCopy
241 .. 258 ' ( IsCop .. . tCopy ) ' : ( IsCopy , NotCopy )
241 .. 265 ' ( IsCop .. . test ( ) ' : { unknown }
242 .. 248 ' IsCopy ' : IsCopy
250 .. 257 ' NotCopy ' : NotCopy
" ###
) ;
}
2020-05-22 16:15:53 +00:00
#[ test ]
fn builtin_fn_def_copy ( ) {
assert_snapshot! (
infer_with_mismatches ( r #"
#[ lang = " copy " ]
trait Copy { }
fn foo ( ) { }
fn bar < T : Copy > ( T ) -> T { }
struct Struct ( usize ) ;
enum Enum { Variant ( usize ) }
trait Test { fn test ( & self ) -> bool ; }
impl < T : Copy > Test for T { }
fn test ( ) {
foo . test ( ) ;
bar . test ( ) ;
Struct . test ( ) ;
Enum ::Variant . test ( ) ;
}
" #, true),
@ r ###"
42 .. 44 ' { } ' : ( )
61 .. 62 'T' : { unknown }
69 .. 71 ' { } ' : ( )
69 .. 71 : expected T , got ( )
146 .. 150 ' self ' : & Self
202 .. 282 ' { .. . t ( ) ; } ' : ( )
208 .. 211 ' foo ' : fn foo ( )
2020-05-29 14:49:52 +00:00
208 .. 218 ' foo . test ( ) ' : bool
2020-05-22 16:15:53 +00:00
224 .. 227 ' bar ' : fn bar < { unknown } > ( { unknown } ) -> { unknown }
2020-05-29 14:49:52 +00:00
224 .. 234 ' bar . test ( ) ' : bool
2020-05-22 16:15:53 +00:00
240 .. 246 ' Struct ' : Struct ( usize ) -> Struct
2020-05-29 14:49:52 +00:00
240 .. 253 ' Struct . test ( ) ' : bool
2020-05-22 16:15:53 +00:00
259 .. 272 ' Enum ::Variant ' : Variant ( usize ) -> Enum
2020-05-29 14:49:52 +00:00
259 .. 279 ' Enum ::.. . test ( ) ' : bool
2020-05-22 16:15:53 +00:00
" ###
) ;
}
2020-05-22 17:13:17 +00:00
#[ test ]
fn builtin_fn_ptr_copy ( ) {
assert_snapshot! (
infer_with_mismatches ( r #"
#[ lang = " copy " ]
trait Copy { }
trait Test { fn test ( & self ) -> bool ; }
impl < T : Copy > Test for T { }
fn test ( f1 : fn ( ) , f2 : fn ( usize ) -> u8 , f3 : fn ( u8 , u8 ) -> & u8 ) {
f1 . test ( ) ;
f2 . test ( ) ;
f3 . test ( ) ;
}
" #, true),
@ r ###"
55 .. 59 ' self ' : & Self
109 .. 111 ' f1 ' : fn ( )
119 .. 121 ' f2 ' : fn ( usize ) -> u8
140 .. 142 ' f3 ' : fn ( u8 , u8 ) -> & u8
163 .. 211 ' { .. . t ( ) ; } ' : ( )
169 .. 171 ' f1 ' : fn ( )
169 .. 178 ' f1 . test ( ) ' : bool
184 .. 186 ' f2 ' : fn ( usize ) -> u8
184 .. 193 ' f2 . test ( ) ' : bool
199 .. 201 ' f3 ' : fn ( u8 , u8 ) -> & u8
199 .. 208 ' f3 . test ( ) ' : bool
" ###
) ;
}
2020-05-22 16:52:07 +00:00
#[ test ]
fn builtin_sized ( ) {
assert_snapshot! (
infer_with_mismatches ( r #"
#[ lang = " sized " ]
trait Sized { }
trait Test { fn test ( & self ) -> bool ; }
impl < T : Sized > Test for T { }
fn test ( ) {
1 u8 . test ( ) ;
( * " foo " ) . test ( ) ; // not Sized
( 1 u8 , 1 u8 ) . test ( ) ;
( 1 u8 , * " foo " ) . test ( ) ; // not Sized
}
" #, true),
@ r ###"
57 .. 61 ' self ' : & Self
114 .. 229 ' { .. . ized } ' : ( )
120 .. 123 ' 1 u8 ' : u8
120 .. 130 ' 1 u8 . test ( ) ' : bool
136 .. 151 ' ( * " foo " ) . test ( ) ' : { unknown }
137 .. 143 ' * " foo " ' : str
138 .. 143 ' " foo " ' : & str
170 .. 180 ' ( 1 u8 , 1 u8 ) ' : ( u8 , u8 )
170 .. 187 ' ( 1 u8 , .. . test ( ) ' : bool
171 .. 174 ' 1 u8 ' : u8
176 .. 179 ' 1 u8 ' : u8
193 .. 206 ' ( 1 u8 , * " foo " ) ' : ( u8 , str )
193 .. 213 ' ( 1 u8 , .. . test ( ) ' : { unknown }
194 .. 197 ' 1 u8 ' : u8
199 .. 205 ' * " foo " ' : str
200 .. 205 ' " foo " ' : & str
" ###
) ;
}
2020-05-29 14:49:52 +00:00
#[ test ]
fn integer_range_iterate ( ) {
let t = type_at (
r #"
2020-06-11 14:22:31 +00:00
//- /main.rs crate:main deps:core
2020-05-29 14:49:52 +00:00
fn test ( ) {
for x in 0 .. 100 { x < | > ; }
}
2020-06-11 14:22:31 +00:00
//- /core.rs crate:core
2020-05-29 14:49:52 +00:00
pub mod ops {
pub struct Range < Idx > {
pub start : Idx ,
pub end : Idx ,
}
}
pub mod iter {
pub trait Iterator {
type Item ;
}
pub trait IntoIterator {
type Item ;
type IntoIter : Iterator < Item = Self ::Item > ;
}
impl < T > IntoIterator for T where T : Iterator {
type Item = < T as Iterator > ::Item ;
type IntoIter = Self ;
}
}
trait Step { }
impl Step for i32 { }
impl Step for i64 { }
impl < A : Step > iter ::Iterator for ops ::Range < A > {
type Item = A ;
}
" #,
) ;
assert_eq! ( t , " i32 " ) ;
}