]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir_ty/src/tests/regression.rs
Add const generics
[rust.git] / crates / hir_ty / src / tests / regression.rs
index 1edec1615fd65a9bc044cdb2c2caad7b7b1a3521..4a65b927ba9d95559fc763440ad3d53607aad64f 100644 (file)
@@ -1,6 +1,6 @@
 use expect_test::expect;
 
-use super::{check_infer, check_types};
+use super::{check_infer, check_no_mismatches, check_types};
 
 #[test]
 fn bug_484() {
@@ -134,6 +134,17 @@ fn test() {
     );
 }
 
+#[test]
+fn array_elements_expected_type() {
+    check_no_mismatches(
+        r#"
+        fn test() {
+            let x: [[u32; 2]; 2] = [[1, 2], [3, 4]];
+        }
+        "#,
+    );
+}
+
 #[test]
 fn infer_std_crash_1() {
     // caused stack overflow, taken from std
@@ -418,55 +429,24 @@ fn test() {
 fn issue_2683_chars_impl() {
     check_types(
         r#"
-//- /main.rs crate:main deps:std
-fn test() {
-    let chars: std::str::Chars<'_>;
-    (chars.next(), chars.nth(1));
-} //^ (Option<char>, Option<char>)
-
-//- /std.rs crate:std
-#[prelude_import]
-use self::prelude::rust_2018::*;
-pub mod prelude {
-    pub mod rust_2018 {
-        pub use crate::iter::Iterator;
-        pub use crate::option::Option;
-    }
+//- minicore: iterator
+pub struct Chars<'a> {}
+impl<'a> Iterator for Chars<'a> {
+    type Item = char;
+    fn next(&mut self) -> Option<char> { loop {} }
 }
 
-pub mod iter {
-    pub use self::traits::Iterator;
-    pub mod traits {
-        pub use self::iterator::Iterator;
-
-        pub mod iterator {
-            pub trait Iterator {
-                type Item;
-                fn next(&mut self) -> Option<Self::Item>;
-                fn nth(&mut self, n: usize) -> Option<Self::Item> {}
-            }
-        }
-    }
-}
-
-pub mod option {
-    pub enum Option<T> {}
-}
-
-pub mod str {
-    pub struct Chars<'a> {}
-    impl<'a> Iterator for Chars<'a> {
-        type Item = char;
-        fn next(&mut self) -> Option<char> {}
-    }
-}
+fn test() {
+    let chars: Chars<'_>;
+    (chars.next(), chars.nth(1));
+} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (Option<char>, Option<char>)
 "#,
     );
 }
 
 #[test]
 fn issue_3642_bad_macro_stackover() {
-    check_types(
+    check_no_mismatches(
         r#"
 #[macro_export]
 macro_rules! match_ast {
@@ -483,7 +463,6 @@ macro_rules! match_ast {
 
 fn main() {
     let anchor = match_ast! {
-       //^ ()
         match parent {
             as => {},
             _ => return None
@@ -736,12 +715,8 @@ fn check<T: PrimInt>(i: T) {
 fn issue_4885() {
     check_infer(
         r#"
-        #[lang = "coerce_unsized"]
-        pub trait CoerceUnsized<T> {}
-
-        trait Future {
-            type Output;
-        }
+        //- minicore: coerce_unsized, future
+        use core::future::Future;
         trait Foo<R> {
             type Bar;
         }
@@ -758,13 +733,13 @@ fn bar<R, K>(key: &K) -> impl Future<Output = K::Bar>
         }
         "#,
         expect![[r#"
-            136..139 'key': &K
-            198..214 '{     ...key) }': impl Future<Output = <K as Foo<R>>::Bar>
-            204..207 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar>
-            204..212 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar>
-            208..211 'key': &K
-            228..231 'key': &K
-            290..293 '{ }': ()
+            70..73 'key': &K
+            132..148 '{     ...key) }': impl Future<Output = <K as Foo<R>>::Bar>
+            138..141 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar>
+            138..146 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar>
+            142..145 'key': &K
+            162..165 'key': &K
+            224..227 '{ }': ()
         "#]],
     );
 }
@@ -827,6 +802,7 @@ pub trait Service<Request> {
 fn issue_4966() {
     check_infer(
         r#"
+        //- minicore: deref
         pub trait IntoIterator {
             type Item;
         }
@@ -837,12 +813,7 @@ struct Map<F> { f: F }
 
         struct Vec<T> {}
 
-        #[lang = "deref"]
-        pub trait Deref {
-            type Target;
-        }
-
-        impl<T> Deref for Vec<T> {
+        impl<T> core::ops::Deref for Vec<T> {
             type Target = [T];
         }
 
@@ -859,23 +830,23 @@ fn main() {
         }
         "#,
         expect![[r#"
-            270..274 'iter': T
-            289..291 '{}': ()
-            303..447 '{     ...r(); }': ()
-            313..318 'inner': Map<|&f64| -> f64>
-            321..345 'Map { ... 0.0 }': Map<|&f64| -> f64>
-            330..343 '|_: &f64| 0.0': |&f64| -> f64
-            331..332 '_': &f64
-            340..343 '0.0': f64
-            356..362 'repeat': Repeat<Map<|&f64| -> f64>>
-            365..390 'Repeat...nner }': Repeat<Map<|&f64| -> f64>>
-            383..388 'inner': Map<|&f64| -> f64>
-            401..404 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
-            407..416 'from_iter': fn from_iter<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>, Repeat<Map<|&f64| -> f64>>>(Repeat<Map<|&f64| -> f64>>) -> Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
-            407..424 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
-            417..423 'repeat': Repeat<Map<|&f64| -> f64>>
-            431..434 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
-            431..444 'vec.foo_bar()': {unknown}
+            225..229 'iter': T
+            244..246 '{}': ()
+            258..402 '{     ...r(); }': ()
+            268..273 'inner': Map<|&f64| -> f64>
+            276..300 'Map { ... 0.0 }': Map<|&f64| -> f64>
+            285..298 '|_: &f64| 0.0': |&f64| -> f64
+            286..287 '_': &f64
+            295..298 '0.0': f64
+            311..317 'repeat': Repeat<Map<|&f64| -> f64>>
+            320..345 'Repeat...nner }': Repeat<Map<|&f64| -> f64>>
+            338..343 'inner': Map<|&f64| -> f64>
+            356..359 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
+            362..371 'from_iter': fn from_iter<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>, Repeat<Map<|&f64| -> f64>>>(Repeat<Map<|&f64| -> f64>>) -> Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
+            362..379 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
+            372..378 'repeat': Repeat<Map<|&f64| -> f64>>
+            386..389 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
+            386..399 'vec.foo_bar()': {unknown}
         "#]],
     );
 }
@@ -973,7 +944,7 @@ fn lifetime_from_chalk_during_deref() {
         r#"
 //- minicore: deref
 struct Box<T: ?Sized> {}
-impl<T> core::ops::Deref for Box<T> {
+impl<T: ?Sized> core::ops::Deref for Box<T> {
     type Target = T;
 
     fn deref(&self) -> &Self::Target {
@@ -995,7 +966,7 @@ trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> {
 
 fn clone_iter<T>(s: Iter<T>) {
     s.inner.clone_box();
-    //^^^^^^^^^^^^^^^^^^^ ()
+  //^^^^^^^^^^^^^^^^^^^ ()
 }
 "#,
     )
@@ -1087,3 +1058,376 @@ fn no_actual_tail(){
         "#]],
     )
 }
+
+#[test]
+fn impl_trait_in_option_9530() {
+    check_types(
+        r#"
+//- minicore: sized
+struct Option<T>;
+impl<T> Option<T> {
+    fn unwrap(self) -> T { loop {} }
+}
+fn make() -> Option<impl Copy> { Option }
+trait Copy {}
+fn test() {
+    let o = make();
+    o.unwrap();
+  //^^^^^^^^^^ impl Copy
+}
+        "#,
+    )
+}
+
+#[test]
+fn bare_dyn_trait_binders_9639() {
+    check_no_mismatches(
+        r#"
+//- minicore: fn, coerce_unsized
+fn infix_parse<T, S>(_state: S, _level_code: &Fn(S)) -> T {
+    loop {}
+}
+
+fn parse_arule() {
+    infix_parse((), &(|_recurse| ()))
+}
+        "#,
+    )
+}
+
+#[test]
+fn call_expected_type_closure() {
+    check_types(
+        r#"
+//- minicore: fn, option
+
+fn map<T, U>(o: Option<T>, f: impl FnOnce(T) -> U) -> Option<U> { loop {} }
+struct S {
+    field: u32
+}
+
+fn test() {
+    let o = Some(S { field: 2 });
+    let _: Option<()> = map(o, |s| { s.field; });
+                                  // ^^^^^^^ u32
+}
+        "#,
+    );
+}
+
+#[test]
+fn coerce_diesel_panic() {
+    check_no_mismatches(
+        r#"
+//- minicore: option
+
+trait TypeMetadata {
+    type MetadataLookup;
+}
+
+pub struct Output<'a, T, DB>
+where
+    DB: TypeMetadata,
+    DB::MetadataLookup: 'a,
+{
+    out: T,
+    metadata_lookup: Option<&'a DB::MetadataLookup>,
+}
+
+impl<'a, T, DB: TypeMetadata> Output<'a, T, DB> {
+    pub fn new(out: T, metadata_lookup: &'a DB::MetadataLookup) -> Self {
+        Output {
+            out,
+            metadata_lookup: Some(metadata_lookup),
+        }
+    }
+}
+        "#,
+    );
+}
+
+#[test]
+fn bitslice_panic() {
+    check_no_mismatches(
+        r#"
+//- minicore: option, deref
+
+pub trait BitView {
+    type Store;
+}
+
+pub struct Lsb0;
+
+pub struct BitArray<V: BitView> { }
+
+pub struct BitSlice<T> { }
+
+impl<V: BitView> core::ops::Deref for BitArray<V> {
+    type Target = BitSlice<V::Store>;
+}
+
+impl<T> BitSlice<T> {
+    pub fn split_first(&self) -> Option<(T, &Self)> { loop {} }
+}
+
+fn multiexp_inner() {
+    let exp: &BitArray<Foo>;
+    exp.split_first();
+}
+        "#,
+    );
+}
+
+#[test]
+fn macro_expands_to_impl_trait() {
+    check_no_mismatches(
+        r#"
+trait Foo {}
+
+macro_rules! ty {
+    () => {
+        impl Foo
+    }
+}
+
+fn foo(_: ty!()) {}
+
+fn bar() {
+    foo(());
+}
+    "#,
+    )
+}
+
+#[test]
+fn nested_macro_in_fn_params() {
+    check_no_mismatches(
+        r#"
+macro_rules! U32Inner {
+    () => {
+        u32
+    };
+}
+
+macro_rules! U32 {
+    () => {
+        U32Inner!()
+    };
+}
+
+fn mamba(a: U32!(), p: u32) -> u32 {
+    a
+}
+    "#,
+    )
+}
+
+#[test]
+fn for_loop_block_expr_iterable() {
+    check_infer(
+        r#"
+fn test() {
+    for _ in { let x = 0; } {
+        let y = 0;
+    }
+}
+        "#,
+        expect![[r#"
+            10..68 '{     ...   } }': ()
+            16..66 'for _ ...     }': ()
+            20..21 '_': {unknown}
+            25..39 '{ let x = 0; }': ()
+            31..32 'x': i32
+            35..36 '0': i32
+            40..66 '{     ...     }': ()
+            54..55 'y': i32
+            58..59 '0': i32
+        "#]],
+    );
+}
+
+#[test]
+fn while_loop_block_expr_iterable() {
+    check_infer(
+        r#"
+fn test() {
+    while { true } {
+        let y = 0;
+    }
+}
+        "#,
+        expect![[r#"
+            10..59 '{     ...   } }': ()
+            16..57 'while ...     }': ()
+            22..30 '{ true }': bool
+            24..28 'true': bool
+            31..57 '{     ...     }': ()
+            45..46 'y': i32
+            49..50 '0': i32
+        "#]],
+    );
+}
+
+#[test]
+fn bug_11242() {
+    // FIXME: wrong, should be u32
+    check_types(
+        r#"
+fn foo<A, B>()
+where
+    A: IntoIterator<Item = u32>,
+    B: IntoIterator<Item = usize>,
+{
+    let _x: <A as IntoIterator>::Item;
+     // ^^ {unknown}
+}
+
+pub trait Iterator {
+    type Item;
+}
+
+pub trait IntoIterator {
+    type Item;
+    type IntoIter: Iterator<Item = Self::Item>;
+}
+
+impl<I: Iterator> IntoIterator for I {
+    type Item = I::Item;
+    type IntoIter = I;
+}
+"#,
+    );
+}
+
+#[test]
+fn bug_11659() {
+    check_no_mismatches(
+        r#"
+struct LinkArray<const N: usize, LD>(LD);
+fn f<const N: usize, LD>(x: LD) -> LinkArray<N, LD> {
+    let r = LinkArray::<N, LD>(x);
+    r
+}
+
+fn test() {
+    let x = f::<2, i32>(5);
+    let y = LinkArray::<52, LinkArray<2, i32>>(x);
+}
+        "#,
+    );
+    check_no_mismatches(
+        r#"
+struct LinkArray<LD, const N: usize>(LD);
+fn f<const N: usize, LD>(x: LD) -> LinkArray<LD, N> {
+    let r = LinkArray::<LD, N>(x);
+    r
+}
+
+fn test() {
+    let x = f::<i32, 2>(5);
+    let y = LinkArray::<LinkArray<i32, 2>, 52>(x);
+}
+        "#,
+    );
+}
+
+#[test]
+fn const_generic_error_tolerance() {
+    check_no_mismatches(
+        r#"
+#[lang = "sized"]
+pub trait Sized {}
+
+struct CT<const N: usize, T>(T);
+struct TC<T, const N: usize>(T);
+fn f<const N: usize, T>(x: T) -> (CT<N, T>, TC<T, N>) {
+    let l = CT::<N, T>(x);
+    let r = TC::<N, T>(x);
+    (l, r)
+}
+
+trait TR1<const N: usize>;
+trait TR2<const N: usize>;
+
+impl<const N: usize, T> TR1<N> for CT<N, T>;
+impl<const N: usize, T> TR1<5> for TC<T, N>;
+impl<const N: usize, T> TR2<N> for CT<T, N>;
+
+trait TR3<const N: usize> {
+    fn tr3(&self) -> &Self;
+}
+
+impl<const N: usize, T> TR3<5> for TC<T, N> {
+    fn tr3(&self) -> &Self {
+        self
+    }
+}
+
+impl<const N: usize, T> TR3<Item = 5> for TC<T, N> {}
+impl<const N: usize, T> TR3<T> for TC<T, N> {}
+
+fn impl_trait<const N: usize>(inp: impl TR1<N>) {}
+fn dyn_trait<const N: usize>(inp: &dyn TR2<N>) {}
+fn impl_trait_bad<'a, const N: usize>(inp: impl TR1<i32>) -> impl TR1<'a, i32> {}
+fn impl_trait_very_bad<const N: usize>(inp: impl TR1<Item = i32>) -> impl TR1<'a, Item = i32, 5, Foo = N> {}
+
+fn test() {
+    f::<2, i32>(5);
+    f::<2, 2>(5);
+    f(5);
+    f::<i32>(5);
+    CT::<52, CT<2, i32>>(x);
+    CT::<CT<2, i32>>(x);
+    impl_trait_bad(5);
+    impl_trait_bad(12);
+    TR3<5>::tr3();
+    TR3<{ 2+3 }>::tr3();
+    TC::<i32, 10>(5).tr3();
+    TC::<i32, 20>(5).tr3();
+    TC::<i32, i32>(5).tr3();
+    TC::<i32, { 7 + 3 }>(5).tr3();
+}
+        "#,
+    );
+}
+
+#[test]
+fn const_generic_impl_trait() {
+    check_no_mismatches(
+        r#"
+        //- minicore: from
+
+        struct Foo<T, const M: usize>;
+
+        trait Tr<T> {
+            fn f(T) -> Self;
+        }
+
+        impl<T, const M: usize> Tr<[T; M]> for Foo<T, M> {
+            fn f(_: [T; M]) -> Self {
+                Self
+            }
+        }
+
+        fn test() {
+            Foo::f([1, 2, 7, 10]);
+        }
+        "#,
+    );
+}
+
+#[test]
+fn nalgebra_factorial() {
+    check_no_mismatches(
+        r#"
+        const FACTORIAL: [u128; 4] = [1, 1, 2, 6];
+
+        fn factorial(n: usize) -> u128 {
+            match FACTORIAL.get(n) {
+                Some(f) => *f,
+                None => panic!("{}! is greater than u128::MAX", n),
+            }
+        }
+        "#,
+    )
+}