Skip to content

Commit 390246c

Browse files
committed
use ObligationCtxt not QueryNormalizer
1 parent f2d9a3d commit 390246c

File tree

2 files changed

+41
-21
lines changed

2 files changed

+41
-21
lines changed

compiler/rustc_trait_selection/src/traits/query/normalize.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -284,14 +284,10 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
284284
let result = tcx.normalize_projection_ty(c_data)?;
285285
// We don't expect ambiguity.
286286
if result.is_ambiguous() {
287-
// Rustdoc normalizes possibly not well-formed types, so only
288-
// treat this as a bug if we're not in rustdoc.
289-
if !tcx.sess.opts.actually_rustdoc {
290-
tcx.sess.delay_span_bug(
291-
DUMMY_SP,
292-
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
293-
);
294-
}
287+
tcx.sess.delay_span_bug(
288+
DUMMY_SP,
289+
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
290+
);
295291
return Err(NoSolution);
296292
}
297293
let InferOk { value: result, obligations } =

src/librustdoc/clean/mod.rs

+37-13
Original file line numberDiff line numberDiff line change
@@ -1666,22 +1666,46 @@ fn normalize<'tcx>(
16661666
}
16671667

16681668
use crate::rustc_trait_selection::infer::TyCtxtInferExt;
1669-
use crate::rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
1669+
use crate::rustc_trait_selection::traits::ObligationCtxt;
16701670
use rustc_middle::traits::ObligationCause;
16711671

1672-
// Try to normalize `<X as Y>::T` to a type
1672+
assert!(
1673+
!ty.has_non_region_infer(),
1674+
"`ty`: {:?} has pre existing infer vars before `InferCtxt` creation",
1675+
ty
1676+
);
1677+
16731678
let infcx = cx.tcx.infer_ctxt().build();
1674-
let normalized = infcx
1675-
.at(&ObligationCause::dummy(), cx.param_env)
1676-
.query_normalize(ty)
1677-
.map(|resolved| infcx.resolve_vars_if_possible(resolved.value));
1678-
match normalized {
1679-
Ok(normalized_value) => {
1680-
debug!("normalized {:?} to {:?}", ty, normalized_value);
1681-
Some(normalized_value)
1682-
}
1683-
Err(err) => {
1684-
debug!("failed to normalize {:?}: {:?}", ty, err);
1679+
// use an `ObligationCtxt` as it has a nice API for dealing with returned obligations from normalization
1680+
// and does not expect us to be inside of typeck. It also does not ICE when the projection could not be
1681+
// normalized like some other normalization routines (`QueryNormalizer`, `normalize_erasing_regions`, etc)
1682+
let ocx = ObligationCtxt::new(&infcx);
1683+
1684+
// Try to normalize `<X as Y>::T` to a type
1685+
let normalized = ocx.normalize(&ObligationCause::dummy(), cx.param_env, ty);
1686+
// We have to ensure that we deal with nested obligations from attempting to normalize as `ty`
1687+
// normalizing to `normalized` is only the case if the nested obligations hold.
1688+
let errs = ocx.select_all_or_error();
1689+
// Evaluating nested obligations might constrain infer vars that were created during normalization
1690+
// so we should resolve any infer vars in `normalized` to their new values.
1691+
let normalized = infcx.resolve_vars_if_possible(normalized);
1692+
1693+
match errs.as_slice() {
1694+
[] if normalized == ty => {
1695+
debug!("normalizing {:?} did not make progress", ty);
1696+
None
1697+
}
1698+
[] => {
1699+
debug!("normalized {:?} to {:?}", ty, normalized);
1700+
1701+
assert!(
1702+
!normalized.has_non_region_infer(),
1703+
"`normalized` has infer vars which would escape the `InferCtxt` they were created in"
1704+
);
1705+
Some(normalized)
1706+
}
1707+
errs => {
1708+
debug!("failed to normalize {:?}: {:?}", ty, errs);
16851709
None
16861710
}
16871711
}

0 commit comments

Comments
 (0)