Merge #9294
9294: internal: introduce minicore -- a subset of libcore for testing r=matklad a=matklad Clearly, we need one more fixed point iteration loop! Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
9bddd2af55
13 changed files with 1140 additions and 1018 deletions
|
|
@ -9,8 +9,8 @@ use test_utils::{
|
|||
use vfs::{file_set::FileSet, VfsPath};
|
||||
|
||||
use crate::{
|
||||
input::CrateName, Change, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, FileRange,
|
||||
SourceDatabaseExt, SourceRoot, SourceRootId,
|
||||
input::CrateName, Change, CrateDisplayName, CrateGraph, CrateId, Edition, Env, FileId,
|
||||
FilePosition, FileRange, SourceDatabaseExt, SourceRoot, SourceRootId,
|
||||
};
|
||||
|
||||
pub const WORKSPACE: SourceRootId = SourceRootId(0);
|
||||
|
|
@ -81,7 +81,7 @@ pub struct ChangeFixture {
|
|||
|
||||
impl ChangeFixture {
|
||||
pub fn parse(ra_fixture: &str) -> ChangeFixture {
|
||||
let fixture = Fixture::parse(ra_fixture);
|
||||
let (mini_core, fixture) = Fixture::parse(ra_fixture);
|
||||
let mut change = Change::new();
|
||||
|
||||
let mut files = Vec::new();
|
||||
|
|
@ -166,6 +166,31 @@ impl ChangeFixture {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(mini_core) = mini_core {
|
||||
let core_file = file_id;
|
||||
file_id.0 += 1;
|
||||
|
||||
let mut fs = FileSet::default();
|
||||
fs.insert(core_file, VfsPath::new_virtual_path("/sysroot/core/lib.rs".to_string()));
|
||||
roots.push(SourceRoot::new_library(fs));
|
||||
|
||||
change.change_file(core_file, Some(Arc::new(mini_core.source_code())));
|
||||
|
||||
let all_crates = crate_graph.crates_in_topological_order();
|
||||
|
||||
let core_crate = crate_graph.add_crate_root(
|
||||
core_file,
|
||||
Edition::Edition2021,
|
||||
Some(CrateDisplayName::from_canonical_name("core".to_string())),
|
||||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Vec::new(),
|
||||
);
|
||||
|
||||
for krate in all_crates {
|
||||
crate_graph.add_dep(krate, CrateName::new("core").unwrap(), core_crate).unwrap();
|
||||
}
|
||||
}
|
||||
roots.push(SourceRoot::new_local(mem::take(&mut file_set)));
|
||||
change.set_roots(roots);
|
||||
change.set_crate_graph(crate_graph);
|
||||
|
|
|
|||
|
|
@ -23,38 +23,29 @@ fn infer_block_expr_type_mismatch() {
|
|||
fn coerce_places() {
|
||||
check_infer(
|
||||
r#"
|
||||
struct S<T> { a: T }
|
||||
//- minicore: coerce_unsized
|
||||
struct S<T> { a: T }
|
||||
|
||||
fn f<T>(_: &[T]) -> T { loop {} }
|
||||
fn g<T>(_: S<&[T]>) -> T { loop {} }
|
||||
fn f<T>(_: &[T]) -> T { loop {} }
|
||||
fn g<T>(_: S<&[T]>) -> T { loop {} }
|
||||
|
||||
fn gen<T>() -> *mut [T; 2] { loop {} }
|
||||
fn test1<U>() -> *mut [U] {
|
||||
gen()
|
||||
}
|
||||
fn gen<T>() -> *mut [T; 2] { loop {} }
|
||||
fn test1<U>() -> *mut [U] {
|
||||
gen()
|
||||
}
|
||||
|
||||
fn test2() {
|
||||
let arr: &[u8; 1] = &[1];
|
||||
fn test2() {
|
||||
let arr: &[u8; 1] = &[1];
|
||||
|
||||
let a: &[_] = arr;
|
||||
let b = f(arr);
|
||||
let c: &[_] = { arr };
|
||||
let d = g(S { a: arr });
|
||||
let e: [&[_]; 1] = [arr];
|
||||
let f: [&[_]; 2] = [arr; 2];
|
||||
let g: (&[_], &[_]) = (arr, arr);
|
||||
}
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
|
||||
"#,
|
||||
let a: &[_] = arr;
|
||||
let b = f(arr);
|
||||
let c: &[_] = { arr };
|
||||
let d = g(S { a: arr });
|
||||
let e: [&[_]; 1] = [arr];
|
||||
let f: [&[_]; 2] = [arr; 2];
|
||||
let g: (&[_], &[_]) = (arr, arr);
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
30..31 '_': &[T]
|
||||
44..55 '{ loop {} }': T
|
||||
|
|
@ -131,60 +122,52 @@ fn infer_let_stmt_coerce() {
|
|||
fn infer_custom_coerce_unsized() {
|
||||
check_infer(
|
||||
r#"
|
||||
struct A<T: ?Sized>(*const T);
|
||||
struct B<T: ?Sized>(*const T);
|
||||
struct C<T: ?Sized> { inner: *const T }
|
||||
//- minicore: coerce_unsized
|
||||
use core::{marker::Unsize, ops::CoerceUnsized};
|
||||
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}
|
||||
struct A<T: ?Sized>(*const T);
|
||||
struct B<T: ?Sized>(*const T);
|
||||
struct C<T: ?Sized> { inner: *const T }
|
||||
|
||||
fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
|
||||
fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
|
||||
fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}
|
||||
|
||||
fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
|
||||
let d = foo1(a);
|
||||
let e = foo2(b);
|
||||
let f = foo3(c);
|
||||
}
|
||||
fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
|
||||
fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
|
||||
fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
|
||||
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
|
||||
"#,
|
||||
fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
|
||||
let d = foo1(a);
|
||||
let e = foo2(b);
|
||||
let f = foo3(c);
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
257..258 'x': A<[T]>
|
||||
278..283 '{ x }': A<[T]>
|
||||
280..281 'x': A<[T]>
|
||||
295..296 'x': B<[T]>
|
||||
316..321 '{ x }': B<[T]>
|
||||
318..319 'x': B<[T]>
|
||||
333..334 'x': C<[T]>
|
||||
354..359 '{ x }': C<[T]>
|
||||
356..357 'x': C<[T]>
|
||||
369..370 'a': A<[u8; 2]>
|
||||
384..385 'b': B<[u8; 2]>
|
||||
399..400 'c': C<[u8; 2]>
|
||||
414..480 '{ ...(c); }': ()
|
||||
424..425 'd': A<[{unknown}]>
|
||||
428..432 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]>
|
||||
428..435 'foo1(a)': A<[{unknown}]>
|
||||
433..434 'a': A<[u8; 2]>
|
||||
445..446 'e': B<[u8]>
|
||||
449..453 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]>
|
||||
449..456 'foo2(b)': B<[u8]>
|
||||
454..455 'b': B<[u8; 2]>
|
||||
466..467 'f': C<[u8]>
|
||||
470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]>
|
||||
470..477 'foo3(c)': C<[u8]>
|
||||
475..476 'c': C<[u8; 2]>
|
||||
306..307 'x': A<[T]>
|
||||
327..332 '{ x }': A<[T]>
|
||||
329..330 'x': A<[T]>
|
||||
344..345 'x': B<[T]>
|
||||
365..370 '{ x }': B<[T]>
|
||||
367..368 'x': B<[T]>
|
||||
382..383 'x': C<[T]>
|
||||
403..408 '{ x }': C<[T]>
|
||||
405..406 'x': C<[T]>
|
||||
418..419 'a': A<[u8; 2]>
|
||||
433..434 'b': B<[u8; 2]>
|
||||
448..449 'c': C<[u8; 2]>
|
||||
463..529 '{ ...(c); }': ()
|
||||
473..474 'd': A<[{unknown}]>
|
||||
477..481 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]>
|
||||
477..484 'foo1(a)': A<[{unknown}]>
|
||||
482..483 'a': A<[u8; 2]>
|
||||
494..495 'e': B<[u8]>
|
||||
498..502 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]>
|
||||
498..505 'foo2(b)': B<[u8]>
|
||||
503..504 'b': B<[u8; 2]>
|
||||
515..516 'f': C<[u8]>
|
||||
519..523 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]>
|
||||
519..526 'foo3(c)': C<[u8]>
|
||||
524..525 'c': C<[u8; 2]>
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
@ -193,21 +176,16 @@ fn infer_custom_coerce_unsized() {
|
|||
fn infer_if_coerce() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test() {
|
||||
let x = if true {
|
||||
foo(&[1])
|
||||
} else {
|
||||
&[1]
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {}
|
||||
"#,
|
||||
//- minicore: unsize
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test() {
|
||||
let x = if true {
|
||||
foo(&[1])
|
||||
} else {
|
||||
&[1]
|
||||
};
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
10..11 'x': &[T]
|
||||
27..38 '{ loop {} }': &[T]
|
||||
|
|
@ -235,25 +213,16 @@ fn infer_if_coerce() {
|
|||
fn infer_if_else_coerce() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test() {
|
||||
let x = if true {
|
||||
&[1]
|
||||
} else {
|
||||
foo(&[1])
|
||||
};
|
||||
}
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
|
||||
"#,
|
||||
//- minicore: coerce_unsized
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test() {
|
||||
let x = if true {
|
||||
&[1]
|
||||
} else {
|
||||
foo(&[1])
|
||||
};
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
10..11 'x': &[T]
|
||||
27..38 '{ loop {} }': &[T]
|
||||
|
|
@ -281,20 +250,16 @@ fn infer_if_else_coerce() {
|
|||
fn infer_match_first_coerce() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test(i: i32) {
|
||||
let x = match i {
|
||||
2 => foo(&[2]),
|
||||
1 => &[1],
|
||||
_ => &[3],
|
||||
};
|
||||
}
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {}
|
||||
"#,
|
||||
//- minicore: unsize
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test(i: i32) {
|
||||
let x = match i {
|
||||
2 => foo(&[2]),
|
||||
1 => &[1],
|
||||
_ => &[3],
|
||||
};
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
10..11 'x': &[T]
|
||||
27..38 '{ loop {} }': &[T]
|
||||
|
|
@ -329,25 +294,16 @@ fn infer_match_first_coerce() {
|
|||
fn infer_match_second_coerce() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test(i: i32) {
|
||||
let x = match i {
|
||||
1 => &[1],
|
||||
2 => foo(&[2]),
|
||||
_ => &[3],
|
||||
};
|
||||
}
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
|
||||
"#,
|
||||
//- minicore: coerce_unsized
|
||||
fn foo<T>(x: &[T]) -> &[T] { loop {} }
|
||||
fn test(i: i32) {
|
||||
let x = match i {
|
||||
1 => &[1],
|
||||
2 => foo(&[2]),
|
||||
_ => &[3],
|
||||
};
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
10..11 'x': &[T]
|
||||
27..38 '{ loop {} }': &[T]
|
||||
|
|
@ -470,15 +426,15 @@ fn coerce_autoderef() {
|
|||
#[test]
|
||||
fn coerce_autoderef_generic() {
|
||||
check_infer_with_mismatches(
|
||||
r"
|
||||
struct Foo;
|
||||
fn takes_ref<T>(x: &T) -> T { *x }
|
||||
fn test() {
|
||||
takes_ref(&Foo);
|
||||
takes_ref(&&Foo);
|
||||
takes_ref(&&&Foo);
|
||||
}
|
||||
",
|
||||
r#"
|
||||
struct Foo;
|
||||
fn takes_ref<T>(x: &T) -> T { *x }
|
||||
fn test() {
|
||||
takes_ref(&Foo);
|
||||
takes_ref(&&Foo);
|
||||
takes_ref(&&&Foo);
|
||||
}
|
||||
"#,
|
||||
expect![[r"
|
||||
28..29 'x': &T
|
||||
40..46 '{ *x }': T
|
||||
|
|
@ -508,30 +464,29 @@ fn coerce_autoderef_generic() {
|
|||
fn coerce_autoderef_block() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
struct String {}
|
||||
#[lang = "deref"]
|
||||
trait Deref { type Target; }
|
||||
impl Deref for String { type Target = str; }
|
||||
fn takes_ref_str(x: &str) {}
|
||||
fn returns_string() -> String { loop {} }
|
||||
fn test() {
|
||||
takes_ref_str(&{ returns_string() });
|
||||
}
|
||||
"#,
|
||||
expect![[r"
|
||||
126..127 'x': &str
|
||||
135..137 '{}': ()
|
||||
168..179 '{ loop {} }': String
|
||||
170..177 'loop {}': !
|
||||
175..177 '{}': ()
|
||||
190..235 '{ ... }); }': ()
|
||||
196..209 'takes_ref_str': fn takes_ref_str(&str)
|
||||
196..232 'takes_...g() })': ()
|
||||
210..231 '&{ ret...ng() }': &String
|
||||
211..231 '{ retu...ng() }': String
|
||||
213..227 'returns_string': fn returns_string() -> String
|
||||
213..229 'return...ring()': String
|
||||
"]],
|
||||
//- minicore: deref
|
||||
struct String {}
|
||||
impl core::ops::Deref for String { type Target = str; }
|
||||
fn takes_ref_str(x: &str) {}
|
||||
fn returns_string() -> String { loop {} }
|
||||
fn test() {
|
||||
takes_ref_str(&{ returns_string() });
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
90..91 'x': &str
|
||||
99..101 '{}': ()
|
||||
132..143 '{ loop {} }': String
|
||||
134..141 'loop {}': !
|
||||
139..141 '{}': ()
|
||||
154..199 '{ ... }); }': ()
|
||||
160..173 'takes_ref_str': fn takes_ref_str(&str)
|
||||
160..196 'takes_...g() })': ()
|
||||
174..195 '&{ ret...ng() }': &String
|
||||
175..195 '{ retu...ng() }': String
|
||||
177..191 'returns_string': fn returns_string() -> String
|
||||
177..193 'return...ring()': String
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -674,25 +629,19 @@ fn coerce_placeholder_ref() {
|
|||
fn coerce_unsize_array() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
|
||||
fn test() {
|
||||
let f: &[usize] = &[1, 2, 3];
|
||||
}
|
||||
//- minicore: coerce_unsized
|
||||
fn test() {
|
||||
let f: &[usize] = &[1, 2, 3];
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
161..198 '{ ... 3]; }': ()
|
||||
171..172 'f': &[usize]
|
||||
185..195 '&[1, 2, 3]': &[usize; 3]
|
||||
186..195 '[1, 2, 3]': [usize; 3]
|
||||
187..188 '1': usize
|
||||
190..191 '2': usize
|
||||
193..194 '3': usize
|
||||
10..47 '{ ... 3]; }': ()
|
||||
20..21 'f': &[usize]
|
||||
34..44 '&[1, 2, 3]': &[usize; 3]
|
||||
35..44 '[1, 2, 3]': [usize; 3]
|
||||
36..37 '1': usize
|
||||
39..40 '2': usize
|
||||
42..43 '3': usize
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
@ -701,42 +650,34 @@ fn coerce_unsize_array() {
|
|||
fn coerce_unsize_trait_object_simple() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
//- minicore: coerce_unsized
|
||||
trait Foo<T, U> {}
|
||||
trait Bar<U, T, X>: Foo<T, U> {}
|
||||
trait Baz<T, X>: Bar<usize, T, X> {}
|
||||
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
struct S<T, X>;
|
||||
impl<T, X> Foo<T, usize> for S<T, X> {}
|
||||
impl<T, X> Bar<usize, T, X> for S<T, X> {}
|
||||
impl<T, X> Baz<T, X> for S<T, X> {}
|
||||
|
||||
trait Foo<T, U> {}
|
||||
trait Bar<U, T, X>: Foo<T, U> {}
|
||||
trait Baz<T, X>: Bar<usize, T, X> {}
|
||||
|
||||
struct S<T, X>;
|
||||
impl<T, X> Foo<T, usize> for S<T, X> {}
|
||||
impl<T, X> Bar<usize, T, X> for S<T, X> {}
|
||||
impl<T, X> Baz<T, X> for S<T, X> {}
|
||||
|
||||
fn test() {
|
||||
let obj: &dyn Baz<i8, i16> = &S;
|
||||
let obj: &dyn Bar<_, i8, i16> = &S;
|
||||
let obj: &dyn Foo<i8, _> = &S;
|
||||
}
|
||||
"#,
|
||||
expect![[r"
|
||||
424..539 '{ ... &S; }': ()
|
||||
434..437 'obj': &dyn Baz<i8, i16>
|
||||
459..461 '&S': &S<i8, i16>
|
||||
460..461 'S': S<i8, i16>
|
||||
471..474 'obj': &dyn Bar<usize, i8, i16>
|
||||
499..501 '&S': &S<i8, i16>
|
||||
500..501 'S': S<i8, i16>
|
||||
511..514 'obj': &dyn Foo<i8, usize>
|
||||
534..536 '&S': &S<i8, {unknown}>
|
||||
535..536 'S': S<i8, {unknown}>
|
||||
"]],
|
||||
fn test() {
|
||||
let obj: &dyn Baz<i8, i16> = &S;
|
||||
let obj: &dyn Bar<_, i8, i16> = &S;
|
||||
let obj: &dyn Foo<i8, _> = &S;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
236..351 '{ ... &S; }': ()
|
||||
246..249 'obj': &dyn Baz<i8, i16>
|
||||
271..273 '&S': &S<i8, i16>
|
||||
272..273 'S': S<i8, i16>
|
||||
283..286 'obj': &dyn Bar<usize, i8, i16>
|
||||
311..313 '&S': &S<i8, i16>
|
||||
312..313 'S': S<i8, i16>
|
||||
323..326 'obj': &dyn Foo<i8, usize>
|
||||
346..348 '&S': &S<i8, {unknown}>
|
||||
347..348 'S': S<i8, {unknown}>
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -761,49 +702,41 @@ fn coerce_unsize_trait_object_to_trait_object() {
|
|||
// 602..606 'obj2': &dyn Baz<i8, i16>
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
//- minicore: coerce_unsized
|
||||
trait Foo<T, U> {}
|
||||
trait Bar<U, T, X>: Foo<T, U> {}
|
||||
trait Baz<T, X>: Bar<usize, T, X> {}
|
||||
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
struct S<T, X>;
|
||||
impl<T, X> Foo<T, usize> for S<T, X> {}
|
||||
impl<T, X> Bar<usize, T, X> for S<T, X> {}
|
||||
impl<T, X> Baz<T, X> for S<T, X> {}
|
||||
|
||||
trait Foo<T, U> {}
|
||||
trait Bar<U, T, X>: Foo<T, U> {}
|
||||
trait Baz<T, X>: Bar<usize, T, X> {}
|
||||
|
||||
struct S<T, X>;
|
||||
impl<T, X> Foo<T, usize> for S<T, X> {}
|
||||
impl<T, X> Bar<usize, T, X> for S<T, X> {}
|
||||
impl<T, X> Baz<T, X> for S<T, X> {}
|
||||
|
||||
fn test() {
|
||||
let obj: &dyn Baz<i8, i16> = &S;
|
||||
let obj: &dyn Bar<_, _, _> = obj;
|
||||
let obj: &dyn Foo<_, _> = obj;
|
||||
let obj2: &dyn Baz<i8, i16> = &S;
|
||||
let _: &dyn Foo<_, _> = obj2;
|
||||
}
|
||||
"#,
|
||||
fn test() {
|
||||
let obj: &dyn Baz<i8, i16> = &S;
|
||||
let obj: &dyn Bar<_, _, _> = obj;
|
||||
let obj: &dyn Foo<_, _> = obj;
|
||||
let obj2: &dyn Baz<i8, i16> = &S;
|
||||
let _: &dyn Foo<_, _> = obj2;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
424..609 '{ ...bj2; }': ()
|
||||
434..437 'obj': &dyn Baz<i8, i16>
|
||||
459..461 '&S': &S<i8, i16>
|
||||
460..461 'S': S<i8, i16>
|
||||
471..474 'obj': &dyn Bar<{unknown}, {unknown}, {unknown}>
|
||||
496..499 'obj': &dyn Baz<i8, i16>
|
||||
509..512 'obj': &dyn Foo<{unknown}, {unknown}>
|
||||
531..534 'obj': &dyn Bar<{unknown}, {unknown}, {unknown}>
|
||||
544..548 'obj2': &dyn Baz<i8, i16>
|
||||
570..572 '&S': &S<i8, i16>
|
||||
571..572 'S': S<i8, i16>
|
||||
582..583 '_': &dyn Foo<{unknown}, {unknown}>
|
||||
602..606 'obj2': &dyn Baz<i8, i16>
|
||||
496..499: expected &dyn Bar<{unknown}, {unknown}, {unknown}>, got &dyn Baz<i8, i16>
|
||||
531..534: expected &dyn Foo<{unknown}, {unknown}>, got &dyn Bar<{unknown}, {unknown}, {unknown}>
|
||||
602..606: expected &dyn Foo<{unknown}, {unknown}>, got &dyn Baz<i8, i16>
|
||||
236..421 '{ ...bj2; }': ()
|
||||
246..249 'obj': &dyn Baz<i8, i16>
|
||||
271..273 '&S': &S<i8, i16>
|
||||
272..273 'S': S<i8, i16>
|
||||
283..286 'obj': &dyn Bar<{unknown}, {unknown}, {unknown}>
|
||||
308..311 'obj': &dyn Baz<i8, i16>
|
||||
321..324 'obj': &dyn Foo<{unknown}, {unknown}>
|
||||
343..346 'obj': &dyn Bar<{unknown}, {unknown}, {unknown}>
|
||||
356..360 'obj2': &dyn Baz<i8, i16>
|
||||
382..384 '&S': &S<i8, i16>
|
||||
383..384 'S': S<i8, i16>
|
||||
394..395 '_': &dyn Foo<{unknown}, {unknown}>
|
||||
414..418 'obj2': &dyn Baz<i8, i16>
|
||||
308..311: expected &dyn Bar<{unknown}, {unknown}, {unknown}>, got &dyn Baz<i8, i16>
|
||||
343..346: expected &dyn Foo<{unknown}, {unknown}>, got &dyn Bar<{unknown}, {unknown}, {unknown}>
|
||||
414..418: expected &dyn Foo<{unknown}, {unknown}>, got &dyn Baz<i8, i16>
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
@ -812,40 +745,32 @@ fn coerce_unsize_trait_object_to_trait_object() {
|
|||
fn coerce_unsize_super_trait_cycle() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
//- minicore: coerce_unsized
|
||||
trait A {}
|
||||
trait B: C + A {}
|
||||
trait C: B {}
|
||||
trait D: C
|
||||
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
struct S;
|
||||
impl A for S {}
|
||||
impl B for S {}
|
||||
impl C for S {}
|
||||
impl D for S {}
|
||||
|
||||
trait A {}
|
||||
trait B: C + A {}
|
||||
trait C: B {}
|
||||
trait D: C
|
||||
|
||||
struct S;
|
||||
impl A for S {}
|
||||
impl B for S {}
|
||||
impl C for S {}
|
||||
impl D for S {}
|
||||
|
||||
fn test() {
|
||||
let obj: &dyn D = &S;
|
||||
let obj: &dyn A = &S;
|
||||
}
|
||||
"#,
|
||||
expect![[r"
|
||||
328..383 '{ ... &S; }': ()
|
||||
338..341 'obj': &dyn D
|
||||
352..354 '&S': &S
|
||||
353..354 'S': S
|
||||
364..367 'obj': &dyn A
|
||||
378..380 '&S': &S
|
||||
379..380 'S': S
|
||||
"]],
|
||||
fn test() {
|
||||
let obj: &dyn D = &S;
|
||||
let obj: &dyn A = &S;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
140..195 '{ ... &S; }': ()
|
||||
150..153 'obj': &dyn D
|
||||
164..166 '&S': &S
|
||||
165..166 'S': S
|
||||
176..179 'obj': &dyn A
|
||||
190..192 '&S': &S
|
||||
191..192 'S': S
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -854,41 +779,35 @@ fn coerce_unsize_generic() {
|
|||
// FIXME: fix the type mismatches here
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
//- minicore: coerce_unsized
|
||||
struct Foo<T> { t: T };
|
||||
struct Bar<T>(Foo<T>);
|
||||
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
|
||||
struct Foo<T> { t: T };
|
||||
struct Bar<T>(Foo<T>);
|
||||
|
||||
fn test() {
|
||||
let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
|
||||
let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
|
||||
}
|
||||
"#,
|
||||
fn test() {
|
||||
let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
|
||||
let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
209..317 '{ ... }); }': ()
|
||||
219..220 '_': &Foo<[usize]>
|
||||
238..259 '&Foo {..., 3] }': &Foo<[usize]>
|
||||
239..259 'Foo { ..., 3] }': Foo<[usize]>
|
||||
248..257 '[1, 2, 3]': [usize; 3]
|
||||
249..250 '1': usize
|
||||
252..253 '2': usize
|
||||
255..256 '3': usize
|
||||
269..270 '_': &Bar<[usize]>
|
||||
288..314 '&Bar(F... 3] })': &Bar<[i32; 3]>
|
||||
289..292 'Bar': Bar<[i32; 3]>(Foo<[i32; 3]>) -> Bar<[i32; 3]>
|
||||
289..314 'Bar(Fo... 3] })': Bar<[i32; 3]>
|
||||
293..313 'Foo { ..., 3] }': Foo<[i32; 3]>
|
||||
302..311 '[1, 2, 3]': [i32; 3]
|
||||
303..304 '1': i32
|
||||
306..307 '2': i32
|
||||
309..310 '3': i32
|
||||
248..257: expected [usize], got [usize; 3]
|
||||
288..314: expected &Bar<[usize]>, got &Bar<[i32; 3]>
|
||||
58..166 '{ ... }); }': ()
|
||||
68..69 '_': &Foo<[usize]>
|
||||
87..108 '&Foo {..., 3] }': &Foo<[usize]>
|
||||
88..108 'Foo { ..., 3] }': Foo<[usize]>
|
||||
97..106 '[1, 2, 3]': [usize; 3]
|
||||
98..99 '1': usize
|
||||
101..102 '2': usize
|
||||
104..105 '3': usize
|
||||
118..119 '_': &Bar<[usize]>
|
||||
137..163 '&Bar(F... 3] })': &Bar<[i32; 3]>
|
||||
138..141 'Bar': Bar<[i32; 3]>(Foo<[i32; 3]>) -> Bar<[i32; 3]>
|
||||
138..163 'Bar(Fo... 3] })': Bar<[i32; 3]>
|
||||
142..162 'Foo { ..., 3] }': Foo<[i32; 3]>
|
||||
151..160 '[1, 2, 3]': [i32; 3]
|
||||
152..153 '1': i32
|
||||
155..156 '2': i32
|
||||
158..159 '3': i32
|
||||
97..106: expected [usize], got [usize; 3]
|
||||
137..163: expected &Bar<[usize]>, got &Bar<[i32; 3]>
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
@ -898,15 +817,7 @@ fn coerce_unsize_apit() {
|
|||
// FIXME: #8984
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
|
||||
//- minicore: coerce_unsized
|
||||
trait Foo {}
|
||||
|
||||
fn test(f: impl Foo) {
|
||||
|
|
@ -914,12 +825,12 @@ fn test(f: impl Foo) {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
210..211 'f': impl Foo
|
||||
223..252 '{ ... &f; }': ()
|
||||
233..234 '_': &dyn Foo
|
||||
247..249 '&f': &impl Foo
|
||||
248..249 'f': impl Foo
|
||||
247..249: expected &dyn Foo, got &impl Foo
|
||||
22..23 'f': impl Foo
|
||||
35..64 '{ ... &f; }': ()
|
||||
45..46 '_': &dyn Foo
|
||||
59..61 '&f': &impl Foo
|
||||
60..61 'f': impl Foo
|
||||
59..61: expected &dyn Foo, got &impl Foo
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
@ -1015,15 +926,7 @@ fn main() {
|
|||
fn coerce_unsize_expected_type() {
|
||||
check_no_mismatches(
|
||||
r#"
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T> {}
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
|
||||
|
||||
//- minicore: coerce_unsized
|
||||
fn main() {
|
||||
let foo: &[u32] = &[1, 2];
|
||||
let foo: &[u32] = match true {
|
||||
|
|
|
|||
|
|
@ -780,10 +780,7 @@ fn test() { (&S).foo(); }
|
|||
fn method_resolution_unsize_array() {
|
||||
check_types(
|
||||
r#"
|
||||
#[lang = "slice"]
|
||||
impl<T> [T] {
|
||||
fn len(&self) -> usize { loop {} }
|
||||
}
|
||||
//- minicore: slice
|
||||
fn test() {
|
||||
let a = [1, 2, 3];
|
||||
a.len();
|
||||
|
|
@ -1178,11 +1175,7 @@ fn main() {
|
|||
fn autoderef_visibility_field() {
|
||||
check_infer(
|
||||
r#"
|
||||
#[lang = "deref"]
|
||||
pub trait Deref {
|
||||
type Target;
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
//- minicore: deref
|
||||
mod a {
|
||||
pub struct Foo(pub char);
|
||||
pub struct Bar(i32);
|
||||
|
|
@ -1191,7 +1184,7 @@ mod a {
|
|||
Self(0)
|
||||
}
|
||||
}
|
||||
impl super::Deref for Bar {
|
||||
impl core::ops::Deref for Bar {
|
||||
type Target = Foo;
|
||||
fn deref(&self) -> &Foo {
|
||||
&Foo('z')
|
||||
|
|
@ -1205,22 +1198,21 @@ mod b {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
67..71 'self': &Self
|
||||
200..231 '{ ... }': Bar
|
||||
214..218 'Self': Bar(i32) -> Bar
|
||||
214..221 'Self(0)': Bar
|
||||
219..220 '0': i32
|
||||
315..319 'self': &Bar
|
||||
329..362 '{ ... }': &Foo
|
||||
343..352 '&Foo('z')': &Foo
|
||||
344..347 'Foo': Foo(char) -> Foo
|
||||
344..352 'Foo('z')': Foo
|
||||
348..351 ''z'': char
|
||||
392..439 '{ ... }': ()
|
||||
406..407 'x': char
|
||||
410..428 'super:...r::new': fn new() -> Bar
|
||||
410..430 'super:...:new()': Bar
|
||||
410..432 'super:...ew().0': char
|
||||
107..138 '{ ... }': Bar
|
||||
121..125 'Self': Bar(i32) -> Bar
|
||||
121..128 'Self(0)': Bar
|
||||
126..127 '0': i32
|
||||
226..230 'self': &Bar
|
||||
240..273 '{ ... }': &Foo
|
||||
254..263 '&Foo('z')': &Foo
|
||||
255..258 'Foo': Foo(char) -> Foo
|
||||
255..263 'Foo('z')': Foo
|
||||
259..262 ''z'': char
|
||||
303..350 '{ ... }': ()
|
||||
317..318 'x': char
|
||||
321..339 'super:...r::new': fn new() -> Bar
|
||||
321..341 'super:...:new()': Bar
|
||||
321..343 'super:...ew().0': char
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
|
@ -1230,11 +1222,7 @@ fn autoderef_visibility_method() {
|
|||
cov_mark::check!(autoderef_candidate_not_visible);
|
||||
check_infer(
|
||||
r#"
|
||||
#[lang = "deref"]
|
||||
pub trait Deref {
|
||||
type Target;
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
//- minicore: deref
|
||||
mod a {
|
||||
pub struct Foo(pub char);
|
||||
impl Foo {
|
||||
|
|
@ -1251,7 +1239,7 @@ mod a {
|
|||
self.0
|
||||
}
|
||||
}
|
||||
impl super::Deref for Bar {
|
||||
impl core::ops::Deref for Bar {
|
||||
type Target = Foo;
|
||||
fn deref(&self) -> &Foo {
|
||||
&Foo('z')
|
||||
|
|
@ -1265,30 +1253,29 @@ mod b {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
67..71 'self': &Self
|
||||
168..172 'self': &Foo
|
||||
182..212 '{ ... }': char
|
||||
196..200 'self': &Foo
|
||||
196..202 'self.0': char
|
||||
288..319 '{ ... }': Bar
|
||||
302..306 'Self': Bar(i32) -> Bar
|
||||
302..309 'Self(0)': Bar
|
||||
307..308 '0': i32
|
||||
338..342 'self': &Bar
|
||||
351..381 '{ ... }': i32
|
||||
365..369 'self': &Bar
|
||||
365..371 'self.0': i32
|
||||
465..469 'self': &Bar
|
||||
479..512 '{ ... }': &Foo
|
||||
493..502 '&Foo('z')': &Foo
|
||||
494..497 'Foo': Foo(char) -> Foo
|
||||
494..502 'Foo('z')': Foo
|
||||
498..501 ''z'': char
|
||||
542..595 '{ ... }': ()
|
||||
556..557 'x': char
|
||||
560..578 'super:...r::new': fn new() -> Bar
|
||||
560..580 'super:...:new()': Bar
|
||||
560..588 'super:...ango()': char
|
||||
75..79 'self': &Foo
|
||||
89..119 '{ ... }': char
|
||||
103..107 'self': &Foo
|
||||
103..109 'self.0': char
|
||||
195..226 '{ ... }': Bar
|
||||
209..213 'Self': Bar(i32) -> Bar
|
||||
209..216 'Self(0)': Bar
|
||||
214..215 '0': i32
|
||||
245..249 'self': &Bar
|
||||
258..288 '{ ... }': i32
|
||||
272..276 'self': &Bar
|
||||
272..278 'self.0': i32
|
||||
376..380 'self': &Bar
|
||||
390..423 '{ ... }': &Foo
|
||||
404..413 '&Foo('z')': &Foo
|
||||
405..408 'Foo': Foo(char) -> Foo
|
||||
405..413 'Foo('z')': Foo
|
||||
409..412 ''z'': char
|
||||
453..506 '{ ... }': ()
|
||||
467..468 'x': char
|
||||
471..489 'super:...r::new': fn new() -> Bar
|
||||
471..491 'super:...:new()': Bar
|
||||
471..499 'super:...ango()': char
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -927,35 +927,33 @@ fn issue_6628() {
|
|||
fn issue_6852() {
|
||||
check_infer(
|
||||
r#"
|
||||
#[lang = "deref"]
|
||||
pub trait Deref {
|
||||
type Target;
|
||||
}
|
||||
//- minicore: deref
|
||||
use core::ops::Deref;
|
||||
|
||||
struct BufWriter {}
|
||||
struct BufWriter {}
|
||||
|
||||
struct Mutex<T> {}
|
||||
struct MutexGuard<'a, T> {}
|
||||
impl<T> Mutex<T> {
|
||||
fn lock(&self) -> MutexGuard<'_, T> {}
|
||||
}
|
||||
impl<'a, T: 'a> Deref for MutexGuard<'a, T> {
|
||||
type Target = T;
|
||||
}
|
||||
fn flush(&self) {
|
||||
let w: &Mutex<BufWriter>;
|
||||
*(w.lock());
|
||||
}
|
||||
"#,
|
||||
struct Mutex<T> {}
|
||||
struct MutexGuard<'a, T> {}
|
||||
impl<T> Mutex<T> {
|
||||
fn lock(&self) -> MutexGuard<'_, T> {}
|
||||
}
|
||||
impl<'a, T: 'a> Deref for MutexGuard<'a, T> {
|
||||
type Target = T;
|
||||
}
|
||||
fn flush(&self) {
|
||||
let w: &Mutex<BufWriter>;
|
||||
*(w.lock());
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
156..160 'self': &Mutex<T>
|
||||
183..185 '{}': ()
|
||||
267..271 'self': &{unknown}
|
||||
273..323 '{ ...()); }': ()
|
||||
283..284 'w': &Mutex<BufWriter>
|
||||
309..320 '*(w.lock())': BufWriter
|
||||
311..312 'w': &Mutex<BufWriter>
|
||||
311..319 'w.lock()': MutexGuard<BufWriter>
|
||||
123..127 'self': &Mutex<T>
|
||||
150..152 '{}': ()
|
||||
234..238 'self': &{unknown}
|
||||
240..290 '{ ...()); }': ()
|
||||
250..251 'w': &Mutex<BufWriter>
|
||||
276..287 '*(w.lock())': BufWriter
|
||||
278..279 'w': &Mutex<BufWriter>
|
||||
278..286 'w.lock()': MutexGuard<BufWriter>
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
@ -977,37 +975,33 @@ fn param_overrides_fn() {
|
|||
fn lifetime_from_chalk_during_deref() {
|
||||
check_types(
|
||||
r#"
|
||||
#[lang = "deref"]
|
||||
pub trait Deref {
|
||||
type Target;
|
||||
}
|
||||
//- minicore: deref
|
||||
struct Box<T: ?Sized> {}
|
||||
impl<T> core::ops::Deref for Box<T> {
|
||||
type Target = T;
|
||||
|
||||
struct Box<T: ?Sized> {}
|
||||
impl<T> Deref for Box<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
trait Iterator {
|
||||
type Item;
|
||||
}
|
||||
|
||||
trait Iterator {
|
||||
type Item;
|
||||
}
|
||||
pub struct Iter<'a, T: 'a> {
|
||||
inner: Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>,
|
||||
}
|
||||
|
||||
pub struct Iter<'a, T: 'a> {
|
||||
inner: Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>,
|
||||
}
|
||||
trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> {
|
||||
fn clone_box(&self);
|
||||
}
|
||||
|
||||
trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> {
|
||||
fn clone_box(&self);
|
||||
}
|
||||
|
||||
fn clone_iter<T>(s: Iter<T>) {
|
||||
s.inner.clone_box();
|
||||
//^^^^^^^^^^^^^^^^^^^ ()
|
||||
}
|
||||
"#,
|
||||
fn clone_iter<T>(s: Iter<T>) {
|
||||
s.inner.clone_box();
|
||||
//^^^^^^^^^^^^^^^^^^^ ()
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ fn type_alias_in_struct_lit() {
|
|||
fn infer_ranges() {
|
||||
check_types(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core
|
||||
//- minicore: range
|
||||
fn test() {
|
||||
let a = ..;
|
||||
let b = 1..;
|
||||
|
|
@ -125,32 +125,6 @@ fn test() {
|
|||
let t = (a, b, c, d, e, f);
|
||||
t;
|
||||
} //^ (RangeFull, RangeFrom<i32>, RangeTo<u32>, Range<usize>, RangeToInclusive<i32>, RangeInclusive<char>)
|
||||
|
||||
//- /core.rs crate:core
|
||||
#[prelude_import] use prelude::*;
|
||||
mod prelude {}
|
||||
|
||||
pub mod ops {
|
||||
pub struct Range<Idx> {
|
||||
pub start: Idx,
|
||||
pub end: Idx,
|
||||
}
|
||||
pub struct RangeFrom<Idx> {
|
||||
pub start: Idx,
|
||||
}
|
||||
struct RangeFull;
|
||||
pub struct RangeInclusive<Idx> {
|
||||
start: Idx,
|
||||
end: Idx,
|
||||
is_empty: u8,
|
||||
}
|
||||
pub struct RangeTo<Idx> {
|
||||
pub end: Idx,
|
||||
}
|
||||
pub struct RangeToInclusive<Idx> {
|
||||
pub end: Idx,
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
@ -175,16 +149,17 @@ fn test() {
|
|||
fn infer_basics() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn test(a: u32, b: isize, c: !, d: &str) {
|
||||
a;
|
||||
b;
|
||||
c;
|
||||
d;
|
||||
1usize;
|
||||
1isize;
|
||||
"test";
|
||||
1.0f32;
|
||||
}"#,
|
||||
fn test(a: u32, b: isize, c: !, d: &str) {
|
||||
a;
|
||||
b;
|
||||
c;
|
||||
d;
|
||||
1usize;
|
||||
1isize;
|
||||
"test";
|
||||
1.0f32;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
8..9 'a': u32
|
||||
16..17 'b': isize
|
||||
|
|
@ -207,15 +182,15 @@ fn infer_basics() {
|
|||
fn infer_let() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn test() {
|
||||
let a = 1isize;
|
||||
let b: usize = 1;
|
||||
let c = b;
|
||||
let d: u32;
|
||||
let e;
|
||||
let f: i32 = e;
|
||||
}
|
||||
"#,
|
||||
fn test() {
|
||||
let a = 1isize;
|
||||
let b: usize = 1;
|
||||
let c = b;
|
||||
let d: u32;
|
||||
let e;
|
||||
let f: i32 = e;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
10..117 '{ ...= e; }': ()
|
||||
20..21 'a': isize
|
||||
|
|
@ -236,17 +211,17 @@ fn infer_let() {
|
|||
fn infer_paths() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn a() -> u32 { 1 }
|
||||
fn a() -> u32 { 1 }
|
||||
|
||||
mod b {
|
||||
fn c() -> u32 { 1 }
|
||||
}
|
||||
mod b {
|
||||
fn c() -> u32 { 1 }
|
||||
}
|
||||
|
||||
fn test() {
|
||||
a();
|
||||
b::c();
|
||||
}
|
||||
"#,
|
||||
fn test() {
|
||||
a();
|
||||
b::c();
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
14..19 '{ 1 }': u32
|
||||
16..17 '1': u32
|
||||
|
|
@ -265,17 +240,17 @@ fn infer_paths() {
|
|||
fn infer_path_type() {
|
||||
check_infer(
|
||||
r#"
|
||||
struct S;
|
||||
struct S;
|
||||
|
||||
impl S {
|
||||
fn foo() -> i32 { 1 }
|
||||
}
|
||||
impl S {
|
||||
fn foo() -> i32 { 1 }
|
||||
}
|
||||
|
||||
fn test() {
|
||||
S::foo();
|
||||
<S>::foo();
|
||||
}
|
||||
"#,
|
||||
fn test() {
|
||||
S::foo();
|
||||
<S>::foo();
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
40..45 '{ 1 }': i32
|
||||
42..43 '1': i32
|
||||
|
|
@ -292,21 +267,21 @@ fn infer_path_type() {
|
|||
fn infer_struct() {
|
||||
check_infer(
|
||||
r#"
|
||||
struct A {
|
||||
b: B,
|
||||
c: C,
|
||||
}
|
||||
struct B;
|
||||
struct C(usize);
|
||||
struct A {
|
||||
b: B,
|
||||
c: C,
|
||||
}
|
||||
struct B;
|
||||
struct C(usize);
|
||||
|
||||
fn test() {
|
||||
let c = C(1);
|
||||
B;
|
||||
let a: A = A { b: B, c: C(1) };
|
||||
a.b;
|
||||
a.c;
|
||||
}
|
||||
"#,
|
||||
fn test() {
|
||||
let c = C(1);
|
||||
B;
|
||||
let a: A = A { b: B, c: C(1) };
|
||||
a.b;
|
||||
a.c;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
71..153 '{ ...a.c; }': ()
|
||||
81..82 'c': C
|
||||
|
|
@ -332,14 +307,15 @@ fn infer_struct() {
|
|||
fn infer_enum() {
|
||||
check_infer(
|
||||
r#"
|
||||
enum E {
|
||||
V1 { field: u32 },
|
||||
V2
|
||||
}
|
||||
fn test() {
|
||||
E::V1 { field: 1 };
|
||||
E::V2;
|
||||
}"#,
|
||||
enum E {
|
||||
V1 { field: u32 },
|
||||
V2
|
||||
}
|
||||
fn test() {
|
||||
E::V1 { field: 1 };
|
||||
E::V2;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
51..89 '{ ...:V2; }': ()
|
||||
57..75 'E::V1 ...d: 1 }': E
|
||||
|
|
@ -353,23 +329,23 @@ fn infer_enum() {
|
|||
fn infer_union() {
|
||||
check_infer(
|
||||
r#"
|
||||
union MyUnion {
|
||||
foo: u32,
|
||||
bar: f32,
|
||||
}
|
||||
union MyUnion {
|
||||
foo: u32,
|
||||
bar: f32,
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let u = MyUnion { foo: 0 };
|
||||
unsafe { baz(u); }
|
||||
let u = MyUnion { bar: 0.0 };
|
||||
unsafe { baz(u); }
|
||||
}
|
||||
fn test() {
|
||||
let u = MyUnion { foo: 0 };
|
||||
unsafe { baz(u); }
|
||||
let u = MyUnion { bar: 0.0 };
|
||||
unsafe { baz(u); }
|
||||
}
|
||||
|
||||
unsafe fn baz(u: MyUnion) {
|
||||
let inner = u.foo;
|
||||
let inner = u.bar;
|
||||
}
|
||||
"#,
|
||||
unsafe fn baz(u: MyUnion) {
|
||||
let inner = u.foo;
|
||||
let inner = u.bar;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
57..172 '{ ...); } }': ()
|
||||
67..68 'u': MyUnion
|
||||
|
|
@ -404,19 +380,19 @@ fn infer_union() {
|
|||
fn infer_refs() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
|
||||
a;
|
||||
*a;
|
||||
&a;
|
||||
&mut a;
|
||||
b;
|
||||
*b;
|
||||
&b;
|
||||
c;
|
||||
*c;
|
||||
d;
|
||||
*d;
|
||||
}
|
||||
fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
|
||||
a;
|
||||
*a;
|
||||
&a;
|
||||
&mut a;
|
||||
b;
|
||||
*b;
|
||||
&b;
|
||||
c;
|
||||
*c;
|
||||
d;
|
||||
*d;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
8..9 'a': &u32
|
||||
|
|
@ -450,11 +426,11 @@ fn infer_refs() {
|
|||
fn infer_raw_ref() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn test(a: i32) {
|
||||
&raw mut a;
|
||||
&raw const a;
|
||||
}
|
||||
"#,
|
||||
fn test(a: i32) {
|
||||
&raw mut a;
|
||||
&raw const a;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
8..9 'a': i32
|
||||
16..53 '{ ...t a; }': ()
|
||||
|
|
@ -524,26 +500,26 @@ h";
|
|||
fn infer_unary_op() {
|
||||
check_infer(
|
||||
r#"
|
||||
enum SomeType {}
|
||||
enum SomeType {}
|
||||
|
||||
fn test(x: SomeType) {
|
||||
let b = false;
|
||||
let c = !b;
|
||||
let a = 100;
|
||||
let d: i128 = -a;
|
||||
let e = -100;
|
||||
let f = !!!true;
|
||||
let g = !42;
|
||||
let h = !10u32;
|
||||
let j = !a;
|
||||
-3.14;
|
||||
!3;
|
||||
-x;
|
||||
!x;
|
||||
-"hello";
|
||||
!"hello";
|
||||
}
|
||||
"#,
|
||||
fn test(x: SomeType) {
|
||||
let b = false;
|
||||
let c = !b;
|
||||
let a = 100;
|
||||
let d: i128 = -a;
|
||||
let e = -100;
|
||||
let f = !!!true;
|
||||
let g = !42;
|
||||
let h = !10u32;
|
||||
let j = !a;
|
||||
-3.14;
|
||||
!3;
|
||||
-x;
|
||||
!x;
|
||||
-"hello";
|
||||
!"hello";
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
26..27 'x': SomeType
|
||||
39..271 '{ ...lo"; }': ()
|
||||
|
|
@ -594,19 +570,19 @@ fn infer_unary_op() {
|
|||
fn infer_backwards() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn takes_u32(x: u32) {}
|
||||
fn takes_u32(x: u32) {}
|
||||
|
||||
struct S { i32_field: i32 }
|
||||
struct S { i32_field: i32 }
|
||||
|
||||
fn test() -> &mut &f64 {
|
||||
let a = unknown_function();
|
||||
takes_u32(a);
|
||||
let b = unknown_function();
|
||||
S { i32_field: b };
|
||||
let c = unknown_function();
|
||||
&mut &c
|
||||
}
|
||||
"#,
|
||||
fn test() -> &mut &f64 {
|
||||
let a = unknown_function();
|
||||
takes_u32(a);
|
||||
let b = unknown_function();
|
||||
S { i32_field: b };
|
||||
let c = unknown_function();
|
||||
&mut &c
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
13..14 'x': u32
|
||||
21..23 '{}': ()
|
||||
|
|
@ -636,23 +612,23 @@ fn infer_backwards() {
|
|||
fn infer_self() {
|
||||
check_infer(
|
||||
r#"
|
||||
struct S;
|
||||
struct S;
|
||||
|
||||
impl S {
|
||||
fn test(&self) {
|
||||
self;
|
||||
}
|
||||
fn test2(self: &Self) {
|
||||
self;
|
||||
}
|
||||
fn test3() -> Self {
|
||||
S {}
|
||||
}
|
||||
fn test4() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
impl S {
|
||||
fn test(&self) {
|
||||
self;
|
||||
}
|
||||
fn test2(self: &Self) {
|
||||
self;
|
||||
}
|
||||
fn test3() -> Self {
|
||||
S {}
|
||||
}
|
||||
fn test4() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
33..37 'self': &S
|
||||
39..60 '{ ... }': ()
|
||||
|
|
@ -672,30 +648,30 @@ fn infer_self() {
|
|||
fn infer_self_as_path() {
|
||||
check_infer(
|
||||
r#"
|
||||
struct S1;
|
||||
struct S2(isize);
|
||||
enum E {
|
||||
V1,
|
||||
V2(u32),
|
||||
}
|
||||
struct S1;
|
||||
struct S2(isize);
|
||||
enum E {
|
||||
V1,
|
||||
V2(u32),
|
||||
}
|
||||
|
||||
impl S1 {
|
||||
fn test() {
|
||||
Self;
|
||||
}
|
||||
}
|
||||
impl S2 {
|
||||
fn test() {
|
||||
Self(1);
|
||||
}
|
||||
}
|
||||
impl E {
|
||||
fn test() {
|
||||
Self::V1;
|
||||
Self::V2(1);
|
||||
}
|
||||
}
|
||||
"#,
|
||||
impl S1 {
|
||||
fn test() {
|
||||
Self;
|
||||
}
|
||||
}
|
||||
impl S2 {
|
||||
fn test() {
|
||||
Self(1);
|
||||
}
|
||||
}
|
||||
impl E {
|
||||
fn test() {
|
||||
Self::V1;
|
||||
Self::V2(1);
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
86..107 '{ ... }': ()
|
||||
96..100 'Self': S1
|
||||
|
|
@ -716,26 +692,26 @@ fn infer_self_as_path() {
|
|||
fn infer_binary_op() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn f(x: bool) -> i32 {
|
||||
0i32
|
||||
}
|
||||
fn f(x: bool) -> i32 {
|
||||
0i32
|
||||
}
|
||||
|
||||
fn test() -> bool {
|
||||
let x = a && b;
|
||||
let y = true || false;
|
||||
let z = x == y;
|
||||
let t = x != y;
|
||||
let minus_forty: isize = -40isize;
|
||||
let h = minus_forty <= CONST_2;
|
||||
let c = f(z || y) + 5;
|
||||
let d = b;
|
||||
let g = minus_forty ^= i;
|
||||
let ten: usize = 10;
|
||||
let ten_is_eleven = ten == some_num;
|
||||
fn test() -> bool {
|
||||
let x = a && b;
|
||||
let y = true || false;
|
||||
let z = x == y;
|
||||
let t = x != y;
|
||||
let minus_forty: isize = -40isize;
|
||||
let h = minus_forty <= CONST_2;
|
||||
let c = f(z || y) + 5;
|
||||
let d = b;
|
||||
let g = minus_forty ^= i;
|
||||
let ten: usize = 10;
|
||||
let ten_is_eleven = ten == some_num;
|
||||
|
||||
ten < 3
|
||||
}
|
||||
"#,
|
||||
ten < 3
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
5..6 'x': bool
|
||||
21..33 '{ 0i32 }': i32
|
||||
|
|
@ -795,11 +771,11 @@ fn infer_binary_op() {
|
|||
fn infer_shift_op() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn test() {
|
||||
1u32 << 5u8;
|
||||
1u32 >> 5u8;
|
||||
}
|
||||
"#,
|
||||
fn test() {
|
||||
1u32 << 5u8;
|
||||
1u32 >> 5u8;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
10..47 '{ ...5u8; }': ()
|
||||
16..20 '1u32': u32
|
||||
|
|
@ -816,29 +792,29 @@ fn infer_shift_op() {
|
|||
fn infer_field_autoderef() {
|
||||
check_infer(
|
||||
r#"
|
||||
struct A {
|
||||
b: B,
|
||||
}
|
||||
struct B;
|
||||
struct A {
|
||||
b: B,
|
||||
}
|
||||
struct B;
|
||||
|
||||
fn test1(a: A) {
|
||||
let a1 = a;
|
||||
a1.b;
|
||||
let a2 = &a;
|
||||
a2.b;
|
||||
let a3 = &mut a;
|
||||
a3.b;
|
||||
let a4 = &&&&&&&a;
|
||||
a4.b;
|
||||
let a5 = &mut &&mut &&mut a;
|
||||
a5.b;
|
||||
}
|
||||
fn test1(a: A) {
|
||||
let a1 = a;
|
||||
a1.b;
|
||||
let a2 = &a;
|
||||
a2.b;
|
||||
let a3 = &mut a;
|
||||
a3.b;
|
||||
let a4 = &&&&&&&a;
|
||||
a4.b;
|
||||
let a5 = &mut &&mut &&mut a;
|
||||
a5.b;
|
||||
}
|
||||
|
||||
fn test2(a1: *const A, a2: *mut A) {
|
||||
a1.b;
|
||||
a2.b;
|
||||
}
|
||||
"#,
|
||||
fn test2(a1: *const A, a2: *mut A) {
|
||||
a1.b;
|
||||
a2.b;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
43..44 'a': A
|
||||
49..212 '{ ...5.b; }': ()
|
||||
|
|
@ -891,58 +867,53 @@ fn infer_field_autoderef() {
|
|||
fn infer_argument_autoderef() {
|
||||
check_infer(
|
||||
r#"
|
||||
#[lang = "deref"]
|
||||
pub trait Deref {
|
||||
type Target;
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
//- minicore: deref
|
||||
use core::ops::Deref;
|
||||
struct A<T>(T);
|
||||
|
||||
struct A<T>(T);
|
||||
impl<T> A<T> {
|
||||
fn foo(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> A<T> {
|
||||
fn foo(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
struct B<T>(T);
|
||||
|
||||
struct B<T>(T);
|
||||
impl<T> Deref for B<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for B<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let t = A::foo(&&B(B(A(42))));
|
||||
}
|
||||
"#,
|
||||
fn test() {
|
||||
let t = A::foo(&&B(B(A(42))));
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
67..71 'self': &Self
|
||||
138..142 'self': &A<T>
|
||||
150..173 '{ ... }': &T
|
||||
160..167 '&self.0': &T
|
||||
161..165 'self': &A<T>
|
||||
161..167 'self.0': T
|
||||
254..258 'self': &B<T>
|
||||
277..300 '{ ... }': &T
|
||||
287..294 '&self.0': &T
|
||||
288..292 'self': &B<T>
|
||||
288..294 'self.0': T
|
||||
314..352 '{ ...))); }': ()
|
||||
324..325 't': &i32
|
||||
328..334 'A::foo': fn foo<i32>(&A<i32>) -> &i32
|
||||
328..349 'A::foo...42))))': &i32
|
||||
335..348 '&&B(B(A(42)))': &&B<B<A<i32>>>
|
||||
336..348 '&B(B(A(42)))': &B<B<A<i32>>>
|
||||
337..338 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
|
||||
337..348 'B(B(A(42)))': B<B<A<i32>>>
|
||||
339..340 'B': B<A<i32>>(A<i32>) -> B<A<i32>>
|
||||
339..347 'B(A(42))': B<A<i32>>
|
||||
341..342 'A': A<i32>(i32) -> A<i32>
|
||||
341..346 'A(42)': A<i32>
|
||||
343..345 '42': i32
|
||||
66..70 'self': &A<T>
|
||||
78..101 '{ ... }': &T
|
||||
88..95 '&self.0': &T
|
||||
89..93 'self': &A<T>
|
||||
89..95 'self.0': T
|
||||
182..186 'self': &B<T>
|
||||
205..228 '{ ... }': &T
|
||||
215..222 '&self.0': &T
|
||||
216..220 'self': &B<T>
|
||||
216..222 'self.0': T
|
||||
242..280 '{ ...))); }': ()
|
||||
252..253 't': &i32
|
||||
256..262 'A::foo': fn foo<i32>(&A<i32>) -> &i32
|
||||
256..277 'A::foo...42))))': &i32
|
||||
263..276 '&&B(B(A(42)))': &&B<B<A<i32>>>
|
||||
264..276 '&B(B(A(42)))': &B<B<A<i32>>>
|
||||
265..266 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
|
||||
265..276 'B(B(A(42)))': B<B<A<i32>>>
|
||||
267..268 'B': B<A<i32>>(A<i32>) -> B<A<i32>>
|
||||
267..275 'B(A(42))': B<A<i32>>
|
||||
269..270 'A': A<i32>(i32) -> A<i32>
|
||||
269..274 'A(42)': A<i32>
|
||||
271..273 '42': i32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
@ -951,62 +922,57 @@ fn infer_argument_autoderef() {
|
|||
fn infer_method_argument_autoderef() {
|
||||
check_infer(
|
||||
r#"
|
||||
#[lang = "deref"]
|
||||
pub trait Deref {
|
||||
type Target;
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
//- minicore: deref
|
||||
use core::ops::Deref;
|
||||
struct A<T>(*mut T);
|
||||
|
||||
struct A<T>(*mut T);
|
||||
impl<T> A<T> {
|
||||
fn foo(&self, x: &A<T>) -> &T {
|
||||
&*x.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> A<T> {
|
||||
fn foo(&self, x: &A<T>) -> &T {
|
||||
&*x.0
|
||||
}
|
||||
}
|
||||
struct B<T>(T);
|
||||
|
||||
struct B<T>(T);
|
||||
impl<T> Deref for B<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for B<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
fn test(a: A<i32>) {
|
||||
let t = A(0 as *mut _).foo(&&B(B(a)));
|
||||
}
|
||||
"#,
|
||||
fn test(a: A<i32>) {
|
||||
let t = A(0 as *mut _).foo(&&B(B(a)));
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
67..71 'self': &Self
|
||||
143..147 'self': &A<T>
|
||||
149..150 'x': &A<T>
|
||||
165..186 '{ ... }': &T
|
||||
175..180 '&*x.0': &T
|
||||
176..180 '*x.0': T
|
||||
177..178 'x': &A<T>
|
||||
177..180 'x.0': *mut T
|
||||
267..271 'self': &B<T>
|
||||
290..313 '{ ... }': &T
|
||||
300..307 '&self.0': &T
|
||||
301..305 'self': &B<T>
|
||||
301..307 'self.0': T
|
||||
325..326 'a': A<i32>
|
||||
336..382 '{ ...))); }': ()
|
||||
346..347 't': &i32
|
||||
350..351 'A': A<i32>(*mut i32) -> A<i32>
|
||||
350..364 'A(0 as *mut _)': A<i32>
|
||||
350..379 'A(0 as...B(a)))': &i32
|
||||
352..353 '0': i32
|
||||
352..363 '0 as *mut _': *mut i32
|
||||
369..378 '&&B(B(a))': &&B<B<A<i32>>>
|
||||
370..378 '&B(B(a))': &B<B<A<i32>>>
|
||||
371..372 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
|
||||
371..378 'B(B(a))': B<B<A<i32>>>
|
||||
373..374 'B': B<A<i32>>(A<i32>) -> B<A<i32>>
|
||||
373..377 'B(a)': B<A<i32>>
|
||||
375..376 'a': A<i32>
|
||||
71..75 'self': &A<T>
|
||||
77..78 'x': &A<T>
|
||||
93..114 '{ ... }': &T
|
||||
103..108 '&*x.0': &T
|
||||
104..108 '*x.0': T
|
||||
105..106 'x': &A<T>
|
||||
105..108 'x.0': *mut T
|
||||
195..199 'self': &B<T>
|
||||
218..241 '{ ... }': &T
|
||||
228..235 '&self.0': &T
|
||||
229..233 'self': &B<T>
|
||||
229..235 'self.0': T
|
||||
253..254 'a': A<i32>
|
||||
264..310 '{ ...))); }': ()
|
||||
274..275 't': &i32
|
||||
278..279 'A': A<i32>(*mut i32) -> A<i32>
|
||||
278..292 'A(0 as *mut _)': A<i32>
|
||||
278..307 'A(0 as...B(a)))': &i32
|
||||
280..281 '0': i32
|
||||
280..291 '0 as *mut _': *mut i32
|
||||
297..306 '&&B(B(a))': &&B<B<A<i32>>>
|
||||
298..306 '&B(B(a))': &B<B<A<i32>>>
|
||||
299..300 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
|
||||
299..306 'B(B(a))': B<B<A<i32>>>
|
||||
301..302 'B': B<A<i32>>(A<i32>) -> B<A<i32>>
|
||||
301..305 'B(a)': B<A<i32>>
|
||||
303..304 'a': A<i32>
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
@ -1015,15 +981,15 @@ fn infer_method_argument_autoderef() {
|
|||
fn infer_in_elseif() {
|
||||
check_infer(
|
||||
r#"
|
||||
struct Foo { field: i32 }
|
||||
fn main(foo: Foo) {
|
||||
if true {
|
||||
struct Foo { field: i32 }
|
||||
fn main(foo: Foo) {
|
||||
if true {
|
||||
|
||||
} else if false {
|
||||
foo.field
|
||||
}
|
||||
}
|
||||
"#,
|
||||
} else if false {
|
||||
foo.field
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
34..37 'foo': Foo
|
||||
44..108 '{ ... } }': ()
|
||||
|
|
@ -1043,28 +1009,29 @@ fn infer_in_elseif() {
|
|||
fn infer_if_match_with_return() {
|
||||
check_infer(
|
||||
r#"
|
||||
fn foo() {
|
||||
let _x1 = if true {
|
||||
1
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let _x2 = if true {
|
||||
2
|
||||
} else {
|
||||
return
|
||||
};
|
||||
let _x3 = match true {
|
||||
true => 3,
|
||||
_ => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
let _x4 = match true {
|
||||
true => 4,
|
||||
_ => return
|
||||
};
|
||||
}"#,
|
||||
fn foo() {
|
||||
let _x1 = if true {
|
||||
1
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let _x2 = if true {
|
||||
2
|
||||
} else {
|
||||
return
|
||||
};
|
||||
let _x3 = match true {
|
||||
true => 3,
|
||||
_ => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
let _x4 = match true {
|
||||
true => 4,
|
||||
_ => return
|
||||
};
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
9..322 '{ ... }; }': ()
|
||||
19..22 '_x1': i32
|
||||
|
|
@ -2639,11 +2606,8 @@ fn f() {
|
|||
fn infer_boxed_self_receiver() {
|
||||
check_infer(
|
||||
r#"
|
||||
#[lang = "deref"]
|
||||
pub trait Deref {
|
||||
type Target;
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
//- minicore: deref
|
||||
use core::ops::Deref;
|
||||
|
||||
struct Box<T>(T);
|
||||
|
||||
|
|
@ -2675,40 +2639,39 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
67..71 'self': &Self
|
||||
175..179 'self': &Box<T>
|
||||
259..263 'self': &Box<Foo<T>>
|
||||
289..291 '{}': ()
|
||||
313..317 'self': &Box<Foo<T>>
|
||||
346..348 '{}': ()
|
||||
368..372 'self': Box<Foo<T>>
|
||||
393..395 '{}': ()
|
||||
409..630 '{ ...r(); }': ()
|
||||
419..424 'boxed': Box<Foo<i32>>
|
||||
427..430 'Box': Box<Foo<i32>>(Foo<i32>) -> Box<Foo<i32>>
|
||||
427..442 'Box(Foo(0_i32))': Box<Foo<i32>>
|
||||
431..434 'Foo': Foo<i32>(i32) -> Foo<i32>
|
||||
431..441 'Foo(0_i32)': Foo<i32>
|
||||
435..440 '0_i32': i32
|
||||
453..457 'bad1': &i32
|
||||
460..465 'boxed': Box<Foo<i32>>
|
||||
460..477 'boxed....nner()': &i32
|
||||
487..492 'good1': &i32
|
||||
495..509 'Foo::get_inner': fn get_inner<i32>(&Box<Foo<i32>>) -> &i32
|
||||
495..517 'Foo::g...boxed)': &i32
|
||||
510..516 '&boxed': &Box<Foo<i32>>
|
||||
511..516 'boxed': Box<Foo<i32>>
|
||||
528..532 'bad2': &Foo<i32>
|
||||
535..540 'boxed': Box<Foo<i32>>
|
||||
535..551 'boxed....self()': &Foo<i32>
|
||||
561..566 'good2': &Foo<i32>
|
||||
569..582 'Foo::get_self': fn get_self<i32>(&Box<Foo<i32>>) -> &Foo<i32>
|
||||
569..590 'Foo::g...boxed)': &Foo<i32>
|
||||
583..589 '&boxed': &Box<Foo<i32>>
|
||||
584..589 'boxed': Box<Foo<i32>>
|
||||
601..606 'inner': Foo<i32>
|
||||
609..614 'boxed': Box<Foo<i32>>
|
||||
609..627 'boxed....nner()': Foo<i32>
|
||||
104..108 'self': &Box<T>
|
||||
188..192 'self': &Box<Foo<T>>
|
||||
218..220 '{}': ()
|
||||
242..246 'self': &Box<Foo<T>>
|
||||
275..277 '{}': ()
|
||||
297..301 'self': Box<Foo<T>>
|
||||
322..324 '{}': ()
|
||||
338..559 '{ ...r(); }': ()
|
||||
348..353 'boxed': Box<Foo<i32>>
|
||||
356..359 'Box': Box<Foo<i32>>(Foo<i32>) -> Box<Foo<i32>>
|
||||
356..371 'Box(Foo(0_i32))': Box<Foo<i32>>
|
||||
360..363 'Foo': Foo<i32>(i32) -> Foo<i32>
|
||||
360..370 'Foo(0_i32)': Foo<i32>
|
||||
364..369 '0_i32': i32
|
||||
382..386 'bad1': &i32
|
||||
389..394 'boxed': Box<Foo<i32>>
|
||||
389..406 'boxed....nner()': &i32
|
||||
416..421 'good1': &i32
|
||||
424..438 'Foo::get_inner': fn get_inner<i32>(&Box<Foo<i32>>) -> &i32
|
||||
424..446 'Foo::g...boxed)': &i32
|
||||
439..445 '&boxed': &Box<Foo<i32>>
|
||||
440..445 'boxed': Box<Foo<i32>>
|
||||
457..461 'bad2': &Foo<i32>
|
||||
464..469 'boxed': Box<Foo<i32>>
|
||||
464..480 'boxed....self()': &Foo<i32>
|
||||
490..495 'good2': &Foo<i32>
|
||||
498..511 'Foo::get_self': fn get_self<i32>(&Box<Foo<i32>>) -> &Foo<i32>
|
||||
498..519 'Foo::g...boxed)': &Foo<i32>
|
||||
512..518 '&boxed': &Box<Foo<i32>>
|
||||
513..518 'boxed': Box<Foo<i32>>
|
||||
530..535 'inner': Foo<i32>
|
||||
538..543 'boxed': Box<Foo<i32>>
|
||||
538..556 'boxed....nner()': Foo<i32>
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ use super::{check_infer, check_infer_with_mismatches, check_types};
|
|||
fn infer_await() {
|
||||
check_types(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core
|
||||
//- minicore: future
|
||||
struct IntFuture;
|
||||
|
||||
impl Future for IntFuture {
|
||||
impl core::future::Future for IntFuture {
|
||||
type Output = u64;
|
||||
}
|
||||
|
||||
|
|
@ -18,16 +18,6 @@ fn test() {
|
|||
let v = r.await;
|
||||
v;
|
||||
} //^ u64
|
||||
|
||||
//- /core.rs crate:core
|
||||
pub mod prelude {
|
||||
pub mod rust_2018 {
|
||||
#[lang = "future_trait"]
|
||||
pub trait Future {
|
||||
type Output;
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
@ -36,25 +26,14 @@ pub mod prelude {
|
|||
fn infer_async() {
|
||||
check_types(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core
|
||||
async fn foo() -> u64 {
|
||||
128
|
||||
}
|
||||
//- minicore: future
|
||||
async fn foo() -> u64 { 128 }
|
||||
|
||||
fn test() {
|
||||
let r = foo();
|
||||
let v = r.await;
|
||||
v;
|
||||
} //^ u64
|
||||
|
||||
//- /core.rs crate:core
|
||||
#[prelude_import] use future::*;
|
||||
mod future {
|
||||
#[lang = "future_trait"]
|
||||
trait Future {
|
||||
type Output;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
@ -63,24 +42,13 @@ mod future {
|
|||
fn infer_desugar_async() {
|
||||
check_types(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core
|
||||
async fn foo() -> u64 {
|
||||
128
|
||||
}
|
||||
//- minicore: future
|
||||
async fn foo() -> u64 { 128 }
|
||||
|
||||
fn test() {
|
||||
let r = foo();
|
||||
r;
|
||||
} //^ impl Future<Output = u64>
|
||||
|
||||
//- /core.rs crate:core
|
||||
#[prelude_import] use future::*;
|
||||
mod future {
|
||||
trait Future {
|
||||
type Output;
|
||||
}
|
||||
}
|
||||
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
@ -89,7 +57,7 @@ mod future {
|
|||
fn infer_async_block() {
|
||||
check_types(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core
|
||||
//- minicore: future, option
|
||||
async fn test() {
|
||||
let a = async { 42 };
|
||||
a;
|
||||
|
|
@ -101,7 +69,7 @@ async fn test() {
|
|||
b;
|
||||
// ^ ()
|
||||
let c = async {
|
||||
let y = Option::None;
|
||||
let y = None;
|
||||
y
|
||||
// ^ Option<u64>
|
||||
};
|
||||
|
|
@ -109,18 +77,6 @@ async fn test() {
|
|||
c;
|
||||
// ^ impl Future<Output = Option<u64>>
|
||||
}
|
||||
|
||||
enum Option<T> { None, Some(T) }
|
||||
|
||||
//- /core.rs crate:core
|
||||
#[prelude_import] use future::*;
|
||||
mod future {
|
||||
#[lang = "future_trait"]
|
||||
trait Future {
|
||||
type Output;
|
||||
}
|
||||
}
|
||||
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
@ -704,14 +660,9 @@ mod ops {
|
|||
fn deref_trait() {
|
||||
check_types(
|
||||
r#"
|
||||
#[lang = "deref"]
|
||||
trait Deref {
|
||||
type Target;
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
|
||||
//- minicore: deref
|
||||
struct Arc<T>;
|
||||
impl<T> Deref for Arc<T> {
|
||||
impl<T> core::ops::Deref for Arc<T> {
|
||||
type Target = T;
|
||||
}
|
||||
|
||||
|
|
@ -731,16 +682,10 @@ fn test(s: Arc<S>) {
|
|||
fn deref_trait_with_inference_var() {
|
||||
check_types(
|
||||
r#"
|
||||
//- /main.rs
|
||||
#[lang = "deref"]
|
||||
trait Deref {
|
||||
type Target;
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
|
||||
//- minicore: deref
|
||||
struct Arc<T>;
|
||||
fn new_arc<T>() -> Arc<T> {}
|
||||
impl<T> Deref for Arc<T> {
|
||||
impl<T> core::ops::Deref for Arc<T> {
|
||||
type Target = T;
|
||||
}
|
||||
|
||||
|
|
@ -761,15 +706,10 @@ fn test() {
|
|||
fn deref_trait_infinite_recursion() {
|
||||
check_types(
|
||||
r#"
|
||||
#[lang = "deref"]
|
||||
trait Deref {
|
||||
type Target;
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
|
||||
//- minicore: deref
|
||||
struct S;
|
||||
|
||||
impl Deref for S {
|
||||
impl core::ops::Deref for S {
|
||||
type Target = S;
|
||||
}
|
||||
|
||||
|
|
@ -784,14 +724,9 @@ fn test(s: S) {
|
|||
fn deref_trait_with_question_mark_size() {
|
||||
check_types(
|
||||
r#"
|
||||
#[lang = "deref"]
|
||||
trait Deref {
|
||||
type Target;
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
|
||||
//- minicore: deref
|
||||
struct Arc<T>;
|
||||
impl<T> Deref for Arc<T> {
|
||||
impl<T: ?Sized> core::ops::Deref for Arc<T> {
|
||||
type Target = T;
|
||||
}
|
||||
|
||||
|
|
@ -2625,12 +2560,9 @@ fn test<T: Trait>() {
|
|||
fn dyn_trait_through_chalk() {
|
||||
check_types(
|
||||
r#"
|
||||
//- minicore: deref
|
||||
struct Box<T> {}
|
||||
#[lang = "deref"]
|
||||
trait Deref {
|
||||
type Target;
|
||||
}
|
||||
impl<T> Deref for Box<T> {
|
||||
impl<T> core::ops::Deref for Box<T> {
|
||||
type Target = T;
|
||||
}
|
||||
trait Trait {
|
||||
|
|
@ -3695,16 +3627,7 @@ impl foo::Foo for u32 {
|
|||
fn infer_async_ret_type() {
|
||||
check_types(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core
|
||||
|
||||
enum Result<T, E> {
|
||||
Ok(T),
|
||||
Err(E),
|
||||
}
|
||||
|
||||
use Result::*;
|
||||
|
||||
|
||||
//- minicore: future, result
|
||||
struct Fooey;
|
||||
|
||||
impl Fooey {
|
||||
|
|
@ -3727,15 +3650,6 @@ async fn get_accounts() -> Result<u32, ()> {
|
|||
// ^ u32
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
//- /core.rs crate:core
|
||||
#[prelude_import] use future::*;
|
||||
mod future {
|
||||
#[lang = "future_trait"]
|
||||
trait Future {
|
||||
type Output;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3000,29 +3000,24 @@ fn foo(ar$0g: &impl Foo + Bar<S>) {}
|
|||
fn test_hover_async_block_impl_trait_has_goto_type_action() {
|
||||
check_actions(
|
||||
r#"
|
||||
//- minicore: future
|
||||
struct S;
|
||||
fn foo() {
|
||||
let fo$0o = async { S };
|
||||
}
|
||||
|
||||
#[prelude_import] use future::*;
|
||||
mod future {
|
||||
#[lang = "future_trait"]
|
||||
pub trait Future { type Output; }
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::future::Future",
|
||||
mod_path: "core::future::Future",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
1,
|
||||
),
|
||||
full_range: 101..163,
|
||||
focus_range: 140..146,
|
||||
full_range: 244..426,
|
||||
focus_range: 283..289,
|
||||
name: "Future",
|
||||
kind: Trait,
|
||||
description: "pub trait Future",
|
||||
|
|
|
|||
|
|
@ -536,17 +536,11 @@ Some multi-line comment$0
|
|||
fn test_completion_await_impls_future() {
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:std
|
||||
use std::future::*;
|
||||
//- minicore: future
|
||||
use core::future::*;
|
||||
struct A {}
|
||||
impl Future for A {}
|
||||
fn foo(a: A) { a.$0 }
|
||||
|
||||
//- /std/lib.rs crate:std
|
||||
pub mod future {
|
||||
#[lang = "future_trait"]
|
||||
pub trait Future {}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw await expr.await
|
||||
|
|
@ -555,20 +549,12 @@ pub mod future {
|
|||
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:std
|
||||
//- minicore: future
|
||||
use std::future::*;
|
||||
fn foo() {
|
||||
let a = async {};
|
||||
a.$0
|
||||
}
|
||||
|
||||
//- /std/lib.rs crate:std
|
||||
pub mod future {
|
||||
#[lang = "future_trait"]
|
||||
pub trait Future {
|
||||
type Output;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw await expr.await
|
||||
|
|
|
|||
|
|
@ -1152,16 +1152,11 @@ fn main() {
|
|||
fn suggest_deref() {
|
||||
check_relevance(
|
||||
r#"
|
||||
#[lang = "deref"]
|
||||
trait Deref {
|
||||
type Target;
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
|
||||
//- minicore: deref
|
||||
struct S;
|
||||
struct T(S);
|
||||
|
||||
impl Deref for T {
|
||||
impl core::ops::Deref for T {
|
||||
type Target = S;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
|
@ -1185,8 +1180,9 @@ fn main() {
|
|||
st T []
|
||||
st S []
|
||||
fn main() []
|
||||
tt Deref []
|
||||
fn foo(…) []
|
||||
md core []
|
||||
tt Sized []
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,9 @@ impl<'a> Project<'a> {
|
|||
profile::init_from(crate::PROFILE);
|
||||
});
|
||||
|
||||
for entry in Fixture::parse(self.fixture) {
|
||||
let (mini_core, fixtures) = Fixture::parse(self.fixture);
|
||||
assert!(mini_core.is_none());
|
||||
for entry in fixtures {
|
||||
let path = tmp_dir.path().join(&entry.path['/'.len_utf8()..]);
|
||||
fs::create_dir_all(path.parent().unwrap()).unwrap();
|
||||
fs::write(path.as_path(), entry.text.as_bytes()).unwrap();
|
||||
|
|
|
|||
|
|
@ -77,6 +77,11 @@ pub struct Fixture {
|
|||
pub introduce_new_source_root: bool,
|
||||
}
|
||||
|
||||
pub struct MiniCore {
|
||||
activated_flags: Vec<String>,
|
||||
valid_flags: Vec<String>,
|
||||
}
|
||||
|
||||
impl Fixture {
|
||||
/// Parses text which looks like this:
|
||||
///
|
||||
|
|
@ -86,12 +91,28 @@ impl Fixture {
|
|||
/// line 2
|
||||
/// //- other meta
|
||||
/// ```
|
||||
pub fn parse(ra_fixture: &str) -> Vec<Fixture> {
|
||||
///
|
||||
/// Fixture can also start with a minicore declaration:
|
||||
///
|
||||
/// ```
|
||||
/// //- minicore: sized
|
||||
/// ```
|
||||
///
|
||||
/// That will include a subset of `libcore` into the fixture, see
|
||||
/// `minicore.rs` for what's available.
|
||||
pub fn parse(ra_fixture: &str) -> (Option<MiniCore>, Vec<Fixture>) {
|
||||
let fixture = trim_indent(ra_fixture);
|
||||
|
||||
let mut fixture = fixture.as_str();
|
||||
let mut mini_core = None;
|
||||
let mut res: Vec<Fixture> = Vec::new();
|
||||
|
||||
let default = if ra_fixture.contains("//-") { None } else { Some("//- /main.rs") };
|
||||
if fixture.starts_with("//- minicore:") {
|
||||
let first_line = fixture.split_inclusive('\n').next().unwrap();
|
||||
mini_core = Some(MiniCore::parse(first_line));
|
||||
fixture = &fixture[first_line.len()..];
|
||||
}
|
||||
|
||||
let default = if fixture.contains("//-") { None } else { Some("//- /main.rs") };
|
||||
|
||||
for (ix, line) in default.into_iter().chain(fixture.split_inclusive('\n')).enumerate() {
|
||||
if line.contains("//-") {
|
||||
|
|
@ -113,7 +134,7 @@ impl Fixture {
|
|||
}
|
||||
}
|
||||
|
||||
res
|
||||
(mini_core, res)
|
||||
}
|
||||
|
||||
//- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
|
||||
|
|
@ -172,6 +193,133 @@ impl Fixture {
|
|||
}
|
||||
}
|
||||
|
||||
impl MiniCore {
|
||||
fn has_flag(&self, flag: &str) -> bool {
|
||||
self.activated_flags.iter().any(|it| it == flag)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn assert_valid_flag(&self, flag: &str) {
|
||||
if !self.valid_flags.iter().any(|it| it == flag) {
|
||||
panic!("invalid flag: {:?}, valid flags: {:?}", flag, self.valid_flags);
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(line: &str) -> MiniCore {
|
||||
let mut res = MiniCore { activated_flags: Vec::new(), valid_flags: Vec::new() };
|
||||
|
||||
let line = line.strip_prefix("//- minicore:").unwrap().trim();
|
||||
for entry in line.split(", ") {
|
||||
if res.has_flag(entry) {
|
||||
panic!("duplicate minicore flag: {:?}", entry)
|
||||
}
|
||||
res.activated_flags.push(entry.to_string())
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Strips parts of minicore.rs which are flagged by inactive flags.
|
||||
///
|
||||
/// This is probably over-engineered to support flags dependencies.
|
||||
pub fn source_code(mut self) -> String {
|
||||
let mut buf = String::new();
|
||||
let raw_mini_core = include_str!("./minicore.rs");
|
||||
let mut lines = raw_mini_core.split_inclusive('\n');
|
||||
|
||||
let mut parsing_flags = false;
|
||||
let mut implications = Vec::new();
|
||||
|
||||
// Parse `//!` preamble and extract flags and dependencies.
|
||||
for line in lines.by_ref() {
|
||||
let line = match line.strip_prefix("//!") {
|
||||
Some(it) => it,
|
||||
None => {
|
||||
assert!(line.trim().is_empty());
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if parsing_flags {
|
||||
let (flag, deps) = line.split_once(':').unwrap();
|
||||
let flag = flag.trim();
|
||||
self.valid_flags.push(flag.to_string());
|
||||
for dep in deps.split(", ") {
|
||||
let dep = dep.trim();
|
||||
if !dep.is_empty() {
|
||||
self.assert_valid_flag(dep);
|
||||
implications.push((flag, dep));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if line.contains("Available flags:") {
|
||||
parsing_flags = true;
|
||||
}
|
||||
}
|
||||
|
||||
for flag in &self.activated_flags {
|
||||
self.assert_valid_flag(flag);
|
||||
}
|
||||
|
||||
// Fixed point loop to compute transitive closure of flags.
|
||||
loop {
|
||||
let mut changed = false;
|
||||
for &(u, v) in implications.iter() {
|
||||
if self.has_flag(u) && !self.has_flag(v) {
|
||||
self.activated_flags.push(v.to_string());
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if !changed {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let mut curr_region = "";
|
||||
let mut seen_regions = Vec::new();
|
||||
for line in lines {
|
||||
let trimmed = line.trim();
|
||||
if let Some(region) = trimmed.strip_prefix("// region:") {
|
||||
assert_eq!(curr_region, "");
|
||||
curr_region = region;
|
||||
continue;
|
||||
}
|
||||
if let Some(region) = trimmed.strip_prefix("// endregion:") {
|
||||
assert_eq!(curr_region, region);
|
||||
curr_region = "";
|
||||
continue;
|
||||
}
|
||||
seen_regions.push(curr_region);
|
||||
|
||||
let mut flag = curr_region;
|
||||
if let Some(idx) = trimmed.find("// :") {
|
||||
flag = &trimmed[idx + "// :".len()..];
|
||||
}
|
||||
|
||||
let skip = if flag == "" {
|
||||
false
|
||||
} else {
|
||||
assert!(!flag.starts_with(' '), "region marker starts with a space: {:?}", flag);
|
||||
self.assert_valid_flag(flag);
|
||||
!self.has_flag(flag)
|
||||
};
|
||||
|
||||
if !skip {
|
||||
buf.push_str(line)
|
||||
}
|
||||
}
|
||||
|
||||
for flag in &self.valid_flags {
|
||||
if !seen_regions.iter().any(|it| it == flag) {
|
||||
panic!("unused minicore flag: {:?}", flag);
|
||||
}
|
||||
}
|
||||
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn parse_fixture_checks_further_indented_metadata() {
|
||||
|
|
@ -189,12 +337,14 @@ fn parse_fixture_checks_further_indented_metadata() {
|
|||
|
||||
#[test]
|
||||
fn parse_fixture_gets_full_meta() {
|
||||
let parsed = Fixture::parse(
|
||||
r"
|
||||
//- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b,atom env:OUTDIR=path/to,OTHER=foo
|
||||
mod m;
|
||||
",
|
||||
let (mini_core, parsed) = Fixture::parse(
|
||||
r#"
|
||||
//- minicore: coerce_unsized
|
||||
//- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b,atom env:OUTDIR=path/to,OTHER=foo
|
||||
mod m;
|
||||
"#,
|
||||
);
|
||||
assert_eq!(mini_core.unwrap().activated_flags, vec!["coerce_unsized".to_string()]);
|
||||
assert_eq!(1, parsed.len());
|
||||
|
||||
let meta = &parsed[0];
|
||||
|
|
|
|||
|
|
@ -23,7 +23,10 @@ use text_size::{TextRange, TextSize};
|
|||
pub use dissimilar::diff as __diff;
|
||||
pub use rustc_hash::FxHashMap;
|
||||
|
||||
pub use crate::{assert_linear::AssertLinear, fixture::Fixture};
|
||||
pub use crate::{
|
||||
assert_linear::AssertLinear,
|
||||
fixture::{Fixture, MiniCore},
|
||||
};
|
||||
|
||||
pub const CURSOR_MARKER: &str = "$0";
|
||||
pub const ESCAPED_CURSOR_MARKER: &str = "\\$0";
|
||||
|
|
|
|||
204
crates/test_utils/src/minicore.rs
Normal file
204
crates/test_utils/src/minicore.rs
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
//! This is a fixture we use for tests that need lang items.
|
||||
//!
|
||||
//! We want to include the minimal subset of core for each test, so this file
|
||||
//! supports "conditional compilation". Tests use the following syntax to include minicore:
|
||||
//!
|
||||
//! //- minicore: flag1, flag2
|
||||
//!
|
||||
//! We then strip all the code marked with other flags.
|
||||
//!
|
||||
//! Available flags:
|
||||
//! sized:
|
||||
//! slice:
|
||||
//! range:
|
||||
//! unsize: sized
|
||||
//! deref: sized
|
||||
//! coerce_unsized: unsize
|
||||
//! pin:
|
||||
//! future: pin
|
||||
//! option:
|
||||
//! result:
|
||||
|
||||
pub mod marker {
|
||||
// region:sized
|
||||
#[lang = "sized"]
|
||||
#[fundamental]
|
||||
#[rustc_specialization_trait]
|
||||
pub trait Sized {}
|
||||
// endregion:sized
|
||||
|
||||
// region:unsize
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {}
|
||||
// endregion:unsize
|
||||
}
|
||||
|
||||
pub mod ops {
|
||||
// region:coerce_unsized
|
||||
mod unsize {
|
||||
use crate::marker::Unsize;
|
||||
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T: ?Sized> {}
|
||||
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
|
||||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {}
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {}
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {}
|
||||
|
||||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a T {}
|
||||
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
|
||||
}
|
||||
pub use self::unsize::CoerceUnsized;
|
||||
// endregion:coerce_unsized
|
||||
|
||||
// region:deref
|
||||
mod deref {
|
||||
#[lang = "deref"]
|
||||
pub trait Deref {
|
||||
#[lang = "deref_target"]
|
||||
type Target: ?Sized;
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
}
|
||||
pub use self::deref::Deref;
|
||||
// endregion:deref
|
||||
|
||||
// region:range
|
||||
mod range {
|
||||
#[lang = "RangeFull"]
|
||||
pub struct RangeFull;
|
||||
|
||||
#[lang = "Range"]
|
||||
pub struct Range<Idx> {
|
||||
pub start: Idx,
|
||||
pub end: Idx,
|
||||
}
|
||||
|
||||
#[lang = "RangeFrom"]
|
||||
pub struct RangeFrom<Idx> {
|
||||
pub start: Idx,
|
||||
}
|
||||
|
||||
#[lang = "RangeTo"]
|
||||
pub struct RangeTo<Idx> {
|
||||
pub end: Idx,
|
||||
}
|
||||
|
||||
#[lang = "RangeInclusive"]
|
||||
pub struct RangeInclusive<Idx> {
|
||||
pub(crate) start: Idx,
|
||||
pub(crate) end: Idx,
|
||||
pub(crate) exhausted: bool,
|
||||
}
|
||||
|
||||
#[lang = "RangeToInclusive"]
|
||||
pub struct RangeToInclusive<Idx> {
|
||||
pub end: Idx,
|
||||
}
|
||||
}
|
||||
pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
|
||||
pub use self::range::{RangeInclusive, RangeToInclusive};
|
||||
// endregion:range
|
||||
}
|
||||
|
||||
// region:slice
|
||||
pub mod slice {
|
||||
#[lang = "slice"]
|
||||
impl<T> [T] {
|
||||
pub fn len(&self) -> usize {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
}
|
||||
// endregion:slice
|
||||
|
||||
// region:option
|
||||
pub mod option {
|
||||
pub enum Option<T> {
|
||||
#[lang = "None"]
|
||||
None,
|
||||
#[lang = "Some"]
|
||||
Some(T),
|
||||
}
|
||||
}
|
||||
// endregion:option
|
||||
|
||||
// region:result
|
||||
pub mod result {
|
||||
pub enum Result<T, E> {
|
||||
#[lang = "Ok"]
|
||||
Ok(T),
|
||||
#[lang = "Err"]
|
||||
Err(E),
|
||||
}
|
||||
}
|
||||
// endregion:result
|
||||
|
||||
// region:pin
|
||||
pub mod pin {
|
||||
#[lang = "pin"]
|
||||
#[fundamental]
|
||||
pub struct Pin<P> {
|
||||
pointer: P,
|
||||
}
|
||||
}
|
||||
// endregion:pin
|
||||
|
||||
// region:future
|
||||
pub mod future {
|
||||
use crate::{
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
#[lang = "future_trait"]
|
||||
pub trait Future {
|
||||
type Output;
|
||||
#[lang = "poll"]
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
|
||||
}
|
||||
}
|
||||
pub mod task {
|
||||
pub enum Poll<T> {
|
||||
#[lang = "Ready"]
|
||||
Ready(T),
|
||||
#[lang = "Pending"]
|
||||
Pending,
|
||||
}
|
||||
|
||||
pub struct Context<'a> {
|
||||
waker: &'a (),
|
||||
}
|
||||
}
|
||||
// endregion:future
|
||||
|
||||
pub mod prelude {
|
||||
pub mod v1 {
|
||||
pub use crate::{
|
||||
marker::Sized, // :sized
|
||||
option::Option::{self, None, Some}, // :option
|
||||
result::Result::{self, Err, Ok}, // :result
|
||||
};
|
||||
}
|
||||
|
||||
pub mod rust_2015 {
|
||||
pub use super::v1::*;
|
||||
}
|
||||
|
||||
pub mod rust_2018 {
|
||||
pub use super::v1::*;
|
||||
}
|
||||
|
||||
pub mod rust_2021 {
|
||||
pub use super::v1::*;
|
||||
}
|
||||
}
|
||||
|
||||
#[prelude_import]
|
||||
#[allow(unused)]
|
||||
use prelude::v1::*;
|
||||
Loading…
Add table
Add a link
Reference in a new issue