WIP use params for APIT

This commit is contained in:
Florian Diebold 2020-01-31 16:05:58 +01:00
parent 33aa2f8e4f
commit f8b7b64bce
3 changed files with 64 additions and 1 deletions

View File

@ -480,7 +480,7 @@ fn collect_const(&mut self, data: &ConstData) {
fn collect_fn(&mut self, data: &FunctionData) {
let body = Arc::clone(&self.body); // avoid borrow checker problem
for (type_ref, pat) in data.params.iter().zip(body.params.iter()) {
let ty = self.make_ty_with_mode(type_ref, ImplTraitLoweringMode::Opaque);
let ty = self.make_ty_with_mode(type_ref, ImplTraitLoweringMode::Param);
self.infer_pat(*pat, &ty, BindingMode::default());
}

View File

@ -30,6 +30,7 @@
Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs,
TraitEnvironment, TraitRef, Ty, TypeCtor,
};
use hir_expand::name::Name;
#[derive(Debug)]
pub struct TyLoweringContext<'a, DB: HirDatabase> {
@ -69,6 +70,10 @@ pub enum ImplTraitLoweringMode {
/// i.e. for arguments of the function we're currently checking, and return
/// types of functions we're calling.
Opaque,
/// `impl Trait` gets lowered into a type variable. Used for argument
/// position impl Trait currently, since it allows us to support that
/// without Chalk.
Param,
/// `impl Trait` gets lowered into a variable that can unify with some
/// type. This is used in places where values flow 'in', i.e. for arguments
/// of functions we're calling, and the return type of the function we're
@ -137,6 +142,11 @@ pub fn from_hir(ctx: &TyLoweringContext<'_, impl HirDatabase>, type_ref: &TypeRe
.collect();
Ty::Opaque(predicates)
}
ImplTraitLoweringMode::Param => {
let idx = ctx.impl_trait_counter.get();
ctx.impl_trait_counter.set(idx + 1);
Ty::Param { idx: idx as u32, name: Name::missing() }
}
ImplTraitLoweringMode::Variable => {
let idx = ctx.impl_trait_counter.get();
ctx.impl_trait_counter.set(idx + 1);

View File

@ -849,6 +849,59 @@ fn test<T: ApplyL>(t: T) {
assert_eq!(t, "{unknown}");
}
#[test]
fn argument_impl_trait() {
assert_snapshot!(
infer_with_mismatches(r#"
trait Trait<T> {
fn foo(&self) -> T;
fn foo2(&self) -> i64;
}
fn bar(impl Trait<u64>) {}
struct S<T>(T);
impl<T> Trait<T> for S<T> {}
fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
x;
y;
let z = S(1);
bar(z);
x.foo();
y.foo();
z.foo();
x.foo2();
y.foo2();
z.foo2();
}
"#, true),
@r###"
[30; 34) 'self': &Self
[55; 59) 'self': &Self
[99; 101) '{}': ()
[111; 112) 'x': impl Trait<u64>
[131; 132) 'y': &impl Trait<u64>
[152; 269) '{ ...2(); }': ()
[158; 159) 'x': impl Trait<u64>
[165; 166) 'y': &impl Trait<u64>
[176; 177) 'z': impl Trait<u64>
[180; 183) 'bar': fn bar() -> impl Trait<u64>
[180; 185) 'bar()': impl Trait<u64>
[191; 192) 'x': impl Trait<u64>
[191; 198) 'x.foo()': u64
[204; 205) 'y': &impl Trait<u64>
[204; 211) 'y.foo()': u64
[217; 218) 'z': impl Trait<u64>
[217; 224) 'z.foo()': u64
[230; 231) 'x': impl Trait<u64>
[230; 238) 'x.foo2()': i64
[244; 245) 'y': &impl Trait<u64>
[244; 252) 'y.foo2()': i64
[258; 259) 'z': impl Trait<u64>
[258; 266) 'z.foo2()': i64
"###
);
}
#[test]
#[ignore]
fn impl_trait() {