Change:
https://crater- This seems like a potential recurrence of , which was fixed in but lacked a test case.
searched nightlies: from nightly-2024-02-01 to nightly-2024-02-29 regressed nightly: nightly-2024-02-20 searched commit range: regressed commit: <details<summarybisected with <a href=''cargo-bisect-rustc</av0.6.8</summaryHost triple: x86_64-unknown-linux-gnu Reproduce with: </detailsRegressed in -- cc
WG-prioritization assigning priority (). label -I-prioritize +P-high
can revert the change from which caused this 2 weeks before this hits stable. We dshould really get a minimization of this issue though :/
(the cause should be this commit )
Interestingly, this builds on nightly. It seems to me that has fixed, or hid, the ICE .
Probably hidden; that's why we need an MCVE. If it has to do w/ a field not in a struct tail, a simple reordering of fields may trigger this bug again.
I'm not sure how small we can make it, but I've reduced this to a more reasonable size. I've ran out of steam on this if someone wants to help it cross the finish line if needed. It's still very convoluted, and more layers could be removed. It's quite fiddly though, removing a bound here or there makes the ICE disappear like a frightened turtle. The ICE is still present on nightly, but I lost track of the actual source while reducing : it used to happen in the collector but now a bit later. I hope it's fine, it's still in codegen and bisects to as well. <details<summaryThis is not a place of honor</summary</details
Reopening to track beta backport.
Backported in .

Discussion:
/// Determines whether the type `ty` is known to meet `bound` and /// returns true if so. Returns false if `ty` either does not meet <del> /// `bound` or is not known to meet bound. </del> <ins> /// `bound` or is not known to meet bound (note that this is /// conservative towards *no impl*, which is the opposite of the /// `evaluate` methods). </ins> pub fn type_known_to_meet_bound_modulo_regions<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>,

def_id: DefId, ) -> bool { let trait_ref = ty::TraitRef::new(infcx.tcx, def_id, [ty]); <del> let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, trait_ref); infcx.predicate_must_hold_modulo_regions(&obligation) </del> <ins> pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref) } /// FIXME(@lcnr): this function doesn't seem right and shouldn't exist? /// /// Ping me on zulip if you want to use this method and need help with finding /// an appropriate replacement. #[instrument(level = "debug", skip(infcx, param_env, pred), ret)] fn pred_known_to_hold_modulo_regions<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, pred: impl ToPredicate<'tcx>, ) -> bool { let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, pred); let result = infcx.evaluate_obligation_no_overflow(&obligation); debug!(?result); if result.must_apply_modulo_regions() { true } else if result.may_apply() { // Sometimes obligations are ambiguous because the recursive evaluator // is not smart enough, so we fall back to fulfillment when we're not certain // that an obligation holds or not. Even still, we must make sure that // the we do no inference in the process of checking this obligation. let goal = infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env)); infcx.probe(|_| { let ocx = ObligationCtxt::new(infcx); ocx.register_obligation(obligation); let errors = ocx.select_all_or_error(); match errors.as_slice() { // Only known to hold if we did no inference. [] => infcx.shallow_resolve(goal) == goal, errors => { debug!(?errors); false } } }) } else { false } </ins> } #[instrument(level = "debug", skip(tcx, elaborated_env))]

<ins> // This is a non-regression test for issues #108721 and its duplicate #123275 (hopefully, because // the test is still convoluted and the ICE is fiddly). // // `pred_known_to_hold_modulo_regions` prevented "unexpected unsized tail" ICEs with warp/hyper but // was unknowingly removed in #120463. //@ build-pass: the ICE happened in codegen use std::future::Future; trait TryFuture: Future { type Ok; } impl<F, T> TryFuture for F where F: ?Sized + Future<Output = Option<T>>, { type Ok = T; } trait Executor {} struct Exec {} trait HttpBody { type Data; } trait ConnStreamExec<F> {} impl<F> ConnStreamExec<F> for Exec where H2Stream<F>: Send {} impl<E, F> ConnStreamExec<F> for E where E: Executor {} struct H2Stream<F> { _fut: F, } trait NewSvcExec<S, E, W: Watcher<S, E>> { fn execute_new_svc(&mut self, _fut: NewSvcTask<S, E, W>) { unimplemented!() } } impl<S, E, W> NewSvcExec<S, E, W> for Exec where W: Watcher<S, E> {} trait Watcher<S, E> { type Future; } struct NoopWatcher; impl<S, E> Watcher<S, E> for NoopWatcher where S: HttpService, E: ConnStreamExec<S::Future>, { type Future = Option<<<S as HttpService>::ResBody as HttpBody>::Data>; } trait Service<Request> { type Response; type Future; } trait HttpService { type ResBody: HttpBody; type Future; } struct Body {} impl HttpBody for Body { type Data = String; } impl<S> HttpService for S where S: Service<(), Response = ()>, { type ResBody = Body; type Future = S::Future; } trait MakeServiceRef<Target> { type ResBody; type Service: HttpService<ResBody = Self::ResBody>; } impl<T, Target, S, F> MakeServiceRef<Target> for T where T: for<'a> Service<&'a Target, Response = S, Future = F>, S: HttpService, { type Service = S; type ResBody = S::ResBody; } fn make_service_fn<F, Target, Ret>(_f: F) -> MakeServiceFn<F> where F: FnMut(&Target) -> Ret, Ret: Future, { unimplemented!() } struct MakeServiceFn<F> { _func: F, } impl<'t, F, Ret, Target, Svc> Service<&'t Target> for MakeServiceFn<F> where F: FnMut(&Target) -> Ret, Ret: Future<Output = Option<Svc>>, { type Response = Svc; type Future = Option<()>; } struct AddrIncoming {} struct Server<I, S, E> { _incoming: I, _make_service: S, _protocol: E, } impl<I, S, E, B> Server<I, S, E> where S: MakeServiceRef<(), ResBody = B>, B: HttpBody, E: ConnStreamExec<<S::Service as HttpService>::Future>, E: NewSvcExec<S::Service, E, NoopWatcher>, { fn serve(&mut self) { let fut = NewSvcTask::new(); self._protocol.execute_new_svc(fut); } } fn serve<S>(_make_service: S) -> Server<AddrIncoming, S, Exec> { unimplemented!() } struct NewSvcTask<S, E, W: Watcher<S, E>> { _state: State<S, E, W>, } struct State<S, E, W: Watcher<S, E>> { _fut: W::Future, } impl<S, E, W: Watcher<S, E>> NewSvcTask<S, E, W> { fn new() -> Self { unimplemented!() } } trait Filter { type Extract; type Future; fn map<F>(self, _fun: F) -> MapFilter<Self, F> where Self: Sized, { unimplemented!() } fn wrap_with<W>(self, _wrapper: W) -> W::Wrapped where Self: Sized, W: Wrap<Self>, { unimplemented!() } } fn service<F>(_filter: F) -> FilteredService<F> where F: Filter, { unimplemented!() } struct FilteredService<F> { _filter: F, } impl<F> Service<()> for FilteredService<F> where F: Filter, { type Response = (); type Future = FilteredFuture<F::Future>; } struct FilteredFuture<F> { _fut: F, } struct MapFilter<T, F> { _filter: T, _func: F, } impl<T, F> Filter for MapFilter<T, F> where T: Filter, F: Func<T::Extract>, { type Extract = F::Output; type Future = MapFilterFuture<T, F>; } struct MapFilterFuture<T: Filter, F> { _extract: T::Future, _func: F, } trait Wrap<F> { type Wrapped; } fn make_filter_fn<F, U>(_func: F) -> FilterFn<F> where F: Fn() -> U, { unimplemented!() } struct FilterFn<F> { _func: F, } impl<F, U> Filter for FilterFn<F> where F: Fn() -> U, U: TryFuture, U::Ok: Send, { type Extract = U::Ok; type Future = Option<U>; } fn trace<F>(_func: F) -> Trace<F> where F: Fn(), { unimplemented!() } struct Trace<F> { _func: F, } impl<FN, F> Wrap<F> for Trace<FN> { type Wrapped = WithTrace<FN, F>; } struct WithTrace<FN, F> { _filter: F, _trace: FN, } impl<FN, F> Filter for WithTrace<FN, F> where F: Filter, { type Extract = (); type Future = (F::Future, fn(F::Extract)); } trait Func<Args> { type Output; } impl<F, R> Func<()> for F where F: Fn() -> R, { type Output = R; } fn main() { let make_service = make_service_fn(|_| { let tracer = trace(|| unimplemented!()); let filter = make_filter_fn(|| std::future::ready(Some(()))) .map(|| "Hello, world") .wrap_with(tracer); let svc = service(filter); std::future::ready(Some(svc)) }); let mut server = serve(make_service); server.serve(); } </ins>