Repository: rust-lang/rust
File: compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs (Rust)

Code before:
use rustc_type_ir::{self as ty, Interner};
use tracing::instrument;

use crate::delegate::SolverDelegate;
use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult};

impl<D, I> EvalCtxt<'_, D>
where
    D: SolverDelegate<Interner = I>,
    I: Interner,
{
    #[instrument(level = "trace", skip(self), ret)]
    pub(super) fn normalize_anon_const(
        &mut self,
        goal: Goal<I, ty::NormalizesTo<I>>,
    ) -> QueryResult<I> {
        // FIXME(ogca): should we also stop ogca normalization during coherence here or just in normalize_free_alias?
        if let Some(normalized_const) = self.evaluate_const(
            goal.param_env,
            ty::UnevaluatedConst::new(
                goal.predicate.alias.def_id.try_into().unwrap(),
                goal.predicate.alias.args,
            ),
        ) {
            self.instantiate_normalizes_to_term(goal, normalized_const.into());
            self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
        } else {
            self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
        }
    }
}


Review comment (bug):
The existing logic here implicitly gives ambiguity during coherence but also *outside* of coherence which I think is undesirable. In the failure case we should check if `goal.predicate.alias.def_id` is an oGCA anon const, and if so return `NoSolution` if we're outside of coherence, otherwise return `AMBIGUOUS`

If we don't do this I think we'll get type inference errors whenever the new solver tries to normalize oGCA anon consts 🤔 e.g.
```rust
//@ compile-flags: -Znext-solver
#![feature(generic_const_items, min_generic_const_args, opaque_generic_const_args)]

#[type_const]
const FOO<const N: usize>: usize = const { N + 1 };

fn foo() {
    let a: [(); FOO::<1>];
}
```
probably fails under your PR right now?

Code after:
use rustc_type_ir::{self as ty, Interner, TypingMode};
use tracing::instrument;

use crate::delegate::SolverDelegate;
use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult};

impl<D, I> EvalCtxt<'_, D>
where
    D: SolverDelegate<Interner = I>,
    I: Interner,
{
    #[instrument(level = "trace", skip(self), ret)]
    pub(super) fn normalize_anon_const(
        &mut self,
        goal: Goal<I, ty::NormalizesTo<I>>,
    ) -> QueryResult<I> {
        if self.typing_mode() == TypingMode::Coherence
            && self.cx().anon_const_kind(goal.predicate.alias.def_id) == ty::AnonConstKind::OGCA
        {
            // During coherence, OGCA consts should be normalized ambiguously
            // because they are opaque but eventually resolved to a real value.
            // We don't want two OGCAs that have the same value to be treated
            // as distinct for coherence purposes. (Just like opaque types.)
            //
            // We can't rely on evaluate_const below because that particular wrapper
            // treats too-generic consts as a successful evaluation.
            self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
        } else if let Some(normalized_const) = self.evaluate_const(
            goal.param_env,
            ty::UnevaluatedConst::new(
                goal.predicate.alias.def_id.try_into().unwrap(),
                goal.predicate.alias.args,
            ),
        ) {
            self.instantiate_normalizes_to_term(goal, normalized_const.into());
            self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
        } else {
            self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
        }
    }
}