Skip to content

Commit 1a97ab3

Browse files
committed
fix: rust-lang#12441 False-positive type-mismatch error with generic future
1 parent e107995 commit 1a97ab3

File tree

2 files changed

+78
-4
lines changed

2 files changed

+78
-4
lines changed

crates/hir-ty/src/chalk_db.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,27 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
241241
.intern(Interner),
242242
),
243243
});
244+
let mut binder = vec![];
245+
binder.push(crate::wrap_empty_binders(impl_bound));
246+
let sized_trait = self
247+
.db
248+
.lang_item(self.krate, SmolStr::new_inline("sized"))
249+
.and_then(|item| item.as_trait());
250+
if let Some(sized_trait_) = sized_trait {
251+
let sized_bound = WhereClause::Implemented(TraitRef {
252+
trait_id: to_chalk_trait_id(sized_trait_),
253+
// Self type as the first parameter.
254+
substitution: Substitution::from1(
255+
Interner,
256+
TyKind::BoundVar(BoundVar {
257+
debruijn: DebruijnIndex::INNERMOST,
258+
index: 0,
259+
})
260+
.intern(Interner),
261+
),
262+
});
263+
binder.push(crate::wrap_empty_binders(sized_bound));
264+
}
244265
let proj_bound = WhereClause::AliasEq(AliasEq {
245266
alias: AliasTy::Projection(ProjectionTy {
246267
associated_ty_id: to_assoc_type_id(future_output),
@@ -255,11 +276,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
255276
ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 })
256277
.intern(Interner),
257278
});
279+
binder.push(crate::wrap_empty_binders(proj_bound));
258280
let bound = OpaqueTyDatumBound {
259-
bounds: make_single_type_binders(vec![
260-
crate::wrap_empty_binders(impl_bound),
261-
crate::wrap_empty_binders(proj_bound),
262-
]),
281+
bounds: make_single_type_binders(binder),
263282
where_clauses: chalk_ir::Binders::empty(Interner, vec![]),
264283
};
265284
// The opaque type has 1 parameter.

crates/hir-ty/src/tests/traits.rs

+55
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,61 @@ async fn test() {
8282
);
8383
}
8484

85+
#[test]
86+
fn auto_sized_async_block() {
87+
check_no_mismatches(
88+
r#"
89+
//- minicore: future, sized
90+
91+
use core::future::Future;
92+
struct MyFut<Fut>(Fut);
93+
94+
impl<Fut> Future for MyFut<Fut>
95+
where Fut: Future
96+
{
97+
type Output = Fut::Output;
98+
}
99+
async fn reproduction() -> usize {
100+
let f = async {999usize};
101+
MyFut(f).await
102+
}
103+
"#,
104+
);
105+
check_no_mismatches(
106+
r#"
107+
//- minicore: future
108+
//#11815
109+
#[lang = "sized"]
110+
pub trait Sized {}
111+
112+
#[lang = "unsize"]
113+
pub trait Unsize<T: ?Sized> {}
114+
115+
#[lang = "coerce_unsized"]
116+
pub trait CoerceUnsized<T> {}
117+
118+
pub unsafe trait Allocator {}
119+
120+
pub struct Global;
121+
unsafe impl Allocator for Global {}
122+
123+
#[lang = "owned_box"]
124+
#[fundamental]
125+
pub struct Box<T: ?Sized, A: Allocator = Global>;
126+
127+
impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}
128+
129+
fn send() -> Box<dyn Future<Output = ()> + Send + 'static>{
130+
box async move {}
131+
}
132+
133+
fn not_send() -> Box<dyn Future<Output = ()> + 'static> {
134+
box async move {}
135+
}
136+
"#,
137+
);
138+
}
139+
85140
#[test]
86141
fn infer_try() {
87142
check_types(

0 commit comments

Comments
 (0)