Merge #8440
8440: Fix crash on syn involving lifetimes returned by Chalk r=flodiebold a=flodiebold If we get lifetime variables back in autoderef, just immediately replace them by static lifetimes for now. Method resolution doesn't really deal correctly with new variables being introduced (this needs to be fixed more properly). This fixes `rust-analyzer analysis-stats --with-deps` crashing in the RA repo. Co-authored-by: Florian Diebold <flodiebold@gmail.com>
This commit is contained in:
commit
b058cb3f65
crates/hir_ty/src
@ -6,14 +6,15 @@
|
||||
use std::iter::successors;
|
||||
|
||||
use base_db::CrateId;
|
||||
use chalk_ir::cast::Cast;
|
||||
use chalk_ir::{cast::Cast, fold::Fold, interner::HasInterner, VariableKind};
|
||||
use hir_def::lang_item::LangItemTarget;
|
||||
use hir_expand::name::name;
|
||||
use log::{info, warn};
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex,
|
||||
InEnvironment, Interner, ProjectionTyExt, Solution, Ty, TyBuilder, TyKind,
|
||||
db::HirDatabase, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds,
|
||||
DebruijnIndex, InEnvironment, Interner, ProjectionTyExt, Solution, Substitution, Ty, TyBuilder,
|
||||
TyKind,
|
||||
};
|
||||
|
||||
const AUTODEREF_RECURSION_LIMIT: usize = 10;
|
||||
@ -103,7 +104,7 @@ fn deref_by_trait(
|
||||
binders: CanonicalVarKinds::from_iter(
|
||||
&Interner,
|
||||
ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new(
|
||||
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
|
||||
VariableKind::Ty(chalk_ir::TyVariableKind::General),
|
||||
chalk_ir::UniverseIndex::ROOT,
|
||||
))),
|
||||
),
|
||||
@ -136,7 +137,9 @@ fn deref_by_trait(
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(Canonical {
|
||||
// FIXME: we remove lifetime variables here since they can confuse
|
||||
// the method resolution code later
|
||||
Some(fixup_lifetime_variables(Canonical {
|
||||
value: vars
|
||||
.value
|
||||
.subst
|
||||
@ -144,7 +147,7 @@ fn deref_by_trait(
|
||||
.assert_ty_ref(&Interner)
|
||||
.clone(),
|
||||
binders: vars.binders.clone(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
Solution::Ambig(_) => {
|
||||
info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution);
|
||||
@ -152,3 +155,32 @@ fn deref_by_trait(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fixup_lifetime_variables<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>(
|
||||
c: Canonical<T>,
|
||||
) -> Canonical<T> {
|
||||
// Removes lifetime variables from the Canonical, replacing them by static lifetimes.
|
||||
let mut i = 0;
|
||||
let subst = Substitution::from_iter(
|
||||
&Interner,
|
||||
c.binders.iter(&Interner).map(|vk| match vk.kind {
|
||||
VariableKind::Ty(_) => {
|
||||
let index = i;
|
||||
i += 1;
|
||||
BoundVar::new(DebruijnIndex::INNERMOST, index).to_ty(&Interner).cast(&Interner)
|
||||
}
|
||||
VariableKind::Lifetime => static_lifetime().cast(&Interner),
|
||||
VariableKind::Const(_) => unimplemented!(),
|
||||
}),
|
||||
);
|
||||
let binders = CanonicalVarKinds::from_iter(
|
||||
&Interner,
|
||||
c.binders.iter(&Interner).filter(|vk| match vk.kind {
|
||||
VariableKind::Ty(_) => true,
|
||||
VariableKind::Lifetime => false,
|
||||
VariableKind::Const(_) => true,
|
||||
}),
|
||||
);
|
||||
let value = subst.apply(c.value, &Interner);
|
||||
Canonical { binders, value }
|
||||
}
|
||||
|
@ -609,6 +609,7 @@ fn iterate_trait_method_candidates(
|
||||
}
|
||||
}
|
||||
known_implemented = true;
|
||||
// FIXME: we shouldn't be ignoring the binders here
|
||||
if callback(&self_ty.value, *item) {
|
||||
return true;
|
||||
}
|
||||
|
@ -974,3 +974,41 @@ fn param_overrides_fn() {
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lifetime_from_chalk_during_deref() {
|
||||
check_types(
|
||||
r#"
|
||||
#[lang = "deref"]
|
||||
pub trait Deref {
|
||||
type Target;
|
||||
}
|
||||
|
||||
struct Box<T: ?Sized> {}
|
||||
impl<T> Deref for Box<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
trait Iterator {
|
||||
type Item;
|
||||
}
|
||||
|
||||
pub struct Iter<'a, T: 'a> {
|
||||
inner: Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>,
|
||||
}
|
||||
|
||||
trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> {
|
||||
fn clone_box(&self);
|
||||
}
|
||||
|
||||
fn clone_iter<T>(s: Iter<T>) {
|
||||
s.inner.clone_box();
|
||||
//^^^^^^^^^^^^^^^^^^^ ()
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user