Skip to content

Commit d10e5d1

Browse files
committed
Convert more of dyn_compatibility to next-solver
1 parent 064f1c7 commit d10e5d1

File tree

2 files changed

+130
-153
lines changed

2 files changed

+130
-153
lines changed

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

Lines changed: 37 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,7 @@
22
33
use std::ops::ControlFlow;
44

5-
use chalk_ir::{
6-
DebruijnIndex,
7-
visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
8-
};
9-
use chalk_solve::rust_ir::InlineBound;
5+
use chalk_ir::DebruijnIndex;
106
use hir_def::{
117
AssocItemId, ConstId, CrateRootModuleId, FunctionId, GenericDefId, HasModule, TraitId,
128
TypeAliasId, lang_item::LangItem, signatures::TraitFlags,
@@ -21,14 +17,14 @@ use rustc_type_ir::{
2117
use smallvec::SmallVec;
2218

2319
use crate::{
24-
AliasEq, AliasTy, Binders, BoundVar, ImplTraitId, Interner, ProjectionTyExt, Ty, TyKind,
25-
WhereClause, all_super_traits,
20+
ImplTraitId, Interner, TyKind, WhereClause, all_super_traits,
2621
db::{HirDatabase, InternedOpaqueTyId},
27-
from_assoc_type_id, from_chalk_trait_id,
22+
from_chalk_trait_id,
2823
generics::trait_self_param_idx,
24+
lower_nextsolver::associated_ty_item_bounds,
2925
next_solver::{
30-
Clauses, DbInterner, GenericArgs, ParamEnv, SolverDefId, TraitPredicate, TypingMode,
31-
infer::DbInternerInferExt, mk_param,
26+
Clause, Clauses, DbInterner, GenericArgs, ParamEnv, SolverDefId, TraitPredicate,
27+
TypingMode, infer::DbInternerInferExt, mk_param,
3228
},
3329
traits::next_trait_solve_in_ctxt,
3430
utils::elaborate_clause_supertraits,
@@ -165,7 +161,7 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b
165161
// but we don't have good way to render such locations.
166162
// So, just return single boolean value for existence of such `Self` reference
167163
fn predicates_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool {
168-
db.generic_predicates(trait_.into())
164+
db.generic_predicates_ns(trait_.into())
169165
.iter()
170166
.any(|pred| predicate_references_self(db, trait_, pred, AllowSelfProjection::No))
171167
}
@@ -177,37 +173,18 @@ fn bounds_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool {
177173
.items
178174
.iter()
179175
.filter_map(|(_, it)| match *it {
180-
AssocItemId::TypeAliasId(id) => {
181-
let assoc_ty_data = db.associated_ty_data(id);
182-
Some(assoc_ty_data)
183-
}
176+
AssocItemId::TypeAliasId(id) => Some(associated_ty_item_bounds(db, id)),
184177
_ => None,
185178
})
186-
.any(|assoc_ty_data| {
187-
assoc_ty_data.binders.skip_binders().bounds.iter().any(|bound| {
188-
let def = from_assoc_type_id(assoc_ty_data.id).into();
189-
match bound.skip_binders() {
190-
InlineBound::TraitBound(it) => it.args_no_self.iter().any(|arg| {
191-
contains_illegal_self_type_reference(
192-
db,
193-
def,
194-
trait_,
195-
arg,
196-
DebruijnIndex::ONE,
197-
AllowSelfProjection::Yes,
198-
)
199-
}),
200-
InlineBound::AliasEqBound(it) => it.parameters.iter().any(|arg| {
201-
contains_illegal_self_type_reference(
202-
db,
203-
def,
204-
trait_,
205-
arg,
206-
DebruijnIndex::ONE,
207-
AllowSelfProjection::Yes,
208-
)
209-
}),
210-
}
179+
.any(|bounds| {
180+
bounds.skip_binder().iter().any(|pred| match pred.skip_binder() {
181+
rustc_type_ir::ExistentialPredicate::Trait(it) => it.args.iter().any(|arg| {
182+
contains_illegal_self_type_reference(db, trait_, &arg, AllowSelfProjection::Yes)
183+
}),
184+
rustc_type_ir::ExistentialPredicate::Projection(it) => it.args.iter().any(|arg| {
185+
contains_illegal_self_type_reference(db, trait_, &arg, AllowSelfProjection::Yes)
186+
}),
187+
rustc_type_ir::ExistentialPredicate::AutoTrait(_) => false,
211188
})
212189
})
213190
}
@@ -218,120 +195,26 @@ enum AllowSelfProjection {
218195
No,
219196
}
220197

221-
fn predicate_references_self(
222-
db: &dyn HirDatabase,
198+
fn predicate_references_self<'db>(
199+
db: &'db dyn HirDatabase,
223200
trait_: TraitId,
224-
predicate: &Binders<Binders<WhereClause>>,
201+
predicate: &Clause<'db>,
225202
allow_self_projection: AllowSelfProjection,
226203
) -> bool {
227-
match predicate.skip_binders().skip_binders() {
228-
WhereClause::Implemented(trait_ref) => {
229-
trait_ref.substitution.iter(Interner).skip(1).any(|arg| {
230-
contains_illegal_self_type_reference(
231-
db,
232-
trait_.into(),
233-
trait_,
234-
arg,
235-
DebruijnIndex::ONE,
236-
allow_self_projection,
237-
)
238-
})
239-
}
240-
WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => {
241-
proj.substitution.iter(Interner).skip(1).any(|arg| {
242-
contains_illegal_self_type_reference(
243-
db,
244-
trait_.into(),
245-
trait_,
246-
arg,
247-
DebruijnIndex::ONE,
248-
allow_self_projection,
249-
)
204+
match predicate.kind().skip_binder() {
205+
ClauseKind::Trait(trait_pred) => trait_pred.trait_ref.args.iter().skip(1).any(|arg| {
206+
contains_illegal_self_type_reference(db, trait_, &arg, allow_self_projection)
207+
}),
208+
ClauseKind::Projection(proj_pred) => {
209+
proj_pred.projection_term.args.iter().skip(1).any(|arg| {
210+
contains_illegal_self_type_reference(db, trait_, &arg, allow_self_projection)
250211
})
251212
}
252213
_ => false,
253214
}
254215
}
255216

256-
fn contains_illegal_self_type_reference<T: TypeVisitable<Interner>>(
257-
db: &dyn HirDatabase,
258-
def: GenericDefId,
259-
trait_: TraitId,
260-
t: &T,
261-
outer_binder: DebruijnIndex,
262-
allow_self_projection: AllowSelfProjection,
263-
) -> bool {
264-
let Some(trait_self_param_idx) = trait_self_param_idx(db, def) else {
265-
return false;
266-
};
267-
struct IllegalSelfTypeVisitor<'a> {
268-
db: &'a dyn HirDatabase,
269-
trait_: TraitId,
270-
super_traits: Option<SmallVec<[TraitId; 4]>>,
271-
trait_self_param_idx: usize,
272-
allow_self_projection: AllowSelfProjection,
273-
}
274-
impl TypeVisitor<Interner> for IllegalSelfTypeVisitor<'_> {
275-
type BreakTy = ();
276-
277-
fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> {
278-
self
279-
}
280-
281-
fn interner(&self) -> Interner {
282-
Interner
283-
}
284-
285-
fn visit_ty(&mut self, ty: &Ty, outer_binder: DebruijnIndex) -> ControlFlow<Self::BreakTy> {
286-
match ty.kind(Interner) {
287-
TyKind::BoundVar(BoundVar { debruijn, index }) => {
288-
if *debruijn == outer_binder && *index == self.trait_self_param_idx {
289-
ControlFlow::Break(())
290-
} else {
291-
ty.super_visit_with(self.as_dyn(), outer_binder)
292-
}
293-
}
294-
TyKind::Alias(AliasTy::Projection(proj)) => match self.allow_self_projection {
295-
AllowSelfProjection::Yes => {
296-
let trait_ = proj.trait_(self.db);
297-
if self.super_traits.is_none() {
298-
self.super_traits = Some(all_super_traits(self.db, self.trait_));
299-
}
300-
if self.super_traits.as_ref().is_some_and(|s| s.contains(&trait_)) {
301-
ControlFlow::Continue(())
302-
} else {
303-
ty.super_visit_with(self.as_dyn(), outer_binder)
304-
}
305-
}
306-
AllowSelfProjection::No => ty.super_visit_with(self.as_dyn(), outer_binder),
307-
},
308-
_ => ty.super_visit_with(self.as_dyn(), outer_binder),
309-
}
310-
}
311-
312-
fn visit_const(
313-
&mut self,
314-
constant: &chalk_ir::Const<Interner>,
315-
outer_binder: DebruijnIndex,
316-
) -> std::ops::ControlFlow<Self::BreakTy> {
317-
constant.data(Interner).ty.super_visit_with(self.as_dyn(), outer_binder)
318-
}
319-
}
320-
321-
let mut visitor = IllegalSelfTypeVisitor {
322-
db,
323-
trait_,
324-
super_traits: None,
325-
trait_self_param_idx,
326-
allow_self_projection,
327-
};
328-
t.visit_with(visitor.as_dyn(), outer_binder).is_break()
329-
}
330-
331-
fn contains_illegal_self_type_reference_ns<
332-
'db,
333-
T: rustc_type_ir::TypeVisitable<DbInterner<'db>>,
334-
>(
217+
fn contains_illegal_self_type_reference<'db, T: rustc_type_ir::TypeVisitable<DbInterner<'db>>>(
335218
db: &'db dyn HirDatabase,
336219
trait_: TraitId,
337220
t: &T,
@@ -440,13 +323,17 @@ where
440323
}
441324

442325
let sig = db.callable_item_signature_ns(func.into());
443-
if sig.skip_binder().inputs().iter().skip(1).any(|ty| {
444-
contains_illegal_self_type_reference_ns(db, trait_, &ty, AllowSelfProjection::Yes)
445-
}) {
326+
if sig
327+
.skip_binder()
328+
.inputs()
329+
.iter()
330+
.skip(1)
331+
.any(|ty| contains_illegal_self_type_reference(db, trait_, &ty, AllowSelfProjection::Yes))
332+
{
446333
cb(MethodViolationCode::ReferencesSelfInput)?;
447334
}
448335

449-
if contains_illegal_self_type_reference_ns(
336+
if contains_illegal_self_type_reference(
450337
db,
451338
trait_,
452339
&sig.skip_binder().output(),
@@ -496,7 +383,7 @@ where
496383
continue;
497384
}
498385

499-
if contains_illegal_self_type_reference_ns(db, trait_, &pred, AllowSelfProjection::Yes) {
386+
if contains_illegal_self_type_reference(db, trait_, &pred, AllowSelfProjection::Yes) {
500387
cb(MethodViolationCode::WhereClauseReferencesSelf)?;
501388
break;
502389
}

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

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ use crate::{
6262
lower::{Diagnostics, PathDiagnosticCallbackData, create_diagnostics},
6363
next_solver::{
6464
AdtDef, AliasTy, Binder, BoundExistentialPredicates, BoundRegionKind, BoundTyKind,
65-
BoundVarKind, BoundVarKinds, Clause, Const, DbInterner, EarlyBinder, EarlyParamRegion,
66-
ErrorGuaranteed, GenericArgs, PolyFnSig, Predicate, Region, SolverDefId, TraitPredicate,
67-
TraitRef, Ty, Tys, abi::Safety, generics::GenericParamDefKind, mapping::ChalkToNextSolver,
65+
BoundVarKind, BoundVarKinds, Clause, Clauses, Const, DbInterner, EarlyBinder,
66+
EarlyParamRegion, ErrorGuaranteed, GenericArgs, PolyFnSig, Predicate, Region, SolverDefId,
67+
TraitPredicate, TraitRef, Ty, Tys, abi::Safety, generics::GenericParamDefKind,
68+
mapping::ChalkToNextSolver,
6869
},
6970
};
7071

@@ -1593,6 +1594,95 @@ fn fn_sig_for_enum_variant_constructor<'db>(
15931594
}))
15941595
}
15951596

1597+
pub(crate) fn associated_ty_item_bounds<'db>(
1598+
db: &'db dyn HirDatabase,
1599+
type_alias: TypeAliasId,
1600+
) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> {
1601+
let trait_ = match type_alias.lookup(db).container {
1602+
ItemContainerId::TraitId(t) => t,
1603+
_ => panic!("associated type not in trait"),
1604+
};
1605+
1606+
let type_alias_data = db.type_alias_signature(type_alias);
1607+
let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
1608+
let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
1609+
let mut ctx = TyLoweringContext::new(
1610+
db,
1611+
&resolver,
1612+
&type_alias_data.store,
1613+
type_alias.into(),
1614+
LifetimeElisionKind::AnonymousReportError,
1615+
);
1616+
// FIXME: we should never create non-existential predicates in the first place
1617+
// For now, use an error type so we don't run into dummy binder issues
1618+
let self_ty = Ty::new_error(interner, ErrorGuaranteed);
1619+
1620+
let mut bounds = Vec::new();
1621+
for bound in &type_alias_data.bounds {
1622+
ctx.lower_type_bound(bound, self_ty, false).for_each(|pred| {
1623+
if let Some(bound) = pred
1624+
.kind()
1625+
.map_bound(|c| match c {
1626+
rustc_type_ir::ClauseKind::Trait(t) => {
1627+
let id = t.def_id();
1628+
let id = match id {
1629+
SolverDefId::TraitId(id) => id,
1630+
_ => unreachable!(),
1631+
};
1632+
let is_auto = db.trait_signature(id).flags.contains(TraitFlags::AUTO);
1633+
if is_auto {
1634+
Some(ExistentialPredicate::AutoTrait(t.def_id()))
1635+
} else {
1636+
Some(ExistentialPredicate::Trait(ExistentialTraitRef::new_from_args(
1637+
interner,
1638+
t.def_id(),
1639+
GenericArgs::new_from_iter(
1640+
interner,
1641+
t.trait_ref.args.iter().skip(1),
1642+
),
1643+
)))
1644+
}
1645+
}
1646+
rustc_type_ir::ClauseKind::Projection(p) => Some(
1647+
ExistentialPredicate::Projection(ExistentialProjection::new_from_args(
1648+
interner,
1649+
p.def_id(),
1650+
GenericArgs::new_from_iter(
1651+
interner,
1652+
p.projection_term.args.iter().skip(1),
1653+
),
1654+
p.term,
1655+
)),
1656+
),
1657+
rustc_type_ir::ClauseKind::TypeOutlives(outlives_predicate) => None,
1658+
rustc_type_ir::ClauseKind::RegionOutlives(_)
1659+
| rustc_type_ir::ClauseKind::ConstArgHasType(_, _)
1660+
| rustc_type_ir::ClauseKind::WellFormed(_)
1661+
| rustc_type_ir::ClauseKind::ConstEvaluatable(_)
1662+
| rustc_type_ir::ClauseKind::HostEffect(_)
1663+
| rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(),
1664+
})
1665+
.transpose()
1666+
{
1667+
bounds.push(bound);
1668+
}
1669+
});
1670+
}
1671+
1672+
if !ctx.unsized_types.contains(&self_ty) {
1673+
let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate());
1674+
let sized_clause = Binder::dummy(ExistentialPredicate::Trait(ExistentialTraitRef::new(
1675+
interner,
1676+
SolverDefId::TraitId(trait_),
1677+
[] as [crate::next_solver::GenericArg<'_>; 0],
1678+
)));
1679+
bounds.push(sized_clause);
1680+
bounds.shrink_to_fit();
1681+
}
1682+
1683+
EarlyBinder::bind(BoundExistentialPredicates::new_from_iter(interner, bounds))
1684+
}
1685+
15961686
pub(crate) fn associated_type_by_name_including_super_traits<'db>(
15971687
db: &'db dyn HirDatabase,
15981688
trait_ref: TraitRef<'db>,

0 commit comments

Comments
 (0)