@@ -8,12 +8,16 @@ use rustc_errors::{ErrorGuaranteed, StashKey};
8
8
use rustc_hir as hir;
9
9
use rustc_hir::intravisit::{self, Visitor};
10
10
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
11
+ use rustc_middle::traits::ObligationCause;
11
12
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
12
13
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
13
14
use rustc_middle::ty::visit::TypeVisitableExt;
15
+ use rustc_middle::ty::TypeSuperFoldable;
14
16
use rustc_middle::ty::{self, Ty, TyCtxt};
15
17
use rustc_span::symbol::sym;
16
18
use rustc_span::Span;
19
+ use rustc_trait_selection::solve;
20
+ use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
17
21
18
22
use std::mem;
19
23
@@ -695,24 +699,22 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
695
699
}
696
700
}
697
701
698
- fn resolve<T>(&mut self, x : T, span: &dyn Locatable) -> T
702
+ fn resolve<T>(&mut self, value : T, span: &dyn Locatable) -> T
699
703
where
700
704
T: TypeFoldable<TyCtxt<'tcx>>,
701
705
{
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());
707
709
708
710
// We may have introduced e.g. `ty::Error`, if inference failed, make sure
709
711
// to mark the `TypeckResults` as tainted in that case, so that downstream
710
712
// 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 );
713
715
}
714
716
715
- x
717
+ value
716
718
}
717
719
}
718
720
@@ -732,15 +734,13 @@ impl Locatable for hir::HirId {
732
734
}
733
735
}
734
736
735
- /// The Resolver. This is the type folding engine that detects
736
- /// unresolved types and so forth.
737
737
struct Resolver<'cx, 'tcx> {
738
738
fcx: &'cx FnCtxt<'cx, 'tcx>,
739
739
span: &'cx dyn Locatable,
740
740
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 ,
744
744
}
745
745
746
746
impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
@@ -749,7 +749,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
749
749
span: &'cx dyn Locatable,
750
750
body: &'tcx hir::Body<'tcx>,
751
751
) -> Resolver<'cx, 'tcx> {
752
- Resolver { fcx, span, body, replaced_with_error: None }
752
+ Resolver { fcx, span, body, should_normalize: fcx.next_trait_solver() }
753
753
}
754
754
755
755
fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
@@ -768,64 +768,73 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
768
768
.emit(),
769
769
}
770
770
}
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
+ }
771
809
}
772
810
773
811
impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
774
812
fn interner(&self) -> TyCtxt<'tcx> {
775
813
self.fcx.tcx
776
814
}
777
815
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
-
807
816
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
808
817
debug_assert!(!r.is_bound(), "Should not be resolving bound region.");
809
818
self.fcx.tcx.lifetimes.re_erased
810
819
}
811
820
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
+
812
825
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
+ })
822
829
}
823
- }
824
830
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
+ }
0 commit comments