|
1 | 1 | use rustc_data_structures::fx::FxIndexSet;
|
2 | 2 | use rustc_hir as hir;
|
3 | 3 | use rustc_hir::def_id::DefId;
|
| 4 | +use rustc_infer::infer::TyCtxtInferExt; |
| 5 | +use rustc_infer::traits::TraitEngine; |
4 | 6 | use rustc_middle::ty::subst::Subst;
|
5 | 7 | use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
|
6 | 8 | use rustc_span::{sym, Span};
|
@@ -356,6 +358,50 @@ fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamE
|
356 | 358 | tcx.param_env(def_id).with_reveal_all_normalized(tcx)
|
357 | 359 | }
|
358 | 360 |
|
| 361 | +fn reveal_all_and_erase_trivial_caller_bounds<'tcx>( |
| 362 | + tcx: TyCtxt<'tcx>, |
| 363 | + param_env: ty::ParamEnv<'tcx>, |
| 364 | +) -> ty::ParamEnv<'tcx> { |
| 365 | + let mut old_caller_bounds = param_env.caller_bounds(); |
| 366 | + loop { |
| 367 | + // The caller bounds that we must continue to include in our ParamEnv, |
| 368 | + // because they cause errors without them... |
| 369 | + let mut needed_caller_bounds = vec![]; |
| 370 | + for (idx, bound) in old_caller_bounds.iter().enumerate() { |
| 371 | + let new_param_env = param_env.with_caller_bounds(tcx.mk_predicates( |
| 372 | + needed_caller_bounds.iter().chain(old_caller_bounds[idx + 1..].iter()).copied(), |
| 373 | + )); |
| 374 | + // a bound is trivial if it does not have const projections |
| 375 | + // (which might induce cycles), and if we can prove that bound |
| 376 | + // given a copy of our param-env that has the bound removed. |
| 377 | + let is_bound_trivial = tcx.infer_ctxt().enter(|infcx| { |
| 378 | + let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot(); |
| 379 | + fulfillcx.register_predicate_obligation( |
| 380 | + &infcx, |
| 381 | + traits::Obligation::new(traits::ObligationCause::dummy(), new_param_env, bound), |
| 382 | + ); |
| 383 | + let errors = fulfillcx.select_all_or_error(&infcx); |
| 384 | + if !errors.is_empty() { |
| 385 | + info!("{:?} is NOT trivial: {:?}", bound, errors); |
| 386 | + } else { |
| 387 | + info!("{:?} is trivial", bound); |
| 388 | + } |
| 389 | + // is trivial iff there are no errors when fulfilling this bound |
| 390 | + errors.is_empty() |
| 391 | + }); |
| 392 | + if !is_bound_trivial { |
| 393 | + needed_caller_bounds.push(bound); |
| 394 | + } |
| 395 | + } |
| 396 | + let new_caller_bounds = tcx.mk_predicates(needed_caller_bounds.into_iter()); |
| 397 | + if new_caller_bounds == old_caller_bounds { |
| 398 | + return param_env.with_caller_bounds(new_caller_bounds).with_reveal_all_normalized(tcx); |
| 399 | + } else { |
| 400 | + old_caller_bounds = new_caller_bounds; |
| 401 | + } |
| 402 | + } |
| 403 | +} |
| 404 | + |
359 | 405 | fn instance_def_size_estimate<'tcx>(
|
360 | 406 | tcx: TyCtxt<'tcx>,
|
361 | 407 | instance_def: ty::InstanceDef<'tcx>,
|
@@ -495,6 +541,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
495 | 541 | def_ident_span,
|
496 | 542 | param_env,
|
497 | 543 | param_env_reveal_all_normalized,
|
| 544 | + reveal_all_and_erase_trivial_caller_bounds, |
498 | 545 | instance_def_size_estimate,
|
499 | 546 | issue33140_self_ty,
|
500 | 547 | impl_defaultness,
|
|
0 commit comments