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
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/type_check/relate_tys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,8 +617,8 @@ impl<'b, 'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for NllTypeRelating<'_
})]);
}

fn try_eagerly_normalize_alias(&mut self, _alias: ty::AliasTy<'tcx>) -> Ty<'tcx> {
fn try_eagerly_normalize_alias(&mut self, alias: ty::AliasTerm<'tcx>) -> ty::Term<'tcx> {
// Past hir typeck, so we don't have to worry about type inference anymore.
self.type_checker.infcx.next_ty_var(self.span())
self.type_checker.infcx.next_term_var_of_alias_kind(alias, self.span())
}
}
16 changes: 14 additions & 2 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,18 @@ impl<'tcx> InferCtxt<'tcx> {
}
}

pub fn next_term_var_of_alias_kind(
&self,
alias: ty::AliasTerm<'tcx>,
span: Span,
) -> ty::Term<'tcx> {
if alias.kind(self.tcx).is_type() {
self.next_ty_var(span).into()
} else {
self.next_const_var(span).into()
}
}

/// Return the universe that the region `r` was created in. For
/// most regions (e.g., `'static`, named regions from the user,
/// etc) this is the root universe U0. For inference variables or
Expand Down Expand Up @@ -1533,8 +1545,8 @@ impl<'tcx> InferCtxt<'tcx> {
&'a self,
param_env: ty::ParamEnv<'tcx>,
span: Span,
alias: ty::AliasTy<'tcx>,
) -> Ty<'tcx> {
alias: ty::AliasTerm<'tcx>,
) -> Term<'tcx> {
let erased =
unsafe { mem::transmute::<&'a InferCtxt<'tcx>, TypeErasedInfcx<'a, 'tcx>>(self) };
self.tcx.try_eagerly_normalize_alias(erased, param_env, span, alias)
Expand Down
365 changes: 205 additions & 160 deletions compiler/rustc_infer/src/infer/relate/generalize.rs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/relate/lattice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
))]);
}

fn try_eagerly_normalize_alias(&mut self, alias: ty::AliasTy<'tcx>) -> Ty<'tcx> {
fn try_eagerly_normalize_alias(&mut self, alias: ty::AliasTerm<'tcx>) -> ty::Term<'tcx> {
self.infcx.try_eagerly_normalize_alias(self.param_env(), self.span(), alias)
}
}
4 changes: 2 additions & 2 deletions compiler/rustc_infer/src/infer/relate/type_relating.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,8 @@ impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for TypeRelating<'_, 'tcx>

fn try_eagerly_normalize_alias(
&mut self,
_alias: rustc_type_ir::AliasTy<<InferCtxt<'tcx> as rustc_type_ir::InferCtxtLike>::Interner>,
) -> <<InferCtxt<'tcx> as rustc_type_ir::InferCtxtLike>::Interner as rustc_type_ir::Interner>::Ty
_alias: rustc_type_ir::AliasTerm<<InferCtxt<'tcx> as rustc_type_ir::InferCtxtLike>::Interner>,
) -> <<InferCtxt<'tcx> as rustc_type_ir::InferCtxtLike>::Interner as rustc_type_ir::Interner>::Term
{
// We only try to eagerly normalize aliases if we're using the new solver.
unreachable!()
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_infer/src/infer/unify_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ impl<'tcx> ConstVariableValue<'tcx> {
ConstVariableValue::Known { value } => Some(value),
}
}

pub(crate) fn is_unknown(&self) -> bool {
match *self {
ConstVariableValue::Unknown { .. } => true,
ConstVariableValue::Known { .. } => false,
}
}
}

#[derive(PartialEq, Copy, Clone, Debug)]
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/hooks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ declare_hooks! {
type_erased_infcx: TypeErasedInfcx<'_, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Span,
alias: ty::AliasTy<'tcx>
) -> Ty<'tcx>;
alias: ty::AliasTerm<'tcx>
) -> ty::Term<'tcx>;
}

/// The `try_eagerly_normalize_alias` hook passes an `Infcx` from where it's called (in `rustc_infer`)
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,13 @@ impl<'tcx> Const<'tcx> {
matches!(self.kind(), ty::ConstKind::Infer(_))
}

pub fn ct_vid(self) -> Option<ty::ConstVid> {
match self.kind() {
ConstKind::Infer(ty::InferConst::Var(vid)) => Some(vid),
_ => None,
}
}

/// Iterator that walks `self` and any types reachable from
/// `self`, in depth-first order. Note that just walks the types
/// that appear in `self`, it does not descend into the fields of
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,13 @@ impl<'tcx> Term<'tcx> {
}
}

pub fn term_vid(self) -> Option<TermVid> {
match self.kind() {
TermKind::Ty(ty) => ty.ty_vid().map(TermVid::Ty),
TermKind::Const(ct) => ct.ct_vid().map(TermVid::Const),
}
}

pub fn is_trivially_wf(&self, tcx: TyCtxt<'tcx>) -> bool {
match self.kind() {
TermKind::Ty(ty) => ty.is_trivially_wf(tcx),
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1051,15 +1051,16 @@ where
let delegate = self.delegate;
let origin_span = self.origin_span;

let mut normalize = |alias: ty::AliasTy<I>| {
let inference_var = self.next_ty_infer();
let mut normalize = |alias: ty::AliasTerm<I>| {
let term = alias.to_term(cx);
let inference_var = self.next_term_infer_of_kind(term);

let goal = Goal::new(
cx,
param_env,
ty::PredicateKind::AliasRelate(
alias.to_ty(cx).into(),
inference_var.into(),
term,
inference_var,
ty::AliasRelationDirection::Equate,
),
);
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_trait_selection/src/solve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub use normalize::{
deeply_normalize, deeply_normalize_with_skipped_universes,
deeply_normalize_with_skipped_universes_and_ambiguous_coroutine_goals,
};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::util::Providers;
use rustc_span::Span;
pub use select::InferCtxtSelectExt;
Expand All @@ -40,15 +40,15 @@ fn try_eagerly_normalize_alias<'a, 'tcx>(
type_erased_infcx: TypeErasedInfcx<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Span,
alias: ty::AliasTy<'tcx>,
) -> Ty<'tcx> {
alias: ty::AliasTerm<'tcx>,
) -> ty::Term<'tcx> {
let infcx = unsafe {
mem::transmute::<TypeErasedInfcx<'a, 'tcx>, &'a InferCtxt<'tcx>>(type_erased_infcx)
};

let ocx = ObligationCtxt::new(infcx);

let infer_term = infcx.next_ty_var(span);
let infer_term = infcx.next_term_var_of_alias_kind(alias, span);

// Dummy because we ignore the error anyway.
// We do provide a span, because this span is used when registering opaque types.
Expand All @@ -59,8 +59,8 @@ fn try_eagerly_normalize_alias<'a, 'tcx>(
cause,
param_env,
ty::PredicateKind::AliasRelate(
alias.to_ty(tcx).into(),
infer_term.into(),
alias.to_term(tcx),
infer_term,
ty::AliasRelationDirection::Equate,
),
);
Expand Down
13 changes: 0 additions & 13 deletions compiler/rustc_type_ir/src/generic_arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,3 @@ pub enum GenericArgKind<I: Interner> {
}

impl<I: Interner> Eq for GenericArgKind<I> {}

#[derive_where(Clone, Copy, PartialEq, Debug; I: Interner)]
#[derive(GenericTypeVisitable)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
)]
pub enum TermKind<I: Interner> {
Ty(I::Ty),
Const(I::Const),
}

impl<I: Interner> Eq for TermKind<I> {}
2 changes: 2 additions & 0 deletions compiler/rustc_type_ir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ mod pattern;
mod predicate;
mod predicate_kind;
mod region_kind;
mod term;
mod ty_info;
mod ty_kind;
mod upcast;
Expand Down Expand Up @@ -78,6 +79,7 @@ pub use predicate_kind::*;
pub use region_kind::*;
pub use rustc_ast_ir::{FloatTy, IntTy, Movability, Mutability, Pinnedness, UintTy};
use rustc_type_ir_macros::GenericTypeVisitable;
pub use term::*;
pub use ty_info::*;
pub use ty_kind::*;
pub use upcast::*;
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_type_ir/src/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,21 @@ impl<I: Interner> Relate<I> for ty::ExistentialTraitRef<I> {
}
}

#[instrument(level = "trace", skip(relation), ret)]
pub fn structurally_relate_terms<I: Interner, R: TypeRelation<I>>(
relation: &mut R,
a: I::Term,
b: I::Term,
) -> RelateResult<I, I::Term> {
if let (Some(a), Some(b)) = (a.as_type(), b.as_type()) {
structurally_relate_tys(relation, a, b).map(|v| v.into())
} else if let (Some(a), Some(b)) = (a.as_const(), b.as_const()) {
structurally_relate_consts(relation, a, b).map(|v| v.into())
} else {
panic!("two different kinds passed into structurally_relate_terms: {a:?}, {b:?}")
}
}

/// Relates `a` and `b` structurally, calling the relation for all nested values.
/// Any semantic equality, e.g. of projections, and inference variables have to be
/// handled by the caller.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_type_ir/src/relate/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ where
/// Register `AliasRelate` obligation(s) that both types must be related to each other.
fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty);

fn try_eagerly_normalize_alias(&mut self, alias: ty::AliasTy<I>) -> I::Ty;
fn try_eagerly_normalize_alias(&mut self, alias: ty::AliasTerm<I>) -> I::Term;
}

pub fn super_combine_tys<Infcx, I, R>(
Expand Down
12 changes: 7 additions & 5 deletions compiler/rustc_type_ir/src/relate/solver_relating.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ pub trait RelateExt: InferCtxtLike {
variance: ty::Variance,
rhs: T,
span: <Self::Interner as Interner>::Span,
normalize: &mut dyn FnMut(ty::AliasTy<Self::Interner>) -> <Self::Interner as Interner>::Ty,
normalize: &mut dyn FnMut(
ty::AliasTerm<Self::Interner>,
) -> <Self::Interner as Interner>::Term,
) -> Result<
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
TypeError<Self::Interner>,
Expand All @@ -41,7 +43,7 @@ impl<I: Interner, Infcx: InferCtxtLike<Interner = I>> RelateExt for Infcx {
variance: ty::Variance,
rhs: T,
span: I::Span,
normalize: &mut dyn FnMut(ty::AliasTy<I>) -> I::Ty,
normalize: &mut dyn FnMut(ty::AliasTerm<I>) -> I::Term,
) -> Result<Vec<Goal<I, I::Predicate>>, TypeError<I>> {
let mut relate = SolverRelating::new(
self,
Expand Down Expand Up @@ -89,7 +91,7 @@ pub struct SolverRelating<'infcx, Infcx, I: Interner> {
span: I::Span,
// Mutable fields.
ambient_variance: ty::Variance,
normalize: &'infcx mut dyn FnMut(ty::AliasTy<I>) -> I::Ty,
normalize: &'infcx mut dyn FnMut(ty::AliasTerm<I>) -> I::Term,
goals: Vec<Goal<I, I::Predicate>>,
/// The cache only tracks the `ambient_variance` as it's the
/// only field which is mutable and which meaningfully changes
Expand Down Expand Up @@ -127,7 +129,7 @@ where
ambient_variance: ty::Variance,
param_env: I::ParamEnv,
span: I::Span,
normalize: &'infcx mut dyn FnMut(ty::AliasTy<I>) -> I::Ty,
normalize: &'infcx mut dyn FnMut(ty::AliasTerm<I>) -> I::Term,
) -> Self {
SolverRelating {
infcx,
Expand Down Expand Up @@ -418,7 +420,7 @@ where
})]);
}

fn try_eagerly_normalize_alias(&mut self, alias: ty::AliasTy<I>) -> I::Ty {
fn try_eagerly_normalize_alias(&mut self, alias: ty::AliasTerm<I>) -> I::Term {
(self.normalize)(alias)
}
}
37 changes: 37 additions & 0 deletions compiler/rustc_type_ir/src/term.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
use rustc_type_ir_macros::GenericTypeVisitable;

use crate::{ConstVid, Interner, TyVid};

#[derive_where(Clone, Copy, PartialEq, Debug; I: Interner)]
#[derive(GenericTypeVisitable)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
)]
pub enum TermKind<I: Interner> {
Ty(I::Ty),
Const(I::Const),
}

impl<I: Interner> Eq for TermKind<I> {}

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum TermVid {
Ty(TyVid),
Const(ConstVid),
}

impl From<TyVid> for TermVid {
fn from(value: TyVid) -> Self {
TermVid::Ty(value)
}
}

impl From<ConstVid> for TermVid {
fn from(value: ConstVid) -> Self {
TermVid::Const(value)
}
}
4 changes: 2 additions & 2 deletions tests/ui/coherence/occurs-check/associated-type.next.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())`
--> $DIR/associated-type.rs:32:1
|
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/coherence/occurs-check/associated-type.old.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())`
--> $DIR/associated-type.rs:32:1
|
Expand Down
13 changes: 13 additions & 0 deletions tests/ui/const-generics/mgca/free-type-alias-recursive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/153831>
//@ check-fail
//@compile-flags: -Znext-solver=globally --emit=obj
#![feature(min_generic_const_args)]
#![expect(incomplete_features)]

type const A: () = A;
//~^ ERROR type mismatch resolving `A normalizes-to _`
//~| ERROR the constant `A` is not of type `()`

fn main() {
A;
}
15 changes: 15 additions & 0 deletions tests/ui/const-generics/mgca/free-type-alias-recursive.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0271]: type mismatch resolving `A normalizes-to _`
--> $DIR/free-type-alias-recursive.rs:7:1
|
LL | type const A: () = A;
| ^^^^^^^^^^^^^^^^ types differ

error: the constant `A` is not of type `()`
--> $DIR/free-type-alias-recursive.rs:7:1
|
LL | type const A: () = A;
| ^^^^^^^^^^^^^^^^ expected `()`, found a different `()`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0271`.
7 changes: 3 additions & 4 deletions tests/ui/const-generics/ogca/coherence-ambiguous.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// FIXME(ogca): this should ERROR not pass!!
//@ check-pass
//@ check-fail

#![feature(generic_const_items, min_generic_const_args, opaque_generic_const_args)]
#![expect(incomplete_features)]
Expand All @@ -12,8 +11,8 @@ trait Trait {}

impl Trait for [(); FOO::<1>] {}
impl Trait for [(); BAR::<1>] {}
// FIXME(ogca): this should ERROR!
//~^ ERROR conflicting implementations of trait `Trait` for type `[(); FOO::<1>]`
impl Trait for [(); BAR::<2>] {}
// FIXME(ogca): this should ERROR!
//~^ ERROR conflicting implementations of trait `Trait` for type `[(); FOO::<1>]`

fn main() {}
Loading
Loading