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

Commit 3ef56c2

Browse files
committed
Auto merge of rust-lang#17845 - ShoyuVanilla:tait, r=Veykril
feat: Implement TAIT and fix ATPIT a bit Closes rust-lang#16296 (Commented on the issue) In rust-lang#16852, I implemented ATPIT, but as I didn't discern ATPIT and other non-assoc TAIT, I guess that it has been working for some TAITs. As the definining usage of TAIT requires it should be appear in the Def body's type(const blocks' type annotations or functions' signatures), this can be done in simlilar way with ATPIT And this PR also corrects some defining-usage resolution for ATPIT
2 parents ec03068 + 18b9458 commit 3ef56c2

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
@@ -1152,11 +1152,10 @@ impl HirDisplay for Ty {
11521152
)?;
11531153
// FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
11541154
}
1155-
ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
1155+
ImplTraitId::TypeAliasImplTrait(alias, idx) => {
11561156
let datas =
11571157
db.type_alias_impl_traits(alias).expect("impl trait id without data");
1158-
let data =
1159-
(*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
1158+
let data = (*datas).as_ref().map(|it| it.impl_traits[idx].bounds.clone());
11601159
let bounds = data.substitute(Interner, &parameters);
11611160
let krate = alias.krate(db.upcast());
11621161
write_bounds_like_dyn_trait_with_prefix(
@@ -1339,7 +1338,7 @@ impl HirDisplay for Ty {
13391338
SizedByDefault::Sized { anchor: krate },
13401339
)?;
13411340
}
1342-
ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
1341+
ImplTraitId::TypeAliasImplTrait(alias, idx) => {
13431342
let datas =
13441343
db.type_alias_impl_traits(alias).expect("impl trait id without data");
13451344
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)