Skip to content
Open
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
12 changes: 12 additions & 0 deletions compiler/rustc_trait_selection/src/solve/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ where
}

let ty::ConstKind::Unevaluated(..) = ct.kind() else { return ct.try_super_fold_with(self) };
// FIXME: `generic_const_exprs` not implemented in the next solver.
if ct.has_non_region_param() {
return Ok(ct);
}

if ct.has_escaping_bound_vars() {
let (ct, mapped_regions, mapped_types, mapped_consts) =
Expand All @@ -240,6 +244,14 @@ where
Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const())
}
}

#[instrument(level = "trace", skip(self), ret)]
fn try_fold_predicate(
&mut self,
p: ty::Predicate<'tcx>,
) -> Result<ty::Predicate<'tcx>, Self::Error> {
if p.allow_normalization() { p.try_super_fold_with(self) } else { Ok(p) }
}
}

// Deeply normalize a value and return it
Expand Down
62 changes: 60 additions & 2 deletions compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ fn do_normalize_predicates<'tcx>(
predicates: Vec<ty::Clause<'tcx>>,
) -> Result<Vec<ty::Clause<'tcx>>, ErrorGuaranteed> {
let span = cause.span;
let original_predicates = predicates.clone();

// FIXME. We should really... do something with these region
// obligations. But this call just continues the older
Expand Down Expand Up @@ -296,8 +297,8 @@ fn do_normalize_predicates<'tcx>(
);
}

match infcx.fully_resolve(predicates) {
Ok(predicates) => Ok(predicates),
let predicates = match infcx.fully_resolve(predicates) {
Ok(predicates) => predicates,
Err(fixup_err) => {
// If we encounter a fixup error, it means that some type
// variable wound up unconstrained. I actually don't know
Expand All @@ -314,7 +315,64 @@ fn do_normalize_predicates<'tcx>(
fixup_err
);
}
};
// The next solver returns nothing for values that contains type error.
// And type error should cause failure later. So we skip the consistency check.
// `generic_const_exprs` is incompatible with next solver now.
if !tcx.next_trait_solver_globally()
&& !predicates.references_error()
&& !tcx.features().generic_const_exprs()
{
let infcx = tcx
.infer_ctxt()
.with_next_trait_solver(true)
.ignoring_regions()
.build(TypingMode::non_body_analysis());
let predicates_by_next: Vec<Option<_>> = original_predicates
.iter()
.cloned()
.map(|p| {
crate::solve::deeply_normalize::<_, ScrubbedTraitError<'tcx>>(
infcx.at(&cause, elaborated_env),
p,
)
.ok()
})
.collect();

// FIXME: next solver adds region constraints that contains placeholders to infcx.
// `infcx.considering_regions` is not checked.
let _errors = infcx.resolve_regions(cause.body_id, elaborated_env, []);

let predicates_by_next = match infcx.fully_resolve(predicates_by_next) {
Ok(predicates) => predicates,
Err(fixup_err) => {
span_bug!(
span,
"inference variables in normalized parameter environment: {}",
fixup_err
);
}
};

for ((orig_pred, old_pred), next_pred) in
original_predicates.iter().zip(&predicates).zip(&predicates_by_next)
{
if let Some(next_pred) = next_pred
&& next_pred == old_pred
{
continue;
}
tcx.dcx().span_err(
span,
format!(
"inconsistency during normalizing env `{:#?}`, old={:#?}, next={:#?}",
orig_pred, old_pred, next_pred
),
);
}
}
Ok(predicates)
}

// FIXME: this is gonna need to be removed ...
Expand Down
6 changes: 5 additions & 1 deletion tests/ui/specialization/fuzzed/fuzzing-ice-134905.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ where
}

trait Check {}
impl<'a, T> Eq for T where <T as Iterate<'a>>::Ty: Valid {}
impl<'a, T> Eq for T
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
where
T: Iterate<'a>,
<T as Iterate<'a>>::Ty: Valid,
{}

trait Valid {}

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/specialization/fuzzed/fuzzing-ice-134905.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ LL | default type Ty = ();
| ^^ the trait `Valid` is not implemented for `()`
|
help: this trait has no implementations, consider adding one
--> $DIR/fuzzing-ice-134905.rs:20:1
--> $DIR/fuzzing-ice-134905.rs:24:1
|
LL | trait Valid {}
| ^^^^^^^^^^^
Expand All @@ -28,7 +28,7 @@ LL | type Ty: Valid;
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
--> $DIR/fuzzing-ice-134905.rs:17:10
|
LL | impl<'a, T> Eq for T where <T as Iterate<'a>>::Ty: Valid {}
LL | impl<'a, T> Eq for T
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
Expand Down
9 changes: 5 additions & 4 deletions tests/ui/specialization/issue-38091-2.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//@ build-fail
//~^ ERROR overflow evaluating the requirement `i32: Check`

#![feature(specialization)]
//~^ WARN the feature `specialization` is incomplete

Expand All @@ -17,7 +14,11 @@ where
}

trait Check {}
impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
impl<'a, T> Check for T
//~^ ERROR: overflow evaluating the requirement `T: Check`
where
T: Iterate<'a>,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should projection alias in param env imply that the trait predicate holds for the next solver?
I add manual trait clause for these three specialization tests to avoid unnecessary lint triggering.

<T as Iterate<'a>>::Ty: Valid {}

trait Valid {}

Expand Down
27 changes: 23 additions & 4 deletions tests/ui/specialization/issue-38091-2.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-38091-2.rs:4:12
--> $DIR/issue-38091-2.rs:1:12
|
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
Expand All @@ -8,16 +8,35 @@ LL | #![feature(specialization)]
= help: consider using `min_specialization` instead, which is more stable and complete
= note: `#[warn(incomplete_features)]` on by default

error[E0275]: overflow evaluating the requirement `i32: Check`
error[E0275]: overflow evaluating the requirement `T: Check`
--> $DIR/issue-38091-2.rs:17:1
|
note: required for `i32` to implement `Iterate<'_>`
--> $DIR/issue-38091-2.rs:11:13
LL | / impl<'a, T> Check for T
LL | |
LL | | where
LL | | T: Iterate<'a>,
LL | | <T as Iterate<'a>>::Ty: Valid {}
| |_________________________________^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_38091_2`)
note: required for `T` to implement `Iterate<'_>`
--> $DIR/issue-38091-2.rs:8:13
|
LL | impl<'a, T> Iterate<'a> for T
| ^^^^^^^^^^^ ^
LL | where
LL | T: Check,
| ----- unsatisfied trait bound introduced here
note: required for `T` to implement `Check`
--> $DIR/issue-38091-2.rs:17:13
|
LL | impl<'a, T> Check for T
| ^^^^^ ^
...
LL | <T as Iterate<'a>>::Ty: Valid {}
| ----- unsatisfied trait bound introduced here
= note: 125 redundant requirements hidden
= note: required for `T` to implement `Iterate<'a>`

error: aborting due to 1 previous error; 1 warning emitted

Expand Down
7 changes: 6 additions & 1 deletion tests/ui/specialization/issue-38091.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ where
}

trait Check {}
impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
impl<'a, T> Check for T
//~^ ERROR: overflow evaluating the requirement `T: Check`
where
T: Iterate<'a>,
<T as Iterate<'a>>::Ty: Valid,
{}

trait Valid {}

Expand Down
37 changes: 34 additions & 3 deletions tests/ui/specialization/issue-38091.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ LL | default type Ty = ();
| ^^ the trait `Valid` is not implemented for `()`
|
help: this trait has no implementations, consider adding one
--> $DIR/issue-38091.rs:20:1
--> $DIR/issue-38091.rs:25:1
|
LL | trait Valid {}
| ^^^^^^^^^^^
Expand All @@ -25,6 +25,37 @@ note: required by a bound in `Iterate::Ty`
LL | type Ty: Valid;
| ^^^^^ required by this bound in `Iterate::Ty`

error: aborting due to 1 previous error; 1 warning emitted
error[E0275]: overflow evaluating the requirement `T: Check`
--> $DIR/issue-38091.rs:18:1
|
LL | / impl<'a, T> Check for T
LL | |
LL | | where
LL | | T: Iterate<'a>,
LL | | <T as Iterate<'a>>::Ty: Valid,
| |__________________________________^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_38091`)
note: required for `T` to implement `Iterate<'_>`
--> $DIR/issue-38091.rs:8:13
|
LL | impl<'a, T> Iterate<'a> for T
| ^^^^^^^^^^^ ^
LL | where
LL | T: Check,
| ----- unsatisfied trait bound introduced here
note: required for `T` to implement `Check`
--> $DIR/issue-38091.rs:18:13
|
LL | impl<'a, T> Check for T
| ^^^^^ ^
...
LL | <T as Iterate<'a>>::Ty: Valid,
| ----- unsatisfied trait bound introduced here
= note: 125 redundant requirements hidden
= note: required for `T` to implement `Iterate<'a>`

error: aborting due to 2 previous errors; 1 warning emitted

For more information about this error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0275, E0277.
For more information about an error, try `rustc --explain E0275`.
100 changes: 20 additions & 80 deletions tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,94 +6,34 @@ LL | #![feature(const_trait_impl, generic_const_exprs)]
|
= help: remove one of these features

error[E0391]: cycle detected when evaluating type-level constant
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
error[E0277]: the trait bound `T: const Trait` is not satisfied
--> $DIR/unsatisfied-const-trait-bound.rs:28:37
|
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `accept0::{constant#0}`...
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
|
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
note: ...which requires checking if `accept0::{constant#0}` is a trivial const...
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
|
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
note: ...which requires building MIR for `accept0::{constant#0}`...
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
|
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
note: ...which requires building an abstract representation for `accept0::{constant#0}`...
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
|
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
note: ...which requires building THIR for `accept0::{constant#0}`...
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
|
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
note: ...which requires type-checking `accept0::{constant#0}`...
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
|
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
= note: ...which again requires evaluating type-level constant, completing the cycle
note: cycle used when checking that `accept0` is well-formed
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
|
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
| ^

error[E0391]: cycle detected when checking if `accept1::{constant#0}` is a trivial const
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
|
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
|
note: ...which requires building MIR for `accept1::{constant#0}`...
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
error[E0277]: the trait bound `T: const Trait` is not satisfied
--> $DIR/unsatisfied-const-trait-bound.rs:32:51
|
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
note: ...which requires building an abstract representation for `accept1::{constant#0}`...
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
|
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
note: ...which requires building THIR for `accept1::{constant#0}`...
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
|
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
note: ...which requires type-checking `accept1::{constant#0}`...
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
| ^

error[E0277]: the trait bound `Ty: const Trait` is not satisfied
--> $DIR/unsatisfied-const-trait-bound.rs:21:15
|
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
note: ...which requires evaluating type-level constant...
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
LL | require::<Ty>();
| ^^
|
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `accept1::{constant#0}`...
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
note: required by a bound in `require`
--> $DIR/unsatisfied-const-trait-bound.rs:8:15
|
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
= note: ...which again requires checking if `accept1::{constant#0}` is a trivial const, completing the cycle
note: cycle used when const-evaluating + checking `accept1::{constant#0}`
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
LL | fn require<T: const Trait>() {}
| ^^^^^^^^^^^ required by this bound in `require`
help: make the `impl` of trait `Trait` `const`
|
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
| ^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
LL | impl const Trait for Ty {
| +++++

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

For more information about this error, try `rustc --explain E0391`.
For more information about this error, try `rustc --explain E0277`.
Loading
Loading