Unnamed repository; edit this file 'description' to name the repository.
Represent async blocks as `TyKind::Coroutine`, not as opaques
Chayim Refael Friedman 6 months ago
parent 9061bd3 · commit dfaf6ac
-rw-r--r--crates/hir-ty/src/display.rs88
-rw-r--r--crates/hir-ty/src/infer.rs1
-rw-r--r--crates/hir-ty/src/infer/expr.rs33
-rw-r--r--crates/hir-ty/src/lib.rs3
-rw-r--r--crates/hir-ty/src/next_solver/generic_arg.rs1
-rw-r--r--crates/hir-ty/src/next_solver/generics.rs26
-rw-r--r--crates/hir-ty/src/next_solver/interner.rs3
-rw-r--r--crates/hir-ty/src/next_solver/ty.rs37
-rw-r--r--crates/hir-ty/src/next_solver/util.rs99
9 files changed, 94 insertions, 197 deletions
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index f8d9add42a..c749a3d24a 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -48,7 +48,7 @@ use triomphe::Arc;
use crate::{
CallableDefId, FnAbi, ImplTraitId, MemoryMap, TraitEnvironment, consteval,
- db::{HirDatabase, InternedClosure},
+ db::{HirDatabase, InternedClosure, InternedCoroutine},
generics::generics,
layout::Layout,
mir::pad16,
@@ -1389,33 +1389,6 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
SizedByDefault::Sized { anchor: krate },
)?;
}
- ImplTraitId::AsyncBlockTypeImplTrait(body, ..) => {
- let future_trait =
- LangItem::Future.resolve_trait(db, body.module(db).krate());
- let output = future_trait.and_then(|t| {
- t.trait_items(db)
- .associated_type_by_name(&Name::new_symbol_root(sym::Output))
- });
- write!(f, "impl ")?;
- if let Some(t) = future_trait {
- f.start_location_link(t.into());
- }
- write!(f, "Future")?;
- if future_trait.is_some() {
- f.end_location_link();
- }
- write!(f, "<")?;
- if let Some(t) = output {
- f.start_location_link(t.into());
- }
- write!(f, "Output")?;
- if output.is_some() {
- f.end_location_link();
- }
- write!(f, " = ")?;
- alias_ty.args.type_at(0).hir_fmt(f)?;
- write!(f, ">")?;
- }
}
}
TyKind::Closure(id, substs) => {
@@ -1567,23 +1540,56 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
}
}
TyKind::Infer(..) => write!(f, "_")?,
- TyKind::Coroutine(_, subst) => {
- if f.display_kind.is_source_code() {
- return Err(HirDisplayError::DisplaySourceCodeError(
- DisplaySourceCodeError::Coroutine,
- ));
- }
+ TyKind::Coroutine(coroutine_id, subst) => {
+ let InternedCoroutine(owner, expr_id) = coroutine_id.0.loc(db);
let CoroutineArgsParts { resume_ty, yield_ty, return_ty, .. } =
subst.split_coroutine_args();
- write!(f, "|")?;
- resume_ty.hir_fmt(f)?;
- write!(f, "|")?;
+ let body = db.body(owner);
+ match &body[expr_id] {
+ hir_def::hir::Expr::Async { .. } => {
+ let future_trait =
+ LangItem::Future.resolve_trait(db, owner.module(db).krate());
+ let output = future_trait.and_then(|t| {
+ t.trait_items(db)
+ .associated_type_by_name(&Name::new_symbol_root(sym::Output))
+ });
+ write!(f, "impl ")?;
+ if let Some(t) = future_trait {
+ f.start_location_link(t.into());
+ }
+ write!(f, "Future")?;
+ if future_trait.is_some() {
+ f.end_location_link();
+ }
+ write!(f, "<")?;
+ if let Some(t) = output {
+ f.start_location_link(t.into());
+ }
+ write!(f, "Output")?;
+ if output.is_some() {
+ f.end_location_link();
+ }
+ write!(f, " = ")?;
+ return_ty.hir_fmt(f)?;
+ write!(f, ">")?;
+ }
+ _ => {
+ if f.display_kind.is_source_code() {
+ return Err(HirDisplayError::DisplaySourceCodeError(
+ DisplaySourceCodeError::Coroutine,
+ ));
+ }
+ write!(f, "|")?;
+ resume_ty.hir_fmt(f)?;
+ write!(f, "|")?;
- write!(f, " yields ")?;
- yield_ty.hir_fmt(f)?;
+ write!(f, " yields ")?;
+ yield_ty.hir_fmt(f)?;
- write!(f, " -> ")?;
- return_ty.hir_fmt(f)?;
+ write!(f, " -> ")?;
+ return_ty.hir_fmt(f)?;
+ }
+ }
}
TyKind::CoroutineWitness(..) => write!(f, "{{coroutine witness}}")?,
TyKind::Pat(_, _) => write!(f, "{{pat}}")?,
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 21b6e053cc..361e66522d 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -1243,7 +1243,6 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
(self.db.type_alias_impl_traits(def), idx)
}
- _ => unreachable!(),
};
let Some(impl_traits) = impl_traits else {
return ty;
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index efb7244ff6..fd4e374d9c 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -18,7 +18,7 @@ use hir_expand::name::Name;
use intern::sym;
use rustc_ast_ir::Mutability;
use rustc_type_ir::{
- AliasTyKind, InferTy, Interner,
+ CoroutineArgs, CoroutineArgsParts, InferTy, Interner,
inherent::{AdtDef, GenericArgs as _, IntoKind, SliceLike, Ty as _},
};
use syntax::ast::RangeOp;
@@ -29,6 +29,7 @@ use crate::{
IncorrectGenericsLenKind, Rawness, TraitEnvironment,
autoderef::overloaded_deref_ty,
consteval,
+ db::InternedCoroutine,
generics::generics,
infer::{
AllowTwoPhase, BreakableKind,
@@ -43,7 +44,7 @@ use crate::{
},
method_resolution::{self, VisibleFromModule},
next_solver::{
- AliasTy, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, TraitRef, Ty, TyKind,
+ Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, TraitRef, Ty, TyKind,
TypeError,
infer::{
InferOk,
@@ -1132,18 +1133,26 @@ impl<'db> InferenceContext<'_, 'db> {
inner_ty: Ty<'db>,
tgt_expr: ExprId,
) -> Ty<'db> {
- // Use the first type parameter as the output type of future.
- // existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
- let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, tgt_expr);
- let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
- Ty::new_alias(
+ let coroutine_id = InternedCoroutine(self.owner, tgt_expr);
+ let coroutine_id = self.db.intern_coroutine(coroutine_id).into();
+ let parent_args = GenericArgs::identity_for_item(self.interner(), self.generic_def.into());
+ Ty::new_coroutine(
self.interner(),
- AliasTyKind::Opaque,
- AliasTy::new(
+ coroutine_id,
+ CoroutineArgs::new(
self.interner(),
- opaque_ty_id,
- GenericArgs::new_from_iter(self.interner(), [inner_ty.into()]),
- ),
+ CoroutineArgsParts {
+ parent_args,
+ kind_ty: self.types.unit,
+ // rustc uses a special lang item type for the resume ty. I don't believe this can cause us problems.
+ resume_ty: self.types.unit,
+ yield_ty: self.types.unit,
+ return_ty: inner_ty,
+ // FIXME: Infer upvars.
+ tupled_upvars_ty: self.types.unit,
+ },
+ )
+ .args,
)
}
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index ecca1ef04d..2942c0f7a9 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -53,7 +53,7 @@ mod variance;
use std::hash::Hash;
-use hir_def::{CallableDefId, TypeOrConstParamId, hir::ExprId, type_ref::Rawness};
+use hir_def::{CallableDefId, TypeOrConstParamId, type_ref::Rawness};
use hir_expand::name::Name;
use indexmap::{IndexMap, map::Entry};
use intern::{Symbol, sym};
@@ -334,7 +334,6 @@ impl FnAbi {
pub enum ImplTraitId<'db> {
ReturnTypeImplTrait(hir_def::FunctionId, next_solver::ImplTraitIdx<'db>),
TypeAliasImplTrait(hir_def::TypeAliasId, next_solver::ImplTraitIdx<'db>),
- AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId),
}
/// 'Canonicalizes' the `t` by replacing any errors with new variables. Also
diff --git a/crates/hir-ty/src/next_solver/generic_arg.rs b/crates/hir-ty/src/next_solver/generic_arg.rs
index 24f22bcb0c..90bd44aee8 100644
--- a/crates/hir-ty/src/next_solver/generic_arg.rs
+++ b/crates/hir-ty/src/next_solver/generic_arg.rs
@@ -446,7 +446,6 @@ impl<'db> rustc_type_ir::inherent::GenericArgs<DbInterner<'db>> for GenericArgs<
signature_parts_ty,
tupled_upvars_ty,
coroutine_captures_by_ref_ty,
- _coroutine_witness_ty,
] => rustc_type_ir::CoroutineClosureArgsParts {
parent_args: GenericArgs::new_from_iter(
DbInterner::conjure(),
diff --git a/crates/hir-ty/src/next_solver/generics.rs b/crates/hir-ty/src/next_solver/generics.rs
index d5a9a6f527..4d164a7e3b 100644
--- a/crates/hir-ty/src/next_solver/generics.rs
+++ b/crates/hir-ty/src/next_solver/generics.rs
@@ -2,10 +2,7 @@
use hir_def::{
ConstParamId, GenericDefId, GenericParamId, LifetimeParamId, TypeOrConstParamId, TypeParamId,
- hir::generics::{
- GenericParams, LocalTypeOrConstParamId, TypeOrConstParamData, TypeParamData,
- TypeParamProvenance,
- },
+ hir::generics::{GenericParams, TypeOrConstParamData},
};
use crate::{db::HirDatabase, generics::parent_generic_def};
@@ -67,27 +64,6 @@ pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
crate::ImplTraitId::TypeAliasImplTrait(type_alias_id, _) => {
(Some(type_alias_id.into()), Vec::new())
}
- crate::ImplTraitId::AsyncBlockTypeImplTrait(_def, _) => {
- let param = TypeOrConstParamData::TypeParamData(TypeParamData {
- name: None,
- default: None,
- provenance: TypeParamProvenance::TypeParamList,
- });
- // Yes, there is a parent but we don't include it in the generics
- // FIXME: It seems utterly sensitive to fake a generic param here.
- // Also, what a horrible mess!
- (
- None,
- vec![mk_ty(
- GenericDefId::FunctionId(salsa::plumbing::FromId::from_id(unsafe {
- salsa::Id::from_index(salsa::Id::MAX_U32 - 1)
- })),
- 0,
- LocalTypeOrConstParamId::from_raw(la_arena::RawIdx::from_u32(0)),
- &param,
- )],
- )
- }
}
}
_ => panic!("No generics for {def:?}"),
diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs
index 06d35ba93d..e3c65689d3 100644
--- a/crates/hir-ty/src/next_solver/interner.rs
+++ b/crates/hir-ty/src/next_solver/interner.rs
@@ -1884,8 +1884,7 @@ impl<'db> Interner for DbInterner<'db> {
let infer = self.db().infer(func.into());
EarlyBinder::bind(infer.type_of_rpit[idx])
}
- crate::ImplTraitId::TypeAliasImplTrait(..)
- | crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
+ crate::ImplTraitId::TypeAliasImplTrait(..) => {
// FIXME(next-solver)
EarlyBinder::bind(Ty::new_error(self, ErrorGuaranteed))
}
diff --git a/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs
index 95ee00d275..1443e2f0b3 100644
--- a/crates/hir-ty/src/next_solver/ty.rs
+++ b/crates/hir-ty/src/next_solver/ty.rs
@@ -26,7 +26,7 @@ use rustc_type_ir::{
use crate::{
ImplTraitId,
- db::HirDatabase,
+ db::{HirDatabase, InternedCoroutine},
next_solver::{
AdtDef, AliasTy, Binder, CallableIdWrapper, Clause, ClauseKind, ClosureIdWrapper, Const,
CoroutineIdWrapper, FnSig, GenericArg, PolyFnSig, Region, TraitRef, TypeAliasIdWrapper,
@@ -546,23 +546,6 @@ impl<'db> Ty<'db> {
.collect()
})
}
- ImplTraitId::AsyncBlockTypeImplTrait(def, _) => {
- let krate = def.module(db).krate();
- if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) {
- // This is only used by type walking.
- // Parameters will be walked outside, and projection predicate is not used.
- // So just provide the Future trait.
- let impl_bound = TraitRef::new(
- interner,
- future_trait.into(),
- GenericArgs::new_from_iter(interner, []),
- )
- .upcast(interner);
- Some(vec![impl_bound])
- } else {
- None
- }
- }
}
}
TyKind::Param(param) => {
@@ -592,6 +575,24 @@ impl<'db> Ty<'db> {
_ => None,
}
}
+ TyKind::Coroutine(coroutine_id, _args) => {
+ let InternedCoroutine(owner, _) = coroutine_id.0.loc(db);
+ let krate = owner.module(db).krate();
+ if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) {
+ // This is only used by type walking.
+ // Parameters will be walked outside, and projection predicate is not used.
+ // So just provide the Future trait.
+ let impl_bound = TraitRef::new(
+ interner,
+ future_trait.into(),
+ GenericArgs::new_from_iter(interner, []),
+ )
+ .upcast(interner);
+ Some(vec![impl_bound])
+ } else {
+ None
+ }
+ }
_ => None,
}
}
diff --git a/crates/hir-ty/src/next_solver/util.rs b/crates/hir-ty/src/next_solver/util.rs
index bb0d0552c7..d113f76a32 100644
--- a/crates/hir-ty/src/next_solver/util.rs
+++ b/crates/hir-ty/src/next_solver/util.rs
@@ -7,11 +7,10 @@ use std::{
use base_db::Crate;
use hir_def::{BlockId, HasModule, lang_item::LangItem};
-use intern::sym;
use la_arena::Idx;
use rustc_abi::{Float, HasDataLayout, Integer, IntegerType, Primitive, ReprOptions};
use rustc_type_ir::{
- ConstKind, CoroutineArgs, DebruijnIndex, FloatTy, GenericArgKind, INNERMOST, IntTy, Interner,
+ ConstKind, CoroutineArgs, DebruijnIndex, FloatTy, INNERMOST, IntTy, Interner,
PredicatePolarity, RegionKind, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable,
TypeVisitableExt, TypeVisitor, UintTy, UniverseIndex,
inherent::{
@@ -32,9 +31,8 @@ use crate::{
};
use super::{
- AliasTerm, AliasTy, Binder, BoundRegion, BoundTy, BoundTyKind, BoundVarKind, BoundVarKinds,
- Clause, ClauseKind, Clauses, Const, DbInterner, EarlyBinder, GenericArgs, Predicate,
- PredicateKind, ProjectionPredicate, Region, SolverDefId, Term, TraitPredicate, TraitRef, Ty,
+ Binder, BoundRegion, BoundTy, Clause, ClauseKind, Clauses, Const, DbInterner, EarlyBinder,
+ GenericArgs, Predicate, PredicateKind, Region, SolverDefId, TraitPredicate, TraitRef, Ty,
TyKind,
fold::{BoundVarReplacer, FnMutDelegate},
};
@@ -578,98 +576,9 @@ pub fn explicit_item_bounds<'db>(
let data = &datas.impl_traits[Idx::from_raw(idx.into_raw())];
EarlyBinder::bind(Clauses::new_from_iter(interner, data.predicates.clone()))
}
- crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
- if let Some((future_trait, future_output)) = LangItem::Future
- .resolve_trait(db, interner.krate.expect("Must have interner.krate"))
- .and_then(|trait_| {
- let alias = trait_.trait_items(db).associated_type_by_name(
- &hir_expand::name::Name::new_symbol_root(sym::Output.clone()),
- )?;
- Some((trait_, alias))
- })
- {
- let args = GenericArgs::identity_for_item(interner, def_id);
- let out = args.as_slice()[0];
- let mut predicates = vec![];
-
- let item_ty = Ty::new_alias(
- interner,
- rustc_type_ir::AliasTyKind::Opaque,
- AliasTy::new_from_args(interner, def_id, args),
- );
-
- let kind = PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
- polarity: rustc_type_ir::PredicatePolarity::Positive,
- trait_ref: TraitRef::new_from_args(
- interner,
- future_trait.into(),
- GenericArgs::new_from_iter(interner, [item_ty.into()]),
- ),
- }));
- predicates.push(Clause(Predicate::new(
- interner,
- Binder::bind_with_vars(
- kind,
- BoundVarKinds::new_from_iter(
- interner,
- [BoundVarKind::Ty(BoundTyKind::Anon)],
- ),
- ),
- )));
- let sized_trait = LangItem::Sized
- .resolve_trait(db, interner.krate.expect("Must have interner.krate"));
- if let Some(sized_trait_) = sized_trait {
- let kind = PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
- polarity: rustc_type_ir::PredicatePolarity::Positive,
- trait_ref: TraitRef::new_from_args(
- interner,
- sized_trait_.into(),
- GenericArgs::new_from_iter(interner, [item_ty.into()]),
- ),
- }));
- predicates.push(Clause(Predicate::new(
- interner,
- Binder::bind_with_vars(
- kind,
- BoundVarKinds::new_from_iter(
- interner,
- [BoundVarKind::Ty(BoundTyKind::Anon)],
- ),
- ),
- )));
- }
- let kind =
- PredicateKind::Clause(ClauseKind::Projection(ProjectionPredicate {
- projection_term: AliasTerm::new_from_args(
- interner,
- future_output.into(),
- GenericArgs::new_from_iter(interner, [item_ty.into()]),
- ),
- term: match out.kind() {
- GenericArgKind::Lifetime(_lt) => panic!(),
- GenericArgKind::Type(ty) => Term::Ty(ty),
- GenericArgKind::Const(const_) => Term::Const(const_),
- },
- }));
- predicates.push(Clause(Predicate::new(
- interner,
- Binder::bind_with_vars(
- kind,
- BoundVarKinds::new_from_iter(
- interner,
- [BoundVarKind::Ty(BoundTyKind::Anon)],
- ),
- ),
- )));
- EarlyBinder::bind(Clauses::new_from_iter(interner, predicates))
- } else {
- // If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback.
- EarlyBinder::bind(Clauses::new_from_iter(interner, []))
- }
- }
}
}
- _ => panic!("Unexpected GeneridDefId"),
+ _ => panic!("Unexpected GenericDefId"),
}
}