Auto merge of #113471 - compiler-errors:new-solver-norm-escaping, r=lcnr
Allow escaping bound vars during `normalize_erasing_regions` in new solver Add `AllowEscapingBoundVars` to `deeply_normalize`, and use it in the new solver in the `query_normalize` routine. Ideally, we'd make all `query_normalize` calls handle pass in `AllowEscapingBoundVars` individually, because really the only `query_normalize` call that needs `AllowEscapingBoundVars::Yes` is the one in `try_normalize_generic_arg_after_erasing_regions`, but I think that's kind of overkill. I am happy to be convinced otherwise, though. r? `@lcnr`
This commit is contained in:
commit
ad963232d9
4 changed files with 55 additions and 22 deletions
|
@ -61,8 +61,27 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
|
|||
self.cause,
|
||||
);
|
||||
|
||||
// This is actually a consequence by the way `normalize_erasing_regions` works currently.
|
||||
// Because it needs to call the `normalize_generic_arg_after_erasing_regions`, it folds
|
||||
// through tys and consts in a `TypeFoldable`. Importantly, it skips binders, leaving us
|
||||
// with trying to normalize with escaping bound vars.
|
||||
//
|
||||
// Here, we just add the universes that we *would* have created had we passed through the binders.
|
||||
//
|
||||
// We *could* replace escaping bound vars eagerly here, but it doesn't seem really necessary.
|
||||
// The rest of the code is already set up to be lazy about replacing bound vars,
|
||||
// and only when we actually have to normalize.
|
||||
let universes = if value.has_escaping_bound_vars() {
|
||||
let mut max_visitor =
|
||||
MaxEscapingBoundVarVisitor { outer_index: ty::INNERMOST, escaping: 0 };
|
||||
value.visit_with(&mut max_visitor);
|
||||
vec![None; max_visitor.escaping]
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
if self.infcx.next_trait_solver() {
|
||||
match crate::solve::deeply_normalize(self, value) {
|
||||
match crate::solve::deeply_normalize_with_skipped_universes(self, value, universes) {
|
||||
Ok(value) => return Ok(Normalized { value, obligations: vec![] }),
|
||||
Err(_errors) => {
|
||||
return Err(NoSolution);
|
||||
|
@ -81,27 +100,9 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
|
|||
obligations: vec![],
|
||||
cache: SsoHashMap::new(),
|
||||
anon_depth: 0,
|
||||
universes: vec![],
|
||||
universes,
|
||||
};
|
||||
|
||||
// This is actually a consequence by the way `normalize_erasing_regions` works currently.
|
||||
// Because it needs to call the `normalize_generic_arg_after_erasing_regions`, it folds
|
||||
// through tys and consts in a `TypeFoldable`. Importantly, it skips binders, leaving us
|
||||
// with trying to normalize with escaping bound vars.
|
||||
//
|
||||
// Here, we just add the universes that we *would* have created had we passed through the binders.
|
||||
//
|
||||
// We *could* replace escaping bound vars eagerly here, but it doesn't seem really necessary.
|
||||
// The rest of the code is already set up to be lazy about replacing bound vars,
|
||||
// and only when we actually have to normalize.
|
||||
if value.has_escaping_bound_vars() {
|
||||
let mut max_visitor =
|
||||
MaxEscapingBoundVarVisitor { outer_index: ty::INNERMOST, escaping: 0 };
|
||||
value.visit_with(&mut max_visitor);
|
||||
if max_visitor.escaping > 0 {
|
||||
normalizer.universes.extend((0..max_visitor.escaping).map(|_| None));
|
||||
}
|
||||
}
|
||||
let result = value.try_fold_with(&mut normalizer);
|
||||
info!(
|
||||
"normalize::<{}>: result={:?} with {} obligations",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue