Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 18b9458

Browse files
committed
feat: Implement TAIT
1 parent bee4926 commit 18b9458

File tree

14 files changed

+288
-188
lines changed

14 files changed

+288
-188
lines changed

src/tools/rust-analyzer/crates/hir-def/src/db.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
160160
fn const_data(&self, konst: ConstId) -> Arc<ConstData>;
161161

162162
#[salsa::invoke(StaticData::static_data_query)]
163-
fn static_data(&self, konst: StaticId) -> Arc<StaticData>;
163+
fn static_data(&self, statik: StaticId) -> Arc<StaticData>;
164164

165165
#[salsa::invoke(Macro2Data::macro2_data_query)]
166166
fn macro2_data(&self, makro: Macro2Id) -> Arc<Macro2Data>;

src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
275275
};
276276
chalk_ir::Binders::new(binders, bound)
277277
}
278-
crate::ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
278+
crate::ImplTraitId::TypeAliasImplTrait(alias, idx) => {
279279
let datas = self
280280
.db
281281
.type_alias_impl_traits(alias)

src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ impl TyExt for Ty {
276276
data.substitute(Interner, &subst).into_value_and_skipped_binders().0
277277
})
278278
}
279-
ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
279+
ImplTraitId::TypeAliasImplTrait(alias, idx) => {
280280
db.type_alias_impl_traits(alias).map(|it| {
281281
let data =
282282
(*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
@@ -295,7 +295,7 @@ impl TyExt for Ty {
295295
data.substitute(Interner, &opaque_ty.substitution)
296296
})
297297
}
298-
ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
298+
ImplTraitId::TypeAliasImplTrait(alias, idx) => {
299299
db.type_alias_impl_traits(alias).map(|it| {
300300
let data =
301301
(*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());

src/tools/rust-analyzer/crates/hir-ty/src/display.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,11 +1151,10 @@ impl HirDisplay for Ty {
11511151
)?;
11521152
// FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
11531153
}
1154-
ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
1154+
ImplTraitId::TypeAliasImplTrait(alias, idx) => {
11551155
let datas =
11561156
db.type_alias_impl_traits(alias).expect("impl trait id without data");
1157-
let data =
1158-
(*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
1157+
let data = (*datas).as_ref().map(|it| it.impl_traits[idx].bounds.clone());
11591158
let bounds = data.substitute(Interner, &parameters);
11601159
let krate = alias.krate(db.upcast());
11611160
write_bounds_like_dyn_trait_with_prefix(
@@ -1338,7 +1337,7 @@ impl HirDisplay for Ty {
13381337
SizedByDefault::Sized { anchor: krate },
13391338
)?;
13401339
}
1341-
ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
1340+
ImplTraitId::TypeAliasImplTrait(alias, idx) => {
13421341
let datas =
13431342
db.type_alias_impl_traits(alias).expect("impl trait id without data");
13441343
let data =

src/tools/rust-analyzer/crates/hir-ty/src/infer.rs

Lines changed: 108 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,14 @@ use hir_def::{
3636
body::Body,
3737
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
3838
data::{ConstData, StaticData},
39-
hir::LabelId,
40-
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, PatId},
39+
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},
4140
lang_item::{LangItem, LangItemTarget},
4241
layout::Integer,
4342
path::{ModPath, Path},
4443
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
4544
type_ref::{LifetimeRef, TypeRef},
46-
AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId,
47-
TupleFieldId, TupleId, TypeAliasId, VariantId,
45+
AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ImplId, ItemContainerId, Lookup,
46+
TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId,
4847
};
4948
use hir_expand::name::Name;
5049
use indexmap::IndexSet;
@@ -785,14 +784,19 @@ impl<'a> InferenceContext<'a> {
785784
fn collect_const(&mut self, data: &ConstData) {
786785
let return_ty = self.make_ty(&data.type_ref);
787786

788-
// Constants might be associated items that define ATPITs.
789-
self.insert_atpit_coercion_table(iter::once(&return_ty));
787+
// Constants might be defining usage sites of TAITs.
788+
self.make_tait_coercion_table(iter::once(&return_ty));
790789

791790
self.return_ty = return_ty;
792791
}
793792

794793
fn collect_static(&mut self, data: &StaticData) {
795-
self.return_ty = self.make_ty(&data.type_ref);
794+
let return_ty = self.make_ty(&data.type_ref);
795+
796+
// Statics might be defining usage sites of TAITs.
797+
self.make_tait_coercion_table(iter::once(&return_ty));
798+
799+
self.return_ty = return_ty;
796800
}
797801

798802
fn collect_fn(&mut self, func: FunctionId) {
@@ -857,11 +861,11 @@ impl<'a> InferenceContext<'a> {
857861
self.return_ty = self.normalize_associated_types_in(return_ty);
858862
self.return_coercion = Some(CoerceMany::new(self.return_ty.clone()));
859863

860-
// Functions might be associated items that define ATPITs.
861-
// To define an ATPITs, that ATPIT must appear in the function's signatures.
864+
// Functions might be defining usage sites of TAITs.
865+
// To define an TAITs, that TAIT must appear in the function's signatures.
862866
// So, it suffices to check for params and return types.
863867
params_and_ret_tys.push(self.return_ty.clone());
864-
self.insert_atpit_coercion_table(params_and_ret_tys.iter());
868+
self.make_tait_coercion_table(params_and_ret_tys.iter());
865869
}
866870

867871
fn insert_inference_vars_for_impl_trait<T>(&mut self, t: T, placeholders: Substitution) -> T
@@ -880,7 +884,7 @@ impl<'a> InferenceContext<'a> {
880884
ImplTraitId::ReturnTypeImplTrait(def, idx) => {
881885
(self.db.return_type_impl_traits(def), idx)
882886
}
883-
ImplTraitId::AssociatedTypeImplTrait(def, idx) => {
887+
ImplTraitId::TypeAliasImplTrait(def, idx) => {
884888
(self.db.type_alias_impl_traits(def), idx)
885889
}
886890
_ => unreachable!(),
@@ -909,23 +913,25 @@ impl<'a> InferenceContext<'a> {
909913
}
910914

911915
/// The coercion of a non-inference var into an opaque type should fail,
912-
/// but not in the defining sites of the ATPITs.
913-
/// In such cases, we insert an proxy inference var for each ATPIT,
914-
/// and coerce into it instead of ATPIT itself.
916+
/// but not in the defining sites of the TAITs.
917+
/// In such cases, we insert an proxy inference var for each TAIT,
918+
/// and coerce into it instead of TAIT itself.
915919
///
916920
/// The inference var stretagy is effective because;
917921
///
918-
/// - It can still unify types that coerced into ATPIT
922+
/// - It can still unify types that coerced into TAITs
919923
/// - We are pushing `impl Trait` bounds into it
920924
///
921925
/// This function inserts a map that maps the opaque type to that proxy inference var.
922-
fn insert_atpit_coercion_table<'b>(&mut self, tys: impl Iterator<Item = &'b Ty>) {
923-
struct OpaqueTyCollector<'a, 'b> {
926+
fn make_tait_coercion_table<'b>(&mut self, tait_candidates: impl Iterator<Item = &'b Ty>) {
927+
struct TypeAliasImplTraitCollector<'a, 'b> {
928+
db: &'b dyn HirDatabase,
924929
table: &'b mut InferenceTable<'a>,
925-
opaque_tys: FxHashMap<OpaqueTyId, Ty>,
930+
assocs: FxHashMap<OpaqueTyId, (ImplId, Ty)>,
931+
non_assocs: FxHashMap<OpaqueTyId, Ty>,
926932
}
927933

928-
impl<'a, 'b> TypeVisitor<Interner> for OpaqueTyCollector<'a, 'b> {
934+
impl<'a, 'b> TypeVisitor<Interner> for TypeAliasImplTraitCollector<'a, 'b> {
929935
type BreakTy = ();
930936

931937
fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> {
@@ -944,59 +950,105 @@ impl<'a> InferenceContext<'a> {
944950
let ty = self.table.resolve_ty_shallow(ty);
945951

946952
if let TyKind::OpaqueType(id, _) = ty.kind(Interner) {
947-
self.opaque_tys.insert(*id, ty.clone());
953+
if let ImplTraitId::TypeAliasImplTrait(alias_id, _) =
954+
self.db.lookup_intern_impl_trait_id((*id).into())
955+
{
956+
let loc = self.db.lookup_intern_type_alias(alias_id);
957+
match loc.container {
958+
ItemContainerId::ImplId(impl_id) => {
959+
self.assocs.insert(*id, (impl_id, ty.clone()));
960+
}
961+
ItemContainerId::ModuleId(..) | ItemContainerId::ExternBlockId(..) => {
962+
self.non_assocs.insert(*id, ty.clone());
963+
}
964+
_ => {}
965+
}
966+
}
948967
}
949968

950969
ty.super_visit_with(self, outer_binder)
951970
}
952971
}
953972

954-
// Early return if this is not happening inside the impl block
955-
let impl_id = if let Some(impl_id) = self.resolver.impl_def() {
956-
impl_id
957-
} else {
958-
return;
973+
let mut collector = TypeAliasImplTraitCollector {
974+
db: self.db,
975+
table: &mut self.table,
976+
assocs: FxHashMap::default(),
977+
non_assocs: FxHashMap::default(),
959978
};
960-
961-
let assoc_tys: FxHashSet<_> = self
962-
.db
963-
.impl_data(impl_id)
964-
.items
965-
.iter()
966-
.filter_map(|item| match item {
967-
AssocItemId::TypeAliasId(alias) => Some(*alias),
968-
_ => None,
969-
})
970-
.collect();
971-
if assoc_tys.is_empty() {
972-
return;
979+
for ty in tait_candidates {
980+
ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST);
973981
}
974982

975-
let mut collector =
976-
OpaqueTyCollector { table: &mut self.table, opaque_tys: FxHashMap::default() };
977-
for ty in tys {
978-
ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST);
983+
// Non-assoc TAITs can be define-used everywhere as long as they are
984+
// in function signatures or const types, etc
985+
let mut taits = collector.non_assocs;
986+
987+
// assoc TAITs(ATPITs) can be only define-used inside their impl block.
988+
// They cannot be define-used in inner items like in the following;
989+
//
990+
// ```
991+
// impl Trait for Struct {
992+
// type Assoc = impl Default;
993+
//
994+
// fn assoc_fn() -> Self::Assoc {
995+
// let foo: Self::Assoc = true; // Allowed here
996+
//
997+
// fn inner() -> Self::Assoc {
998+
// false // Not allowed here
999+
// }
1000+
//
1001+
// foo
1002+
// }
1003+
// }
1004+
// ```
1005+
let impl_id = match self.owner {
1006+
DefWithBodyId::FunctionId(it) => {
1007+
let loc = self.db.lookup_intern_function(it);
1008+
if let ItemContainerId::ImplId(impl_id) = loc.container {
1009+
Some(impl_id)
1010+
} else {
1011+
None
1012+
}
1013+
}
1014+
DefWithBodyId::ConstId(it) => {
1015+
let loc = self.db.lookup_intern_const(it);
1016+
if let ItemContainerId::ImplId(impl_id) = loc.container {
1017+
Some(impl_id)
1018+
} else {
1019+
None
1020+
}
1021+
}
1022+
_ => None,
1023+
};
1024+
1025+
if let Some(impl_id) = impl_id {
1026+
taits.extend(collector.assocs.into_iter().filter_map(|(id, (impl_, ty))| {
1027+
if impl_ == impl_id {
1028+
Some((id, ty))
1029+
} else {
1030+
None
1031+
}
1032+
}));
9791033
}
980-
let atpit_coercion_table: FxHashMap<_, _> = collector
981-
.opaque_tys
1034+
1035+
let tait_coercion_table: FxHashMap<_, _> = taits
9821036
.into_iter()
983-
.filter_map(|(opaque_ty_id, ty)| {
984-
if let ImplTraitId::AssociatedTypeImplTrait(alias_id, _) =
985-
self.db.lookup_intern_impl_trait_id(opaque_ty_id.into())
1037+
.filter_map(|(id, ty)| {
1038+
if let ImplTraitId::TypeAliasImplTrait(alias_id, _) =
1039+
self.db.lookup_intern_impl_trait_id(id.into())
9861040
{
987-
if assoc_tys.contains(&alias_id) {
988-
let alias_placeholders = TyBuilder::placeholder_subst(self.db, alias_id);
989-
let ty = self.insert_inference_vars_for_impl_trait(ty, alias_placeholders);
990-
return Some((opaque_ty_id, ty));
991-
}
1041+
let subst = TyBuilder::placeholder_subst(self.db, alias_id);
1042+
let ty = self.insert_inference_vars_for_impl_trait(ty, subst);
1043+
Some((id, ty))
1044+
} else {
1045+
None
9921046
}
993-
994-
None
9951047
})
9961048
.collect();
9971049

998-
if !atpit_coercion_table.is_empty() {
999-
self.table.atpit_coercion_table = Some(atpit_coercion_table);
1050+
if !tait_coercion_table.is_empty() {
1051+
self.table.tait_coercion_table = Some(tait_coercion_table);
10001052
}
10011053
}
10021054

src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,16 +276,16 @@ impl InferenceTable<'_> {
276276
return success(simple(Adjust::NeverToAny)(to_ty.clone()), to_ty.clone(), vec![]);
277277
}
278278

279-
// If we are coercing into an ATPIT, coerce into its proxy inference var, instead.
279+
// If we are coercing into a TAIT, coerce into its proxy inference var, instead.
280280
let mut to_ty = to_ty;
281281
let _to;
282-
if let Some(atpit_table) = &self.atpit_coercion_table {
282+
if let Some(tait_table) = &self.tait_coercion_table {
283283
if let TyKind::OpaqueType(opaque_ty_id, _) = to_ty.kind(Interner) {
284284
if !matches!(
285285
from_ty.kind(Interner),
286286
TyKind::InferenceVar(..) | TyKind::OpaqueType(..)
287287
) {
288-
if let Some(ty) = atpit_table.get(opaque_ty_id) {
288+
if let Some(ty) = tait_table.get(opaque_ty_id) {
289289
_to = ty.clone();
290290
to_ty = &_to;
291291
}

src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ type ChalkInferenceTable = chalk_solve::infer::InferenceTable<Interner>;
224224
pub(crate) struct InferenceTable<'a> {
225225
pub(crate) db: &'a dyn HirDatabase,
226226
pub(crate) trait_env: Arc<TraitEnvironment>,
227-
pub(crate) atpit_coercion_table: Option<FxHashMap<OpaqueTyId, Ty>>,
227+
pub(crate) tait_coercion_table: Option<FxHashMap<OpaqueTyId, Ty>>,
228228
var_unification_table: ChalkInferenceTable,
229229
type_variable_table: SmallVec<[TypeVariableFlags; 16]>,
230230
pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
@@ -244,7 +244,7 @@ impl<'a> InferenceTable<'a> {
244244
InferenceTable {
245245
db,
246246
trait_env,
247-
atpit_coercion_table: None,
247+
tait_coercion_table: None,
248248
var_unification_table: ChalkInferenceTable::new(),
249249
type_variable_table: SmallVec::new(),
250250
pending_obligations: Vec::new(),

src/tools/rust-analyzer/crates/hir-ty/src/layout.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ pub fn layout_of_ty_query(
391391
let infer = db.infer(func.into());
392392
return db.layout_of_ty(infer.type_of_rpit[idx].clone(), trait_env);
393393
}
394-
crate::ImplTraitId::AssociatedTypeImplTrait(..) => {
394+
crate::ImplTraitId::TypeAliasImplTrait(..) => {
395395
return Err(LayoutError::NotImplemented);
396396
}
397397
crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {

src/tools/rust-analyzer/crates/hir-ty/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ impl TypeFoldable<Interner> for CallableSig {
595595
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
596596
pub enum ImplTraitId {
597597
ReturnTypeImplTrait(hir_def::FunctionId, ImplTraitIdx),
598-
AssociatedTypeImplTrait(hir_def::TypeAliasId, ImplTraitIdx),
598+
TypeAliasImplTrait(hir_def::TypeAliasId, ImplTraitIdx),
599599
AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId),
600600
}
601601
impl InternValueTrivial for ImplTraitId {}

src/tools/rust-analyzer/crates/hir-ty/src/lower.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ impl<'a> TyLoweringContext<'a> {
341341

342342
let impl_trait_id = origin.either(
343343
|f| ImplTraitId::ReturnTypeImplTrait(f, idx),
344-
|a| ImplTraitId::AssociatedTypeImplTrait(a, idx),
344+
|a| ImplTraitId::TypeAliasImplTrait(a, idx),
345345
);
346346
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
347347
let generics =
@@ -2131,7 +2131,6 @@ pub(crate) fn type_alias_impl_traits(
21312131
if let Some(type_ref) = &data.type_ref {
21322132
let _ty = ctx.lower_ty(type_ref);
21332133
}
2134-
let generics = generics(db.upcast(), def.into());
21352134
let type_alias_impl_traits = ImplTraits {
21362135
impl_traits: match ctx.impl_trait_mode {
21372136
ImplTraitLoweringState::Opaque(x) => x.into_inner(),
@@ -2141,6 +2140,7 @@ pub(crate) fn type_alias_impl_traits(
21412140
if type_alias_impl_traits.impl_traits.is_empty() {
21422141
None
21432142
} else {
2143+
let generics = generics(db.upcast(), def.into());
21442144
Some(Arc::new(make_binders(db, &generics, type_alias_impl_traits)))
21452145
}
21462146
}

src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ impl FallibleTypeFolder<Interner> for Filler<'_> {
8282
};
8383
filler.try_fold_ty(infer.type_of_rpit[idx].clone(), outer_binder)
8484
}
85-
crate::ImplTraitId::AssociatedTypeImplTrait(..) => {
86-
not_supported!("associated type impl trait");
85+
crate::ImplTraitId::TypeAliasImplTrait(..) => {
86+
not_supported!("type alias impl trait");
8787
}
8888
crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
8989
not_supported!("async block impl trait");

0 commit comments

Comments
 (0)