Skip to content

Commit 2ccfd04

Browse files
committed
use ObligationCtxt not QueryNormalizer
1 parent 0fd7ce9 commit 2ccfd04

File tree

2 files changed

+40
-21
lines changed

2 files changed

+40
-21
lines changed

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

+4-8
Original file line numberDiff line numberDiff line change
@@ -294,14 +294,10 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
294294
}?;
295295
// We don't expect ambiguity.
296296
if result.is_ambiguous() {
297-
// Rustdoc normalizes possibly not well-formed types, so only
298-
// treat this as a bug if we're not in rustdoc.
299-
if !tcx.sess.opts.actually_rustdoc {
300-
tcx.sess.delay_span_bug(
301-
DUMMY_SP,
302-
format!("unexpected ambiguity: {c_data:?} {result:?}"),
303-
);
304-
}
297+
tcx.sess.delay_span_bug(
298+
DUMMY_SP,
299+
format!("unexpected ambiguity: {c_data:?} {result:?}"),
300+
);
305301
return Err(NoSolution);
306302
}
307303
let InferOk { value: result, obligations } = infcx

src/librustdoc/clean/mod.rs

+36-13
Original file line numberDiff line numberDiff line change
@@ -1902,22 +1902,45 @@ fn normalize<'tcx>(
19021902
}
19031903

19041904
use crate::rustc_trait_selection::infer::TyCtxtInferExt;
1905-
use crate::rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
1905+
use crate::rustc_trait_selection::traits::ObligationCtxt;
19061906
use rustc_middle::traits::ObligationCause;
19071907

1908-
// Try to normalize `<X as Y>::T` to a type
1908+
assert!(
1909+
!ty.has_non_region_infer(),
1910+
"`ty`: {ty:?} has pre existing infer vars before `InferCtxt` creation",
1911+
);
1912+
19091913
let infcx = cx.tcx.infer_ctxt().build();
1910-
let normalized = infcx
1911-
.at(&ObligationCause::dummy(), cx.param_env)
1912-
.query_normalize(ty)
1913-
.map(|resolved| infcx.resolve_vars_if_possible(resolved.value));
1914-
match normalized {
1915-
Ok(normalized_value) => {
1916-
debug!("normalized {ty:?} to {normalized_value:?}");
1917-
Some(normalized_value)
1918-
}
1919-
Err(err) => {
1920-
debug!("failed to normalize {ty:?}: {err:?}");
1914+
// use an `ObligationCtxt` as it has a nice API for dealing with returned obligations from normalization
1915+
// and does not expect us to be inside of typeck. It also does not ICE when the projection could not be
1916+
// normalized like some other normalization routines (`QueryNormalizer`, `normalize_erasing_regions`, etc)
1917+
let ocx = ObligationCtxt::new(&infcx);
1918+
1919+
// Try to normalize `<X as Y>::T` to a type
1920+
let normalized = ocx.normalize(&ObligationCause::dummy(), cx.param_env, ty);
1921+
// We have to ensure that we deal with nested obligations from attempting to normalize as `ty`
1922+
// normalizing to `normalized` is only the case if the nested obligations hold.
1923+
let errs = ocx.select_all_or_error();
1924+
// Evaluating nested obligations might constrain infer vars that were created during normalization
1925+
// so we should resolve any infer vars in `normalized` to their new values.
1926+
let normalized = infcx.resolve_vars_if_possible(normalized);
1927+
1928+
match errs.as_slice() {
1929+
[] if normalized == ty => {
1930+
debug!("normalizing {ty:?} did not make progress");
1931+
None
1932+
}
1933+
[] => {
1934+
debug!("normalized {ty:?} to {normalized:?}");
1935+
1936+
assert!(
1937+
!normalized.has_non_region_infer(),
1938+
"`normalized` has infer vars which would escape the `InferCtxt` they were created in"
1939+
);
1940+
Some(normalized)
1941+
}
1942+
errs => {
1943+
debug!("failed to normalize {ty:?}: {errs:?}");
19211944
None
19221945
}
19231946
}

0 commit comments

Comments
 (0)