diff --git a/chalk-solve/src/clauses.rs b/chalk-solve/src/clauses.rs index e795c8fd63e..bb96de4fbe2 100644 --- a/chalk-solve/src/clauses.rs +++ b/chalk-solve/src/clauses.rs @@ -161,14 +161,16 @@ pub fn push_auto_trait_impls( TyKind::Foreign(_) => Ok(()), // closures require binders, while the other types do not - TyKind::Closure(closure_id, _) => { - let binders = builder - .db - .closure_upvars(*closure_id, &Substitution::empty(interner)); - builder.push_binders(binders, |builder, upvar_ty| { - let conditions = iter::once(mk_ref(upvar_ty)); - builder.push_clause(consequence, conditions); - }); + TyKind::Closure(closure_id, substs) => { + let closure_fn_substitution = builder.db.closure_fn_substitution(*closure_id, substs); + let binders = builder.db.closure_upvars(*closure_id, substs); + let upvars = binders.substitute(builder.db.interner(), &closure_fn_substitution); + + // in a same behavior as for non-auto traits (reuse the code) we can require that + // every bound type must implement this auto-trait + use crate::clauses::builtin_traits::needs_impl_for_tys; + needs_impl_for_tys(builder.db, builder, consequence, Some(upvars).into_iter()); + Ok(()) } TyKind::Generator(generator_id, _) => { diff --git a/tests/test/closures.rs b/tests/test/closures.rs index 40f8d78f78d..4bd0379c54e 100644 --- a/tests/test/closures.rs +++ b/tests/test/closures.rs @@ -280,3 +280,35 @@ fn closure_implements_fn_traits() { } } } + +#[test] +fn closures_propagate_auto_traits() { + test! { + program { + #[auto] + trait Send { } + + closure foo(self,) {} + + closure with_ty(self,) { T } + } + + goal { + foo: Send + } yields { + expect![["Unique"]] + } + + goal { + forall { with_ty: Send } + } yields { + expect![["No possible solution"]] + } + + goal { + forall { if (T: Send) { with_ty: Send } } + } yields { + expect![["Unique"]] + } + } +}