Skip to content

Commit

Permalink
use ObligationCtxt not QueryNormalizer
Browse files Browse the repository at this point in the history
  • Loading branch information
BoxyUwU committed Mar 30, 2023
1 parent f2d9a3d commit 390246c
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 21 deletions.
12 changes: 4 additions & 8 deletions compiler/rustc_trait_selection/src/traits/query/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,14 +284,10 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
let result = tcx.normalize_projection_ty(c_data)?;
// We don't expect ambiguity.
if result.is_ambiguous() {
// Rustdoc normalizes possibly not well-formed types, so only
// treat this as a bug if we're not in rustdoc.
if !tcx.sess.opts.actually_rustdoc {
tcx.sess.delay_span_bug(
DUMMY_SP,
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
);
}
tcx.sess.delay_span_bug(
DUMMY_SP,
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
);
return Err(NoSolution);
}
let InferOk { value: result, obligations } =
Expand Down
50 changes: 37 additions & 13 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1666,22 +1666,46 @@ fn normalize<'tcx>(
}

use crate::rustc_trait_selection::infer::TyCtxtInferExt;
use crate::rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use crate::rustc_trait_selection::traits::ObligationCtxt;
use rustc_middle::traits::ObligationCause;

// Try to normalize `<X as Y>::T` to a type
assert!(
!ty.has_non_region_infer(),
"`ty`: {:?} has pre existing infer vars before `InferCtxt` creation",
ty
);

let infcx = cx.tcx.infer_ctxt().build();
let normalized = infcx
.at(&ObligationCause::dummy(), cx.param_env)
.query_normalize(ty)
.map(|resolved| infcx.resolve_vars_if_possible(resolved.value));
match normalized {
Ok(normalized_value) => {
debug!("normalized {:?} to {:?}", ty, normalized_value);
Some(normalized_value)
}
Err(err) => {
debug!("failed to normalize {:?}: {:?}", ty, err);
// use an `ObligationCtxt` as it has a nice API for dealing with returned obligations from normalization
// and does not expect us to be inside of typeck. It also does not ICE when the projection could not be
// normalized like some other normalization routines (`QueryNormalizer`, `normalize_erasing_regions`, etc)
let ocx = ObligationCtxt::new(&infcx);

// Try to normalize `<X as Y>::T` to a type
let normalized = ocx.normalize(&ObligationCause::dummy(), cx.param_env, ty);
// We have to ensure that we deal with nested obligations from attempting to normalize as `ty`
// normalizing to `normalized` is only the case if the nested obligations hold.
let errs = ocx.select_all_or_error();
// Evaluating nested obligations might constrain infer vars that were created during normalization
// so we should resolve any infer vars in `normalized` to their new values.
let normalized = infcx.resolve_vars_if_possible(normalized);

match errs.as_slice() {
[] if normalized == ty => {
debug!("normalizing {:?} did not make progress", ty);
None
}
[] => {
debug!("normalized {:?} to {:?}", ty, normalized);

assert!(
!normalized.has_non_region_infer(),
"`normalized` has infer vars which would escape the `InferCtxt` they were created in"
);
Some(normalized)
}
errs => {
debug!("failed to normalize {:?}: {:?}", ty, errs);
None
}
}
Expand Down

0 comments on commit 390246c

Please sign in to comment.