Skip to content

Commit ed0e78e

Browse files
committed
Auto merge of rust-lang#118751 - lcnr:writeback-change, r=<try>
refactor writeback: emit normalization errors with new solver implements rust-lang#118725 (comment) r? `@compiler-errors` `@BoxyUwU` whoever comes first n stuff
2 parents ae612be + 84a6e68 commit ed0e78e

13 files changed

+102
-115
lines changed

Diff for: compiler/rustc_hir_typeck/src/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,6 @@ fn typeck_with_fallback<'tcx>(
283283

284284
fcx.check_asms();
285285

286-
fcx.infcx.skip_region_resolution();
287-
288286
let typeck_results = fcx.resolve_type_vars_in_body(body);
289287

290288
// Consistency check our TypeckResults instance can hold all ItemLocalIds

Diff for: compiler/rustc_hir_typeck/src/writeback.rs

+70-61
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@ use rustc_errors::{ErrorGuaranteed, StashKey};
88
use rustc_hir as hir;
99
use rustc_hir::intravisit::{self, Visitor};
1010
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
11+
use rustc_middle::traits::ObligationCause;
1112
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
1213
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
1314
use rustc_middle::ty::visit::TypeVisitableExt;
15+
use rustc_middle::ty::TypeSuperFoldable;
1416
use rustc_middle::ty::{self, Ty, TyCtxt};
1517
use rustc_span::symbol::sym;
1618
use rustc_span::Span;
19+
use rustc_trait_selection::solve;
20+
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
1721

1822
use std::mem;
1923

@@ -695,24 +699,22 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
695699
}
696700
}
697701

698-
fn resolve<T>(&mut self, x: T, span: &dyn Locatable) -> T
702+
fn resolve<T>(&mut self, value: T, span: &dyn Locatable) -> T
699703
where
700704
T: TypeFoldable<TyCtxt<'tcx>>,
701705
{
702-
let mut resolver = Resolver::new(self.fcx, span, self.body);
703-
let x = x.fold_with(&mut resolver);
704-
if cfg!(debug_assertions) && x.has_infer() {
705-
span_bug!(span.to_span(self.fcx.tcx), "writeback: `{:?}` has inference variables", x);
706-
}
706+
let value = self.fcx.resolve_vars_if_possible(value);
707+
let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body));
708+
assert!(!value.has_infer());
707709

708710
// We may have introduced e.g. `ty::Error`, if inference failed, make sure
709711
// to mark the `TypeckResults` as tainted in that case, so that downstream
710712
// users of the typeck results don't produce extra errors, or worse, ICEs.
711-
if let Some(e) = resolver.replaced_with_error {
712-
self.typeck_results.tainted_by_errors = Some(e);
713+
if let Err(guar) = value.error_reported() {
714+
self.typeck_results.tainted_by_errors = Some(guar);
713715
}
714716

715-
x
717+
value
716718
}
717719
}
718720

@@ -732,15 +734,13 @@ impl Locatable for hir::HirId {
732734
}
733735
}
734736

735-
/// The Resolver. This is the type folding engine that detects
736-
/// unresolved types and so forth.
737737
struct Resolver<'cx, 'tcx> {
738738
fcx: &'cx FnCtxt<'cx, 'tcx>,
739739
span: &'cx dyn Locatable,
740740
body: &'tcx hir::Body<'tcx>,
741-
742-
/// Set to `Some` if any `Ty` or `ty::Const` had to be replaced with an `Error`.
743-
replaced_with_error: Option<ErrorGuaranteed>,
741+
/// Whether we should normalize using the new solver, disabled
742+
/// both when using the old solver and when resolving predicates.
743+
should_normalize: bool,
744744
}
745745

746746
impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
@@ -749,7 +749,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
749749
span: &'cx dyn Locatable,
750750
body: &'tcx hir::Body<'tcx>,
751751
) -> Resolver<'cx, 'tcx> {
752-
Resolver { fcx, span, body, replaced_with_error: None }
752+
Resolver { fcx, span, body, should_normalize: fcx.next_trait_solver() }
753753
}
754754

755755
fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
@@ -768,64 +768,73 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
768768
.emit(),
769769
}
770770
}
771+
772+
fn handle_term<T>(
773+
&mut self,
774+
value: T,
775+
outer_exclusive_binder: impl FnOnce(T) -> ty::DebruijnIndex,
776+
new_err: impl Fn(TyCtxt<'tcx>, ErrorGuaranteed) -> T,
777+
) -> T
778+
where
779+
T: Into<ty::GenericArg<'tcx>> + Copy,
780+
T: TypeFoldable<TyCtxt<'tcx>>,
781+
T: TypeSuperFoldable<TyCtxt<'tcx>>,
782+
{
783+
let tcx = self.fcx.tcx;
784+
// We must deeply normalize in the new solver, since later lints
785+
// expect that types that show up in the typeck are fully
786+
// normalized.
787+
let value = if self.should_normalize {
788+
let body_id = tcx.hir().body_owner_def_id(self.body.id());
789+
let cause = ObligationCause::misc(self.span.to_span(tcx), body_id);
790+
let at = self.fcx.at(&cause, self.fcx.param_env);
791+
let universes = vec![None; outer_exclusive_binder(value).as_usize()];
792+
solve::deeply_normalize_with_skipped_universes(at, value, universes).unwrap_or_else(
793+
|errors| {
794+
let guar = self.fcx.err_ctxt().report_fulfillment_errors(errors);
795+
new_err(tcx, guar)
796+
},
797+
)
798+
} else {
799+
value
800+
};
801+
802+
if value.has_non_region_infer() {
803+
let guar = self.report_error(value);
804+
new_err(tcx, guar)
805+
} else {
806+
tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased)
807+
}
808+
}
771809
}
772810

773811
impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
774812
fn interner(&self) -> TyCtxt<'tcx> {
775813
self.fcx.tcx
776814
}
777815

778-
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
779-
let tcx = self.fcx.tcx;
780-
match self.fcx.fully_resolve(t) {
781-
Ok(t) if self.fcx.next_trait_solver() => {
782-
// We must normalize erasing regions here, since later lints
783-
// expect that types that show up in the typeck are fully
784-
// normalized.
785-
if let Ok(t) = tcx.try_normalize_erasing_regions(self.fcx.param_env, t) {
786-
t
787-
} else {
788-
tcx.fold_regions(t, |_, _| tcx.lifetimes.re_erased)
789-
}
790-
}
791-
Ok(t) => {
792-
// Do not anonymize late-bound regions
793-
// (e.g. keep `for<'a>` named `for<'a>`).
794-
// This allows NLL to generate error messages that
795-
// refer to the higher-ranked lifetime names written by the user.
796-
tcx.fold_regions(t, |_, _| tcx.lifetimes.re_erased)
797-
}
798-
Err(_) => {
799-
debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
800-
let e = self.report_error(t);
801-
self.replaced_with_error = Some(e);
802-
Ty::new_error(self.fcx.tcx, e)
803-
}
804-
}
805-
}
806-
807816
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
808817
debug_assert!(!r.is_bound(), "Should not be resolving bound region.");
809818
self.fcx.tcx.lifetimes.re_erased
810819
}
811820

821+
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
822+
self.handle_term(ty, Ty::outer_exclusive_binder, Ty::new_error)
823+
}
824+
812825
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
813-
match self.fcx.fully_resolve(ct) {
814-
Ok(ct) => self.fcx.tcx.erase_regions(ct),
815-
Err(_) => {
816-
debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
817-
let e = self.report_error(ct);
818-
self.replaced_with_error = Some(e);
819-
ty::Const::new_error(self.fcx.tcx, e, ct.ty())
820-
}
821-
}
826+
self.handle_term(ct, ty::Const::outer_exclusive_binder, |tcx, guar| {
827+
ty::Const::new_error(tcx, guar, ct.ty())
828+
})
822829
}
823-
}
824830

825-
///////////////////////////////////////////////////////////////////////////
826-
// During type check, we store promises with the result of trait
827-
// lookup rather than the actual results (because the results are not
828-
// necessarily available immediately). These routines unwind the
829-
// promises. It is expected that we will have already reported any
830-
// errors that may be encountered, so if the promises store an error,
831-
// a dummy result is returned.
831+
fn fold_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
832+
// Do not normalize predicates in the new solver. The new solver is
833+
// supposed to handle unnormalized predicates and incorrectly normalizing
834+
// them can be unsound, e.g. for `WellFormed` predicates.
835+
let prev = mem::replace(&mut self.should_normalize, false);
836+
let predicate = predicate.super_fold_with(self);
837+
self.should_normalize = prev;
838+
predicate
839+
}
840+
}

Diff for: compiler/rustc_infer/src/infer/outlives/mod.rs

+1-27
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use self::env::OutlivesEnvironment;
33
use super::region_constraints::RegionConstraintData;
44
use super::{InferCtxt, RegionResolutionError};
55
use crate::infer::free_regions::RegionRelations;
6-
use crate::infer::lexical_region_resolve::{self, LexicalRegionResolutions};
6+
use crate::infer::lexical_region_resolve;
77
use rustc_middle::traits::query::OutlivesBound;
88
use rustc_middle::ty;
99

@@ -37,32 +37,6 @@ pub fn explicit_outlives_bounds<'tcx>(
3737
}
3838

3939
impl<'tcx> InferCtxt<'tcx> {
40-
pub fn skip_region_resolution(&self) {
41-
let (var_infos, _) = {
42-
let mut inner = self.inner.borrow_mut();
43-
let inner = &mut *inner;
44-
// Note: `inner.region_obligations` may not be empty, because we
45-
// didn't necessarily call `process_registered_region_obligations`.
46-
// This is okay, because that doesn't introduce new vars.
47-
inner
48-
.region_constraint_storage
49-
.take()
50-
.expect("regions already resolved")
51-
.with_log(&mut inner.undo_log)
52-
.into_infos_and_data()
53-
};
54-
55-
let lexical_region_resolutions = LexicalRegionResolutions {
56-
values: rustc_index::IndexVec::from_elem_n(
57-
crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased),
58-
var_infos.len(),
59-
),
60-
};
61-
62-
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
63-
assert!(old_value.is_none());
64-
}
65-
6640
/// Process the region constraints and return any errors that
6741
/// result. After this, no more unification operations should be
6842
/// done -- or the compiler will panic -- but it is legal to use

Diff for: compiler/rustc_trait_selection/src/solve/mod.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@ mod trait_goals;
4242

4343
pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt};
4444
pub use fulfill::FulfillmentCtxt;
45-
pub(crate) use normalize::{
46-
deeply_normalize, deeply_normalize_for_diagnostics, deeply_normalize_with_skipped_universes,
47-
};
45+
pub(crate) use normalize::deeply_normalize_for_diagnostics;
46+
pub use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
4847

4948
#[derive(Debug, Clone, Copy)]
5049
enum SolverMode {

Diff for: compiler/rustc_trait_selection/src/solve/normalize.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use super::FulfillmentCtxt;
1717

1818
/// Deeply normalize all aliases in `value`. This does not handle inference and expects
1919
/// its input to be already fully resolved.
20-
pub(crate) fn deeply_normalize<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
20+
pub fn deeply_normalize<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
2121
at: At<'_, 'tcx>,
2222
value: T,
2323
) -> Result<T, Vec<FulfillmentError<'tcx>>> {
@@ -31,7 +31,7 @@ pub(crate) fn deeply_normalize<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
3131
/// Additionally takes a list of universes which represents the binders which have been
3232
/// entered before passing `value` to the function. This is currently needed for
3333
/// `normalize_erasing_regions`, which skips binders as it walks through a type.
34-
pub(crate) fn deeply_normalize_with_skipped_universes<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
34+
pub fn deeply_normalize_with_skipped_universes<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
3535
at: At<'_, 'tcx>,
3636
value: T,
3737
universes: Vec<Option<UniverseIndex>>,

Diff for: tests/ui/traits/new-solver/alias-bound-unsound.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,6 @@ fn main() {
2727
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
2828
//~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item`
2929
//~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`
30+
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
3031
println!("{x}");
3132
}

Diff for: tests/ui/traits/new-solver/alias-bound-unsound.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ LL | drop(<() as Foo>::copy_me(&x));
5252
|
5353
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
5454

55-
error: aborting due to 6 previous errors
55+
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
56+
--> $DIR/alias-bound-unsound.rs:24:10
57+
|
58+
LL | drop(<() as Foo>::copy_me(&x));
59+
| ^^^^^^^^^^^^^^^^^^^^^^^^
60+
|
61+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
62+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
63+
64+
error: aborting due to 7 previous errors
5665

5766
For more information about this error, try `rustc --explain E0275`.

Diff for: tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
// compile-flags: -Ztrait-solver=next
22
// known-bug: trait-system-refactor-initiative#60
3-
// dont-check-failure-status
4-
// dont-check-compiler-stderr
53

64
// Generalizing a projection containing an inference variable
75
// which cannot be named by the `root_vid` can result in ambiguity.

Diff for: tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr

+2-11
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,8 @@
1-
error[E0284]: type annotations needed: cannot satisfy `<<Leaf as WithAssoc<_>>::Assoc as Id>::Assoc == <<Leaf as WithAssoc<_>>::Assoc as Id>::Assoc`
1+
error[E0284]: type annotations needed: cannot satisfy `<<Rigid as IdHigherRankedBound>::Assoc as WithAssoc<<Wrapper<Leaf> as Id>::Assoc>>::Assoc normalizes-to <<Leaf as WithAssoc<_>>::Assoc as Id>::Assoc`
22
--> $DIR/generalize-proj-new-universe-index-2.rs:74:5
33
|
44
LL | bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<<Leaf as WithAssoc<_>>::Assoc as Id>::Assoc == <<Leaf as WithAssoc<_>>::Assoc as Id>::Assoc`
6-
|
7-
note: required by a bound in `bound`
8-
--> $DIR/generalize-proj-new-universe-index-2.rs:69:21
9-
|
10-
LL | fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
11-
| ----- required by a bound in this function
12-
LL | where
13-
LL | T: WithAssoc<U, Assoc = V>,
14-
| ^^^^^^^^^ required by this bound in `bound`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<<Rigid as IdHigherRankedBound>::Assoc as WithAssoc<<Wrapper<Leaf> as Id>::Assoc>>::Assoc normalizes-to <<Leaf as WithAssoc<_>>::Assoc as Id>::Assoc`
156

167
error: aborting due to 1 previous error
178

Diff for: tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
//~ ERROR overflow
21
// compile-flags: -Ztrait-solver=next
32

43
trait Foo1 {
@@ -15,6 +14,7 @@ fn needs_bar<S: Bar>() {}
1514
fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
1615
needs_bar::<T::Assoc1>();
1716
//~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
17+
//~| ERROR overflow evaluating the requirement `<T as Foo2>::Assoc2`
1818
}
1919

2020
fn main() {}

Diff for: tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.stderr

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
2-
--> $DIR/recursive-self-normalization-2.rs:16:17
2+
--> $DIR/recursive-self-normalization-2.rs:15:17
33
|
44
LL | needs_bar::<T::Assoc1>();
55
| ^^^^^^^^^
66
|
77
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
88
note: required by a bound in `needs_bar`
9-
--> $DIR/recursive-self-normalization-2.rs:13:17
9+
--> $DIR/recursive-self-normalization-2.rs:12:17
1010
|
1111
LL | fn needs_bar<S: Bar>() {}
1212
| ^^^ required by this bound in `needs_bar`
1313

1414
error[E0275]: overflow evaluating the requirement `<T as Foo2>::Assoc2`
15+
--> $DIR/recursive-self-normalization-2.rs:15:5
16+
|
17+
LL | needs_bar::<T::Assoc1>();
18+
| ^^^^^^^^^^^^^^^^^^^^^^
1519
|
1620
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
1721

Diff for: tests/ui/traits/new-solver/overflow/recursive-self-normalization.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
//~ ERROR overflow evaluating the requirement `<T as Foo>::Assoc` [E0275]
21
// compile-flags: -Ztrait-solver=next
32

43
trait Foo {
@@ -11,6 +10,7 @@ fn needs_bar<S: Bar>() {}
1110
fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
1211
needs_bar::<T::Assoc>();
1312
//~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
13+
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc` [E0275]
1414
}
1515

1616
fn main() {}

0 commit comments

Comments
 (0)