Change:
<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --I created an empty hello world project with Cargo, the "gluon" library to it, then tried to compile. I understand this is something more than just an incompatibility between the nightly compiler and the library. Does not occur on stable. There's no code, I to of an empty project. : </details
It looks like the bound regions are preventing us from normalizing an opaque type, leading us to conclude that the LHS and RHS types are not actually equal.
cc
Well I thought our subtyping check would catch such things? Cc It would be great to get a minimal testcase out of this.
I thought something like this could be used to reproduce the problem, but so far I could not get it to ICE:
You're missing the from the original. Here's a short repro: <hr/For the record, the thing of note about is that it (, even, presumably accounting for the two errors), the function (which ) The function is 's , with the signature:
Nice, a repro! So return-position impl-trait is crucial here. (We don't really need a bisect as we know that this got introduced by checking that MIR assignments are properly typed, so removing that label as well.) Any proposal for how this could be handled? I don't even understand why it doesn't work, I thought we are deleting all the lifetimes, but clearly not enough of them.^^ Would moving back to a "type fold" (instead of this relator thing we are currently doing) help?
Marked this as p-critical as per the
I'm afraid I have no idea how to fix this. I tried using a , to no avail. I also tried switching the validation type comparison back to a , but that did not help either. The only thing I can offer is disabling the sanity check for assignments entirely. I wonder if the check that has in the cranelift backend can handle this case.
I thought that code was already getting a passed into it
Is the problem really due to alone, or do the late-bound lifetimes cause it? Because the ICE message kind of looks like they are the thing that causes issues:
Late-bound lifetimes work elsewhere though and the is needed to reproduce the problem.
Are you normalizing? The aspect is not going to be used unless you actually normalize. You might need to do the hacky excessive erasure of lifetimes before even attempting to normalize as the bound lifetimes may block normalization. (so the bottom-up folder could erase lifetimes then normalize, at every single step)
It does handle this. I just tried to compile the repro with cgclif. Compilation fails on the same as without cgclif, but not before cg_clif successfully finished codegen.
What was the link to that check again?
calling with a reveal-all doesn't help. :/
hm, interesting. That looks like it would bail if the types are inside a struct, tuple or array though?
found a fix, I coded it up:
for the record, I specifically meant after removing all the bound lifetimes. miri already normalizes, so it would have to be stronger than that. (EDIT: appears to do what I was suggesting, although it shouldn't be necessary, see below) <hr/However, I believe I may have found the bug, and it's actually in normalization itself: That condition shouldn't be there - IIRC I copied it from the arm. While for associated type projections it makes sense, due to having to look up the (which may have different results depending on how the lifetimes are bound, or be unsound, I guess), it does not for , which behaves more like a type alias, and which should be completely sound to normalize under a binder. cc
the old code doesn't normalize, so I don't see how changes to normalization could help. Also I don't know any of that code so it likely makes more sense for someone else to take over then.
This regressed in which is a rollup, I guess due to
This regressed in I removed the label because we knew that, but it's not helpful -- we don't want to just revert that PR as that would mean not checking MIR assignments any more.
right, I was going over the prioritization process and noticed that the PR where this regressed was lacking. I wasn't suggesting more than just that :).
Reopening as the problem remains on beta. can you do a backport?
is already , still this can be left open until we do the actual backport.
Oh I thought the beta PR would get nominated? Clearly I do not know the process. Feel free to close again if that's the process. :)
Hm, when you say "beta PR" -- is there a dedicated PR intended for beta backport? Or is slated for beta backport? Whichever PR's commits should be cherry-picked onto beta should get nominated.
Oh gosh now I confused everyone.^^ What I thought would happen is that someone cherry-picks onto the beta branch, opens that PR, and then marks it as nominated for the team to discuss. But best to ignore me as I clearly have no idea how you are doing backports.^^
the way it works is ... a PR that was made against master is labelled with requesting a backport for beta or requesting a backport for stable. During the following compiler weekly meeting members vote if the request should be accepted or rejected. If it is accepted a label or is and at that point ports that PR to the corresponding beta/stable branch. If it request is declined the or label is removed leaving the backport without effect.
We experienced a minor regression with the fix in PR , but there are known workarounds. The fix caused new "reached the type-length limit" compiler errors in our project. In our particular case, we didn't need the tracing::instrument spans that were creating the large types, so we deleted them (see ). This is a known issue in tracing - they increase the type-length limit as a workaround. It's also a known issue in rustc (). I the bisect-rustc regression report to that issue as
The fix seems to have been backported to beta. Can we close this?
What's the link to the beta PR? Yes I think it can be closed then.

Discussion:
use super::MirPass; use rustc_index::bit_set::BitSet; <ins> use rustc_infer::infer::TyCtxtInferExt; </ins> use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{PlaceContext, Visitor};

AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceRef, Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo, }; <del> use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; </del> <ins> use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeFoldable}; </ins> use rustc_target::abi::Size; #[derive(Copy, Clone, Debug)]

return true; } <del> struct LifetimeIgnoreRelation<'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, } impl TypeRelation<'tcx> for LifetimeIgnoreRelation<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env } fn tag(&self) -> &'static str { "librustc_mir::transform::validate" } fn a_is_expected(&self) -> bool { true } fn relate_with_variance<T: Relate<'tcx>>( &mut self, _: ty::Variance, a: T, b: T, ) -> RelateResult<'tcx, T> { // Ignore variance, require types to be exactly the same. self.relate(a, b) } fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { if a == b { // Short-circuit. return Ok(a); } ty::relate::super_relate_tys(self, a, b) } fn regions( &mut self, a: ty::Region<'tcx>, _b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { // Ignore regions. Ok(a) } fn consts( &mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { ty::relate::super_relate_consts(self, a, b) } fn binders<T>( &mut self, a: ty::Binder<T>, b: ty::Binder<T>, ) -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx>, { self.relate(a.skip_binder(), b.skip_binder())?; Ok(a) } } // Instantiate and run relation. let mut relator: LifetimeIgnoreRelation<'tcx> = LifetimeIgnoreRelation { tcx: tcx, param_env }; relator.relate(src, dest).is_ok() </del> <ins> // Normalize lifetimes away on both sides, then compare. let param_env = param_env.with_reveal_all_normalized(tcx); let normalize = |ty: Ty<'tcx>| { tcx.normalize_erasing_regions( param_env, ty.fold_with(&mut BottomUpFolder { tcx, // FIXME: We erase all late-bound lifetimes, but this is not fully correct. // If you have a type like `<for<'a> fn(&'a u32) as SomeTrait>::Assoc`, // this is not necessarily equivalent to `<fn(&'static u32) as SomeTrait>::Assoc`, // since one may have an `impl SomeTrait for fn(&32)` and // `impl SomeTrait for fn(&'static u32)` at the same time which // specify distinct values for Assoc. (See also #56105) lt_op: |_| tcx.lifetimes.re_erased, // Leave consts and types unchanged. ct_op: |ct| ct, ty_op: |ty| ty, }), ) }; tcx.infer_ctxt().enter(|infcx| infcx.can_eq(param_env, normalize(src), normalize(dest)).is_ok()) </ins> } struct TypeChecker<'a, 'tcx> {

let ty = ty.super_fold_with(self); match *ty.kind() { <del> ty::Opaque(def_id, substs) => { </del> <ins> ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { </ins> // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal() { Reveal::UserFacing => ty,

let ty = ty.super_fold_with(self); let res = (|| match *ty.kind() { <del> ty::Opaque(def_id, substs) => { </del> <ins> ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { </ins> // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal() { Reveal::UserFacing => ty,

<del> // build-pass // Regression test for #72793. // FIXME: This still shows ICE with `-Zmir-opt-level=2`. #![feature(type_alias_impl_trait)] trait T { type Item; } type Alias<'a> = impl T<Item = &'a ()>; struct S; impl<'a> T for &'a S { type Item = &'a (); } fn filter_positive<'a>() -> Alias<'a> { &S } fn with_positive(fun: impl Fn(Alias<'_>)) { fun(filter_positive()); } fn main() { with_positive(|_| ()); } </del>