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:
bors[bot] 2021-06-15 20:14:36 +00:00 committed by GitHub
commit 9bddd2af55
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 1140 additions and 1018 deletions

View file

@ -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);

View file

@ -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 {

View file

@ -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
"#]],
)
}

View file

@ -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();
//^^^^^^^^^^^^^^^^^^^ ()
}
"#,
)
}

View file

@ -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>
"#]],
);
}

View file

@ -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;
}
}
"#,
);
}

View file

@ -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",

View file

@ -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

View file

@ -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 []
"#]],
)
}

View file

@ -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();

View file

@ -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];

View file

@ -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";

View 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::*;