2019-12-03 12:38:54 +00:00
use insta ::assert_snapshot ;
2019-12-15 20:06:08 +00:00
2019-12-03 12:38:54 +00:00
use ra_db ::fixture ::WithFixture ;
2019-12-15 20:06:08 +00:00
use super ::{ infer , infer_with_mismatches , type_at , type_at_pos } ;
use crate ::test_db ::TestDB ;
2019-12-03 12:38:54 +00:00
#[ test ]
fn infer_await ( ) {
let ( db , pos ) = TestDB ::with_position (
r #"
//- /main.rs crate:main deps:std
struct IntFuture ;
impl Future for IntFuture {
type Output = u64 ;
}
fn test ( ) {
let r = IntFuture ;
let v = r . await ;
v < | > ;
}
//- /std.rs crate:std
#[ 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 #"
//- /main.rs crate:main deps:std
async fn foo ( ) -> u64 {
128
}
fn test ( ) {
let r = foo ( ) ;
let v = r . await ;
v < | > ;
}
//- /std.rs crate:std
#[ 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 #"
//- /main.rs crate:main deps:std
async fn foo ( ) -> u64 {
128
}
fn test ( ) {
let r = foo ( ) ;
r < | > ;
}
//- /std.rs crate:std
#[ 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 #"
//- /main.rs crate:main deps:std
fn test ( ) {
let r : Result < i32 , u64 > = Result ::Ok ( 1 ) ;
let v = r ? ;
v < | > ;
}
//- /std.rs crate:std
#[ 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 #"
//- /main.rs crate:main deps:std
use std ::collections ::Vec ;
fn test ( ) {
let v = Vec ::new ( ) ;
v . push ( " foo " ) ;
for x in v {
x < | > ;
}
}
//- /std.rs crate:std
#[ prelude_import ] use iter ::* ;
mod iter {
trait IntoIterator {
type Item ;
}
}
mod collections {
struct Vec < T > { }
impl < T > Vec < T > {
fn new ( ) -> Self { Vec { } }
fn push ( & mut self , t : T ) { }
}
impl < T > crate ::iter ::IntoIterator for Vec < T > {
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 ###"
[ 86 ; 87 ) 't' : T
[ 92 ; 94 ) ' { } ' : ( )
[ 105 ; 144 ) ' { .. . ( s ) ; } ' : ( )
[ 115 ; 116 ) 's' : S < u32 >
2020-01-28 20:42:58 +00:00
[ 119 ; 120 ) 'S' : S < u32 > ( u32 ) -> S < u32 >
2019-12-03 12:38:54 +00:00
[ 119 ; 129 ) ' S ( unknown ) ' : S < u32 >
[ 121 ; 128 ) ' unknown ' : u32
2020-01-28 20:42:58 +00:00
[ 135 ; 138 ) ' foo ' : fn foo < S < u32 > > ( S < u32 > ) -> ( )
2019-12-03 12:38:54 +00:00
[ 135 ; 141 ) ' foo ( s ) ' : ( )
[ 139 ; 140 ) 's' : S < u32 >
" ###
) ;
}
#[ 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 ###"
[ 87 ; 88 ) 't' : T
[ 98 ; 100 ) ' { } ' : ( )
[ 111 ; 163 ) ' { .. . ( s ) ; } ' : ( )
[ 121 ; 122 ) 's' : S < u32 >
2020-01-28 20:42:58 +00:00
[ 125 ; 126 ) 'S' : S < u32 > ( u32 ) -> S < u32 >
2019-12-03 12:38:54 +00:00
[ 125 ; 135 ) ' S ( unknown ) ' : S < u32 >
[ 127 ; 134 ) ' unknown ' : u32
[ 145 ; 146 ) 'x' : u32
2020-01-28 20:42:58 +00:00
[ 154 ; 157 ) ' foo ' : fn foo < u32 , S < u32 > > ( S < u32 > ) -> u32
2019-12-03 12:38:54 +00:00
[ 154 ; 160 ) ' foo ( s ) ' : u32
[ 158 ; 159 ) 's' : S < u32 >
" ###
) ;
2020-02-14 18:16:42 +00:00
}
#[ test ]
fn trait_default_method_self_bound_implements_trait ( ) {
test_utils ::covers! ( trait_self_implements_self ) ;
assert_snapshot! (
infer ( r #"
trait Trait {
fn foo ( & self ) -> i64 ;
fn bar ( & self ) -> {
let x = self . foo ( ) ;
}
}
" #),
@ r ###"
[ 27 ; 31 ) ' self ' : & Self
[ 53 ; 57 ) ' self ' : & Self
[ 62 ; 97 ) ' { .. . } ' : ( )
[ 76 ; 77 ) 'x' : i64
[ 80 ; 84 ) ' self ' : & Self
[ 80 ; 90 ) ' self . foo ( ) ' : i64
" ###
) ;
}
#[ test ]
fn trait_default_method_self_bound_implements_super_trait ( ) {
test_utils ::covers! ( trait_self_implements_self ) ;
assert_snapshot! (
infer ( r #"
trait SuperTrait {
fn foo ( & self ) -> i64 ;
}
trait Trait : SuperTrait {
fn bar ( & self ) -> {
let x = self . foo ( ) ;
}
}
" #),
@ r ###"
[ 32 ; 36 ) ' self ' : & Self
[ 86 ; 90 ) ' self ' : & Self
[ 95 ; 130 ) ' { .. . } ' : ( )
[ 109 ; 110 ) 'x' : i64
[ 113 ; 117 ) ' self ' : & Self
[ 113 ; 123 ) ' self . foo ( ) ' : i64
" ###
) ;
2019-12-03 12:38:54 +00:00
}
#[ test ]
fn infer_project_associated_type ( ) {
// y, z, a don't yet work because of https://github.com/rust-lang/chalk/issues/234
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 ###"
[ 108 ; 261 ) ' { .. . ter ; } ' : ( )
[ 118 ; 119 ) 'x' : u32
[ 145 ; 146 ) '1' : u32
[ 156 ; 157 ) 'y' : { unknown }
[ 183 ; 192 ) ' no_matter ' : { unknown }
[ 202 ; 203 ) 'z' : { unknown }
[ 215 ; 224 ) ' no_matter ' : { unknown }
[ 234 ; 235 ) 'a' : { unknown }
[ 249 ; 258 ) ' no_matter ' : { unknown }
" ###
) ;
}
#[ 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 ###"
[ 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
2020-01-31 14:57:44 +00:00
[ 248 ; 252 ) ' foo1 ' : fn foo1 < S > ( S ) -> < S as Iterable > ::Item
2019-12-03 12:38:54 +00:00
[ 248 ; 255 ) ' foo1 ( S ) ' : u32
[ 253 ; 254 ) 'S' : S
[ 265 ; 266 ) 'y' : u32
2020-01-31 14:57:44 +00:00
[ 269 ; 273 ) ' foo2 ' : fn foo2 < S > ( S ) -> < S as Iterable > ::Item
2019-12-03 12:38:54 +00:00
[ 269 ; 276 ) ' foo2 ( S ) ' : u32
[ 274 ; 275 ) 'S' : S
[ 286 ; 287 ) 'z' : u32
2020-01-31 14:57:44 +00:00
[ 290 ; 294 ) ' foo3 ' : fn foo3 < S > ( S ) -> < S as Iterable > ::Item
2019-12-03 12:38:54 +00:00
[ 290 ; 297 ) ' foo3 ( S ) ' : u32
[ 295 ; 296 ) 'S' : S
" ###
) ;
}
#[ 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 ###"
[ 67 ; 100 ) ' { .. . own ; } ' : ( )
[ 77 ; 78 ) 'y' : { unknown }
[ 90 ; 97 ) ' unknown ' : { unknown }
" ###
) ;
}
#[ test ]
fn infer_const_body ( ) {
assert_snapshot! (
infer ( r #"
const A : u32 = 1 + 1 ;
static B : u64 = { let x = 1 ; x } ;
" #),
@ r ###"
[ 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
" ###
) ;
}
#[ 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 ###"
[ 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
" ###
) ;
}
#[ 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 ###"
[ 44 ; 102 ) ' { .. . 0 ( 2 ) } ' : u64
[ 54 ; 55 ) 'a' : S
[ 58 ; 59 ) 'S' : S ( fn ( u32 ) -> u64 ) -> S
[ 58 ; 68 ) ' S ( | i | 2 * i ) ' : S
2019-12-20 17:53:40 +00:00
[ 60 ; 67 ) ' | i | 2 * i ' : | u32 | -> u64
[ 61 ; 62 ) 'i' : u32
[ 64 ; 65 ) '2' : u32
[ 64 ; 67 ) ' 2 * i ' : u32
[ 66 ; 67 ) 'i' : u32
2019-12-03 12:38:54 +00:00
[ 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
" ###
) ;
}
#[ test ]
fn indexing_arrays ( ) {
assert_snapshot! (
infer ( " fn main() { &mut [9][2]; } " ) ,
@ r ###"
[ 10 ; 26 ) ' { & mut .. . [ 2 ] ; } ' : ( )
[ 12 ; 23 ) ' & mut [ 9 ] [ 2 ] ' : & mut { unknown }
2020-01-28 14:31:43 +00:00
[ 17 ; 20 ) ' [ 9 ] ' : [ i32 ; _ ]
2019-12-03 12:38:54 +00:00
[ 17 ; 23 ) ' [ 9 ] [ 2 ] ' : { unknown }
[ 18 ; 19 ) '9' : i32
[ 21 ; 22 ) '2' : i32
" ###
)
}
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 ;
let b = a [ 1 ] ;
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 ] ;
let b = a [ 1 ] ;
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 < | > ;
}
" #,
) ;
// FIXME here Chalk doesn't normalize the type to a placeholder. I think we
// need to add a rule like Normalize(<T as ApplyL>::Out -> ApplyL::Out<T>)
// to the trait env ourselves here; probably Chalk can't do this by itself.
// assert_eq!(t, "ApplyL::Out<[missing name]>");
assert_eq! ( t , " {unknown} " ) ;
}
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 ###"
[ 30 ; 34 ) ' self ' : & Self
[ 55 ; 59 ) ' self ' : & Self
2020-02-02 12:04:22 +00:00
[ 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
2020-02-07 15:39:48 +00:00
[ 234 ; 237 ) ' bar ' : fn bar ( S < u16 > ) -> ( )
2020-02-02 12:04:22 +00:00
[ 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 ###"
[ 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 } ' : ( )
2020-02-07 15:39:48 +00:00
[ 307 ; 315 ) ' Foo ::bar ' : fn bar < { unknown } , { unknown } > ( S ) -> { unknown }
2020-02-07 15:24:09 +00:00
[ 307 ; 318 ) ' Foo ::bar ( S ) ' : { unknown }
[ 316 ; 317 ) 'S' : S
2020-02-07 15:39:48 +00:00
[ 324 ; 339 ) ' < F as Foo > ::bar ' : fn bar < F , { unknown } > ( S ) -> { unknown }
2020-02-07 15:24:09 +00:00
[ 324 ; 342 ) ' < F as .. . bar ( S ) ' : { unknown }
[ 340 ; 341 ) 'S' : S
2020-02-07 15:39:48 +00:00
[ 348 ; 354 ) ' F ::bar ' : fn bar < F , { unknown } > ( S ) -> { unknown }
2020-02-07 15:24:09 +00:00
[ 348 ; 357 ) ' F ::bar ( S ) ' : { unknown }
[ 355 ; 356 ) 'S' : S
2020-02-07 15:39:48 +00:00
[ 363 ; 378 ) ' Foo ::bar ::< u32 > ' : fn bar < { unknown } , u32 > ( S ) -> u32
2020-02-07 15:24:09 +00:00
[ 363 ; 381 ) ' Foo ::b .. . 32 > ( S ) ' : u32
[ 379 ; 380 ) 'S' : S
2020-02-07 15:39:48 +00:00
[ 387 ; 409 ) ' < F as .. . :< u32 > ' : fn bar < F , u32 > ( S ) -> u32
2020-02-07 15:24:09 +00:00
[ 387 ; 412 ) ' < F as .. . 32 > ( S ) ' : u32
[ 410 ; 411 ) 'S' : S
2020-02-07 15:39:48 +00:00
[ 419 ; 422 ) ' foo ' : fn foo < { unknown } > ( S ) -> { unknown }
2020-02-07 15:24:09 +00:00
[ 419 ; 425 ) ' foo ( S ) ' : { unknown }
[ 423 ; 424 ) 'S' : S
2020-02-07 15:39:48 +00:00
[ 431 ; 441 ) ' foo ::< u32 > ' : fn foo < u32 > ( S ) -> u32
2020-02-07 15:24:09 +00:00
[ 431 ; 444 ) ' foo ::< u32 > ( S ) ' : u32
[ 442 ; 443 ) 'S' : S
2020-02-07 15:39:48 +00:00
[ 450 ; 465 ) ' foo ::< u32 , i32 > ' : fn foo < u32 > ( S ) -> u32
2020-02-07 15:24:09 +00:00
[ 450 ; 468 ) ' foo ::< .. . 32 > ( S ) ' : u32
[ 466 ; 467 ) 'S' : S
" ###
) ;
}
#[ 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 ###"
[ 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 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 ###"
[ 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 ) -> ( )
" ###
) ;
}
2019-12-03 12:38:54 +00:00
#[ test ]
2020-01-27 20:38:10 +00:00
#[ ignore ]
2019-12-03 12:38:54 +00:00
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 ###"
[ 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
" ###
) ;
}
#[ 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 ###"
[ 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
" ###
) ;
}
#[ 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 ###"
[ 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
" ###
) ;
}
#[ 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-01-24 15:46:43 +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 ###"
[ 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 ) ' : { unknown }
[ 300 ; 301 ) 'x' : T
2020-01-28 20:42:58 +00:00
[ 308 ; 312 ) ' get2 ' : fn get2 < { unknown } , T > ( T ) -> { unknown }
2019-12-03 12:38:54 +00:00
[ 308 ; 315 ) ' get2 ( x ) ' : { unknown }
[ 313 ; 314 ) 'x' : T
2020-01-28 20:42:58 +00:00
[ 321 ; 324 ) ' get ' : fn get < impl Trait < Type = i64 > > ( impl Trait < Type = i64 > ) -> < impl Trait < Type = i64 > as Trait > ::Type
2019-12-03 12:38:54 +00:00
[ 321 ; 327 ) ' get ( y ) ' : { unknown }
[ 325 ; 326 ) 'y' : impl Trait < Type = i64 >
2020-01-28 20:42:58 +00:00
[ 333 ; 337 ) ' get2 ' : fn get2 < { unknown } , impl Trait < Type = i64 > > ( impl Trait < Type = i64 > ) -> { unknown }
2019-12-03 12:38:54 +00:00
[ 333 ; 340 ) ' get2 ( y ) ' : { unknown }
[ 338 ; 339 ) 'y' : impl Trait < Type = i64 >
2020-01-28 20:42:58 +00:00
[ 346 ; 349 ) ' get ' : fn get < S < u64 > > ( S < u64 > ) -> < S < u64 > as Trait > ::Type
2019-12-03 12:38:54 +00:00
[ 346 ; 357 ) ' get ( set ( S ) ) ' : u64
2020-01-28 20:42:58 +00:00
[ 350 ; 353 ) ' set ' : fn set < S < u64 > > ( S < u64 > ) -> S < u64 >
2019-12-03 12:38:54 +00:00
[ 350 ; 356 ) ' set ( S ) ' : S < u64 >
[ 354 ; 355 ) 'S' : S < u64 >
2020-01-28 20:42:58 +00:00
[ 363 ; 367 ) ' get2 ' : fn get2 < u64 , S < u64 > > ( S < u64 > ) -> u64
2019-12-03 12:38:54 +00:00
[ 363 ; 375 ) ' get2 ( set ( S ) ) ' : u64
2020-01-28 20:42:58 +00:00
[ 368 ; 371 ) ' set ' : fn set < S < u64 > > ( S < u64 > ) -> S < u64 >
2019-12-03 12:38:54 +00:00
[ 368 ; 374 ) ' set ( S ) ' : S < u64 >
[ 372 ; 373 ) 'S' : S < u64 >
2020-01-28 20:42:58 +00:00
[ 381 ; 385 ) ' get2 ' : fn get2 < str , S < str > > ( S < str > ) -> str
2019-12-03 12:38:54 +00:00
[ 381 ; 395 ) ' get2 ( S ::< str > ) ' : str
[ 386 ; 394 ) ' S ::< str > ' : S < str >
" ###
) ;
}
#[ 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 ( ) {
// std::env::set_var("CHALK_DEBUG", "1");
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 ###"
[ 62 ; 66 ) ' self ' : Self
[ 164 ; 165 ) 'x' : T
[ 170 ; 186 ) ' { .. . o ( ) ; } ' : ( )
[ 176 ; 177 ) 'x' : T
[ 176 ; 183 ) ' x . foo ( ) ' : { unknown }
" ###
) ;
}
#[ 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 ###"
[ 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
" ###
) ;
}
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 ###"
[ 50 ; 54 ) ' self ' : & Self
[ 63 ; 65 ) ' { } ' : ( )
[ 116 ; 117 ) 'x' : & impl Trait1
[ 133 ; 149 ) ' { .. . o ( ) ; } ' : ( )
[ 139 ; 140 ) 'x' : & impl Trait1
[ 139 ; 146 ) ' x . foo ( ) ' : u32
" ###
) ;
}
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 ###"
[ 44 ; 45 ) 'x' : T
[ 50 ; 66 ) ' { .. . o ( ) ; } ' : ( )
[ 56 ; 57 ) 'x' : T
[ 56 ; 63 ) ' x . foo ( ) ' : { unknown }
" ###
) ;
}
#[ 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 ###"
[ 103 ; 104 ) 't' : T
[ 114 ; 116 ) ' { } ' : ( )
[ 146 ; 147 ) 't' : T
[ 157 ; 160 ) ' { t } ' : T
[ 158 ; 159 ) 't' : T
[ 259 ; 280 ) ' { .. . S ) ) ; } ' : ( )
2020-01-28 20:42:58 +00:00
[ 265 ; 269 ) ' get2 ' : fn get2 < u64 , S < u64 > > ( S < u64 > ) -> u64
2019-12-03 12:38:54 +00:00
[ 265 ; 277 ) ' get2 ( set ( S ) ) ' : u64
2020-01-28 20:42:58 +00:00
[ 270 ; 273 ) ' set ' : fn set < S < u64 > > ( S < u64 > ) -> S < u64 >
2019-12-03 12:38:54 +00:00
[ 270 ; 276 ) ' set ( S ) ' : S < u64 >
[ 274 ; 275 ) 'S' : S < u64 >
" ###
) ;
}
#[ 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 ###"
[ 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 ) ) ' : { unknown }
[ 174 ; 180 ) ' ( 1 , 2 ) ' : ( u32 , u64 )
[ 175 ; 176 ) '1' : u32
[ 178 ; 179 ) '2' : u64
" ###
) ;
}
#[ 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 ###"
[ 148 ; 152 ) ' self ' : Option < T >
[ 154 ; 155 ) 'f' : F
[ 173 ; 175 ) ' { } ' : ( )
[ 189 ; 308 ) ' { .. . 1 ) ; } ' : ( )
[ 199 ; 200 ) 'x' : Option < u32 >
2020-01-29 20:30:24 +00:00
[ 203 ; 215 ) ' Option ::Some ' : Some < u32 > ( u32 ) -> Option < u32 >
2019-12-03 12:38:54 +00:00
[ 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
" ###
) ;
}
#[ 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 ###"
[ 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
" ###
) ;
}
#[ 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 ###"
[ 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
2020-01-28 20:42:58 +00:00
[ 371 ; 375 ) ' foo1 ' : fn foo1 < S , u64 , | S | -> u64 > ( S , | S | -> u64 ) -> u64
2019-12-03 12:38:54 +00:00
[ 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
2020-01-28 20:42:58 +00:00
[ 409 ; 413 ) ' foo2 ' : fn foo2 < S , u64 , | S | -> u64 > ( | S | -> u64 , S ) -> u64
2019-12-03 12:38:54 +00:00
[ 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
" ###
) ;
}
#[ 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 " ) ;
}
#[ 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
#[ 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 ###"
2019-12-15 17:56:38 +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 ) ' { } ' : ( )
2020-02-07 14:13:00 +00:00
[ 214 ; 310 ) ' { .. . t ( ) ) } ' : S < { unknown } >
2019-12-15 17:56:38 +00:00
[ 224 ; 226 ) ' s1 ' : S < u32 >
2020-02-07 14:13:00 +00:00
[ 229 ; 230 ) 'S' : S < u32 > ( u32 ) -> S < u32 >
2019-12-15 17:56:38 +00:00
[ 229 ; 241 ) ' S ( default ( ) ) ' : S < u32 >
2020-02-07 14:13:00 +00:00
[ 231 ; 238 ) ' default ' : fn default < u32 > ( ) -> u32
2019-12-15 17:56:38 +00:00
[ 231 ; 240 ) ' default ( ) ' : u32
2020-02-07 15:39:48 +00:00
[ 247 ; 250 ) ' foo ' : fn foo ( S < u32 > ) -> ( )
2019-12-15 17:56:38 +00:00
[ 247 ; 254 ) ' foo ( s1 ) ' : ( )
[ 251 ; 253 ) ' s1 ' : S < u32 >
[ 264 ; 265 ) 'x' : i32
2020-02-07 15:39:48 +00:00
[ 273 ; 276 ) ' bar ' : fn bar < i32 > ( S < i32 > ) -> i32
2019-12-15 17:56:38 +00:00
[ 273 ; 290 ) ' bar ( S ( .. . lt ( ) ) ) ' : i32
2020-02-07 14:13:00 +00:00
[ 277 ; 278 ) 'S' : S < i32 > ( i32 ) -> S < i32 >
2019-12-15 17:56:38 +00:00
[ 277 ; 289 ) ' S ( default ( ) ) ' : S < i32 >
2020-02-07 14:13:00 +00:00
[ 279 ; 286 ) ' default ' : fn default < i32 > ( ) -> i32
2019-12-15 17:56:38 +00:00
[ 279 ; 288 ) ' default ( ) ' : i32
2020-02-07 14:13:00 +00:00
[ 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 ###"
[ 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' : & ( )
" ###
) ;
}