Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove predicate queries #129532

Closed
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
1 change: 0 additions & 1 deletion compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ pub fn provide(providers: &mut Providers) {
explicit_implied_predicates_of: predicates_of::explicit_implied_predicates_of,
explicit_supertraits_containing_assoc_item:
predicates_of::explicit_supertraits_containing_assoc_item,
trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
type_param_predicates: predicates_of::type_param_predicates,
trait_def,
adt_def,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect/item_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn associated_type_bounds<'tcx>(
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);

let trait_def_id = tcx.local_parent(assoc_item_def_id);
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id);
let trait_predicates = tcx.predicates_of(trait_def_id);

let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| {
match pred.kind().skip_binder() {
Expand Down
155 changes: 48 additions & 107 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,122 +459,63 @@ fn const_evaluatable_predicates_of(
collector.preds
}

pub(super) fn trait_explicit_predicates_and_bounds(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
) -> ty::GenericPredicates<'_> {
assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
gather_explicit_predicates_of(tcx, def_id)
}

pub(super) fn explicit_predicates_of<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
) -> ty::GenericPredicates<'tcx> {
let def_kind = tcx.def_kind(def_id);
if let DefKind::Trait = def_kind {
// Remove bounds on associated types from the predicates, they will be
// returned by `explicit_item_bounds`.
let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id);
let trait_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);

let is_assoc_item_ty = |ty: Ty<'tcx>| {
// For a predicate from a where clause to become a bound on an
// associated type:
// * It must use the identity args of the item.
// * We're in the scope of the trait, so we can't name any
// parameters of the GAT. That means that all we need to
// check are that the args of the projection are the
// identity args of the trait.
// * It must be an associated type for this trait (*not* a
// supertrait).
if let ty::Alias(ty::Projection, projection) = ty.kind() {
projection.args == trait_identity_args
// FIXME(return_type_notation): This check should be more robust
&& !tcx.is_impl_trait_in_trait(projection.def_id)
&& tcx.associated_item(projection.def_id).container_id(tcx)
== def_id.to_def_id()
} else {
false
}
};

let predicates: Vec<_> = predicates_and_bounds
if matches!(def_kind, DefKind::AnonConst)
&& tcx.features().generic_const_exprs
&& let Some(defaulted_param_def_id) =
tcx.hir().opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
{
// In `generics_of` we set the generics' parent to be our parent's parent which means that
// we lose out on the predicates of our actual parent if we dont return those predicates here.
// (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
//
// struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait;
// ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling
// ^^^ explicit_predicates_of on
// parent item we dont have set as the
// parent of generics returned by `generics_of`
//
// In the above code we want the anon const to have predicates in its param env for `T: Trait`
// and we would be calling `explicit_predicates_of(Foo)` here
let parent_def_id = tcx.local_parent(def_id);
let parent_preds = tcx.explicit_predicates_of(parent_def_id);

// If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter
// will ICE because of #106994. FIXME(generic_const_exprs): remove this when a more general solution
// to #106994 is implemented.
let filtered_predicates = parent_preds
.predicates
.iter()
.copied()
.filter(|(pred, _)| match pred.kind().skip_binder() {
ty::ClauseKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()),
ty::ClauseKind::Projection(proj) => {
!is_assoc_item_ty(proj.projection_term.self_ty())
}
ty::ClauseKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
_ => true,
})
.collect();
if predicates.len() == predicates_and_bounds.predicates.len() {
predicates_and_bounds
} else {
ty::GenericPredicates {
parent: predicates_and_bounds.parent,
predicates: tcx.arena.alloc_slice(&predicates),
effects_min_tys: predicates_and_bounds.effects_min_tys,
}
}
} else {
if matches!(def_kind, DefKind::AnonConst)
&& tcx.features().generic_const_exprs
&& let Some(defaulted_param_def_id) =
tcx.hir().opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
{
// In `generics_of` we set the generics' parent to be our parent's parent which means that
// we lose out on the predicates of our actual parent if we dont return those predicates here.
// (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
//
// struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait;
// ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling
// ^^^ explicit_predicates_of on
// parent item we dont have set as the
// parent of generics returned by `generics_of`
//
// In the above code we want the anon const to have predicates in its param env for `T: Trait`
// and we would be calling `explicit_predicates_of(Foo)` here
let parent_def_id = tcx.local_parent(def_id);
let parent_preds = tcx.explicit_predicates_of(parent_def_id);

// If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter
// will ICE because of #106994. FIXME(generic_const_exprs): remove this when a more general solution
// to #106994 is implemented.
let filtered_predicates = parent_preds
.predicates
.into_iter()
.filter(|(pred, _)| {
if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() {
match ct.kind() {
ty::ConstKind::Param(param_const) => {
let defaulted_param_idx = tcx
.generics_of(parent_def_id)
.param_def_id_to_index[&defaulted_param_def_id.to_def_id()];
param_const.index < defaulted_param_idx
}
_ => bug!(
"`ConstArgHasType` in `predicates_of`\
that isn't a `Param` const"
),
.into_iter()
.filter(|(pred, _)| {
if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() {
match ct.kind() {
ty::ConstKind::Param(param_const) => {
let defaulted_param_idx = tcx
.generics_of(parent_def_id)
.param_def_id_to_index[&defaulted_param_def_id.to_def_id()];
param_const.index < defaulted_param_idx
}
} else {
true
_ => bug!(
"`ConstArgHasType` in `predicates_of`\
that isn't a `Param` const"
),
}
})
.cloned();
return GenericPredicates {
parent: parent_preds.parent,
predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
effects_min_tys: parent_preds.effects_min_tys,
};
}
gather_explicit_predicates_of(tcx, def_id)
} else {
true
}
})
.cloned();
return GenericPredicates {
parent: parent_preds.parent,
predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
effects_min_tys: parent_preds.effects_min_tys,
};
}
gather_explicit_predicates_of(tcx, def_id)
}

/// Ensures that the super-predicates of the trait with a `DefId`
Expand Down
18 changes: 0 additions & 18 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,24 +608,6 @@ rustc_queries! {
desc { "getting wasm import module map" }
}

/// Returns everything that looks like a predicate written explicitly
/// by the user on a trait item.
///
/// Traits are unusual, because predicates on associated types are
/// converted into bounds on that type for backwards compatibility:
///
/// trait X where Self::U: Copy { type U; }
///
/// becomes
///
/// trait X { type U: Copy; }
///
/// `explicit_predicates_of` and `explicit_item_bounds` will then take
/// the appropriate subsets of the predicates here.
query trait_explicit_predicates_and_bounds(key: LocalDefId) -> ty::GenericPredicates<'tcx> {
desc { |tcx| "computing explicit predicates of trait `{}`", tcx.def_path_str(key) }
}

/// Returns the predicates written explicitly by the user.
///
/// You should probably use `predicates_of` unless you're looking for
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ trait Foo {
}

impl Foo for () {
type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied
type Assoc = bool;
//~^ ERROR the trait bound `bool: Bar` is not satisfied
}

trait Baz
Expand All @@ -16,7 +17,9 @@ where
}

impl Baz for () {
type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied
type Assoc = bool;
//~^ ERROR the trait bound `bool: Bar` is not satisfied
//~| ERROR the trait bound `bool: Bar` is not satisfied
}

trait Bat
Expand All @@ -27,7 +30,9 @@ where
}

impl Bat for () {
type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied
type Assoc = bool;
//~^ ERROR the trait bound `bool: Bar` is not satisfied
//~| ERROR the trait bound `bool: Bar` is not satisfied
}

fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,27 @@ LL | type Assoc: Bar;
| ^^^ required by this bound in `Foo::Assoc`

error[E0277]: the trait bound `bool: Bar` is not satisfied
--> $DIR/point-at-type-on-obligation-failure-2.rs:19:18
--> $DIR/point-at-type-on-obligation-failure-2.rs:20:18
|
LL | type Assoc = bool;
| ^^^^ the trait `Bar` is not implemented for `bool`, which is required by `<() as Baz>::Assoc: Bar`
|
help: this trait has no implementations, consider adding one
--> $DIR/point-at-type-on-obligation-failure-2.rs:1:1
|
LL | trait Bar {}
| ^^^^^^^^^
note: required by a bound in `Baz`
--> $DIR/point-at-type-on-obligation-failure-2.rs:14:18
|
LL | trait Baz
| --- required by a bound in this trait
LL | where
LL | Self::Assoc: Bar,
| ^^^ required by this bound in `Baz`

error[E0277]: the trait bound `bool: Bar` is not satisfied
--> $DIR/point-at-type-on-obligation-failure-2.rs:20:18
|
LL | type Assoc = bool;
| ^^^^ the trait `Bar` is not implemented for `bool`
Expand All @@ -27,7 +47,7 @@ help: this trait has no implementations, consider adding one
LL | trait Bar {}
| ^^^^^^^^^
note: required by a bound in `Baz::Assoc`
--> $DIR/point-at-type-on-obligation-failure-2.rs:13:18
--> $DIR/point-at-type-on-obligation-failure-2.rs:14:18
|
LL | Self::Assoc: Bar,
| ^^^ required by this bound in `Baz::Assoc`
Expand All @@ -36,7 +56,27 @@ LL | type Assoc;
| ----- required by a bound in this associated type

error[E0277]: the trait bound `bool: Bar` is not satisfied
--> $DIR/point-at-type-on-obligation-failure-2.rs:30:18
--> $DIR/point-at-type-on-obligation-failure-2.rs:33:18
|
LL | type Assoc = bool;
| ^^^^ the trait `Bar` is not implemented for `bool`, which is required by `<() as Bat>::Assoc: Bar`
|
help: this trait has no implementations, consider adding one
--> $DIR/point-at-type-on-obligation-failure-2.rs:1:1
|
LL | trait Bar {}
| ^^^^^^^^^
note: required by a bound in `Bat`
--> $DIR/point-at-type-on-obligation-failure-2.rs:27:27
|
LL | trait Bat
| --- required by a bound in this trait
LL | where
LL | <Self as Bat>::Assoc: Bar,
| ^^^ required by this bound in `Bat`

error[E0277]: the trait bound `bool: Bar` is not satisfied
--> $DIR/point-at-type-on-obligation-failure-2.rs:33:18
|
LL | type Assoc = bool;
| ^^^^ the trait `Bar` is not implemented for `bool`
Expand All @@ -47,14 +87,14 @@ help: this trait has no implementations, consider adding one
LL | trait Bar {}
| ^^^^^^^^^
note: required by a bound in `Bat::Assoc`
--> $DIR/point-at-type-on-obligation-failure-2.rs:24:27
--> $DIR/point-at-type-on-obligation-failure-2.rs:27:27
|
LL | <Self as Bat>::Assoc: Bar,
| ^^^ required by this bound in `Bat::Assoc`
LL | {
LL | type Assoc;
| ----- required by a bound in this associated type

error: aborting due to 3 previous errors
error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0277`.
2 changes: 1 addition & 1 deletion tests/ui/const-generics/not_wf_param_in_rpitit.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ LL | trait Trait<const N: Trait = bar> {
| ^^^^^
|
= note: ...which immediately requires computing type of `Trait::N` again
note: cycle used when computing explicit predicates of trait `Trait`
note: cycle used when computing explicit predicates of `Trait`
--> $DIR/not_wf_param_in_rpitit.rs:3:1
|
LL | trait Trait<const N: Trait = bar> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ LL | trait Trait<const N: Trait = bar> {
| ^^^^^
|
= note: ...which immediately requires computing type of `Trait::N` again
note: cycle used when computing explicit predicates of trait `Trait`
note: cycle used when computing explicit predicates of `Trait`
--> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:1
|
LL | trait Trait<const N: Trait = bar> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ note: ...which requires computing type of `Bar::M`...
LL | trait Bar<const M: Foo<2>> {}
| ^^^^^^^^^^^^^^^
= note: ...which again requires computing type of `Foo::N`, completing the cycle
note: cycle used when computing explicit predicates of trait `Foo`
note: cycle used when computing explicit predicates of `Foo`
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:1
|
LL | trait Foo<const N: Bar<2>> {
Expand Down
Loading