mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
Auto merge of #14424 - Veykril:local-trait-impls, r=Veykril
fix: Properly handle local trait impls Before we only handled trait impls that came from the block of either the trait or the target type, we now handle them correctly by tracking the block we are currently inferring from, then walking that up to collect all block trait impls.
This commit is contained in:
commit
f73510560f
@ -93,6 +93,8 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
|
||||
///
|
||||
/// The `block_def_map` for block 0 would return `None`, while `block_def_map` of block 1 would
|
||||
/// return a `DefMap` containing `inner`.
|
||||
// FIXME: This actually can't return None anymore as we no longer allocate block scopes for
|
||||
// non item declaring blocks
|
||||
#[salsa::invoke(DefMap::block_def_map_query)]
|
||||
fn block_def_map(&self, block: BlockId) -> Option<Arc<DefMap>>;
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
//! The implementation of `RustIrDatabase` for Chalk, which provides information
|
||||
//! about the code that Chalk needs.
|
||||
use std::sync::Arc;
|
||||
use std::{iter, sync::Arc};
|
||||
|
||||
use cov_mark::hit;
|
||||
use tracing::debug;
|
||||
|
||||
use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds};
|
||||
@ -12,17 +11,16 @@ use base_db::CrateId;
|
||||
use hir_def::{
|
||||
expr::Movability,
|
||||
lang_item::{lang_attr, LangItem, LangItemTarget},
|
||||
AssocItemId, GenericDefId, HasModule, ItemContainerId, Lookup, ModuleId, TypeAliasId,
|
||||
AssocItemId, BlockId, GenericDefId, HasModule, ItemContainerId, Lookup, TypeAliasId,
|
||||
};
|
||||
use hir_expand::name::name;
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
display::HirDisplay,
|
||||
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, make_binders,
|
||||
make_single_type_binders,
|
||||
from_assoc_type_id, from_chalk_trait_id, make_binders, make_single_type_binders,
|
||||
mapping::{from_chalk, ToChalk, TypeAliasAsValue},
|
||||
method_resolution::{TraitImpls, TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
|
||||
method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
|
||||
to_assoc_type_id, to_chalk_trait_id,
|
||||
traits::ChalkContext,
|
||||
utils::generics,
|
||||
@ -108,53 +106,41 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
||||
_ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]),
|
||||
};
|
||||
|
||||
fn local_impls(db: &dyn HirDatabase, module: ModuleId) -> Option<Arc<TraitImpls>> {
|
||||
let block = module.containing_block()?;
|
||||
hit!(block_local_impls);
|
||||
db.trait_impls_in_block(block)
|
||||
}
|
||||
|
||||
// Note: Since we're using impls_for_trait, only impls where the trait
|
||||
// can be resolved should ever reach Chalk. impl_datum relies on that
|
||||
// and will panic if the trait can't be resolved.
|
||||
let in_deps = self.db.trait_impls_in_deps(self.krate);
|
||||
let in_self = self.db.trait_impls_in_crate(self.krate);
|
||||
let trait_module = trait_.module(self.db.upcast());
|
||||
let type_module = match self_ty_fp {
|
||||
Some(TyFingerprint::Adt(adt_id)) => Some(adt_id.module(self.db.upcast())),
|
||||
Some(TyFingerprint::ForeignType(type_id)) => {
|
||||
Some(from_foreign_def_id(type_id).module(self.db.upcast()))
|
||||
}
|
||||
Some(TyFingerprint::Dyn(trait_id)) => Some(trait_id.module(self.db.upcast())),
|
||||
_ => None,
|
||||
};
|
||||
let impl_maps = [
|
||||
Some(in_deps),
|
||||
Some(in_self),
|
||||
local_impls(self.db, trait_module),
|
||||
type_module.and_then(|m| local_impls(self.db, m)),
|
||||
];
|
||||
|
||||
let impl_maps = [in_deps, in_self];
|
||||
let block_impls = iter::successors(self.block, |&block_id| {
|
||||
cov_mark::hit!(block_local_impls);
|
||||
self.db
|
||||
.block_def_map(block_id)
|
||||
.and_then(|map| map.parent())
|
||||
.and_then(|module| module.containing_block())
|
||||
})
|
||||
.filter_map(|block_id| self.db.trait_impls_in_block(block_id));
|
||||
|
||||
let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db);
|
||||
|
||||
let result: Vec<_> = if fps.is_empty() {
|
||||
debug!("Unrestricted search for {:?} impls...", trait_);
|
||||
impl_maps
|
||||
.iter()
|
||||
.filter_map(|o| o.as_ref())
|
||||
.flat_map(|impls| impls.for_trait(trait_).map(id_to_chalk))
|
||||
.collect()
|
||||
} else {
|
||||
impl_maps
|
||||
.iter()
|
||||
.filter_map(|o| o.as_ref())
|
||||
.flat_map(|impls| {
|
||||
fps.iter().flat_map(move |fp| {
|
||||
impls.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk)
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
let mut result = vec![];
|
||||
match fps {
|
||||
[] => {
|
||||
debug!("Unrestricted search for {:?} impls...", trait_);
|
||||
impl_maps.into_iter().chain(block_impls).for_each(|impls| {
|
||||
result.extend(impls.for_trait(trait_).map(id_to_chalk));
|
||||
});
|
||||
}
|
||||
fps => {
|
||||
impl_maps.into_iter().chain(block_impls).for_each(|impls| {
|
||||
result.extend(
|
||||
fps.iter().flat_map(|fp| {
|
||||
impls.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk)
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
debug!("impls_for_trait returned {} impls", result.len());
|
||||
result
|
||||
@ -193,7 +179,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
||||
&self,
|
||||
environment: &chalk_ir::Environment<Interner>,
|
||||
) -> chalk_ir::ProgramClauses<Interner> {
|
||||
self.db.program_clauses_for_chalk_env(self.krate, environment.clone())
|
||||
self.db.program_clauses_for_chalk_env(self.krate, self.block, environment.clone())
|
||||
}
|
||||
|
||||
fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatum> {
|
||||
@ -451,9 +437,10 @@ impl<'a> chalk_ir::UnificationDatabase<Interner> for &'a dyn HirDatabase {
|
||||
pub(crate) fn program_clauses_for_chalk_env_query(
|
||||
db: &dyn HirDatabase,
|
||||
krate: CrateId,
|
||||
block: Option<BlockId>,
|
||||
environment: chalk_ir::Environment<Interner>,
|
||||
) -> chalk_ir::ProgramClauses<Interner> {
|
||||
chalk_solve::program_clauses_for_env(&ChalkContext { db, krate }, &environment)
|
||||
chalk_solve::program_clauses_for_env(&ChalkContext { db, krate, block }, &environment)
|
||||
}
|
||||
|
||||
pub(crate) fn associated_ty_data_query(
|
||||
|
@ -129,7 +129,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>;
|
||||
|
||||
#[salsa::invoke(TraitImpls::trait_impls_in_block_query)]
|
||||
fn trait_impls_in_block(&self, krate: BlockId) -> Option<Arc<TraitImpls>>;
|
||||
fn trait_impls_in_block(&self, block: BlockId) -> Option<Arc<TraitImpls>>;
|
||||
|
||||
#[salsa::invoke(TraitImpls::trait_impls_in_deps_query)]
|
||||
fn trait_impls_in_deps(&self, krate: CrateId) -> Arc<TraitImpls>;
|
||||
@ -197,6 +197,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
fn trait_solve(
|
||||
&self,
|
||||
krate: CrateId,
|
||||
block: Option<BlockId>,
|
||||
goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
|
||||
) -> Option<crate::Solution>;
|
||||
|
||||
@ -204,6 +205,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
fn trait_solve_query(
|
||||
&self,
|
||||
krate: CrateId,
|
||||
block: Option<BlockId>,
|
||||
goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
|
||||
) -> Option<crate::Solution>;
|
||||
|
||||
@ -211,6 +213,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
fn program_clauses_for_chalk_env(
|
||||
&self,
|
||||
krate: CrateId,
|
||||
block: Option<BlockId>,
|
||||
env: chalk_ir::Environment<Interner>,
|
||||
) -> chalk_ir::ProgramClauses<Interner>;
|
||||
}
|
||||
@ -232,10 +235,11 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult>
|
||||
fn trait_solve_wait(
|
||||
db: &dyn HirDatabase,
|
||||
krate: CrateId,
|
||||
block: Option<BlockId>,
|
||||
goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
|
||||
) -> Option<crate::Solution> {
|
||||
let _p = profile::span("trait_solve::wait");
|
||||
db.trait_solve_query(krate, goal)
|
||||
db.trait_solve_query(krate, block, goal)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -40,7 +40,7 @@ use crate::{
|
||||
db::HirDatabase, fold_tys, fold_tys_and_consts, infer::coerce::CoerceMany,
|
||||
lower::ImplTraitLoweringMode, static_lifetime, to_assoc_type_id, AliasEq, AliasTy, Const,
|
||||
DomainGoal, GenericArg, Goal, ImplTraitId, InEnvironment, Interner, ProjectionTy, RpitId,
|
||||
Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind,
|
||||
Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
|
||||
};
|
||||
|
||||
// This lint has a false positive here. See the link below for details.
|
||||
@ -442,7 +442,6 @@ pub(crate) struct InferenceContext<'a> {
|
||||
pub(crate) body: &'a Body,
|
||||
pub(crate) resolver: Resolver,
|
||||
table: unify::InferenceTable<'a>,
|
||||
trait_env: Arc<TraitEnvironment>,
|
||||
/// The traits in scope, disregarding block modules. This is used for caching purposes.
|
||||
traits_in_scope: FxHashSet<TraitId>,
|
||||
pub(crate) result: InferenceResult,
|
||||
@ -516,8 +515,7 @@ impl<'a> InferenceContext<'a> {
|
||||
let trait_env = db.trait_environment_for_body(owner);
|
||||
InferenceContext {
|
||||
result: InferenceResult::default(),
|
||||
table: unify::InferenceTable::new(db, trait_env.clone()),
|
||||
trait_env,
|
||||
table: unify::InferenceTable::new(db, trait_env),
|
||||
return_ty: TyKind::Error.intern(Interner), // set in collect_* calls
|
||||
resume_yield_tys: None,
|
||||
return_coercion: None,
|
||||
|
@ -636,7 +636,7 @@ impl<'a> InferenceTable<'a> {
|
||||
// Need to find out in what cases this is necessary
|
||||
let solution = self
|
||||
.db
|
||||
.trait_solve(krate, canonicalized.value.clone().cast(Interner))
|
||||
.trait_solve(krate, self.trait_env.block, canonicalized.value.clone().cast(Interner))
|
||||
.ok_or(TypeError)?;
|
||||
|
||||
match solution {
|
||||
|
@ -3,6 +3,7 @@
|
||||
use std::{
|
||||
iter::{repeat, repeat_with},
|
||||
mem,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use chalk_ir::{
|
||||
@ -15,7 +16,7 @@ use hir_def::{
|
||||
generics::TypeOrConstParamData,
|
||||
lang_item::LangItem,
|
||||
path::{GenericArg, GenericArgs},
|
||||
ConstParamId, FieldId, ItemContainerId, Lookup,
|
||||
BlockId, ConstParamId, FieldId, ItemContainerId, Lookup,
|
||||
};
|
||||
use hir_expand::name::{name, Name};
|
||||
use stdx::always;
|
||||
@ -147,19 +148,19 @@ impl<'a> InferenceContext<'a> {
|
||||
self.infer_top_pat(pat, &input_ty);
|
||||
self.result.standard_types.bool_.clone()
|
||||
}
|
||||
Expr::Block { statements, tail, label, id: _ } => {
|
||||
self.infer_block(tgt_expr, statements, *tail, *label, expected)
|
||||
Expr::Block { statements, tail, label, id } => {
|
||||
self.infer_block(tgt_expr, *id, statements, *tail, *label, expected)
|
||||
}
|
||||
Expr::Unsafe { id: _, statements, tail } => {
|
||||
self.infer_block(tgt_expr, statements, *tail, None, expected)
|
||||
Expr::Unsafe { id, statements, tail } => {
|
||||
self.infer_block(tgt_expr, *id, statements, *tail, None, expected)
|
||||
}
|
||||
Expr::Const { id: _, statements, tail } => {
|
||||
Expr::Const { id, statements, tail } => {
|
||||
self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
|
||||
this.infer_block(tgt_expr, statements, *tail, None, expected)
|
||||
this.infer_block(tgt_expr, *id, statements, *tail, None, expected)
|
||||
})
|
||||
.1
|
||||
}
|
||||
Expr::Async { id: _, statements, tail } => {
|
||||
Expr::Async { id, statements, tail } => {
|
||||
let ret_ty = self.table.new_type_var();
|
||||
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
||||
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
|
||||
@ -170,6 +171,7 @@ impl<'a> InferenceContext<'a> {
|
||||
self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
|
||||
this.infer_block(
|
||||
tgt_expr,
|
||||
*id,
|
||||
statements,
|
||||
*tail,
|
||||
None,
|
||||
@ -394,7 +396,7 @@ impl<'a> InferenceContext<'a> {
|
||||
}
|
||||
}
|
||||
let trait_ = fn_x
|
||||
.get_id(self.db, self.trait_env.krate)
|
||||
.get_id(self.db, self.table.trait_env.krate)
|
||||
.expect("We just used it");
|
||||
let trait_data = self.db.trait_data(trait_);
|
||||
if let Some(func) = trait_data.method_by_name(&fn_x.method_name()) {
|
||||
@ -787,7 +789,7 @@ impl<'a> InferenceContext<'a> {
|
||||
let canonicalized = self.canonicalize(base_ty.clone());
|
||||
let receiver_adjustments = method_resolution::resolve_indexing_op(
|
||||
self.db,
|
||||
self.trait_env.clone(),
|
||||
self.table.trait_env.clone(),
|
||||
canonicalized.value,
|
||||
index_trait,
|
||||
);
|
||||
@ -1205,6 +1207,7 @@ impl<'a> InferenceContext<'a> {
|
||||
fn infer_block(
|
||||
&mut self,
|
||||
expr: ExprId,
|
||||
block_id: Option<BlockId>,
|
||||
statements: &[Statement],
|
||||
tail: Option<ExprId>,
|
||||
label: Option<LabelId>,
|
||||
@ -1212,6 +1215,11 @@ impl<'a> InferenceContext<'a> {
|
||||
) -> Ty {
|
||||
let coerce_ty = expected.coercion_target_type(&mut self.table);
|
||||
let g = self.resolver.update_to_inner_scope(self.db.upcast(), self.owner, expr);
|
||||
let prev_env = block_id.map(|block_id| {
|
||||
let prev_env = self.table.trait_env.clone();
|
||||
Arc::make_mut(&mut self.table.trait_env).block = Some(block_id);
|
||||
prev_env
|
||||
});
|
||||
|
||||
let (break_ty, ty) =
|
||||
self.with_breakable_ctx(BreakableKind::Block, Some(coerce_ty.clone()), label, |this| {
|
||||
@ -1300,6 +1308,9 @@ impl<'a> InferenceContext<'a> {
|
||||
}
|
||||
});
|
||||
self.resolver.reset_to_guard(g);
|
||||
if let Some(prev_env) = prev_env {
|
||||
self.table.trait_env = prev_env;
|
||||
}
|
||||
|
||||
break_ty.unwrap_or(ty)
|
||||
}
|
||||
@ -1398,7 +1409,7 @@ impl<'a> InferenceContext<'a> {
|
||||
method_resolution::lookup_method(
|
||||
self.db,
|
||||
&canonicalized_receiver.value,
|
||||
self.trait_env.clone(),
|
||||
self.table.trait_env.clone(),
|
||||
self.get_traits_in_scope().as_ref().left_or_else(|&it| it),
|
||||
VisibleFromModule::Filter(self.resolver.module()),
|
||||
name,
|
||||
@ -1431,7 +1442,7 @@ impl<'a> InferenceContext<'a> {
|
||||
let resolved = method_resolution::lookup_method(
|
||||
self.db,
|
||||
&canonicalized_receiver.value,
|
||||
self.trait_env.clone(),
|
||||
self.table.trait_env.clone(),
|
||||
self.get_traits_in_scope().as_ref().left_or_else(|&it| it),
|
||||
VisibleFromModule::Filter(self.resolver.module()),
|
||||
method_name,
|
||||
|
@ -462,7 +462,8 @@ impl<'a> InferenceTable<'a> {
|
||||
pub(crate) fn try_obligation(&mut self, goal: Goal) -> Option<Solution> {
|
||||
let in_env = InEnvironment::new(&self.trait_env.env, goal);
|
||||
let canonicalized = self.canonicalize(in_env);
|
||||
let solution = self.db.trait_solve(self.trait_env.krate, canonicalized.value);
|
||||
let solution =
|
||||
self.db.trait_solve(self.trait_env.krate, self.trait_env.block, canonicalized.value);
|
||||
solution
|
||||
}
|
||||
|
||||
@ -597,7 +598,11 @@ impl<'a> InferenceTable<'a> {
|
||||
&mut self,
|
||||
canonicalized: &Canonicalized<InEnvironment<Goal>>,
|
||||
) -> bool {
|
||||
let solution = self.db.trait_solve(self.trait_env.krate, canonicalized.value.clone());
|
||||
let solution = self.db.trait_solve(
|
||||
self.trait_env.krate,
|
||||
self.trait_env.block,
|
||||
canonicalized.value.clone(),
|
||||
);
|
||||
|
||||
match solution {
|
||||
Some(Solution::Unique(canonical_subst)) => {
|
||||
@ -684,7 +689,11 @@ impl<'a> InferenceTable<'a> {
|
||||
environment: trait_env.clone(),
|
||||
};
|
||||
let canonical = self.canonicalize(obligation.clone());
|
||||
if self.db.trait_solve(krate, canonical.value.cast(Interner)).is_some() {
|
||||
if self
|
||||
.db
|
||||
.trait_solve(krate, self.trait_env.block, canonical.value.cast(Interner))
|
||||
.is_some()
|
||||
{
|
||||
self.register_obligation(obligation.goal);
|
||||
let return_ty = self.normalize_projection_ty(projection);
|
||||
for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
|
||||
@ -695,7 +704,11 @@ impl<'a> InferenceTable<'a> {
|
||||
environment: trait_env.clone(),
|
||||
};
|
||||
let canonical = self.canonicalize(obligation.clone());
|
||||
if self.db.trait_solve(krate, canonical.value.cast(Interner)).is_some() {
|
||||
if self
|
||||
.db
|
||||
.trait_solve(krate, self.trait_env.block, canonical.value.cast(Interner))
|
||||
.is_some()
|
||||
{
|
||||
return Some((fn_x, arg_tys, return_ty));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
//! The type system. We currently use this to infer types for completion, hover
|
||||
//! information and various assists.
|
||||
|
||||
#![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
|
||||
|
||||
#[allow(unused)]
|
||||
|
@ -1507,7 +1507,7 @@ pub(crate) fn trait_environment_query(
|
||||
|
||||
let env = chalk_ir::Environment::new(Interner).add_clauses(Interner, clauses);
|
||||
|
||||
Arc::new(TraitEnvironment { krate, traits_from_clauses: traits_in_scope, env })
|
||||
Arc::new(TraitEnvironment { krate, block: None, traits_from_clauses: traits_in_scope, env })
|
||||
}
|
||||
|
||||
/// Resolve the where clause(s) of an item with generics.
|
||||
|
@ -271,6 +271,7 @@ pub struct InherentImpls {
|
||||
|
||||
impl InherentImpls {
|
||||
pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
|
||||
let _p = profile::span("inherent_impls_in_crate_query").detail(|| format!("{krate:?}"));
|
||||
let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() };
|
||||
|
||||
let crate_def_map = db.crate_def_map(krate);
|
||||
@ -284,13 +285,14 @@ impl InherentImpls {
|
||||
db: &dyn HirDatabase,
|
||||
block: BlockId,
|
||||
) -> Option<Arc<Self>> {
|
||||
let _p = profile::span("inherent_impls_in_block_query");
|
||||
let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() };
|
||||
if let Some(block_def_map) = db.block_def_map(block) {
|
||||
impls.collect_def_map(db, &block_def_map);
|
||||
impls.shrink_to_fit();
|
||||
return Some(Arc::new(impls));
|
||||
}
|
||||
None
|
||||
|
||||
let block_def_map = db.block_def_map(block)?;
|
||||
impls.collect_def_map(db, &block_def_map);
|
||||
impls.shrink_to_fit();
|
||||
|
||||
Some(Arc::new(impls))
|
||||
}
|
||||
|
||||
fn shrink_to_fit(&mut self) {
|
||||
@ -1140,7 +1142,7 @@ fn iterate_trait_method_candidates(
|
||||
};
|
||||
if !known_implemented {
|
||||
let goal = generic_implements_goal(db, env.clone(), t, &canonical_self_ty);
|
||||
if db.trait_solve(env.krate, goal.cast(Interner)).is_none() {
|
||||
if db.trait_solve(env.krate, env.block, goal.cast(Interner)).is_none() {
|
||||
continue 'traits;
|
||||
}
|
||||
}
|
||||
@ -1317,7 +1319,7 @@ pub fn resolve_indexing_op(
|
||||
let deref_chain = autoderef_method_receiver(&mut table, ty);
|
||||
for (ty, adj) in deref_chain {
|
||||
let goal = generic_implements_goal(db, env.clone(), index_trait, &ty);
|
||||
if db.trait_solve(env.krate, goal.cast(Interner)).is_some() {
|
||||
if db.trait_solve(env.krate, env.block, goal.cast(Interner)).is_some() {
|
||||
return Some(adj);
|
||||
}
|
||||
}
|
||||
@ -1342,14 +1344,12 @@ fn is_valid_candidate(
|
||||
) -> IsValidCandidate {
|
||||
let db = table.db;
|
||||
match item {
|
||||
AssocItemId::FunctionId(m) => {
|
||||
is_valid_fn_candidate(table, m, name, receiver_ty, self_ty, visible_from_module)
|
||||
AssocItemId::FunctionId(f) => {
|
||||
is_valid_fn_candidate(table, f, name, receiver_ty, self_ty, visible_from_module)
|
||||
}
|
||||
AssocItemId::ConstId(c) => {
|
||||
let data = db.const_data(c);
|
||||
check_that!(receiver_ty.is_none());
|
||||
|
||||
check_that!(name.map_or(true, |n| data.name.as_ref() == Some(n)));
|
||||
check_that!(name.map_or(true, |n| db.const_data(c).name.as_ref() == Some(n)));
|
||||
|
||||
if let Some(from_module) = visible_from_module {
|
||||
if !db.const_visibility(c).is_visible_from(db.upcast(), from_module) {
|
||||
@ -1473,7 +1473,7 @@ pub fn implements_trait(
|
||||
trait_: TraitId,
|
||||
) -> bool {
|
||||
let goal = generic_implements_goal(db, env.clone(), trait_, ty);
|
||||
let solution = db.trait_solve(env.krate, goal.cast(Interner));
|
||||
let solution = db.trait_solve(env.krate, env.block, goal.cast(Interner));
|
||||
|
||||
solution.is_some()
|
||||
}
|
||||
@ -1485,7 +1485,7 @@ pub fn implements_trait_unique(
|
||||
trait_: TraitId,
|
||||
) -> bool {
|
||||
let goal = generic_implements_goal(db, env.clone(), trait_, ty);
|
||||
let solution = db.trait_solve(env.krate, goal.cast(Interner));
|
||||
let solution = db.trait_solve(env.krate, env.block, goal.cast(Interner));
|
||||
|
||||
matches!(solution, Some(crate::Solution::Unique(_)))
|
||||
}
|
||||
|
@ -3717,7 +3717,6 @@ async fn get_accounts() -> Result<u32, ()> {
|
||||
|
||||
#[test]
|
||||
fn local_impl_1() {
|
||||
check!(block_local_impls);
|
||||
check_types(
|
||||
r#"
|
||||
trait Trait<T> {
|
||||
@ -3739,7 +3738,6 @@ fn test() {
|
||||
|
||||
#[test]
|
||||
fn local_impl_2() {
|
||||
check!(block_local_impls);
|
||||
check_types(
|
||||
r#"
|
||||
struct S;
|
||||
@ -3761,7 +3759,6 @@ fn test() {
|
||||
|
||||
#[test]
|
||||
fn local_impl_3() {
|
||||
check!(block_local_impls);
|
||||
check_types(
|
||||
r#"
|
||||
trait Trait<T> {
|
||||
@ -3785,6 +3782,33 @@ fn test() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn foreign_trait_with_local_trait_impl() {
|
||||
check!(block_local_impls);
|
||||
check(
|
||||
r#"
|
||||
mod module {
|
||||
pub trait T {
|
||||
const C: usize;
|
||||
fn f(&self);
|
||||
}
|
||||
}
|
||||
|
||||
fn f() {
|
||||
use module::T;
|
||||
impl T for usize {
|
||||
const C: usize = 0;
|
||||
fn f(&self) {}
|
||||
}
|
||||
0usize.f();
|
||||
//^^^^^^^^^^ type: ()
|
||||
usize::C;
|
||||
//^^^^^^^^type: usize
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn associated_type_sized_bounds() {
|
||||
check_infer(
|
||||
|
@ -9,7 +9,7 @@ use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver};
|
||||
use base_db::CrateId;
|
||||
use hir_def::{
|
||||
lang_item::{LangItem, LangItemTarget},
|
||||
TraitId,
|
||||
BlockId, TraitId,
|
||||
};
|
||||
use hir_expand::name::{name, Name};
|
||||
use stdx::panic_context;
|
||||
@ -27,6 +27,7 @@ const CHALK_SOLVER_FUEL: i32 = 1000;
|
||||
pub(crate) struct ChalkContext<'a> {
|
||||
pub(crate) db: &'a dyn HirDatabase,
|
||||
pub(crate) krate: CrateId,
|
||||
pub(crate) block: Option<BlockId>,
|
||||
}
|
||||
|
||||
fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> {
|
||||
@ -44,6 +45,7 @@ fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> {
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct TraitEnvironment {
|
||||
pub krate: CrateId,
|
||||
pub block: Option<BlockId>,
|
||||
// FIXME make this a BTreeMap
|
||||
pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>,
|
||||
pub env: chalk_ir::Environment<Interner>,
|
||||
@ -53,6 +55,7 @@ impl TraitEnvironment {
|
||||
pub fn empty(krate: CrateId) -> Self {
|
||||
TraitEnvironment {
|
||||
krate,
|
||||
block: None,
|
||||
traits_from_clauses: Vec::new(),
|
||||
env: chalk_ir::Environment::new(Interner),
|
||||
}
|
||||
@ -79,6 +82,7 @@ pub(crate) fn normalize_projection_query(
|
||||
pub(crate) fn trait_solve_query(
|
||||
db: &dyn HirDatabase,
|
||||
krate: CrateId,
|
||||
block: Option<BlockId>,
|
||||
goal: Canonical<InEnvironment<Goal>>,
|
||||
) -> Option<Solution> {
|
||||
let _p = profile::span("trait_solve_query").detail(|| match &goal.value.goal.data(Interner) {
|
||||
@ -104,15 +108,16 @@ pub(crate) fn trait_solve_query(
|
||||
// We currently don't deal with universes (I think / hope they're not yet
|
||||
// relevant for our use cases?)
|
||||
let u_canonical = chalk_ir::UCanonical { canonical: goal, universes: 1 };
|
||||
solve(db, krate, &u_canonical)
|
||||
solve(db, krate, block, &u_canonical)
|
||||
}
|
||||
|
||||
fn solve(
|
||||
db: &dyn HirDatabase,
|
||||
krate: CrateId,
|
||||
block: Option<BlockId>,
|
||||
goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<Interner>>>,
|
||||
) -> Option<chalk_solve::Solution<Interner>> {
|
||||
let context = ChalkContext { db, krate };
|
||||
let context = ChalkContext { db, krate, block };
|
||||
tracing::debug!("solve goal: {:?}", goal);
|
||||
let mut solver = create_chalk_solver();
|
||||
|
||||
|
@ -3331,7 +3331,7 @@ impl Type {
|
||||
binders: CanonicalVarKinds::empty(Interner),
|
||||
};
|
||||
|
||||
db.trait_solve(self.env.krate, goal).is_some()
|
||||
db.trait_solve(self.env.krate, self.env.block, goal).is_some()
|
||||
}
|
||||
|
||||
pub fn normalize_trait_assoc_type(
|
||||
|
Loading…
Reference in New Issue
Block a user