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

Fold item bounds before proving them in check_type_bounds in new solver #125786

Merged
merged 2 commits into from
May 31, 2024
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
29 changes: 27 additions & 2 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2026,10 +2026,19 @@ pub(super) fn check_type_bounds<'tcx>(
// to its definition type. This should be the param-env we use to *prove* the
// predicate too, but we don't do that because of performance issues.
// See <https://github.com/rust-lang/rust/pull/117542#issue-1976337685>.
let trait_projection_ty = Ty::new_projection(tcx, trait_ty.def_id, rebased_args);
let impl_identity_ty = tcx.type_of(impl_ty.def_id).instantiate_identity();
Comment on lines +2029 to +2030
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this into the next_solver branch?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then it happens once per for mut obligation in util::elaborate(tcx, obligations) {.

I could invert the if statement, and duplicate the for loop?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right, didn't see the for loop 👍

let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
for mut obligation in util::elaborate(tcx, obligations) {
let normalized_predicate =
ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate);
let normalized_predicate = if infcx.next_trait_solver() {
obligation.predicate.fold_with(&mut ReplaceTy {
tcx,
from: trait_projection_ty,
to: impl_identity_ty,
})
} else {
ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate)
};
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
obligation.predicate = normalized_predicate;

Expand All @@ -2050,6 +2059,22 @@ pub(super) fn check_type_bounds<'tcx>(
ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
}

struct ReplaceTy<'tcx> {
tcx: TyCtxt<'tcx>,
from: Ty<'tcx>,
to: Ty<'tcx>,
}

impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceTy<'tcx> {
fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}

fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if self.from == ty { self.to } else { ty.super_fold_with(self) }
}
}

/// Install projection predicates that allow GATs to project to their own
/// definition types. This is not allowed in general in cases of default
/// associated types in trait definitions, or when specialization is involved,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0277]: the trait bound `NotClone: Clone` is not satisfied
--> $DIR/defaults-suitability.rs:13:22
--> $DIR/defaults-suitability.rs:16:22
|
LL | type Ty: Clone = NotClone;
| ^^^^^^^^ the trait `Clone` is not implemented for `NotClone`
|
note: required by a bound in `Tr::Ty`
--> $DIR/defaults-suitability.rs:13:14
--> $DIR/defaults-suitability.rs:16:14
|
LL | type Ty: Clone = NotClone;
| ^^^^^ required by this bound in `Tr::Ty`
Expand All @@ -16,13 +16,13 @@ LL | struct NotClone;
|

error[E0277]: the trait bound `NotClone: Clone` is not satisfied
--> $DIR/defaults-suitability.rs:22:15
--> $DIR/defaults-suitability.rs:25:15
|
LL | type Ty = NotClone;
| ^^^^^^^^ the trait `Clone` is not implemented for `NotClone`
|
note: required by a bound in `Tr2::Ty`
--> $DIR/defaults-suitability.rs:20:15
--> $DIR/defaults-suitability.rs:23:15
|
LL | Self::Ty: Clone,
| ^^^^^ required by this bound in `Tr2::Ty`
Expand All @@ -36,14 +36,14 @@ LL | struct NotClone;
|

error[E0277]: the trait bound `T: Clone` is not satisfied
--> $DIR/defaults-suitability.rs:28:23
--> $DIR/defaults-suitability.rs:31:23
|
LL | type Bar: Clone = Vec<T>;
| ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `Vec<T>: Clone`
|
= note: required for `Vec<T>` to implement `Clone`
note: required by a bound in `Foo::Bar`
--> $DIR/defaults-suitability.rs:28:15
--> $DIR/defaults-suitability.rs:31:15
|
LL | type Bar: Clone = Vec<T>;
| ^^^^^ required by this bound in `Foo::Bar`
Expand All @@ -53,30 +53,30 @@ LL | trait Foo<T: std::clone::Clone> {
| +++++++++++++++++++

error[E0277]: the trait bound `(): Foo<Self>` is not satisfied
--> $DIR/defaults-suitability.rs:34:29
--> $DIR/defaults-suitability.rs:37:29
|
LL | type Assoc: Foo<Self> = ();
| ^^ the trait `Foo<Self>` is not implemented for `()`
|
help: this trait has no implementations, consider adding one
--> $DIR/defaults-suitability.rs:27:1
--> $DIR/defaults-suitability.rs:30:1
|
LL | trait Foo<T> {
| ^^^^^^^^^^^^
note: required by a bound in `Bar::Assoc`
--> $DIR/defaults-suitability.rs:34:17
--> $DIR/defaults-suitability.rs:37:17
|
LL | type Assoc: Foo<Self> = ();
| ^^^^^^^^^ required by this bound in `Bar::Assoc`

error[E0277]: the trait bound `NotClone: IsU8<NotClone>` is not satisfied
--> $DIR/defaults-suitability.rs:56:18
--> $DIR/defaults-suitability.rs:59:18
|
LL | type Assoc = NotClone;
| ^^^^^^^^ the trait `IsU8<NotClone>` is not implemented for `NotClone`
|
note: required by a bound in `D::Assoc`
--> $DIR/defaults-suitability.rs:53:18
--> $DIR/defaults-suitability.rs:56:18
|
LL | Self::Assoc: IsU8<Self::Assoc>,
| ^^^^^^^^^^^^^^^^^ required by this bound in `D::Assoc`
Expand All @@ -85,14 +85,14 @@ LL | type Assoc = NotClone;
| ----- required by a bound in this associated type

error[E0277]: the trait bound `<Self as Foo2<T>>::Baz: Clone` is not satisfied
--> $DIR/defaults-suitability.rs:65:23
--> $DIR/defaults-suitability.rs:68:23
|
LL | type Bar: Clone = Vec<Self::Baz>;
| ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo2<T>>::Baz`, which is required by `Vec<<Self as Foo2<T>>::Baz>: Clone`
|
= note: required for `Vec<<Self as Foo2<T>>::Baz>` to implement `Clone`
note: required by a bound in `Foo2::Bar`
--> $DIR/defaults-suitability.rs:65:15
--> $DIR/defaults-suitability.rs:68:15
|
LL | type Bar: Clone = Vec<Self::Baz>;
| ^^^^^ required by this bound in `Foo2::Bar`
Expand All @@ -102,14 +102,14 @@ LL | trait Foo2<T> where <Self as Foo2<T>>::Baz: Clone {
| +++++++++++++++++++++++++++++++++++

error[E0277]: the trait bound `<Self as Foo25<T>>::Baz: Clone` is not satisfied
--> $DIR/defaults-suitability.rs:74:23
--> $DIR/defaults-suitability.rs:77:23
|
LL | type Bar: Clone = Vec<Self::Baz>;
| ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo25<T>>::Baz`, which is required by `Vec<<Self as Foo25<T>>::Baz>: Clone`
|
= note: required for `Vec<<Self as Foo25<T>>::Baz>` to implement `Clone`
note: required by a bound in `Foo25::Bar`
--> $DIR/defaults-suitability.rs:74:15
--> $DIR/defaults-suitability.rs:77:15
|
LL | type Bar: Clone = Vec<Self::Baz>;
| ^^^^^ required by this bound in `Foo25::Bar`
Expand All @@ -119,13 +119,13 @@ LL | trait Foo25<T: Clone> where <Self as Foo25<T>>::Baz: Clone {
| ++++++++++++++++++++++++++++++++++++

error[E0277]: the trait bound `T: Clone` is not satisfied
--> $DIR/defaults-suitability.rs:87:16
--> $DIR/defaults-suitability.rs:90:16
|
LL | type Baz = T;
| ^ the trait `Clone` is not implemented for `T`
|
note: required by a bound in `Foo3::Baz`
--> $DIR/defaults-suitability.rs:84:16
--> $DIR/defaults-suitability.rs:87:16
|
LL | Self::Baz: Clone,
| ^^^^^ required by this bound in `Foo3::Baz`
Expand Down
142 changes: 142 additions & 0 deletions tests/ui/associated-types/defaults-suitability.next.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
error[E0277]: the trait bound `NotClone: Clone` is not satisfied
--> $DIR/defaults-suitability.rs:16:22
|
LL | type Ty: Clone = NotClone;
| ^^^^^^^^ the trait `Clone` is not implemented for `NotClone`
|
note: required by a bound in `Tr::Ty`
--> $DIR/defaults-suitability.rs:16:14
|
LL | type Ty: Clone = NotClone;
| ^^^^^ required by this bound in `Tr::Ty`
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
LL + #[derive(Clone)]
LL | struct NotClone;
|

error[E0277]: the trait bound `NotClone: Clone` is not satisfied
--> $DIR/defaults-suitability.rs:25:15
|
LL | type Ty = NotClone;
| ^^^^^^^^ the trait `Clone` is not implemented for `NotClone`
|
note: required by a bound in `Tr2::Ty`
--> $DIR/defaults-suitability.rs:23:15
|
LL | Self::Ty: Clone,
| ^^^^^ required by this bound in `Tr2::Ty`
LL | {
LL | type Ty = NotClone;
| -- required by a bound in this associated type
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
LL + #[derive(Clone)]
LL | struct NotClone;
|

error[E0277]: the trait bound `T: Clone` is not satisfied
--> $DIR/defaults-suitability.rs:31:23
|
LL | type Bar: Clone = Vec<T>;
| ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `Vec<T>: Clone`
|
= note: required for `Vec<T>` to implement `Clone`
note: required by a bound in `Foo::Bar`
--> $DIR/defaults-suitability.rs:31:15
|
LL | type Bar: Clone = Vec<T>;
| ^^^^^ required by this bound in `Foo::Bar`
help: consider restricting type parameter `T`
|
LL | trait Foo<T: std::clone::Clone> {
| +++++++++++++++++++

error[E0277]: the trait bound `(): Foo<Self>` is not satisfied
--> $DIR/defaults-suitability.rs:37:29
|
LL | type Assoc: Foo<Self> = ();
| ^^ the trait `Foo<Self>` is not implemented for `()`
|
help: this trait has no implementations, consider adding one
--> $DIR/defaults-suitability.rs:30:1
|
LL | trait Foo<T> {
| ^^^^^^^^^^^^
note: required by a bound in `Bar::Assoc`
--> $DIR/defaults-suitability.rs:37:17
|
LL | type Assoc: Foo<Self> = ();
| ^^^^^^^^^ required by this bound in `Bar::Assoc`

error[E0277]: the trait bound `NotClone: IsU8<NotClone>` is not satisfied
--> $DIR/defaults-suitability.rs:59:18
|
LL | type Assoc = NotClone;
| ^^^^^^^^ the trait `IsU8<NotClone>` is not implemented for `NotClone`
|
note: required by a bound in `D::Assoc`
--> $DIR/defaults-suitability.rs:56:18
|
LL | Self::Assoc: IsU8<Self::Assoc>,
| ^^^^^^^^^^^^^^^^^ required by this bound in `D::Assoc`
...
LL | type Assoc = NotClone;
| ----- required by a bound in this associated type

error[E0277]: the trait bound `<Self as Foo2<T>>::Baz: Clone` is not satisfied
--> $DIR/defaults-suitability.rs:68:23
|
LL | type Bar: Clone = Vec<Self::Baz>;
| ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo2<T>>::Baz`, which is required by `Vec<<Self as Foo2<T>>::Baz>: Clone`
|
= note: required for `Vec<<Self as Foo2<T>>::Baz>` to implement `Clone`
note: required by a bound in `Foo2::Bar`
--> $DIR/defaults-suitability.rs:68:15
|
LL | type Bar: Clone = Vec<Self::Baz>;
| ^^^^^ required by this bound in `Foo2::Bar`
help: consider further restricting the associated type
|
LL | trait Foo2<T> where <Self as Foo2<T>>::Baz: Clone {
| +++++++++++++++++++++++++++++++++++

error[E0277]: the trait bound `<Self as Foo25<T>>::Baz: Clone` is not satisfied
--> $DIR/defaults-suitability.rs:77:23
|
LL | type Bar: Clone = Vec<Self::Baz>;
| ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo25<T>>::Baz`, which is required by `Vec<<Self as Foo25<T>>::Baz>: Clone`
|
= note: required for `Vec<<Self as Foo25<T>>::Baz>` to implement `Clone`
note: required by a bound in `Foo25::Bar`
--> $DIR/defaults-suitability.rs:77:15
|
LL | type Bar: Clone = Vec<Self::Baz>;
| ^^^^^ required by this bound in `Foo25::Bar`
help: consider further restricting the associated type
|
LL | trait Foo25<T: Clone> where <Self as Foo25<T>>::Baz: Clone {
| ++++++++++++++++++++++++++++++++++++

error[E0277]: the trait bound `T: Clone` is not satisfied
--> $DIR/defaults-suitability.rs:90:16
|
LL | type Baz = T;
| ^ the trait `Clone` is not implemented for `T`
|
note: required by a bound in `Foo3::Baz`
--> $DIR/defaults-suitability.rs:87:16
|
LL | Self::Baz: Clone,
| ^^^^^ required by this bound in `Foo3::Baz`
...
LL | type Baz = T;
| --- required by a bound in this associated type
help: consider further restricting type parameter `T`
|
LL | Self::Baz: Clone, T: std::clone::Clone
| ~~~~~~~~~~~~~~~~~~~~~~

error: aborting due to 8 previous errors

For more information about this error, try `rustc --explain E0277`.
3 changes: 3 additions & 0 deletions tests/ui/associated-types/defaults-suitability.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//! Checks that associated type defaults are properly validated.
//!
//! This means:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
error[E0277]: `Self` doesn't implement `std::fmt::Display`
--> $DIR/defaults-unsound-62211-1.rs:26:96
--> $DIR/defaults-unsound-62211-1.rs:24:96
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^ `Self` cannot be formatted with the default formatter
|
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `UncheckedCopy::Output`
--> $DIR/defaults-unsound-62211-1.rs:26:86
--> $DIR/defaults-unsound-62211-1.rs:24:86
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^^^^ required by this bound in `UncheckedCopy::Output`
Expand All @@ -16,13 +16,13 @@ LL | trait UncheckedCopy: Sized + std::fmt::Display {
| +++++++++++++++++++

error[E0277]: cannot add-assign `&'static str` to `Self`
--> $DIR/defaults-unsound-62211-1.rs:26:96
--> $DIR/defaults-unsound-62211-1.rs:24:96
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^ no implementation for `Self += &'static str`
|
note: required by a bound in `UncheckedCopy::Output`
--> $DIR/defaults-unsound-62211-1.rs:26:47
--> $DIR/defaults-unsound-62211-1.rs:24:47
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
Expand All @@ -32,13 +32,13 @@ LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
| +++++++++++++++++++++++++

error[E0277]: the trait bound `Self: Deref` is not satisfied
--> $DIR/defaults-unsound-62211-1.rs:26:96
--> $DIR/defaults-unsound-62211-1.rs:24:96
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^ the trait `Deref` is not implemented for `Self`
|
note: required by a bound in `UncheckedCopy::Output`
--> $DIR/defaults-unsound-62211-1.rs:26:25
--> $DIR/defaults-unsound-62211-1.rs:24:25
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
Expand All @@ -48,13 +48,13 @@ LL | trait UncheckedCopy: Sized + Deref {
| +++++++

error[E0277]: the trait bound `Self: Copy` is not satisfied
--> $DIR/defaults-unsound-62211-1.rs:26:96
--> $DIR/defaults-unsound-62211-1.rs:24:96
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^ the trait `Copy` is not implemented for `Self`
|
note: required by a bound in `UncheckedCopy::Output`
--> $DIR/defaults-unsound-62211-1.rs:26:18
--> $DIR/defaults-unsound-62211-1.rs:24:18
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^ required by this bound in `UncheckedCopy::Output`
Expand Down
Loading
Loading