Represent async blocks as TyKind::Coroutine, not as opaques
This commit is contained in:
parent
d6d007c290
commit
c859e76f57
9 changed files with 94 additions and 197 deletions
|
|
@ -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}}")?,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
¶m,
|
||||
)],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => panic!("No generics for {def:?}"),
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue