Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions crates/hir-ty/src/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}
Expand Down
112 changes: 15 additions & 97 deletions crates/hir-ty/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1624,105 +1624,23 @@ pub(crate) fn trait_environment_query<'db>(
db: &'db dyn HirDatabase,
def: GenericDefId,
) -> Arc<TraitEnvironment<'db>> {
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<T1, T2, ...>` 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(&param_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)]
Expand Down
19 changes: 13 additions & 6 deletions crates/hir-ty/src/tests/incremental.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
]
"#]],
);
Expand Down Expand Up @@ -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",
Expand All @@ -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",
]
Expand Down Expand Up @@ -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",
Expand All @@ -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",
Expand All @@ -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",
]
"#]],
Expand Down Expand Up @@ -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",
Expand All @@ -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",
Expand All @@ -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_",
]
"#]],
);
Expand Down
26 changes: 25 additions & 1 deletion crates/hir-ty/src/tests/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -5032,3 +5031,28 @@ fn main() {
"#]],
);
}

#[test]
fn implicit_sized_bound_on_param() {
check(
r#"
//- minicore: sized
struct PBox<T, A>(T, A);

impl<T, A> PBox<T, A> {
fn token_with(self) {}
}

trait MoveMessage {
fn token<A>(self, alloc: A)
where
Self: Sized,
{
let b = PBox::<Self, A>(self, alloc);
b.token_with();
// ^^^^^^^^^^^^^^ type: ()
}
}
"#,
);
}
2 changes: 1 addition & 1 deletion crates/ide-completion/src/tests/flyimport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
"#]],
);
}
Expand Down