Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/source_analyzer.rs')
| -rw-r--r-- | crates/hir/src/source_analyzer.rs | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 6d265c460e..687f130af4 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -13,10 +13,10 @@ use std::{ use either::Either; use hir_def::{ AdtId, AssocItemId, CallableDefId, ConstId, DefWithBodyId, ExpressionStoreOwnerId, FieldId, - FunctionId, GenericDefId, LocalFieldId, ModuleDefId, StructId, VariantId, + FunctionId, GenericDefId, HasModule, LocalFieldId, ModuleDefId, StructId, VariantId, expr_store::{ Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, HygieneId, - lower::ExprCollector, + lower::{ExprCollector, lower_generic_params}, path::Path, scope::{ExprScopes, ScopeId}, }, @@ -44,7 +44,7 @@ use hir_ty::{ AliasTy, DbInterner, DefaultAny, EarlyBinder, ErrorGuaranteed, GenericArgs, ParamEnv, Region, Ty, TyKind, TypingMode, infer::DbInternerInferExt, }, - traits::structurally_normalize_ty, + traits::{WherePredicateEvaluation, structurally_normalize_ty, where_predicate_must_hold}, }; use intern::sym; use itertools::Itertools; @@ -63,7 +63,8 @@ use syntax::{ use crate::{ Adt, AnyFunctionId, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const, DeriveHelper, EnumVariant, Field, Function, GenericSubstitution, Local, Macro, ModuleDef, - SemanticsImpl, Static, Struct, ToolModule, Trait, TupleField, Type, TypeAlias, TypeOwnerId, + PredicateEvaluationResult, SemanticsImpl, Static, Struct, ToolModule, Trait, TupleField, Type, + TypeAlias, TypeOwnerId, db::HirDatabase, semantics::{PathResolution, PathResolutionPerNs}, }; @@ -364,6 +365,52 @@ impl<'db> SourceAnalyzer<'db> { )) } + pub(crate) fn evaluate_where_clause( + &self, + db: &'db dyn HirDatabase, + where_clause: ast::WhereClause, + ) -> PredicateEvaluationResult { + let Some(owner) = self.owner() else { + // FIXME + return PredicateEvaluationResult::unsupported( + "predicate evaluation is only supported inside an item", + ); + }; + let generic_def = owner.generic_def(db); + let module = generic_def.module(db); + let (store, params, _) = + lower_generic_params(db, module, generic_def, self.file_id, None, Some(where_clause)); + let predicates = params.where_predicates(); + if predicates.is_empty() { + return PredicateEvaluationResult::holds("predicate does not impose any obligations"); + } + + let env = self.trait_environment(db); + for predicate in predicates { + match where_predicate_must_hold( + db, + &self.resolver, + &store, + owner, + generic_def, + env, + predicate, + ) { + WherePredicateEvaluation::Holds | WherePredicateEvaluation::NoObligations => {} + WherePredicateEvaluation::HasErrors => { + return PredicateEvaluationResult::invalid( + "predicate contains unresolved names or invalid type syntax", + ); + } + WherePredicateEvaluation::NotProven => { + return PredicateEvaluationResult::not_proven("predicate is not known to hold"); + } + } + } + + PredicateEvaluationResult::holds("predicate holds") + } + pub(crate) fn expr_id(&self, expr: ast::Expr) -> Option<ExprOrPatId> { let src = InFile { file_id: self.file_id, value: expr }; self.store_sm()?.node_expr(src.as_ref()) |