mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 13:48:50 +00:00
Merge #5319
5319: Chalk upgrade r=flodiebold a=flodiebold - upgrade Chalk - make use of Chalk's `Unsize` impls, remove ours - use Chalk's built-in array type - search efficiently for impls for an int/float variable - output Chalk tracing logs in hir_ty tests Fixes #2534. Fixes #5057. Fixes #4374. Fixes #4281. Co-authored-by: Florian Diebold <flodiebold@gmail.com> Co-authored-by: Florian Diebold <florian.diebold@freiheit.com>
This commit is contained in:
commit
39e049d2a1
13 changed files with 428 additions and 361 deletions
101
Cargo.lock
generated
101
Cargo.lock
generated
|
@ -33,6 +33,15 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.31"
|
||||
|
@ -51,6 +60,17 @@ version = "0.5.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.0"
|
||||
|
@ -124,9 +144,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
|||
|
||||
[[package]]
|
||||
name = "chalk-derive"
|
||||
version = "0.15.0"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7379caa72d04103fcfd9bde5642b816f58e3ffd6a0d39347e9e35a066648226"
|
||||
checksum = "9396f12a23b1a40d5019aa81bc0cbd7ccd2c9736d6bc4afc95868533c2346dcb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -134,36 +154,36 @@ dependencies = [
|
|||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chalk-engine"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e8afe48b5663504b485791ab4fae69cf4864869a71ceec9c758fd4d03423722"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-ir",
|
||||
"rustc-hash",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chalk-ir"
|
||||
version = "0.15.0"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "231e391a03c1fc45874171d92be9542efedc939bac59d9501ee28b9521feb406"
|
||||
checksum = "87e9c67d500717d65ede27affb7ae40efe240d86fbefff1006fe0ffb62d4caf9"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chalk-solve"
|
||||
version = "0.15.0"
|
||||
name = "chalk-recursive"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72c969c0fd06ad50538253327ca3445ff02cc9d0209f94c3cbf198ad9d365b48"
|
||||
checksum = "a8fd2ac0fc06c857b95614d229bbe8ea317d1d94a7e8b9442a3f05c9a2c2d5f4"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-ir",
|
||||
"chalk-solve",
|
||||
"rustc-hash",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chalk-solve"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a79166f2405c1e51eadcc1344f5ee833c7b391532dd78f64a0731a9a123cc58"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-engine",
|
||||
"chalk-ir",
|
||||
"ena",
|
||||
"itertools",
|
||||
|
@ -171,6 +191,7 @@ dependencies = [
|
|||
"rustc-hash",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"tracing-tree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -971,6 +992,16 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quanta"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4f7a1905379198075914bc93d32a5465c40474f90a078bb13439cb00c547bcc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.7"
|
||||
|
@ -1103,6 +1134,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"arrayvec",
|
||||
"chalk-ir",
|
||||
"chalk-recursive",
|
||||
"chalk-solve",
|
||||
"ena",
|
||||
"expect",
|
||||
|
@ -1120,6 +1152,9 @@ dependencies = [
|
|||
"smallvec",
|
||||
"stdx",
|
||||
"test_utils",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"tracing-tree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1722,6 +1757,15 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.1.13"
|
||||
|
@ -1856,7 +1900,7 @@ version = "0.2.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c72c8cf3ec4ed69fef614d011a5ae4274537a8a8c59133558029bd731eb71659"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"ansi_term 0.11.0",
|
||||
"chrono",
|
||||
"lazy_static",
|
||||
"matchers",
|
||||
|
@ -1870,6 +1914,21 @@ dependencies = [
|
|||
"tracing-serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-tree"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a389731c9e6c56fef11e438e5b6afae861d5bc301c8b4bdca8d19f0e830d82"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"atty",
|
||||
"chrono",
|
||||
"quanta",
|
||||
"termcolor",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.4"
|
||||
|
|
|
@ -27,9 +27,14 @@ test_utils = { path = "../test_utils" }
|
|||
|
||||
scoped-tls = "1"
|
||||
|
||||
chalk-solve = { version = "0.15.0" }
|
||||
chalk-ir = { version = "0.15.0" }
|
||||
chalk-solve = { version = "0.17.0" }
|
||||
chalk-ir = { version = "0.17.0" }
|
||||
chalk-recursive = { version = "0.17.0" }
|
||||
|
||||
[dev-dependencies]
|
||||
insta = "0.16.0"
|
||||
expect = { path = "../expect" }
|
||||
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] }
|
||||
tracing-tree = { version = "0.1.3" }
|
||||
|
|
|
@ -6,8 +6,10 @@ use std::{iter, sync::Arc};
|
|||
|
||||
use arrayvec::ArrayVec;
|
||||
use hir_def::{
|
||||
lang_item::LangItemTarget, type_ref::Mutability, AssocContainerId, AssocItemId, FunctionId,
|
||||
HasModule, ImplId, Lookup, TraitId,
|
||||
builtin_type::{IntBitness, Signedness},
|
||||
lang_item::LangItemTarget,
|
||||
type_ref::Mutability,
|
||||
AssocContainerId, AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use ra_db::CrateId;
|
||||
|
@ -16,9 +18,12 @@ use rustc_hash::{FxHashMap, FxHashSet};
|
|||
|
||||
use super::Substs;
|
||||
use crate::{
|
||||
autoderef, db::HirDatabase, primitive::FloatBitness, utils::all_super_traits, ApplicationTy,
|
||||
Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, TypeCtor,
|
||||
TypeWalk,
|
||||
autoderef,
|
||||
db::HirDatabase,
|
||||
primitive::{FloatBitness, FloatTy, IntTy},
|
||||
utils::all_super_traits,
|
||||
ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind,
|
||||
TypeCtor, TypeWalk,
|
||||
};
|
||||
|
||||
/// This is used as a key for indexing impls.
|
||||
|
@ -39,6 +44,62 @@ impl TyFingerprint {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Unsigned,
|
||||
bitness: IntBitness::X8,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Unsigned,
|
||||
bitness: IntBitness::X16,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Unsigned,
|
||||
bitness: IntBitness::X32,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Unsigned,
|
||||
bitness: IntBitness::X64,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Unsigned,
|
||||
bitness: IntBitness::X128,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Unsigned,
|
||||
bitness: IntBitness::Xsize,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
bitness: IntBitness::X8,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
bitness: IntBitness::X16,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
bitness: IntBitness::X32,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
bitness: IntBitness::X64,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
bitness: IntBitness::X128,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
bitness: IntBitness::Xsize,
|
||||
})),
|
||||
];
|
||||
|
||||
pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [
|
||||
TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 })),
|
||||
TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 })),
|
||||
];
|
||||
|
||||
/// Trait impls defined or available in some crate.
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct TraitImpls {
|
||||
|
|
|
@ -37,6 +37,15 @@ use crate::{
|
|||
// against snapshots of the expected results using insta. Use cargo-insta to
|
||||
// update the snapshots.
|
||||
|
||||
fn setup_tracing() -> tracing::subscriber::DefaultGuard {
|
||||
use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry};
|
||||
use tracing_tree::HierarchicalLayer;
|
||||
let filter = EnvFilter::from_env("CHALK_DEBUG");
|
||||
let layer = HierarchicalLayer::default().with_indent_amount(2).with_writer(std::io::stderr);
|
||||
let subscriber = Registry::default().with(filter).with(layer);
|
||||
tracing::subscriber::set_default(subscriber)
|
||||
}
|
||||
|
||||
fn check_types(ra_fixture: &str) {
|
||||
check_types_impl(ra_fixture, false)
|
||||
}
|
||||
|
@ -46,6 +55,7 @@ fn check_types_source_code(ra_fixture: &str) {
|
|||
}
|
||||
|
||||
fn check_types_impl(ra_fixture: &str, display_source: bool) {
|
||||
let _tracing = setup_tracing();
|
||||
let db = TestDB::with_files(ra_fixture);
|
||||
let mut checked_one = false;
|
||||
for (file_id, annotations) in db.extract_annotations() {
|
||||
|
@ -86,6 +96,7 @@ fn infer(ra_fixture: &str) -> String {
|
|||
}
|
||||
|
||||
fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
|
||||
let _tracing = setup_tracing();
|
||||
let (db, file_id) = TestDB::with_single_file(content);
|
||||
|
||||
let mut buf = String::new();
|
||||
|
|
|
@ -662,7 +662,53 @@ fn test() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn coerce_unsize_trait_object() {
|
||||
fn coerce_unsize_trait_object_simple() {
|
||||
assert_snapshot!(
|
||||
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 {}
|
||||
|
||||
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;
|
||||
}
|
||||
"#, true),
|
||||
@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}>
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// The rust reference says this should be possible, but rustc doesn't implement
|
||||
// it. We used to support it, but Chalk doesn't.
|
||||
#[ignore]
|
||||
fn coerce_unsize_trait_object_to_trait_object() {
|
||||
assert_snapshot!(
|
||||
infer_with_mismatches(r#"
|
||||
#[lang = "sized"]
|
||||
|
@ -735,16 +781,17 @@ impl D for S {}
|
|||
|
||||
fn test() {
|
||||
let obj: &dyn D = &S;
|
||||
let obj: &dyn A = obj;
|
||||
let obj: &dyn A = &S;
|
||||
}
|
||||
"#, true),
|
||||
@r###"
|
||||
328..384 '{ ...obj; }': ()
|
||||
328..383 '{ ... &S; }': ()
|
||||
338..341 'obj': &dyn D
|
||||
352..354 '&S': &S
|
||||
353..354 'S': S
|
||||
364..367 'obj': &dyn A
|
||||
378..381 'obj': &dyn D
|
||||
378..380 '&S': &S
|
||||
379..380 'S': S
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1991,6 +1991,28 @@ fn test() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fn_item_fn_trait() {
|
||||
check_types(
|
||||
r#"
|
||||
#[lang = "fn_once"]
|
||||
trait FnOnce<Args> {
|
||||
type Output;
|
||||
}
|
||||
|
||||
struct S;
|
||||
|
||||
fn foo() -> S {}
|
||||
|
||||
fn takes_closure<U, F: FnOnce() -> U>(f: F) -> U { f() }
|
||||
|
||||
fn test() {
|
||||
takes_closure(foo);
|
||||
} //^^^^^^^^^^^^^^^^^^ S
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unselected_projection_in_trait_env_1() {
|
||||
check_types(
|
||||
|
@ -3000,74 +3022,47 @@ fn infer_box_fn_arg() {
|
|||
|
||||
#[test]
|
||||
fn infer_dyn_fn_output() {
|
||||
assert_snapshot!(
|
||||
infer(
|
||||
r#"
|
||||
//- /lib.rs deps:std
|
||||
check_types(
|
||||
r#"
|
||||
#[lang = "fn_once"]
|
||||
pub trait FnOnce<Args> {
|
||||
type Output;
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
#[lang = "fn_once"]
|
||||
pub trait FnOnce<Args> {
|
||||
type Output;
|
||||
#[lang = "fn"]
|
||||
pub trait Fn<Args>: FnOnce<Args> {
|
||||
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
#[lang = "fn"]
|
||||
pub trait Fn<Args>:FnOnce<Args> {
|
||||
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
#[lang = "deref"]
|
||||
pub trait Deref {
|
||||
type Target: ?Sized;
|
||||
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
|
||||
#[lang = "owned_box"]
|
||||
pub struct Box<T: ?Sized> {
|
||||
inner: *mut T,
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Deref for Box<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
let f: Box<dyn Fn() -> i32> = box(|| 5);
|
||||
let x = f();
|
||||
}
|
||||
"#
|
||||
),
|
||||
@r###"
|
||||
100..104 'self': Self
|
||||
106..110 'args': Args
|
||||
219..223 'self': &Self
|
||||
225..229 'args': Args
|
||||
333..337 'self': &Self
|
||||
503..507 'self': &Box<T>
|
||||
515..542 '{ ... }': &T
|
||||
525..536 '&self.inner': &*mut T
|
||||
526..530 'self': &Box<T>
|
||||
526..536 'self.inner': *mut T
|
||||
555..620 '{ ...f(); }': ()
|
||||
565..566 'f': Box<dyn Fn<(), Output = i32>>
|
||||
591..600 'box(|| 5)': Box<|| -> i32>
|
||||
595..599 '|| 5': || -> i32
|
||||
598..599 '5': i32
|
||||
610..611 'x': FnOnce::Output<dyn Fn<(), Output = i32>, ()>
|
||||
614..615 'f': Box<dyn Fn<(), Output = i32>>
|
||||
614..617 'f()': FnOnce::Output<dyn Fn<(), Output = i32>, ()>
|
||||
"###
|
||||
fn foo() {
|
||||
let f: &dyn Fn() -> i32;
|
||||
f();
|
||||
//^^^ i32
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variable_kinds() {
|
||||
fn infer_dyn_fn_once_output() {
|
||||
check_types(
|
||||
r#"
|
||||
#[lang = "fn_once"]
|
||||
pub trait FnOnce<Args> {
|
||||
type Output;
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
let f: dyn FnOnce() -> i32;
|
||||
f();
|
||||
//^^^ i32
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variable_kinds_1() {
|
||||
check_types(
|
||||
r#"
|
||||
trait Trait<T> { fn get(self, t: T) -> T; }
|
||||
|
@ -3083,3 +3078,20 @@ fn test() {
|
|||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variable_kinds_2() {
|
||||
check_types(
|
||||
r#"
|
||||
trait Trait { fn get(self) -> Self; }
|
||||
impl Trait for u128 {}
|
||||
impl Trait for f32 {}
|
||||
fn test() {
|
||||
1.get();
|
||||
//^^^^^^^ u128
|
||||
(1.).get();
|
||||
//^^^^^^^^^^ f32
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use chalk_ir::cast::Cast;
|
||||
use chalk_solve::Solver;
|
||||
use hir_def::{
|
||||
expr::ExprId, lang_item::LangItemTarget, DefWithBodyId, ImplId, TraitId, TypeAliasId,
|
||||
};
|
||||
|
@ -32,9 +33,10 @@ struct ChalkContext<'a> {
|
|||
krate: CrateId,
|
||||
}
|
||||
|
||||
fn create_chalk_solver() -> chalk_solve::Solver<Interner> {
|
||||
let solver_choice = chalk_solve::SolverChoice::recursive();
|
||||
solver_choice.into_solver()
|
||||
fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> {
|
||||
let overflow_depth = 100;
|
||||
let caching_enabled = true;
|
||||
chalk_recursive::RecursiveSolver::new(overflow_depth, caching_enabled)
|
||||
}
|
||||
|
||||
/// A set of clauses that we assume to be true. E.g. if we are inside this function:
|
||||
|
@ -293,13 +295,8 @@ pub enum Impl {
|
|||
/// A normal impl from an impl block.
|
||||
ImplDef(ImplId),
|
||||
/// Closure types implement the Fn traits synthetically.
|
||||
// FIXME: implement closure support from Chalk, remove this
|
||||
ClosureFnTraitImpl(ClosureFnTraitImplData),
|
||||
/// [T; n]: Unsize<[T]>
|
||||
UnsizeArray,
|
||||
/// T: Unsize<dyn Trait> where T: Trait
|
||||
UnsizeToTraitObject(TraitId),
|
||||
/// dyn Trait: Unsize<dyn SuperTrait> if Trait: SuperTrait
|
||||
UnsizeToSuperTraitObject(UnsizeToSuperTraitObjectData),
|
||||
}
|
||||
/// This exists just for Chalk, because our ImplIds are only unique per module.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
//! This module provides the built-in trait implementations, e.g. to make
|
||||
//! closures implement `Fn`.
|
||||
use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId};
|
||||
use hir_def::{expr::Expr, TraitId, TypeAliasId};
|
||||
use hir_expand::name::name;
|
||||
use ra_db::CrateId;
|
||||
|
||||
use super::{AssocTyValue, Impl, UnsizeToSuperTraitObjectData};
|
||||
use super::{AssocTyValue, Impl};
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
utils::{all_super_traits, generics},
|
||||
ApplicationTy, Binders, BoundVar, DebruijnIndex, GenericPredicate, Substs, TraitRef, Ty,
|
||||
TypeCtor, TypeWalk,
|
||||
db::HirDatabase, ApplicationTy, BoundVar, DebruijnIndex, Substs, TraitRef, Ty, TypeCtor,
|
||||
};
|
||||
|
||||
pub(super) struct BuiltinImplData {
|
||||
|
@ -31,7 +28,7 @@ pub(super) fn get_builtin_impls(
|
|||
krate: CrateId,
|
||||
ty: &Ty,
|
||||
// The first argument for the trait, if present
|
||||
arg: &Option<Ty>,
|
||||
_arg: &Option<Ty>,
|
||||
trait_: TraitId,
|
||||
mut callback: impl FnMut(Impl),
|
||||
) {
|
||||
|
@ -50,60 +47,12 @@ pub(super) fn get_builtin_impls(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
let unsize_trait = get_unsize_trait(db, krate);
|
||||
if let Some(actual_trait) = unsize_trait {
|
||||
if trait_ == actual_trait {
|
||||
get_builtin_unsize_impls(db, krate, ty, arg, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_builtin_unsize_impls(
|
||||
db: &dyn HirDatabase,
|
||||
krate: CrateId,
|
||||
ty: &Ty,
|
||||
// The first argument for the trait, if present
|
||||
arg: &Option<Ty>,
|
||||
mut callback: impl FnMut(Impl),
|
||||
) {
|
||||
if !check_unsize_impl_prerequisites(db, krate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, .. }) = ty {
|
||||
callback(Impl::UnsizeArray);
|
||||
return; // array is unsized, the rest of the impls shouldn't apply
|
||||
}
|
||||
|
||||
if let Some(target_trait) = arg.as_ref().and_then(|t| t.dyn_trait_ref()) {
|
||||
// FIXME what about more complicated dyn tys with marker traits?
|
||||
if let Some(trait_ref) = ty.dyn_trait_ref() {
|
||||
if trait_ref.trait_ != target_trait.trait_ {
|
||||
let super_traits = all_super_traits(db.upcast(), trait_ref.trait_);
|
||||
if super_traits.contains(&target_trait.trait_) {
|
||||
callback(Impl::UnsizeToSuperTraitObject(UnsizeToSuperTraitObjectData {
|
||||
trait_: trait_ref.trait_,
|
||||
super_trait: target_trait.trait_,
|
||||
}));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// FIXME only for sized types
|
||||
callback(Impl::UnsizeToTraitObject(target_trait.trait_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn impl_datum(db: &dyn HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData {
|
||||
match impl_ {
|
||||
Impl::ImplDef(_) => unreachable!(),
|
||||
Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data),
|
||||
Impl::UnsizeArray => array_unsize_impl_datum(db, krate),
|
||||
Impl::UnsizeToTraitObject(trait_) => trait_object_unsize_impl_datum(db, krate, trait_),
|
||||
Impl::UnsizeToSuperTraitObject(data) => {
|
||||
super_trait_object_unsize_impl_datum(db, krate, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,145 +176,3 @@ fn closure_fn_trait_output_assoc_ty_value(
|
|||
value: output_ty,
|
||||
}
|
||||
}
|
||||
|
||||
// Array unsizing
|
||||
|
||||
fn check_unsize_impl_prerequisites(db: &dyn HirDatabase, krate: CrateId) -> bool {
|
||||
// the Unsize trait needs to exist and have two type parameters (Self and T)
|
||||
let unsize_trait = match get_unsize_trait(db, krate) {
|
||||
Some(t) => t,
|
||||
None => return false,
|
||||
};
|
||||
let generic_params = generics(db.upcast(), unsize_trait.into());
|
||||
generic_params.len() == 2
|
||||
}
|
||||
|
||||
fn array_unsize_impl_datum(db: &dyn HirDatabase, krate: CrateId) -> BuiltinImplData {
|
||||
// impl<T> Unsize<[T]> for [T; _]
|
||||
// (this can be a single impl because we don't distinguish array sizes currently)
|
||||
|
||||
let trait_ = get_unsize_trait(db, krate) // get unsize trait
|
||||
// the existence of the Unsize trait has been checked before
|
||||
.expect("Unsize trait missing");
|
||||
|
||||
let var = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
|
||||
let substs = Substs::builder(2)
|
||||
.push(Ty::apply_one(TypeCtor::Array, var.clone()))
|
||||
.push(Ty::apply_one(TypeCtor::Slice, var))
|
||||
.build();
|
||||
|
||||
let trait_ref = TraitRef { trait_, substs };
|
||||
|
||||
BuiltinImplData {
|
||||
num_vars: 1,
|
||||
trait_ref,
|
||||
where_clauses: Vec::new(),
|
||||
assoc_ty_values: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
// Trait object unsizing
|
||||
|
||||
fn trait_object_unsize_impl_datum(
|
||||
db: &dyn HirDatabase,
|
||||
krate: CrateId,
|
||||
trait_: TraitId,
|
||||
) -> BuiltinImplData {
|
||||
// impl<T, T1, ...> Unsize<dyn Trait<T1, ...>> for T where T: Trait<T1, ...>
|
||||
|
||||
let unsize_trait = get_unsize_trait(db, krate) // get unsize trait
|
||||
// the existence of the Unsize trait has been checked before
|
||||
.expect("Unsize trait missing");
|
||||
|
||||
let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
|
||||
|
||||
let target_substs = Substs::build_for_def(db, trait_)
|
||||
.push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)))
|
||||
.fill_with_bound_vars(DebruijnIndex::ONE, 1)
|
||||
.build();
|
||||
let num_vars = target_substs.len();
|
||||
let target_trait_ref = TraitRef { trait_, substs: target_substs };
|
||||
let target_bounds = vec![GenericPredicate::Implemented(target_trait_ref)];
|
||||
|
||||
let self_substs =
|
||||
Substs::build_for_def(db, trait_).fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build();
|
||||
let self_trait_ref = TraitRef { trait_, substs: self_substs };
|
||||
let where_clauses = vec![GenericPredicate::Implemented(self_trait_ref)];
|
||||
|
||||
let impl_substs = Substs::builder(2).push(self_ty).push(Ty::Dyn(target_bounds.into())).build();
|
||||
|
||||
let trait_ref = TraitRef { trait_: unsize_trait, substs: impl_substs };
|
||||
|
||||
BuiltinImplData { num_vars, trait_ref, where_clauses, assoc_ty_values: Vec::new() }
|
||||
}
|
||||
|
||||
fn super_trait_object_unsize_impl_datum(
|
||||
db: &dyn HirDatabase,
|
||||
krate: CrateId,
|
||||
data: UnsizeToSuperTraitObjectData,
|
||||
) -> BuiltinImplData {
|
||||
// impl<T1, ...> Unsize<dyn SuperTrait> for dyn Trait<T1, ...>
|
||||
|
||||
let unsize_trait = get_unsize_trait(db, krate) // get unsize trait
|
||||
// the existence of the Unsize trait has been checked before
|
||||
.expect("Unsize trait missing");
|
||||
|
||||
let self_substs = Substs::build_for_def(db, data.trait_)
|
||||
.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
|
||||
.build();
|
||||
let self_trait_ref = TraitRef { trait_: data.trait_, substs: self_substs.clone() };
|
||||
|
||||
let num_vars = self_substs.len() - 1;
|
||||
|
||||
// we need to go from our trait to the super trait, substituting type parameters
|
||||
let path = crate::utils::find_super_trait_path(db.upcast(), data.trait_, data.super_trait);
|
||||
|
||||
let mut current_trait_ref = self_trait_ref.clone();
|
||||
for t in path.into_iter().skip(1) {
|
||||
let bounds = db.generic_predicates(current_trait_ref.trait_.into());
|
||||
let super_trait_ref = bounds
|
||||
.iter()
|
||||
.find_map(|b| match &b.value {
|
||||
GenericPredicate::Implemented(tr)
|
||||
if tr.trait_ == t
|
||||
&& tr.substs[0]
|
||||
== Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)) =>
|
||||
{
|
||||
Some(Binders { value: tr, num_binders: b.num_binders })
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.expect("trait bound for known super trait not found");
|
||||
current_trait_ref = super_trait_ref.cloned().subst(¤t_trait_ref.substs);
|
||||
}
|
||||
|
||||
// We need to renumber the variables a bit now: from ^0.0, ^0.1, ^0.2, ...
|
||||
// to ^0.0, ^1.0, ^1.1. The reason for this is that the first variable comes
|
||||
// from the dyn Trait binder, while the other variables come from the impl.
|
||||
let new_substs = Substs::builder(num_vars + 1)
|
||||
.push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)))
|
||||
.fill_with_bound_vars(DebruijnIndex::ONE, 0)
|
||||
.build();
|
||||
|
||||
let self_bounds =
|
||||
vec![GenericPredicate::Implemented(self_trait_ref.subst_bound_vars(&new_substs))];
|
||||
let super_bounds =
|
||||
vec![GenericPredicate::Implemented(current_trait_ref.subst_bound_vars(&new_substs))];
|
||||
|
||||
let substs = Substs::builder(2)
|
||||
.push(Ty::Dyn(self_bounds.into()))
|
||||
.push(Ty::Dyn(super_bounds.into()))
|
||||
.build();
|
||||
|
||||
let trait_ref = TraitRef { trait_: unsize_trait, substs };
|
||||
|
||||
BuiltinImplData { num_vars, trait_ref, where_clauses: Vec::new(), assoc_ty_values: Vec::new() }
|
||||
}
|
||||
|
||||
fn get_unsize_trait(db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
|
||||
let target = db.lang_item(krate, "unsize".into())?;
|
||||
match target {
|
||||
LangItemTarget::TraitId(t) => Some(t),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::sync::Arc;
|
|||
|
||||
use log::debug;
|
||||
|
||||
use chalk_ir::{fold::shift::Shift, GenericArg, TypeName};
|
||||
use chalk_ir::{fold::shift::Shift, CanonicalVarKinds, GenericArg, TypeName};
|
||||
use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
|
||||
|
||||
use hir_def::{
|
||||
|
@ -14,7 +14,10 @@ use ra_db::{salsa::InternKey, CrateId};
|
|||
|
||||
use super::{builtin, AssocTyValue, ChalkContext, Impl};
|
||||
use crate::{
|
||||
db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics,
|
||||
db::HirDatabase,
|
||||
display::HirDisplay,
|
||||
method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
|
||||
utils::generics,
|
||||
CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor,
|
||||
};
|
||||
use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders};
|
||||
|
@ -66,13 +69,31 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
|||
&self,
|
||||
trait_id: TraitId,
|
||||
parameters: &[GenericArg<Interner>],
|
||||
binders: &CanonicalVarKinds<Interner>,
|
||||
) -> Vec<ImplId> {
|
||||
debug!("impls_for_trait {:?}", trait_id);
|
||||
let trait_: hir_def::TraitId = from_chalk(self.db, trait_id);
|
||||
|
||||
let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone());
|
||||
|
||||
fn binder_kind(ty: &Ty, binders: &CanonicalVarKinds<Interner>) -> Option<chalk_ir::TyKind> {
|
||||
if let Ty::Bound(bv) = ty {
|
||||
let binders = binders.as_slice(&Interner);
|
||||
if bv.debruijn == DebruijnIndex::INNERMOST {
|
||||
if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind {
|
||||
return Some(tk);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
let self_ty_fp = TyFingerprint::for_impl(&ty);
|
||||
let fps: &[TyFingerprint] = match binder_kind(&ty, binders) {
|
||||
Some(chalk_ir::TyKind::Integer) => &ALL_INT_FPS,
|
||||
Some(chalk_ir::TyKind::Float) => &ALL_FLOAT_FPS,
|
||||
_ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]),
|
||||
};
|
||||
|
||||
// Note: Since we're using impls_for_trait, only impls where the trait
|
||||
// can be resolved should ever reach Chalk. `impl_datum` relies on that
|
||||
|
@ -83,17 +104,21 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
|||
|
||||
let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db);
|
||||
|
||||
let mut result: Vec<_> = match self_ty_fp {
|
||||
Some(fp) => impl_maps
|
||||
.iter()
|
||||
.flat_map(|crate_impl_defs| {
|
||||
crate_impl_defs.for_trait_and_self_ty(trait_, fp).map(id_to_chalk)
|
||||
})
|
||||
.collect(),
|
||||
None => impl_maps
|
||||
let mut result: Vec<_> = if fps.is_empty() {
|
||||
debug!("Unrestricted search for {:?} impls...", trait_);
|
||||
impl_maps
|
||||
.iter()
|
||||
.flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk))
|
||||
.collect(),
|
||||
.collect()
|
||||
} else {
|
||||
impl_maps
|
||||
.iter()
|
||||
.flat_map(|crate_impl_defs| {
|
||||
fps.iter().flat_map(move |fp| {
|
||||
crate_impl_defs.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk)
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
|
||||
let arg: Option<Ty> =
|
||||
|
@ -219,6 +244,22 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
|||
// FIXME: implement closure support
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn trait_name(&self, _trait_id: chalk_ir::TraitId<Interner>) -> String {
|
||||
unimplemented!()
|
||||
}
|
||||
fn adt_name(&self, _struct_id: chalk_ir::AdtId<Interner>) -> String {
|
||||
unimplemented!()
|
||||
}
|
||||
fn assoc_type_name(&self, _assoc_ty_id: chalk_ir::AssocTypeId<Interner>) -> String {
|
||||
unimplemented!()
|
||||
}
|
||||
fn opaque_type_name(&self, _opaque_ty_id: chalk_ir::OpaqueTyId<Interner>) -> String {
|
||||
unimplemented!()
|
||||
}
|
||||
fn fn_def_name(&self, _fn_def_id: chalk_ir::FnDefId<Interner>) -> String {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn program_clauses_for_chalk_env_query(
|
||||
|
@ -354,12 +395,18 @@ pub(crate) fn struct_datum_query(
|
|||
fundamental: false,
|
||||
phantom_data: false,
|
||||
};
|
||||
let struct_datum_bound = rust_ir::AdtDatumBound {
|
||||
fields: Vec::new(), // FIXME add fields (only relevant for auto traits)
|
||||
where_clauses,
|
||||
// FIXME provide enum variants properly (for auto traits)
|
||||
let variant = rust_ir::AdtVariantDatum {
|
||||
fields: Vec::new(), // FIXME add fields (only relevant for auto traits),
|
||||
};
|
||||
let struct_datum_bound = rust_ir::AdtDatumBound { variants: vec![variant], where_clauses };
|
||||
let struct_datum = StructDatum {
|
||||
// FIXME set ADT kind
|
||||
kind: rust_ir::AdtKind::Struct,
|
||||
id: struct_id,
|
||||
binders: make_binders(struct_datum_bound, num_params),
|
||||
flags,
|
||||
};
|
||||
let struct_datum =
|
||||
StructDatum { id: struct_id, binders: make_binders(struct_datum_bound, num_params), flags };
|
||||
Arc::new(struct_datum)
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ impl chalk_ir::interner::Interner for Interner {
|
|||
type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>;
|
||||
type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>;
|
||||
type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>;
|
||||
type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
|
||||
type DefId = InternId;
|
||||
type InternedAdtId = crate::TypeCtorId;
|
||||
type Identifier = TypeAliasId;
|
||||
|
@ -349,6 +350,20 @@ impl chalk_ir::interner::Interner for Interner {
|
|||
) -> &'a [chalk_ir::CanonicalVarKind<Self>] {
|
||||
&canonical_var_kinds
|
||||
}
|
||||
|
||||
fn intern_constraints<E>(
|
||||
&self,
|
||||
data: impl IntoIterator<Item = Result<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>, E>>,
|
||||
) -> Result<Self::InternedConstraints, E> {
|
||||
data.into_iter().collect()
|
||||
}
|
||||
|
||||
fn constraints_data<'a>(
|
||||
&self,
|
||||
constraints: &'a Self::InternedConstraints,
|
||||
) -> &'a [chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>] {
|
||||
constraints
|
||||
}
|
||||
}
|
||||
|
||||
impl chalk_ir::interner::HasInterner for Interner {
|
||||
|
|
|
@ -29,6 +29,7 @@ impl ToChalk for Ty {
|
|||
match self {
|
||||
Ty::Apply(apply_ty) => match apply_ty.ctor {
|
||||
TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters),
|
||||
TypeCtor::Array => array_to_chalk(db, apply_ty.parameters),
|
||||
TypeCtor::FnPtr { num_args: _ } => {
|
||||
let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner);
|
||||
chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution })
|
||||
|
@ -61,13 +62,13 @@ impl ToChalk for Ty {
|
|||
Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner),
|
||||
Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
|
||||
Ty::Dyn(predicates) => {
|
||||
let where_clauses = chalk_ir::QuantifiedWhereClauses::from(
|
||||
let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
|
||||
&Interner,
|
||||
predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)),
|
||||
);
|
||||
let bounded_ty = chalk_ir::DynTy {
|
||||
bounds: make_binders(where_clauses, 1),
|
||||
lifetime: LIFETIME_PLACEHOLDER.to_lifetime(&Interner),
|
||||
lifetime: FAKE_PLACEHOLDER.to_lifetime(&Interner),
|
||||
};
|
||||
chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner)
|
||||
}
|
||||
|
@ -92,6 +93,7 @@ impl ToChalk for Ty {
|
|||
chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name {
|
||||
TypeName::Error => Ty::Unknown,
|
||||
TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution),
|
||||
TypeName::Array => array_from_chalk(db, apply_ty.substitution),
|
||||
_ => {
|
||||
let ctor = from_chalk(db, apply_ty.name);
|
||||
let parameters = from_chalk(db, apply_ty.substitution);
|
||||
|
@ -138,7 +140,7 @@ impl ToChalk for Ty {
|
|||
}
|
||||
}
|
||||
|
||||
const LIFETIME_PLACEHOLDER: PlaceholderIndex =
|
||||
const FAKE_PLACEHOLDER: PlaceholderIndex =
|
||||
PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX };
|
||||
|
||||
/// We currently don't model lifetimes, but Chalk does. So, we have to insert a
|
||||
|
@ -149,10 +151,10 @@ fn ref_to_chalk(
|
|||
subst: Substs,
|
||||
) -> chalk_ir::Ty<Interner> {
|
||||
let arg = subst[0].clone().to_chalk(db);
|
||||
let lifetime = LIFETIME_PLACEHOLDER.to_lifetime(&Interner);
|
||||
let lifetime = FAKE_PLACEHOLDER.to_lifetime(&Interner);
|
||||
chalk_ir::ApplicationTy {
|
||||
name: TypeName::Ref(mutability.to_chalk(db)),
|
||||
substitution: chalk_ir::Substitution::from(
|
||||
substitution: chalk_ir::Substitution::from_iter(
|
||||
&Interner,
|
||||
vec![lifetime.cast(&Interner), arg.cast(&Interner)],
|
||||
),
|
||||
|
@ -173,11 +175,40 @@ fn ref_from_chalk(
|
|||
Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys))
|
||||
}
|
||||
|
||||
/// We currently don't model constants, but Chalk does. So, we have to insert a
|
||||
/// fake constant here, because Chalks built-in logic may expect it to be there.
|
||||
fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> {
|
||||
let arg = subst[0].clone().to_chalk(db);
|
||||
let usize_ty = chalk_ir::ApplicationTy {
|
||||
name: TypeName::Scalar(Scalar::Uint(chalk_ir::UintTy::Usize)),
|
||||
substitution: chalk_ir::Substitution::empty(&Interner),
|
||||
}
|
||||
.intern(&Interner);
|
||||
let const_ = FAKE_PLACEHOLDER.to_const(&Interner, usize_ty);
|
||||
chalk_ir::ApplicationTy {
|
||||
name: TypeName::Array,
|
||||
substitution: chalk_ir::Substitution::from_iter(
|
||||
&Interner,
|
||||
vec![arg.cast(&Interner), const_.cast(&Interner)],
|
||||
),
|
||||
}
|
||||
.intern(&Interner)
|
||||
}
|
||||
|
||||
/// Here we remove the const from the type we got from Chalk.
|
||||
fn array_from_chalk(db: &dyn HirDatabase, subst: chalk_ir::Substitution<Interner>) -> Ty {
|
||||
let tys = subst
|
||||
.iter(&Interner)
|
||||
.filter_map(|p| Some(from_chalk(db, p.ty(&Interner)?.clone())))
|
||||
.collect();
|
||||
Ty::apply(TypeCtor::Array, Substs(tys))
|
||||
}
|
||||
|
||||
impl ToChalk for Substs {
|
||||
type Chalk = chalk_ir::Substitution<Interner>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> {
|
||||
chalk_ir::Substitution::from(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db)))
|
||||
chalk_ir::Substitution::from_iter(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db)))
|
||||
}
|
||||
|
||||
fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs {
|
||||
|
@ -263,6 +294,7 @@ impl ToChalk for TypeCtor {
|
|||
TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()),
|
||||
TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)),
|
||||
TypeCtor::Slice => TypeName::Slice,
|
||||
TypeCtor::Array => TypeName::Array,
|
||||
TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)),
|
||||
TypeCtor::Str => TypeName::Str,
|
||||
TypeCtor::FnDef(callable_def) => {
|
||||
|
@ -271,10 +303,8 @@ impl ToChalk for TypeCtor {
|
|||
}
|
||||
TypeCtor::Never => TypeName::Never,
|
||||
|
||||
TypeCtor::Adt(_)
|
||||
| TypeCtor::Array
|
||||
| TypeCtor::FnPtr { .. }
|
||||
| TypeCtor::Closure { .. } => {
|
||||
// FIXME convert these
|
||||
TypeCtor::Adt(_) | TypeCtor::FnPtr { .. } | TypeCtor::Closure { .. } => {
|
||||
// other TypeCtors get interned and turned into a chalk StructId
|
||||
let struct_id = db.intern_type_ctor(self).into();
|
||||
TypeName::Adt(struct_id)
|
||||
|
@ -492,6 +522,11 @@ impl ToChalk for GenericPredicate {
|
|||
// we shouldn't get these from Chalk
|
||||
panic!("encountered LifetimeOutlives from Chalk")
|
||||
}
|
||||
|
||||
chalk_ir::WhereClause::TypeOutlives(_) => {
|
||||
// we shouldn't get these from Chalk
|
||||
panic!("encountered TypeOutlives from Chalk")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -570,7 +605,10 @@ where
|
|||
)
|
||||
});
|
||||
let value = self.value.to_chalk(db);
|
||||
chalk_ir::Canonical { value, binders: chalk_ir::CanonicalVarKinds::from(&Interner, kinds) }
|
||||
chalk_ir::Canonical {
|
||||
value,
|
||||
binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
|
||||
|
@ -691,7 +729,7 @@ where
|
|||
T: HasInterner<Interner = Interner>,
|
||||
{
|
||||
chalk_ir::Binders::new(
|
||||
chalk_ir::VariableKinds::from(
|
||||
chalk_ir::VariableKinds::from_iter(
|
||||
&Interner,
|
||||
std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)).take(num_vars),
|
||||
),
|
||||
|
|
|
@ -157,7 +157,7 @@ impl DebugContext<'_> {
|
|||
_ => panic!("associated type not in trait"),
|
||||
};
|
||||
let trait_data = self.0.trait_data(trait_);
|
||||
let params = projection_ty.substitution.parameters(&Interner);
|
||||
let params = projection_ty.substitution.as_slice(&Interner);
|
||||
write!(fmt, "<{:?} as {}", ¶ms[0], trait_data.name,)?;
|
||||
if params.len() > 1 {
|
||||
write!(
|
||||
|
|
|
@ -110,38 +110,6 @@ pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) ->
|
|||
result
|
||||
}
|
||||
|
||||
/// Finds a path from a trait to one of its super traits. Returns an empty
|
||||
/// vector if there is no path.
|
||||
pub(super) fn find_super_trait_path(
|
||||
db: &dyn DefDatabase,
|
||||
trait_: TraitId,
|
||||
super_trait: TraitId,
|
||||
) -> Vec<TraitId> {
|
||||
let mut result = Vec::with_capacity(2);
|
||||
result.push(trait_);
|
||||
return if go(db, super_trait, &mut result) { result } else { Vec::new() };
|
||||
|
||||
fn go(db: &dyn DefDatabase, super_trait: TraitId, path: &mut Vec<TraitId>) -> bool {
|
||||
let trait_ = *path.last().unwrap();
|
||||
if trait_ == super_trait {
|
||||
return true;
|
||||
}
|
||||
|
||||
for tt in direct_super_traits(db, trait_) {
|
||||
if path.contains(&tt) {
|
||||
continue;
|
||||
}
|
||||
path.push(tt);
|
||||
if go(db, super_trait, path) {
|
||||
return true;
|
||||
} else {
|
||||
path.pop();
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn associated_type_by_name_including_super_traits(
|
||||
db: &dyn HirDatabase,
|
||||
trait_ref: TraitRef,
|
||||
|
|
Loading…
Reference in a new issue