From 9ceff9f803cc0d93878b68533df77bf3748617f1 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 17 Nov 2025 04:00:54 +0200 Subject: [PATCH] Derive ParamEnv from GenericPredicates Instead of relowering them. This way we save time and prevent mismatches. --- crates/hir-ty/src/generics.rs | 5 - crates/hir-ty/src/lower.rs | 112 +++---------------- crates/hir-ty/src/tests/incremental.rs | 19 +++- crates/hir-ty/src/tests/traits.rs | 26 ++++- crates/ide-completion/src/tests/flyimport.rs | 2 +- 5 files changed, 54 insertions(+), 110 deletions(-) diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs index 26e03aa01a1d..5f0261437b77 100644 --- a/crates/hir-ty/src/generics.rs +++ b/crates/hir-ty/src/generics.rs @@ -60,11 +60,6 @@ impl Generics { self.params.where_predicates().iter() } - pub(crate) fn has_no_predicates(&self) -> bool { - self.params.has_no_predicates() - && self.parent_generics.as_ref().is_none_or(|g| g.params.has_no_predicates()) - } - pub(crate) fn is_empty(&self) -> bool { self.params.is_empty() && self.parent_generics.as_ref().is_none_or(|g| g.params.is_empty()) } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index adc48b57d58e..a20c299d0cbb 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -1624,105 +1624,23 @@ pub(crate) fn trait_environment_query<'db>( db: &'db dyn HirDatabase, def: GenericDefId, ) -> Arc> { - let generics = generics(db, def); - if generics.has_no_predicates() && generics.is_empty() { - return TraitEnvironment::empty(def.krate(db)); - } - - let resolver = def.resolver(db); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - generics.store(), - def, - LifetimeElisionKind::AnonymousReportError, - ); - let mut traits_in_scope = Vec::new(); - let mut clauses = Vec::new(); - for maybe_parent_generics in - std::iter::successors(Some(&generics), |generics| generics.parent_generics()) - { - ctx.store = maybe_parent_generics.store(); - for pred in maybe_parent_generics.where_predicates() { - for pred in ctx.lower_where_predicate(pred, false, &generics, PredicateFilter::All) { - if let rustc_type_ir::ClauseKind::Trait(tr) = pred.kind().skip_binder() { - traits_in_scope.push((tr.self_ty(), tr.def_id().0)); - } - clauses.push(pred); - } - } - - push_const_arg_has_type_predicates(db, &mut clauses, maybe_parent_generics); - } - - if let Some(trait_id) = def.assoc_trait_container(db) { - // add `Self: Trait` to the environment in trait - // function default implementations (and speculative code - // inside consts or type aliases) - cov_mark::hit!(trait_self_implements_self); - let trait_ref = TraitRef::identity(ctx.interner, trait_id.into()); - let clause = Clause(Predicate::new( - ctx.interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::Trait( - TraitPredicate { trait_ref, polarity: rustc_type_ir::PredicatePolarity::Positive }, - ))), - )); - clauses.push(clause); - } - - let explicitly_unsized_tys = ctx.unsized_types; - - let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()); - if let Some(sized_trait) = sized_trait { - let (mut generics, mut def_id) = - (crate::next_solver::generics::generics(db, def.into()), def); - loop { - let self_idx = trait_self_param_idx(db, def_id); - for (idx, p) in generics.own_params.iter().enumerate() { - if let Some(self_idx) = self_idx - && p.index() as usize == self_idx - { - continue; - } - let GenericParamId::TypeParamId(param_id) = p.id else { - continue; - }; - let idx = idx as u32 + generics.parent_count as u32; - let param_ty = Ty::new_param(ctx.interner, param_id, idx); - if explicitly_unsized_tys.contains(¶m_ty) { - continue; - } - let trait_ref = TraitRef::new_from_args( - ctx.interner, - sized_trait.into(), - GenericArgs::new_from_iter(ctx.interner, [param_ty.into()]), - ); - let clause = Clause(Predicate::new( - ctx.interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause( - rustc_type_ir::ClauseKind::Trait(TraitPredicate { - trait_ref, - polarity: rustc_type_ir::PredicatePolarity::Positive, - }), - )), - )); - clauses.push(clause); - } - - if let Some(g) = generics.parent { - generics = crate::next_solver::generics::generics(db, g.into()); - def_id = g; - } else { - break; - } - } - } - - let clauses = rustc_type_ir::elaborate::elaborate(ctx.interner, clauses); - let clauses = Clauses::new_from_iter(ctx.interner, clauses); + let module = def.module(db); + let interner = DbInterner::new_with(db, Some(module.krate()), module.containing_block()); + let predicates = GenericPredicates::query_all(db, def); + let traits_in_scope = predicates + .iter_identity_copied() + .filter_map(|pred| match pred.kind().skip_binder() { + ClauseKind::Trait(tr) => Some((tr.self_ty(), tr.def_id().0)), + _ => None, + }) + .collect(); + let clauses = rustc_type_ir::elaborate::elaborate(interner, predicates.iter_identity_copied()); + let clauses = Clauses::new_from_iter(interner, clauses); let env = ParamEnv { clauses }; - TraitEnvironment::new(resolver.krate(), None, traits_in_scope.into_boxed_slice(), env) + // FIXME: We should normalize projections here, like rustc does. + + TraitEnvironment::new(module.krate(), module.containing_block(), traits_in_scope, env) } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/crates/hir-ty/src/tests/incremental.rs b/crates/hir-ty/src/tests/incremental.rs index 1b64bfddb814..e98e5e48284d 100644 --- a/crates/hir-ty/src/tests/incremental.rs +++ b/crates/hir-ty/src/tests/incremental.rs @@ -44,10 +44,12 @@ fn foo() -> i32 { "body_shim", "body_with_source_map_shim", "trait_environment_shim", + "GenericPredicates < 'db >::query_with_diagnostics_", + "lang_item", + "crate_lang_items", "ImplTraits < 'db >::return_type_impl_traits_", "expr_scopes_shim", "lang_item", - "crate_lang_items", ] "#]], ); @@ -131,18 +133,21 @@ fn baz() -> i32 { "body_shim", "body_with_source_map_shim", "trait_environment_shim", - "ImplTraits < 'db >::return_type_impl_traits_", - "expr_scopes_shim", + "GenericPredicates < 'db >::query_with_diagnostics_", "lang_item", "crate_lang_items", "attrs_shim", "attrs_shim", + "ImplTraits < 'db >::return_type_impl_traits_", + "expr_scopes_shim", + "lang_item", "infer_shim", "function_signature_shim", "function_signature_with_source_map_shim", "body_shim", "body_with_source_map_shim", "trait_environment_shim", + "GenericPredicates < 'db >::query_with_diagnostics_", "ImplTraits < 'db >::return_type_impl_traits_", "expr_scopes_shim", "infer_shim", @@ -151,6 +156,7 @@ fn baz() -> i32 { "body_shim", "body_with_source_map_shim", "trait_environment_shim", + "GenericPredicates < 'db >::query_with_diagnostics_", "ImplTraits < 'db >::return_type_impl_traits_", "expr_scopes_shim", ] @@ -581,6 +587,7 @@ fn main() { "body_shim", "body_with_source_map_shim", "trait_environment_shim", + "GenericPredicates < 'db >::query_with_diagnostics_", "lang_item", "crate_lang_items", "attrs_shim", @@ -591,6 +598,7 @@ fn main() { "function_signature_shim", "function_signature_with_source_map_shim", "trait_environment_shim", + "GenericPredicates < 'db >::query_with_diagnostics_", "ImplTraits < 'db >::return_type_impl_traits_", "expr_scopes_shim", "struct_signature_shim", @@ -609,7 +617,6 @@ fn main() { "impl_trait_with_diagnostics_shim", "impl_self_ty_with_diagnostics_shim", "GenericPredicates < 'db >::query_with_diagnostics_", - "GenericPredicates < 'db >::query_with_diagnostics_", "lang_item", ] "#]], @@ -677,7 +684,7 @@ fn main() { "function_signature_shim", "body_with_source_map_shim", "body_shim", - "trait_environment_shim", + "GenericPredicates < 'db >::query_with_diagnostics_", "crate_lang_items", "attrs_shim", "attrs_shim", @@ -686,6 +693,7 @@ fn main() { "ImplTraits < 'db >::return_type_impl_traits_", "infer_shim", "function_signature_with_source_map_shim", + "GenericPredicates < 'db >::query_with_diagnostics_", "ImplTraits < 'db >::return_type_impl_traits_", "expr_scopes_shim", "struct_signature_with_source_map_shim", @@ -699,7 +707,6 @@ fn main() { "impl_trait_with_diagnostics_shim", "impl_self_ty_with_diagnostics_shim", "GenericPredicates < 'db >::query_with_diagnostics_", - "GenericPredicates < 'db >::query_with_diagnostics_", ] "#]], ); diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index 87f488f7aafa..eb4ae5ec8a97 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -349,7 +349,6 @@ fn test() { #[test] fn trait_default_method_self_bound_implements_trait() { - cov_mark::check!(trait_self_implements_self); check( r#" trait Trait { @@ -5032,3 +5031,28 @@ fn main() { "#]], ); } + +#[test] +fn implicit_sized_bound_on_param() { + check( + r#" +//- minicore: sized +struct PBox(T, A); + +impl PBox { + fn token_with(self) {} +} + +trait MoveMessage { + fn token(self, alloc: A) + where + Self: Sized, + { + let b = PBox::(self, alloc); + b.token_with(); + // ^^^^^^^^^^^^^^ type: () + } +} + "#, + ); +} diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs index 155f0b5a9815..e139a5e27088 100644 --- a/crates/ide-completion/src/tests/flyimport.rs +++ b/crates/ide-completion/src/tests/flyimport.rs @@ -780,9 +780,9 @@ fn main() { } "#, expect![[r#" - me random_method(…) (use dep::test_mod::TestTrait) fn(&self) DEPRECATED ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8 DEPRECATED fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED + me random_method(…) (use dep::test_mod::TestTrait) fn(&self) DEPRECATED "#]], ); }