Ignore type bindings in generic_predicates_for_param

This allows us to handle more cases without a query cycle, which
includes certain cases that rustc accepted. That in turn means we avoid
triggering salsa-rs/salsa#257 on valid code (it will still happen if the
user writes an actual cycle).

We actually accept more definitions than rustc now; that's because rustc
only ignores bindings when looking up super traits, whereas we now also
ignore them when looking for predicates to disambiguate associated type
shorthand. We could introduce a separate query for super traits if
necessary, but for now I think this should be fine.
This commit is contained in:
Florian Diebold 2021-03-20 20:07:36 +01:00
parent 0623bb4d71
commit d8f8b495ad
6 changed files with 52 additions and 19 deletions

View file

@ -571,13 +571,22 @@ impl HirDisplay for Ty {
write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
}
TypeParamProvenance::ArgumentImplTrait => {
let bounds = f.db.generic_predicates_for_param(id);
let substs = Substitution::type_params_for_generics(f.db, &generics);
write_bounds_like_dyn_trait_with_prefix(
"impl",
&bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(),
f,
)?;
let bounds = f
.db
.generic_predicates(id.parent)
.into_iter()
.map(|pred| pred.clone().subst(&substs))
.filter(|wc| match &wc {
WhereClause::Implemented(tr) => tr.self_type_parameter() == self,
WhereClause::AliasEq(AliasEq {
alias: AliasTy::Projection(proj),
ty: _,
}) => proj.self_type_parameter() == self,
_ => false,
})
.collect::<Vec<_>>();
write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?;
}
}
}