-use expect::expect;
+use expect_test::expect;
use super::{check_infer, check_types};
);
}
+#[test]
+fn infer_box_with_allocator() {
+ check_types(
+ r#"
+//- /main.rs crate:main deps:std
+fn test() {
+ let x = box 1;
+ let t = (x, box x, box &1, box [1]);
+ t;
+} //^ (Box<i32, {unknown}>, Box<Box<i32, {unknown}>, {unknown}>, Box<&i32, {unknown}>, Box<[i32; _], {unknown}>)
+
+//- /std.rs crate:std
+#[prelude_import] use prelude::*;
+mod boxed {
+ #[lang = "owned_box"]
+ pub struct Box<T: ?Sized, A: Allocator> {
+ inner: *mut T,
+ allocator: A,
+ }
+}
+"#,
+ );
+}
+
#[test]
fn infer_adt_self() {
check_types(
mod b {
impl super::A {
- fn bar(&self, x: u64) -> i64 {}
+ pub fn bar(&self, x: u64) -> i64 {}
}
}
31..35 'self': A
37..38 'x': u32
52..54 '{}': ()
- 102..106 'self': &A
- 108..109 'x': u64
- 123..125 '{}': ()
- 143..144 'a': A
- 149..197 '{ ...(1); }': ()
- 155..156 'a': A
- 155..163 'a.foo(1)': i32
- 161..162 '1': u32
- 169..180 '(&a).bar(1)': i64
- 170..172 '&a': &A
- 171..172 'a': A
- 178..179 '1': u64
- 186..187 'a': A
- 186..194 'a.bar(1)': i64
- 192..193 '1': u64
+ 106..110 'self': &A
+ 112..113 'x': u64
+ 127..129 '{}': ()
+ 147..148 'a': A
+ 153..201 '{ ...(1); }': ()
+ 159..160 'a': A
+ 159..167 'a.foo(1)': i32
+ 165..166 '1': u32
+ 173..184 '(&a).bar(1)': i64
+ 174..176 '&a': &A
+ 175..176 'a': A
+ 182..183 '1': u64
+ 190..191 'a': A
+ 190..198 'a.bar(1)': i64
+ 196..197 '1': u64
"#]],
);
}
fn effects_smoke_test() {
check_infer(
r#"
- fn main() {
+ async fn main() {
let x = unsafe { 92 };
let y = async { async { () }.await };
let z = try { () };
+ let w = const { 92 };
let t = 'a: { 92 };
}
+
+ #[prelude_import] use future::*;
+
+ mod future {
+ #[lang = "future_trait"]
+ pub trait Future { type Output; }
+ }
"#,
expect![[r#"
- 10..130 '{ ...2 }; }': ()
- 20..21 'x': i32
- 24..37 'unsafe { 92 }': i32
- 31..37 '{ 92 }': i32
- 33..35 '92': i32
- 47..48 'y': {unknown}
- 57..79 '{ asyn...wait }': {unknown}
- 59..77 'async ....await': {unknown}
- 65..71 '{ () }': ()
- 67..69 '()': ()
- 89..90 'z': {unknown}
- 93..103 'try { () }': {unknown}
- 97..103 '{ () }': ()
- 99..101 '()': ()
- 113..114 't': i32
- 121..127 '{ 92 }': i32
- 123..125 '92': i32
+ 16..162 '{ ...2 }; }': ()
+ 26..27 'x': i32
+ 30..43 'unsafe { 92 }': i32
+ 37..43 '{ 92 }': i32
+ 39..41 '92': i32
+ 53..54 'y': impl Future<Output = ()>
+ 57..85 'async ...wait }': impl Future<Output = ()>
+ 63..85 '{ asyn...wait }': ()
+ 65..77 'async { () }': impl Future<Output = ()>
+ 65..83 'async ....await': ()
+ 71..77 '{ () }': ()
+ 73..75 '()': ()
+ 95..96 'z': {unknown}
+ 99..109 'try { () }': {unknown}
+ 103..109 '{ () }': ()
+ 105..107 '()': ()
+ 119..120 'w': i32
+ 123..135 'const { 92 }': i32
+ 129..135 '{ 92 }': i32
+ 131..133 '92': i32
+ 145..146 't': i32
+ 153..159 '{ 92 }': i32
+ 155..157 '92': i32
"#]],
)
}
);
}
+#[test]
+fn infer_labelled_block_break_with_val() {
+ check_infer(
+ r#"
+ fn default<T>() -> T { loop {} }
+ fn foo() {
+ let _x = 'outer: {
+ let inner = 'inner: {
+ let i = default();
+ if (break 'outer i) {
+ break 'inner 5i8;
+ } else if true {
+ break 'inner 6;
+ }
+ break 'inner 'innermost: { 0 };
+ 42
+ };
+ break 'outer inner < 8;
+ };
+ }
+ "#,
+ expect![[r#"
+ 21..32 '{ loop {} }': T
+ 23..30 'loop {}': !
+ 28..30 '{}': ()
+ 42..381 '{ ... }; }': ()
+ 52..54 '_x': bool
+ 65..378 '{ ... }': bool
+ 79..84 'inner': i8
+ 95..339 '{ ... }': i8
+ 113..114 'i': bool
+ 117..124 'default': fn default<bool>() -> bool
+ 117..126 'default()': bool
+ 140..270 'if (br... }': ()
+ 144..158 'break 'outer i': !
+ 157..158 'i': bool
+ 160..209 '{ ... }': ()
+ 178..194 'break ...er 5i8': !
+ 191..194 '5i8': i8
+ 215..270 'if tru... }': ()
+ 218..222 'true': bool
+ 223..270 '{ ... }': ()
+ 241..255 'break 'inner 6': !
+ 254..255 '6': i8
+ 283..313 'break ... { 0 }': !
+ 308..313 '{ 0 }': i8
+ 310..311 '0': i8
+ 327..329 '42': i8
+ 349..371 'break ...er < 8': !
+ 362..367 'inner': i8
+ 362..371 'inner < 8': bool
+ 370..371 '8': i8
+ "#]],
+ );
+}
+
#[test]
fn generic_default() {
check_infer(
"#]],
);
}
+
+#[test]
+fn infer_operator_overload() {
+ cov_mark::check!(infer_expr_inner_binary_operator_overload);
+
+ check_infer(
+ r#"
+ struct V2([f32; 2]);
+
+ #[lang = "add"]
+ pub trait Add<Rhs = Self> {
+ /// The resulting type after applying the `+` operator.
+ type Output;
+
+ /// Performs the `+` operation.
+ #[must_use]
+ fn add(self, rhs: Rhs) -> Self::Output;
+ }
+
+ impl Add<V2> for V2 {
+ type Output = V2;
+
+ fn add(self, rhs: V2) -> V2 {
+ let x = self.0[0] + rhs.0[0];
+ let y = self.0[1] + rhs.0[1];
+ V2([x, y])
+ }
+ }
+
+ fn test() {
+ let va = V2([0.0, 1.0]);
+ let vb = V2([0.0, 1.0]);
+
+ let r = va + vb;
+ }
+
+ "#,
+ expect![[r#"
+ 207..211 'self': Self
+ 213..216 'rhs': Rhs
+ 299..303 'self': V2
+ 305..308 'rhs': V2
+ 320..422 '{ ... }': V2
+ 334..335 'x': f32
+ 338..342 'self': V2
+ 338..344 'self.0': [f32; _]
+ 338..347 'self.0[0]': {unknown}
+ 338..358 'self.0...s.0[0]': f32
+ 345..346 '0': i32
+ 350..353 'rhs': V2
+ 350..355 'rhs.0': [f32; _]
+ 350..358 'rhs.0[0]': {unknown}
+ 356..357 '0': i32
+ 372..373 'y': f32
+ 376..380 'self': V2
+ 376..382 'self.0': [f32; _]
+ 376..385 'self.0[1]': {unknown}
+ 376..396 'self.0...s.0[1]': f32
+ 383..384 '1': i32
+ 388..391 'rhs': V2
+ 388..393 'rhs.0': [f32; _]
+ 388..396 'rhs.0[1]': {unknown}
+ 394..395 '1': i32
+ 406..408 'V2': V2([f32; _]) -> V2
+ 406..416 'V2([x, y])': V2
+ 409..415 '[x, y]': [f32; _]
+ 410..411 'x': f32
+ 413..414 'y': f32
+ 436..519 '{ ... vb; }': ()
+ 446..448 'va': V2
+ 451..453 'V2': V2([f32; _]) -> V2
+ 451..465 'V2([0.0, 1.0])': V2
+ 454..464 '[0.0, 1.0]': [f32; _]
+ 455..458 '0.0': f32
+ 460..463 '1.0': f32
+ 475..477 'vb': V2
+ 480..482 'V2': V2([f32; _]) -> V2
+ 480..494 'V2([0.0, 1.0])': V2
+ 483..493 '[0.0, 1.0]': [f32; _]
+ 484..487 '0.0': f32
+ 489..492 '1.0': f32
+ 505..506 'r': V2
+ 509..511 'va': V2
+ 509..516 'va + vb': V2
+ 514..516 'vb': V2
+ "#]],
+ );
+}
+
+#[test]
+fn infer_const_params() {
+ check_infer(
+ r#"
+ fn foo<const FOO: usize>() {
+ let bar = FOO;
+ }
+ "#,
+ expect![[r#"
+ 27..49 '{ ...FOO; }': ()
+ 37..40 'bar': usize
+ 43..46 'FOO': usize
+ "#]],
+ );
+}
+
+#[test]
+fn infer_inner_type() {
+ check_infer(
+ r#"
+ fn foo() {
+ struct S { field: u32 }
+ let s = S { field: 0 };
+ let f = s.field;
+ }
+ "#,
+ expect![[r#"
+ 9..89 '{ ...eld; }': ()
+ 47..48 's': S
+ 51..65 'S { field: 0 }': S
+ 62..63 '0': u32
+ 75..76 'f': u32
+ 79..80 's': S
+ 79..86 's.field': u32
+ "#]],
+ );
+}
+
+#[test]
+fn infer_nested_inner_type() {
+ check_infer(
+ r#"
+ fn foo() {
+ {
+ let s = S { field: 0 };
+ let f = s.field;
+ }
+ struct S { field: u32 }
+ }
+ "#,
+ expect![[r#"
+ 9..109 '{ ...32 } }': ()
+ 15..79 '{ ... }': ()
+ 29..30 's': S
+ 33..47 'S { field: 0 }': S
+ 44..45 '0': u32
+ 61..62 'f': u32
+ 65..66 's': S
+ 65..72 's.field': u32
+ "#]],
+ );
+}
+
+#[test]
+fn inner_use_enum_rename() {
+ check_infer(
+ r#"
+ enum Request {
+ Info
+ }
+
+ fn f() {
+ use Request as R;
+
+ let r = R::Info;
+ match r {
+ R::Info => {}
+ }
+ }
+ "#,
+ expect![[r#"
+ 34..123 '{ ... } }': ()
+ 67..68 'r': Request
+ 71..78 'R::Info': Request
+ 84..121 'match ... }': ()
+ 90..91 'r': Request
+ 102..109 'R::Info': Request
+ 113..115 '{}': ()
+ "#]],
+ )
+}
+
+#[test]
+fn box_into_vec() {
+ check_infer(
+ r#"
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "unsize"]
+pub trait Unsize<T: ?Sized> {}
+
+#[lang = "coerce_unsized"]
+pub trait CoerceUnsized<T> {}
+
+pub unsafe trait Allocator {}
+
+pub struct Global;
+unsafe impl Allocator for Global {}
+
+#[lang = "owned_box"]
+#[fundamental]
+pub struct Box<T: ?Sized, A: Allocator = Global>;
+
+impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}
+
+pub struct Vec<T, A: Allocator = Global> {}
+
+#[lang = "slice"]
+impl<T> [T] {}
+
+#[lang = "slice_alloc"]
+impl<T> [T] {
+ pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
+ unimplemented!()
+ }
+}
+
+fn test() {
+ let vec = <[_]>::into_vec(box [1i32]);
+}
+"#,
+ expect![[r#"
+ 569..573 'self': Box<[T], A>
+ 602..634 '{ ... }': Vec<T, A>
+ 612..628 'unimpl...ted!()': Vec<T, A>
+ 648..694 '{ ...2]); }': ()
+ 658..661 'vec': Vec<i32, Global>
+ 664..679 '<[_]>::into_vec': fn into_vec<i32, Global>(Box<[i32], Global>) -> Vec<i32, Global>
+ 664..691 '<[_]>:...1i32])': Vec<i32, Global>
+ 680..690 'box [1i32]': Box<[i32; _], Global>
+ 684..690 '[1i32]': [i32; _]
+ 685..689 '1i32': i32
+ "#]],
+ )
+}
+
+#[test]
+fn cfgd_out_assoc_items() {
+ check_types(
+ r#"
+struct S;
+
+impl S {
+ #[cfg(FALSE)]
+ const C: S = S;
+}
+
+fn f() {
+ S::C;
+ //^^^^ {unknown}
+}
+ "#,
+ )
+}