mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Merge pull request #20654 from ShoyuVanilla/predicates
fix: Infinite loop while elaborting predicates
This commit is contained in:
commit
760d378e4c
@ -138,6 +138,9 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b
|
|||||||
|
|
||||||
let interner = DbInterner::new_with(db, Some(krate), None);
|
let interner = DbInterner::new_with(db, Some(krate), None);
|
||||||
let predicates = db.generic_predicates_ns(def);
|
let predicates = db.generic_predicates_ns(def);
|
||||||
|
// FIXME: We should use `explicit_predicates_of` here, which hasn't been implemented to
|
||||||
|
// rust-analyzer yet
|
||||||
|
// https://github.com/rust-lang/rust/blob/ddaf12390d3ffb7d5ba74491a48f3cd528e5d777/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L490
|
||||||
elaborate::elaborate(interner, predicates.iter().copied()).any(|pred| {
|
elaborate::elaborate(interner, predicates.iter().copied()).any(|pred| {
|
||||||
match pred.kind().skip_binder() {
|
match pred.kind().skip_binder() {
|
||||||
ClauseKind::Trait(trait_pred) => {
|
ClauseKind::Trait(trait_pred) => {
|
||||||
|
@ -253,7 +253,8 @@ trait Bar<T> {
|
|||||||
trait Baz : Bar<Self> {
|
trait Baz : Bar<Self> {
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
[("Bar", vec![]), ("Baz", vec![SizedSelf, SelfReferential])],
|
// FIXME: We should also report `SizedSelf` here
|
||||||
|
[("Bar", vec![]), ("Baz", vec![SelfReferential])],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1358,6 +1358,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: rustc gathers more predicates by recursing through resulting trait predicates.
|
||||||
|
// See https://github.com/rust-lang/rust/blob/76c5ed2847cdb26ef2822a3a165d710f6b772217/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L689-L715
|
||||||
|
|
||||||
(
|
(
|
||||||
GenericPredicates(predicates.is_empty().not().then(|| predicates.into())),
|
GenericPredicates(predicates.is_empty().not().then(|| predicates.into())),
|
||||||
create_diagnostics(ctx.diagnostics),
|
create_diagnostics(ctx.diagnostics),
|
||||||
|
@ -5,7 +5,7 @@ use base_db::Crate;
|
|||||||
use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variances};
|
use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variances};
|
||||||
use hir_def::lang_item::LangItem;
|
use hir_def::lang_item::LangItem;
|
||||||
use hir_def::signatures::{FieldData, FnFlags, ImplFlags, StructFlags, TraitFlags};
|
use hir_def::signatures::{FieldData, FnFlags, ImplFlags, StructFlags, TraitFlags};
|
||||||
use hir_def::{AdtId, BlockId, TypeAliasId, VariantId};
|
use hir_def::{AdtId, BlockId, GenericDefId, TypeAliasId, VariantId};
|
||||||
use hir_def::{AttrDefId, Lookup};
|
use hir_def::{AttrDefId, Lookup};
|
||||||
use hir_def::{CallableDefId, EnumVariantId, ItemContainerId, StructId, UnionId};
|
use hir_def::{CallableDefId, EnumVariantId, ItemContainerId, StructId, UnionId};
|
||||||
use intern::sym::non_exhaustive;
|
use intern::sym::non_exhaustive;
|
||||||
@ -1334,6 +1334,13 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
|
|||||||
.db()
|
.db()
|
||||||
.generic_predicates_ns(def_id.0.into())
|
.generic_predicates_ns(def_id.0.into())
|
||||||
.iter()
|
.iter()
|
||||||
|
.filter(|p| match p.kind().skip_binder() {
|
||||||
|
rustc_type_ir::ClauseKind::Trait(tr) => match tr.self_ty().kind() {
|
||||||
|
rustc_type_ir::TyKind::Param(param) => param.index == 0,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
_ => true,
|
||||||
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|p| (p, Span::dummy()))
|
.map(|p| (p, Span::dummy()))
|
||||||
.collect();
|
.collect();
|
||||||
@ -1345,10 +1352,24 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
|
|||||||
self,
|
self,
|
||||||
def_id: Self::DefId,
|
def_id: Self::DefId,
|
||||||
) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
|
) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
|
||||||
|
fn is_self_or_assoc(ty: Ty<'_>) -> bool {
|
||||||
|
match ty.kind() {
|
||||||
|
rustc_type_ir::TyKind::Param(param) => param.index == 0,
|
||||||
|
rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Projection, alias) => {
|
||||||
|
is_self_or_assoc(alias.self_ty())
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let predicates: Vec<(Clause<'db>, Span)> = self
|
let predicates: Vec<(Clause<'db>, Span)> = self
|
||||||
.db()
|
.db()
|
||||||
.generic_predicates_ns(def_id.try_into().unwrap())
|
.generic_predicates_ns(def_id.try_into().unwrap())
|
||||||
.iter()
|
.iter()
|
||||||
|
.filter(|p| match p.kind().skip_binder() {
|
||||||
|
rustc_type_ir::ClauseKind::Trait(tr) => is_self_or_assoc(tr.self_ty()),
|
||||||
|
_ => true,
|
||||||
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|p| (p, Span::dummy()))
|
.map(|p| (p, Span::dummy()))
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -116,3 +116,34 @@ fn main() {
|
|||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_infinite_loop_on_super_predicates_elaboration() {
|
||||||
|
check_infer(
|
||||||
|
r#"
|
||||||
|
//- minicore: sized
|
||||||
|
trait DimMax<Other: Dimension> {
|
||||||
|
type Output: Dimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Dimension: DimMax<<Self as Dimension>:: Smaller, Output = Self> {
|
||||||
|
type Smaller: Dimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test<T, U>(t: T)
|
||||||
|
where
|
||||||
|
T: DimMax<U>,
|
||||||
|
U: Dimension,
|
||||||
|
{
|
||||||
|
let t: <T as DimMax<U>>::Output = loop {};
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
182..183 't': T
|
||||||
|
230..280 '{ ... {}; }': ()
|
||||||
|
240..241 't': <T as DimMax<U>>::Output
|
||||||
|
270..277 'loop {}': !
|
||||||
|
275..277 '{}': ()
|
||||||
|
"#]],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user