Change:
File: season two auto-reduced (treereduce-rust): original: Version information ` Command: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongProgram output</strong</summary<p</p</details
cc
I cannot reproduce the original anymore, but does reproduce. The body is impossible because of the where clauses, so no MIR opts should ever run on it... I'll take a look.
I can still reproduce this with the original mvce when I use the flags that I listed.
bisected with searched nightlies: from nightly-2023-09-01 to nightly-2023-10-01 regressed nightly: nightly-2023-09-09 searched commit range: regressed commit: bisected with <a href=''cargo-bisect-rustc</av0.6.8 cc oli was right:
The bisection here isn't useful sadly, but thank you anyways. I took a look and yeah, the issue is what I suspected. () checks whether there are any impossible predicates (like here). It sadly has to filter out "non-global" predicates, which belongs to. It has to do this because of overflows as mentioned above. told me that the new trait solvers non-fatal handling of overflow will allow this to be fixed. But until then, there's nothing we can do. As for getting the code working, the solution here so to avoid these impossible bounds wherever possible. In the example here, that's easy to do, just delete it. In that's a bit more annoying, I don't really see a solution. We could try playing whack-a-mole by trying to make the MIR opts sorta-handle these cases that slip through, but I don't think that's very sustainable. Might work at least for the trivial cases like though, but I don't open PRs for that.
another one
I'm afraid that this has reached stable with 1.78. I couldn't reproduce it with the minimal example in the previous comment, but a crate of mine now fails on stable, but compiled fine on 1.77.2: <details<summaryfull output</summary</detailsThe code responsible for this is fairly simple: Removing that impl makes the crate compile again. Will we still just wait for the new solver, now that it's a stable-stable regression?
I managed to minimize the example from : (, ICE in release mode)

Discussion:
if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.kind() && let ty::Slice(..) = ref_ty.kind() <ins> // The user may have written a predicate like `[T]: Sized` in their where clauses, // which makes slices scalars. && self.places[place].value_index.is_none() </ins> { <del> assert!(self.places[place].value_index.is_none(), "slices are not scalars"); </del> // Prepend new child to the linked list. let len = self.places.push(PlaceInfo::new(Some(TrackElem::DerefLen))); self.places[len].next_sibling = self.places[place].first_child;

opportunities: Vec::new(), }; <del> for (bb, bbdata) in body.basic_blocks.iter_enumerated() { debug!(?bb, term = ?bbdata.terminator()); if bbdata.is_cleanup || loop_headers.contains(bb) { continue; } let Some((discr, targets)) = bbdata.terminator().kind.as_switch() else { continue }; let Some(discr) = discr.place() else { continue }; debug!(?discr, ?bb); let discr_ty = discr.ty(body, tcx).ty; let Ok(discr_layout) = finder.ecx.layout_of(discr_ty) else { continue }; let Some(discr) = finder.map.find(discr.as_ref()) else { continue }; debug!(?discr); let cost = CostChecker::new(tcx, param_env, None, body); let mut state = State::new(ConditionSet::default(), finder.map); let conds = if let Some((value, then, else_)) = targets.as_static_if() { let Some(value) = ScalarInt::try_from_uint(value, discr_layout.size) else { continue; }; arena.alloc_from_iter([ Condition { value, polarity: Polarity::Eq, target: then }, Condition { value, polarity: Polarity::Ne, target: else_ }, ]) } else { arena.alloc_from_iter(targets.iter().filter_map(|(value, target)| { let value = ScalarInt::try_from_uint(value, discr_layout.size)?; Some(Condition { value, polarity: Polarity::Eq, target }) })) }; let conds = ConditionSet(conds); state.insert_value_idx(discr, conds, finder.map); finder.find_opportunity(bb, state, cost, 0); </del> <ins> for bb in body.basic_blocks.indices() { finder.start_from_switch(bb); </ins> } let opportunities = finder.opportunities;

} /// Recursion entry point to find threading opportunities. <ins> #[instrument(level = "trace", skip(self))] fn start_from_switch(&mut self, bb: BasicBlock) -> Option<!> { let bbdata = &self.body[bb]; if bbdata.is_cleanup || self.loop_headers.contains(bb) { return None; } let (discr, targets) = bbdata.terminator().kind.as_switch()?; let discr = discr.place()?; debug!(?discr, ?bb); let discr_ty = discr.ty(self.body, self.tcx).ty; let discr_layout = self.ecx.layout_of(discr_ty).ok()?; let discr = self.map.find(discr.as_ref())?; debug!(?discr); let cost = CostChecker::new(self.tcx, self.param_env, None, self.body); let mut state = State::new(ConditionSet::default(), self.map); let conds = if let Some((value, then, else_)) = targets.as_static_if() { let value = ScalarInt::try_from_uint(value, discr_layout.size)?; self.arena.alloc_from_iter([ Condition { value, polarity: Polarity::Eq, target: then }, Condition { value, polarity: Polarity::Ne, target: else_ }, ]) } else { self.arena.alloc_from_iter(targets.iter().filter_map(|(value, target)| { let value = ScalarInt::try_from_uint(value, discr_layout.size)?; Some(Condition { value, polarity: Polarity::Eq, target }) })) }; let conds = ConditionSet(conds); state.insert_value_idx(discr, conds, self.map); self.find_opportunity(bb, state, cost, 0); None } /// Recursively walk statements backwards from this bb's terminator to find threading /// opportunities. </ins> #[instrument(level = "trace", skip(self, cost), ret)] fn find_opportunity( &mut self,

self.process_switch_int(discr, targets, bb, &mut state); self.find_opportunity(pred, state, cost, depth + 1); } <del> _ => self.recurse_through_terminator(pred, &state, &cost, depth), </del> <ins> _ => self.recurse_through_terminator(pred, || state, &cost, depth), </ins> } <del> } else { </del> <ins> } else if let &[ref predecessors @ .., last_pred] = &predecessors[..] { </ins> for &pred in predecessors { <del> self.recurse_through_terminator(pred, &state, &cost, depth); </del> <ins> self.recurse_through_terminator(pred, || state.clone(), &cost, depth); </ins> } <ins> self.recurse_through_terminator(last_pred, || state, &cost, depth); </ins> } let new_tos = &mut self.opportunities[last_non_rec..];

None } <del> #[instrument(level = "trace", skip(self, cost))] </del> <ins> #[instrument(level = "trace", skip(self, state, cost))] </ins> fn recurse_through_terminator( &mut self, bb: BasicBlock, <del> state: &State<ConditionSet<'a>>, </del> <ins> // Pass a closure that may clone the state, as we don't want to do it each time. state: impl FnOnce() -> State<ConditionSet<'a>>, </ins> cost: &CostChecker<'_, 'tcx>, depth: usize, ) {

}; // We can recurse through this terminator. <del> let mut state = state.clone(); </del> <ins> let mut state = state(); </ins> if let Some(place_to_flood) = place_to_flood { state.flood_with(place_to_flood.as_ref(), self.map, ConditionSet::default()); }

<del> //@ known-bug: #116721 //@ compile-flags: -Zmir-opt-level=3 --emit=mir fn hey<T>(it: &[T]) where [T]: Clone, { } fn main() {} </del>

<ins> //@ build-pass //@ compile-flags: -Zmir-opt-level=3 --emit=mir fn hey<T>(it: &[T]) where [T]: Clone, { } fn main() {} </ins>