mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
fix: Properly handle local trait impls
This commit is contained in:
parent
284c1741d6
commit
342fd2b9f3
@ -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