Skip to content

Commit 67daa02

Browse files
committed
Normalize OGCA ambiguously for coherence purposes
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.)
1 parent 7dc3a0c commit 67daa02

9 files changed

Lines changed: 81 additions & 21 deletions

File tree

compiler/rustc_middle/src/ty/consts.rs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::borrow::Cow;
22

33
use rustc_data_structures::intern::Interned;
44
use rustc_error_messages::MultiSpan;
5-
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
5+
use rustc_macros::HashStable;
66
use rustc_type_ir::walk::TypeWalker;
77
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
88

@@ -335,19 +335,3 @@ impl<'tcx> Const<'tcx> {
335335
TypeWalker::new(self.into())
336336
}
337337
}
338-
339-
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, HashStable)]
340-
pub enum AnonConstKind {
341-
/// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope
342-
GCE,
343-
/// stable `min_const_generics` anon consts are not allowed to use any generic parameters
344-
MCG,
345-
/// `feature(opaque_generic_const_args)` anon consts are allowed to use arbitrary
346-
/// generic parameters in scope, but only if they syntactically reference them.
347-
OGCA,
348-
/// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters
349-
/// but must not depend on the actual instantiation. See #76200 for more information
350-
RepeatExprCount,
351-
/// anon consts outside of the type system, e.g. enum discriminants
352-
NonTypeSystem,
353-
}

compiler/rustc_middle/src/ty/context.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
245245
fn const_of_item(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
246246
self.const_of_item(def_id)
247247
}
248+
fn anon_const_kind(self, def_id: DefId) -> ty::AnonConstKind {
249+
self.anon_const_kind(def_id)
250+
}
248251

249252
type AdtDef = ty::AdtDef<'tcx>;
250253
fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef {

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ pub use self::closure::{
7676
place_to_string_for_capture,
7777
};
7878
pub use self::consts::{
79-
AnonConstKind, AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr,
80-
ExprKind, ScalarInt, SimdAlign, UnevaluatedConst, ValTree, ValTreeKindExt, Value,
79+
AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr, ExprKind, ScalarInt,
80+
SimdAlign, UnevaluatedConst, ValTree, ValTreeKindExt, Value,
8181
};
8282
pub use self::context::{
8383
CtxtInterners, CurrentGcx, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls,

compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ where
1414
&mut self,
1515
goal: Goal<I, ty::NormalizesTo<I>>,
1616
) -> QueryResult<I> {
17+
// FIXME(ogca): should we also stop ogca normalization during coherence here or just in normalize_free_alias?
1718
if let Some(normalized_const) = self.evaluate_const(
1819
goal.param_env,
1920
ty::UnevaluatedConst::new(

compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
//! Since a free alias is never ambiguous, this just computes the `type_of` of
55
//! the alias and registers the where-clauses of the type alias.
66
7-
use rustc_type_ir::{self as ty, Interner};
7+
use rustc_type_ir::inherent::*;
8+
use rustc_type_ir::{self as ty,TypingMode, Interner};
89

910
use crate::delegate::SolverDelegate;
1011
use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource, QueryResult};
@@ -32,7 +33,19 @@ where
3233
let actual = if free_alias.kind(cx).is_type() {
3334
cx.type_of(free_alias.def_id).instantiate(cx, free_alias.args).into()
3435
} else {
35-
cx.const_of_item(free_alias.def_id).instantiate(cx, free_alias.args).into()
36+
let ct = cx.const_of_item(free_alias.def_id).instantiate(cx, free_alias.args);
37+
if self.typing_mode() == TypingMode::Coherence
38+
&& let ty::ConstKind::Unevaluated(uv) = ct.kind()
39+
&& self.cx().anon_const_kind(uv.def.into()) == ty::AnonConstKind::OGCA
40+
{
41+
// During coherence, OGCA consts should be normalized ambiguously
42+
// because they are opaque but eventually resolved to a real value.
43+
// We don't want two OGCAs that have the same value to be treated
44+
// as distinct for coherence purposes.
45+
// (Just like opaque types.)
46+
return self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
47+
}
48+
ct.into()
3649
};
3750

3851
self.instantiate_normalizes_to_term(goal, actual);

compiler/rustc_type_ir/src/const_kind.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,23 @@ impl<I: Interner> ValTreeKind<I> {
200200
}
201201
}
202202
}
203+
204+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
205+
#[cfg_attr(
206+
feature = "nightly",
207+
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
208+
)]
209+
pub enum AnonConstKind {
210+
/// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope
211+
GCE,
212+
/// stable `min_const_generics` anon consts are not allowed to use any generic parameters
213+
MCG,
214+
/// `feature(opaque_generic_const_args)` anon consts are allowed to use arbitrary
215+
/// generic parameters in scope, but only if they syntactically reference them.
216+
OGCA,
217+
/// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters
218+
/// but must not depend on the actual instantiation. See #76200 for more information
219+
RepeatExprCount,
220+
/// anon consts outside of the type system, e.g. enum discriminants
221+
NonTypeSystem,
222+
}

compiler/rustc_type_ir/src/interner.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ pub trait Interner:
207207
fn type_of_opaque_hir_typeck(self, def_id: Self::LocalDefId)
208208
-> ty::EarlyBinder<Self, Self::Ty>;
209209
fn const_of_item(self, def_id: Self::DefId) -> ty::EarlyBinder<Self, Self::Const>;
210+
fn anon_const_kind(self, def_id: Self::DefId) -> ty::AnonConstKind;
210211

211212
type AdtDef: AdtDef<Self>;
212213
fn adt_def(self, adt_def_id: Self::AdtId) -> Self::AdtDef;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![feature(generic_const_items, min_generic_const_args, opaque_generic_const_args)]
2+
#![expect(incomplete_features)]
3+
4+
#[type_const]
5+
const FOO<const N: usize>: usize = const { N + 1 };
6+
7+
#[type_const]
8+
const BAR<const N: usize>: usize = const { N + 1 };
9+
10+
trait Trait {}
11+
12+
impl Trait for [(); FOO::<1>] {}
13+
impl Trait for [(); BAR::<1>] {}
14+
//~^ ERROR conflicting implementations of trait `Trait` for type `[(); FOO::<1>]`
15+
impl Trait for [(); BAR::<2>] {}
16+
//~^ ERROR conflicting implementations of trait `Trait` for type `[(); FOO::<1>]`
17+
18+
fn main() {}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0119]: conflicting implementations of trait `Trait` for type `[(); FOO::<1>]`
2+
--> $DIR/coherence-ambiguous.rs:13:1
3+
|
4+
LL | impl Trait for [(); FOO::<1>] {}
5+
| ----------------------------- first implementation here
6+
LL | impl Trait for [(); BAR::<1>] {}
7+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); FOO::<1>]`
8+
9+
error[E0119]: conflicting implementations of trait `Trait` for type `[(); FOO::<1>]`
10+
--> $DIR/coherence-ambiguous.rs:15:1
11+
|
12+
LL | impl Trait for [(); FOO::<1>] {}
13+
| ----------------------------- first implementation here
14+
...
15+
LL | impl Trait for [(); BAR::<2>] {}
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); FOO::<1>]`
17+
18+
error: aborting due to 2 previous errors
19+
20+
For more information about this error, try `rustc --explain E0119`.

0 commit comments

Comments
 (0)