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
3 changes: 2 additions & 1 deletion compiler/rustc_trait_selection/src/solve/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ where
fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
let infcx = self.at.infcx;
debug_assert_eq!(ct, infcx.shallow_resolve_const(ct));
if !ct.has_aliases() {
// FIXME: `generic_const_exprs` causes query cycle problem. Same as the old solver.
if !ct.has_aliases() || infcx.tcx.features().generic_const_exprs() {
Comment on lines +220 to +221
Copy link
Contributor

Choose a reason for hiding this comment

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

hmm, disable the lint if generic_const_exprs is enabled instead

return Ok(ct);
}

Expand Down
33 changes: 33 additions & 0 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 All @@ -283,6 +284,38 @@ fn do_normalize_predicates<'tcx>(

debug!("do_normalize_predicates: normalized predicates = {:?}", predicates);

// The next solver returns nothing for values that contains type error.
// And type error should cause failure later. So we skip the consistency check.
if !tcx.next_trait_solver_globally() && !predicates.references_error() {
let infcx = tcx
.infer_ctxt()
.with_next_trait_solver(true)
.ignoring_regions()
.build(TypingMode::non_body_analysis());
for (orig_pred, pred_by_old) in original_predicates.into_iter().zip(&predicates) {
let inconsistent_pred_by_next =
match crate::solve::deeply_normalize::<_, ScrubbedTraitError<'tcx>>(
infcx.at(&cause, elaborated_env),
orig_pred,
) {
Ok(pred_by_next) => {
if pred_by_next == *pred_by_old {
continue;
}
Some(pred_by_next)
}
Err(_) => None,
};
tcx.dcx().span_err(
span,
format!(
"inconsistency during normalizing env `{:#?}`, old={:#?}, next={:#?}",
orig_pred, pred_by_old, inconsistent_pred_by_next
),
);
}
}

// We can use the `elaborated_env` here; the region code only
// cares about declarations like `'a: 'b`.
// FIXME: It's very weird that we ignore region obligations but apparently
Expand Down
4 changes: 3 additions & 1 deletion tests/ui/const-generics/generic_const_exprs/cross-crate-2.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//@ check-pass
//@ aux-build: cross-crate-2.rs

//~? ERROR: inconsistency during normalizing env
//~? ERROR: inconsistency during normalizing env

extern crate cross_crate_2;

use cross_crate_2::Foo;
Expand Down
18 changes: 18 additions & 0 deletions tests/ui/const-generics/generic_const_exprs/cross-crate-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error: inconsistency during normalizing env `Binder { value: ConstEvaluatable(UnevaluatedConst { def: DefId(20:8 ~ cross_crate_2[bdab]::{impl#0}::{constant#0}), args: [N/#0] }), bound_vars: [] }`, old=Binder { value: ConstEvaluatable(UnevaluatedConst { def: DefId(20:8 ~ cross_crate_2[bdab]::{impl#0}::{constant#0}), args: [N/#0] }), bound_vars: [] }, next=Some(
Binder { value: ConstEvaluatable({const error}), bound_vars: [] },
)
--> $DIR/auxiliary/cross-crate-2.rs:10:5
|
LL | pub fn new() -> Self {
| ^^^^^^^^^^^^^^^^^^^^

error: inconsistency during normalizing env `Binder { value: TraitPredicate(<[u8; cross_crate_2::::{impl#0}::{constant#0}] as std::marker::Sized>, polarity:Positive), bound_vars: [] }`, old=Binder { value: TraitPredicate(<[u8; cross_crate_2::::{impl#0}::{constant#0}] as std::marker::Sized>, polarity:Positive), bound_vars: [] }, next=Some(
Binder { value: TraitPredicate(<[u8; {const error}] as std::marker::Sized>, polarity:Positive), bound_vars: [] },
)
--> $DIR/auxiliary/cross-crate-2.rs:10:5
|
LL | pub fn new() -> Self {
| ^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ trait Trait {}
impl<const N: u32> Trait for A<N> {}

impl<const N: u32> Trait for A<N> {}
//~^ ERROR: conflicting implementations of trait

pub fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ error[E0423]: expected value, found builtin type `u8`
LL | struct A<const N: u32 = 1, const M: u32 = u8>;
| ^^ not a value

error: aborting due to 1 previous error
error[E0119]: conflicting implementations of trait `Trait` for type `A<_>`
--> $DIR/unknown-alias-defkind-anonconst-ice-116710.rs:12:1
|
LL | impl<const N: u32> Trait for A<N> {}
| --------------------------------- first implementation here
LL |
LL | impl<const N: u32> Trait for A<N> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A<_>`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0423`.
Some errors have detailed explanations: E0119, E0423.
For more information about an error, try `rustc --explain E0119`.
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`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error: inconsistency during normalizing env `Binder { value: TraitPredicate(<<T as Trait>::Assoc as Trait>, polarity:Positive), bound_vars: [] }`, old=Binder { value: TraitPredicate(<T as Trait>, polarity:Positive), bound_vars: [] }, next=None
--> $DIR/normalize-param-env-4.rs:16:1
|
LL | / fn foo<T>()
LL | |
LL | |
LL | | where
LL | | <T as Trait>::Assoc: Trait,
| |_______________________________^

error: inconsistency during normalizing env `Binder { value: TraitPredicate(<<T as Trait>::Assoc as std::marker::MetaSized>, polarity:Positive), bound_vars: [] }`, old=Binder { value: TraitPredicate(<T as std::marker::MetaSized>, polarity:Positive), bound_vars: [] }, next=None
--> $DIR/normalize-param-env-4.rs:16:1
|
LL | / fn foo<T>()
LL | |
LL | |
LL | | where
LL | | <T as Trait>::Assoc: Trait,
| |_______________________________^

error: aborting due to 2 previous errors

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: Trait`
--> $DIR/normalize-param-env-4.rs:19:26
--> $DIR/normalize-param-env-4.rs:20:26
|
LL | <T as Trait>::Assoc: Trait,
| ^^^^^
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@[next] known-bug: #92505
//@[current] check-pass

trait Trait {
type Assoc;
Expand All @@ -15,6 +14,8 @@ impl<T> Trait for T {
fn impls_trait<T: Trait>() {}

fn foo<T>()
//[current]~^ ERROR: inconsistency during normalizing env
//[current]~| ERROR: inconsistency during normalizing env
where
<T as Trait>::Assoc: Trait,
{
Expand Down
Loading