Skip to content

Commit 835ed00

Browse files
committed
Auto merge of rust-lang#118751 - lcnr:writeback-change, r=compiler-errors
refactor writeback: emit normalization errors with new solver implements rust-lang#118725 (comment) r? `@compiler-errors` `@BoxyUwU` whoever comes first n stuff
2 parents 27d8a57 + 0bea818 commit 835ed00

File tree

16 files changed

+104
-119
lines changed

16 files changed

+104
-119
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
479479
match assoc_item.kind {
480480
ty::AssocKind::Fn => {
481481
let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi();
482-
fn_maybe_err(tcx, assoc_item.ident(tcx).span, abi);
482+
forbid_intrinsic_abi(tcx, assoc_item.ident(tcx).span, abi);
483483
}
484484
ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
485485
let trait_args = GenericArgs::identity_for_item(tcx, id.owner_id);

compiler/rustc_hir_analysis/src/check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ fn get_owner_return_paths(
141141
/// Forbid defining intrinsics in Rust code,
142142
/// as they must always be defined by the compiler.
143143
// FIXME: Move this to a more appropriate place.
144-
pub fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
144+
pub fn forbid_intrinsic_abi(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
145145
if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
146146
tcx.sess.span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block");
147147
}

compiler/rustc_hir_typeck/src/check.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_hir as hir;
88
use rustc_hir::def::DefKind;
99
use rustc_hir::intravisit::Visitor;
1010
use rustc_hir::lang_items::LangItem;
11-
use rustc_hir_analysis::check::{check_function_signature, fn_maybe_err};
11+
use rustc_hir_analysis::check::{check_function_signature, forbid_intrinsic_abi};
1212
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1313
use rustc_infer::infer::RegionVariableOrigin;
1414
use rustc_middle::ty::{self, Binder, Ty, TyCtxt};
@@ -53,7 +53,7 @@ pub(super) fn check_fn<'a, 'tcx>(
5353

5454
let span = body.value.span;
5555

56-
fn_maybe_err(tcx, span, fn_sig.abi);
56+
forbid_intrinsic_abi(tcx, span, fn_sig.abi);
5757

5858
if let Some(kind) = body.coroutine_kind
5959
&& can_be_coroutine.is_some()

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

compiler/rustc_hir_typeck/src/writeback.rs

+68-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,71 @@ 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>> + TypeSuperFoldable<TyCtxt<'tcx>> + Copy,
780+
{
781+
let tcx = self.fcx.tcx;
782+
// We must deeply normalize in the new solver, since later lints
783+
// expect that types that show up in the typeck are fully
784+
// normalized.
785+
let value = if self.should_normalize {
786+
let body_id = tcx.hir().body_owner_def_id(self.body.id());
787+
let cause = ObligationCause::misc(self.span.to_span(tcx), body_id);
788+
let at = self.fcx.at(&cause, self.fcx.param_env);
789+
let universes = vec![None; outer_exclusive_binder(value).as_usize()];
790+
solve::deeply_normalize_with_skipped_universes(at, value, universes).unwrap_or_else(
791+
|errors| {
792+
let guar = self.fcx.err_ctxt().report_fulfillment_errors(errors);
793+
new_err(tcx, guar)
794+
},
795+
)
796+
} else {
797+
value
798+
};
799+
800+
if value.has_non_region_infer() {
801+
let guar = self.report_error(value);
802+
new_err(tcx, guar)
803+
} else {
804+
tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased)
805+
}
806+
}
771807
}
772808

773809
impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
774810
fn interner(&self) -> TyCtxt<'tcx> {
775811
self.fcx.tcx
776812
}
777813

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-
807814
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
808815
debug_assert!(!r.is_bound(), "Should not be resolving bound region.");
809816
self.fcx.tcx.lifetimes.re_erased
810817
}
811818

819+
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
820+
self.handle_term(ty, Ty::outer_exclusive_binder, Ty::new_error)
821+
}
822+
812823
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-
}
824+
self.handle_term(ct, ty::Const::outer_exclusive_binder, |tcx, guar| {
825+
ty::Const::new_error(tcx, guar, ct.ty())
826+
})
822827
}
823-
}
824828

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.
829+
fn fold_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
830+
// Do not normalize predicates in the new solver. The new solver is
831+
// supposed to handle unnormalized predicates and incorrectly normalizing
832+
// them can be unsound, e.g. for `WellFormed` predicates.
833+
let prev = mem::replace(&mut self.should_normalize, false);
834+
let predicate = predicate.super_fold_with(self);
835+
self.should_normalize = prev;
836+
predicate
837+
}
838+
}

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

compiler/rustc_trait_selection/src/solve/mod.rs

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

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

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

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>>,

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
}

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`.

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.

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

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() {}

0 commit comments

Comments
 (0)