mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 13:51:31 +00:00
⬆️ rust-analyzer
This commit is contained in:
parent
459bbb4222
commit
f5fde4df43
76 changed files with 1613 additions and 654 deletions
|
@ -150,6 +150,14 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
|||
id: chalk_db::AssociatedTyValueId,
|
||||
) -> Arc<chalk_db::AssociatedTyValue>;
|
||||
|
||||
#[salsa::invoke(crate::traits::normalize_projection_query)]
|
||||
#[salsa::transparent]
|
||||
fn normalize_projection(
|
||||
&self,
|
||||
projection: crate::ProjectionTy,
|
||||
env: Arc<crate::TraitEnvironment>,
|
||||
) -> Ty;
|
||||
|
||||
#[salsa::invoke(trait_solve_wait)]
|
||||
#[salsa::transparent]
|
||||
fn trait_solve(
|
||||
|
|
|
@ -533,6 +533,7 @@ impl HirDisplay for Ty {
|
|||
f.db.upcast(),
|
||||
ItemInNs::Types((*def_id).into()),
|
||||
module_id,
|
||||
false,
|
||||
) {
|
||||
write!(f, "{}", path)?;
|
||||
} else {
|
||||
|
|
|
@ -673,10 +673,6 @@ impl<'a> InferenceContext<'a> {
|
|||
)
|
||||
}
|
||||
|
||||
fn resolve_obligations_as_possible(&mut self) {
|
||||
self.table.resolve_obligations_as_possible();
|
||||
}
|
||||
|
||||
fn push_obligation(&mut self, o: DomainGoal) {
|
||||
self.table.register_obligation(o.cast(Interner));
|
||||
}
|
||||
|
@ -696,7 +692,6 @@ impl<'a> InferenceContext<'a> {
|
|||
}
|
||||
|
||||
fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
|
||||
self.resolve_obligations_as_possible();
|
||||
self.table.resolve_ty_shallow(ty)
|
||||
}
|
||||
|
||||
|
|
|
@ -196,20 +196,6 @@ pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
|
|||
make_binders_with_count(db, usize::MAX, generics, value)
|
||||
}
|
||||
|
||||
// FIXME: get rid of this
|
||||
pub fn make_canonical<T: HasInterner<Interner = Interner>>(
|
||||
value: T,
|
||||
kinds: impl IntoIterator<Item = TyVariableKind>,
|
||||
) -> Canonical<T> {
|
||||
let kinds = kinds.into_iter().map(|tk| {
|
||||
chalk_ir::CanonicalVarKind::new(
|
||||
chalk_ir::VariableKind::Ty(tk),
|
||||
chalk_ir::UniverseIndex::ROOT,
|
||||
)
|
||||
});
|
||||
Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds) }
|
||||
}
|
||||
|
||||
// FIXME: get rid of this, just replace it by FnPointer
|
||||
/// A function signature as seen by type inference: Several parameter types and
|
||||
/// one return type.
|
||||
|
|
|
@ -914,22 +914,10 @@ fn iterate_trait_method_candidates(
|
|||
let db = table.db;
|
||||
let env = table.trait_env.clone();
|
||||
let self_is_array = matches!(self_ty.kind(Interner), chalk_ir::TyKind::Array(..));
|
||||
// if ty is `dyn Trait`, the trait doesn't need to be in scope
|
||||
let inherent_trait =
|
||||
self_ty.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
|
||||
let env_traits = matches!(self_ty.kind(Interner), TyKind::Placeholder(_))
|
||||
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope
|
||||
.then(|| {
|
||||
env.traits_in_scope_from_clauses(self_ty.clone())
|
||||
.flat_map(|t| all_super_traits(db.upcast(), t))
|
||||
})
|
||||
.into_iter()
|
||||
.flatten();
|
||||
let traits = inherent_trait.chain(env_traits).chain(traits_in_scope.iter().copied());
|
||||
|
||||
let canonical_self_ty = table.canonicalize(self_ty.clone()).value;
|
||||
|
||||
'traits: for t in traits {
|
||||
'traits: for &t in traits_in_scope {
|
||||
let data = db.trait_data(t);
|
||||
|
||||
// Traits annotated with `#[rustc_skip_array_during_method_dispatch]` are skipped during
|
||||
|
@ -979,6 +967,44 @@ fn iterate_inherent_methods(
|
|||
) -> ControlFlow<()> {
|
||||
let db = table.db;
|
||||
let env = table.trait_env.clone();
|
||||
|
||||
// For trait object types and placeholder types with trait bounds, the methods of the trait and
|
||||
// its super traits are considered inherent methods. This matters because these methods have
|
||||
// higher priority than the other traits' methods, which would be considered in
|
||||
// `iterate_trait_method_candidates()` only after this function.
|
||||
match self_ty.kind(Interner) {
|
||||
TyKind::Placeholder(_) => {
|
||||
let env = table.trait_env.clone();
|
||||
let traits = env
|
||||
.traits_in_scope_from_clauses(self_ty.clone())
|
||||
.flat_map(|t| all_super_traits(db.upcast(), t));
|
||||
iterate_inherent_trait_methods(
|
||||
self_ty,
|
||||
table,
|
||||
name,
|
||||
receiver_ty,
|
||||
receiver_adjustments.clone(),
|
||||
callback,
|
||||
traits,
|
||||
)?;
|
||||
}
|
||||
TyKind::Dyn(_) => {
|
||||
if let Some(principal_trait) = self_ty.dyn_trait() {
|
||||
let traits = all_super_traits(db.upcast(), principal_trait);
|
||||
iterate_inherent_trait_methods(
|
||||
self_ty,
|
||||
table,
|
||||
name,
|
||||
receiver_ty,
|
||||
receiver_adjustments.clone(),
|
||||
callback,
|
||||
traits.into_iter(),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let def_crates = match def_crates(db, self_ty, env.krate) {
|
||||
Some(k) => k,
|
||||
None => return ControlFlow::Continue(()),
|
||||
|
@ -1020,6 +1046,28 @@ fn iterate_inherent_methods(
|
|||
}
|
||||
return ControlFlow::Continue(());
|
||||
|
||||
fn iterate_inherent_trait_methods(
|
||||
self_ty: &Ty,
|
||||
table: &mut InferenceTable<'_>,
|
||||
name: Option<&Name>,
|
||||
receiver_ty: Option<&Ty>,
|
||||
receiver_adjustments: Option<ReceiverAdjustments>,
|
||||
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId) -> ControlFlow<()>,
|
||||
traits: impl Iterator<Item = TraitId>,
|
||||
) -> ControlFlow<()> {
|
||||
let db = table.db;
|
||||
for t in traits {
|
||||
let data = db.trait_data(t);
|
||||
for &(_, item) in data.items.iter() {
|
||||
// We don't pass `visible_from_module` as all trait items should be visible.
|
||||
if is_valid_candidate(table, name, receiver_ty, item, self_ty, None) {
|
||||
callback(receiver_adjustments.clone().unwrap_or_default(), item)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
fn impls_for_self_ty(
|
||||
impls: &InherentImpls,
|
||||
self_ty: &Ty,
|
||||
|
|
|
@ -1218,6 +1218,40 @@ fn main() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dyn_trait_method_priority() {
|
||||
check_types(
|
||||
r#"
|
||||
//- minicore: from
|
||||
trait Trait {
|
||||
fn into(&self) -> usize { 0 }
|
||||
}
|
||||
|
||||
fn foo(a: &dyn Trait) {
|
||||
let _ = a.into();
|
||||
//^usize
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trait_method_priority_for_placeholder_type() {
|
||||
check_types(
|
||||
r#"
|
||||
//- minicore: from
|
||||
trait Trait {
|
||||
fn into(&self) -> usize { 0 }
|
||||
}
|
||||
|
||||
fn foo<T: Trait>(a: &T) {
|
||||
let _ = a.into();
|
||||
//^usize
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn autoderef_visibility_field() {
|
||||
check(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Trait solving using Chalk.
|
||||
|
||||
use std::env::var;
|
||||
use std::{env::var, sync::Arc};
|
||||
|
||||
use chalk_ir::GoalData;
|
||||
use chalk_recursive::Cache;
|
||||
|
@ -12,8 +12,9 @@ use stdx::panic_context;
|
|||
use syntax::SmolStr;
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Goal, Guidance, InEnvironment,
|
||||
Interner, Solution, TraitRefExt, Ty, TyKind, WhereClause,
|
||||
db::HirDatabase, infer::unify::InferenceTable, AliasEq, AliasTy, Canonical, DomainGoal, Goal,
|
||||
Guidance, InEnvironment, Interner, ProjectionTy, Solution, TraitRefExt, Ty, TyKind,
|
||||
WhereClause,
|
||||
};
|
||||
|
||||
/// This controls how much 'time' we give the Chalk solver before giving up.
|
||||
|
@ -64,6 +65,16 @@ impl TraitEnvironment {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn normalize_projection_query(
|
||||
db: &dyn HirDatabase,
|
||||
projection: ProjectionTy,
|
||||
env: Arc<TraitEnvironment>,
|
||||
) -> Ty {
|
||||
let mut table = InferenceTable::new(db, env);
|
||||
let ty = table.normalize_projection_ty(projection);
|
||||
table.resolve_completely(ty)
|
||||
}
|
||||
|
||||
/// Solve a trait goal using Chalk.
|
||||
pub(crate) fn trait_solve_query(
|
||||
db: &dyn HirDatabase,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue