mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
fix: std::error::Error
is object unsafe
This commit is contained in:
parent
0ae42bd425
commit
231083958a
4 changed files with 45 additions and 21 deletions
|
@ -154,6 +154,9 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||||
#[salsa::invoke(crate::lower::generic_predicates_query)]
|
#[salsa::invoke(crate::lower::generic_predicates_query)]
|
||||||
fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates;
|
fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates;
|
||||||
|
|
||||||
|
#[salsa::invoke(crate::lower::generic_predicates_without_parent_query)]
|
||||||
|
fn generic_predicates_without_parent(&self, def: GenericDefId) -> GenericPredicates;
|
||||||
|
|
||||||
#[salsa::invoke(crate::lower::trait_environment_for_body_query)]
|
#[salsa::invoke(crate::lower::trait_environment_for_body_query)]
|
||||||
#[salsa::transparent]
|
#[salsa::transparent]
|
||||||
fn trait_environment_for_body(&self, def: DefWithBodyId) -> Arc<TraitEnvironment>;
|
fn trait_environment_for_body(&self, def: DefWithBodyId) -> Arc<TraitEnvironment>;
|
||||||
|
|
|
@ -1700,6 +1700,28 @@ pub(crate) fn generic_predicates_query(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
def: GenericDefId,
|
def: GenericDefId,
|
||||||
) -> GenericPredicates {
|
) -> GenericPredicates {
|
||||||
|
generic_predicates_filtered_by(db, def, |_, _| true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolve the where clause(s) of an item with generics,
|
||||||
|
/// except the ones inherited from the parent
|
||||||
|
pub(crate) fn generic_predicates_without_parent_query(
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
def: GenericDefId,
|
||||||
|
) -> GenericPredicates {
|
||||||
|
generic_predicates_filtered_by(db, def, |_, d| *d == def)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolve the where clause(s) of an item with generics,
|
||||||
|
/// except the ones inherited from the parent
|
||||||
|
fn generic_predicates_filtered_by<F>(
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
def: GenericDefId,
|
||||||
|
filter: F,
|
||||||
|
) -> GenericPredicates
|
||||||
|
where
|
||||||
|
F: Fn(&WherePredicate, &GenericDefId) -> bool,
|
||||||
|
{
|
||||||
let resolver = def.resolver(db.upcast());
|
let resolver = def.resolver(db.upcast());
|
||||||
let (impl_trait_lowering, param_lowering) = match def {
|
let (impl_trait_lowering, param_lowering) = match def {
|
||||||
GenericDefId::FunctionId(_) => {
|
GenericDefId::FunctionId(_) => {
|
||||||
|
@ -1714,6 +1736,7 @@ pub(crate) fn generic_predicates_query(
|
||||||
|
|
||||||
let mut predicates = resolver
|
let mut predicates = resolver
|
||||||
.where_predicates_in_scope()
|
.where_predicates_in_scope()
|
||||||
|
.filter(|(pred, def)| filter(pred, def))
|
||||||
.flat_map(|(pred, def)| {
|
.flat_map(|(pred, def)| {
|
||||||
ctx.lower_where_predicate(pred, def, false).map(|p| make_binders(db, &generics, p))
|
ctx.lower_where_predicate(pred, def, false).map(|p| make_binders(db, &generics, p))
|
||||||
})
|
})
|
||||||
|
|
|
@ -12,7 +12,7 @@ use hir_def::{
|
||||||
lang_item::LangItem, AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId,
|
lang_item::LangItem, AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId,
|
||||||
TypeAliasId,
|
TypeAliasId,
|
||||||
};
|
};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::FxHashSet;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -417,30 +417,11 @@ where
|
||||||
cb(MethodViolationCode::UndispatchableReceiver)?;
|
cb(MethodViolationCode::UndispatchableReceiver)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let predicates = &*db.generic_predicates(func.into());
|
let predicates = &*db.generic_predicates_without_parent(func.into());
|
||||||
let mut parent_predicates = (*db.generic_predicates(trait_.into()))
|
|
||||||
.iter()
|
|
||||||
.map(|b| b.skip_binders().skip_binders().clone())
|
|
||||||
.fold(FxHashMap::default(), |mut acc, item| {
|
|
||||||
acc.entry(item)
|
|
||||||
.and_modify(|cnt| {
|
|
||||||
*cnt += 1;
|
|
||||||
})
|
|
||||||
.or_insert(1);
|
|
||||||
acc
|
|
||||||
});
|
|
||||||
let trait_self_idx = trait_self_param_idx(db.upcast(), func.into());
|
let trait_self_idx = trait_self_param_idx(db.upcast(), func.into());
|
||||||
for pred in predicates {
|
for pred in predicates {
|
||||||
let pred = pred.skip_binders().skip_binders();
|
let pred = pred.skip_binders().skip_binders();
|
||||||
|
|
||||||
// Skip predicates from parent, i.e. the trait that contains this method
|
|
||||||
if let Some(cnt) = parent_predicates.get_mut(pred) {
|
|
||||||
if *cnt > 0 {
|
|
||||||
*cnt -= 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if matches!(pred, WhereClause::TypeOutlives(_)) {
|
if matches!(pred, WhereClause::TypeOutlives(_)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -361,3 +361,20 @@ pub trait Trait {
|
||||||
[("Trait", vec![])],
|
[("Trait", vec![])],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn std_error_is_object_safe() {
|
||||||
|
check_object_safety(
|
||||||
|
r#"
|
||||||
|
//- minicore: fmt, dispatch_from_dyn
|
||||||
|
trait Erased<'a>: 'a {}
|
||||||
|
|
||||||
|
pub struct Request<'a>(dyn Erased<'a> + 'a);
|
||||||
|
|
||||||
|
pub trait Error: core::fmt::Debug + core::fmt::Display {
|
||||||
|
fn provide<'a>(&'a self, request: &mut Request<'a>);
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
[("Error", vec![])],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue