fix: #12441 False-positive type-mismatch error with generic future

This commit is contained in:
bitgaoshu 2022-06-03 10:28:01 +08:00
parent e10799536a
commit 1a97ab34db
2 changed files with 78 additions and 4 deletions

View file

@ -241,6 +241,27 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
.intern(Interner), .intern(Interner),
), ),
}); });
let mut binder = vec![];
binder.push(crate::wrap_empty_binders(impl_bound));
let sized_trait = self
.db
.lang_item(self.krate, SmolStr::new_inline("sized"))
.and_then(|item| item.as_trait());
if let Some(sized_trait_) = sized_trait {
let sized_bound = WhereClause::Implemented(TraitRef {
trait_id: to_chalk_trait_id(sized_trait_),
// Self type as the first parameter.
substitution: Substitution::from1(
Interner,
TyKind::BoundVar(BoundVar {
debruijn: DebruijnIndex::INNERMOST,
index: 0,
})
.intern(Interner),
),
});
binder.push(crate::wrap_empty_binders(sized_bound));
}
let proj_bound = WhereClause::AliasEq(AliasEq { let proj_bound = WhereClause::AliasEq(AliasEq {
alias: AliasTy::Projection(ProjectionTy { alias: AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(future_output), associated_ty_id: to_assoc_type_id(future_output),
@ -255,11 +276,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }) ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 })
.intern(Interner), .intern(Interner),
}); });
binder.push(crate::wrap_empty_binders(proj_bound));
let bound = OpaqueTyDatumBound { let bound = OpaqueTyDatumBound {
bounds: make_single_type_binders(vec![ bounds: make_single_type_binders(binder),
crate::wrap_empty_binders(impl_bound),
crate::wrap_empty_binders(proj_bound),
]),
where_clauses: chalk_ir::Binders::empty(Interner, vec![]), where_clauses: chalk_ir::Binders::empty(Interner, vec![]),
}; };
// The opaque type has 1 parameter. // The opaque type has 1 parameter.

View file

@ -82,6 +82,61 @@ async fn test() {
); );
} }
#[test]
fn auto_sized_async_block() {
check_no_mismatches(
r#"
//- minicore: future, sized
use core::future::Future;
struct MyFut<Fut>(Fut);
impl<Fut> Future for MyFut<Fut>
where Fut: Future
{
type Output = Fut::Output;
}
async fn reproduction() -> usize {
let f = async {999usize};
MyFut(f).await
}
"#,
);
check_no_mismatches(
r#"
//- minicore: future
//#11815
#[lang = "sized"]
pub trait Sized {}
#[lang = "unsize"]
pub trait Unsize<T: ?Sized> {}
#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {}
pub unsafe trait Allocator {}
pub struct Global;
unsafe impl Allocator for Global {}
#[lang = "owned_box"]
#[fundamental]
pub struct Box<T: ?Sized, A: Allocator = Global>;
impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}
fn send() -> Box<dyn Future<Output = ()> + Send + 'static>{
box async move {}
}
fn not_send() -> Box<dyn Future<Output = ()> + 'static> {
box async move {}
}
"#,
);
}
#[test] #[test]
fn infer_try() { fn infer_try() {
check_types( check_types(