]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_typeck/src/check/compare_method.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / compiler / rustc_typeck / src / check / compare_method.rs
index 95c82a7d2c3d8e15a419b2cb1e4e6d491358cc17..666498403c4f7c57acdbe420f4a0eddaf53bb1a8 100644 (file)
@@ -1,11 +1,15 @@
+use super::potentially_plural_count;
+use crate::check::regionck::OutlivesEnvironmentExt;
+use crate::check::wfcheck;
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
-use rustc_data_structures::stable_set::FxHashSet;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit;
 use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
-use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::{self, TyCtxtInferExt};
 use rustc_infer::traits::util;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
@@ -14,11 +18,11 @@ use rustc_middle::ty::{self, DefIdTree};
 use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
 use rustc_span::Span;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
-use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
+use rustc_trait_selection::traits::{
+    self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
+};
 use std::iter;
 
-use super::{potentially_plural_count, FnCtxt, Inherited};
-
 /// Checks that a method from an impl conforms to the signature of
 /// the same method as declared in the trait.
 ///
@@ -31,14 +35,13 @@ use super::{potentially_plural_count, FnCtxt, Inherited};
 pub(crate) fn compare_impl_method<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &ty::AssocItem,
-    impl_m_span: Span,
     trait_m: &ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
     trait_item_span: Option<Span>,
 ) {
     debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref);
 
-    let impl_m_span = tcx.sess.source_map().guess_head_span(impl_m_span);
+    let impl_m_span = tcx.def_span(impl_m.def_id);
 
     if let Err(_) = compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref) {
         return;
@@ -78,17 +81,19 @@ fn compare_predicate_entailment<'tcx>(
     let trait_to_impl_substs = impl_trait_ref.substs;
 
     // This node-id should be used for the `body_id` field on each
-    // `ObligationCause` (and the `FnCtxt`). This is what
-    // `regionck_item` expects.
+    // `ObligationCause` (and the `FnCtxt`).
+    //
+    // FIXME(@lcnr): remove that after removing `cause.body_id` from
+    // obligations.
     let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
-
     // We sometimes modify the span further down.
     let mut cause = ObligationCause::new(
         impl_m_span,
         impl_m_hir_id,
-        ObligationCauseCode::CompareImplMethodObligation {
+        ObligationCauseCode::CompareImplItemObligation {
             impl_item_def_id: impl_m.def_id.expect_local(),
             trait_item_def_id: trait_m.def_id,
+            kind: impl_m.kind,
         },
     );
 
@@ -160,7 +165,7 @@ fn compare_predicate_entailment<'tcx>(
 
     // Create mapping from trait to placeholder.
     let trait_to_placeholder_substs =
-        impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container.id(), trait_to_impl_substs);
+        impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs);
     debug!("compare_impl_method: trait_to_placeholder_substs={:?}", trait_to_placeholder_substs);
 
     let impl_m_generics = tcx.generics_of(impl_m.def_id);
@@ -169,14 +174,7 @@ fn compare_predicate_entailment<'tcx>(
     let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
 
     // Check region bounds.
-    check_region_bounds_on_impl_item(
-        tcx,
-        impl_m_span,
-        impl_m,
-        trait_m,
-        &trait_m_generics,
-        &impl_m_generics,
-    )?;
+    check_region_bounds_on_impl_item(tcx, impl_m, trait_m, &trait_m_generics, &impl_m_generics)?;
 
     // Create obligations for each predicate declared by the impl
     // definition in the context of the trait's parameter
@@ -208,33 +206,31 @@ fn compare_predicate_entailment<'tcx>(
         Reveal::UserFacing,
         hir::Constness::NotConst,
     );
-    let param_env =
-        traits::normalize_param_env_or_error(tcx, impl_m.def_id, param_env, normalize_cause);
+    let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
 
-    tcx.infer_ctxt().enter(|infcx| {
-        let inh = Inherited::new(infcx, impl_m.def_id.expect_local());
-        let infcx = &inh.infcx;
+    tcx.infer_ctxt().enter(|ref infcx| {
+        let ocx = ObligationCtxt::new(infcx);
 
         debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
 
         let mut selcx = traits::SelectionContext::new(&infcx);
-
         let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
         for (predicate, span) in iter::zip(impl_m_own_bounds.predicates, impl_m_own_bounds.spans) {
             let normalize_cause = traits::ObligationCause::misc(span, impl_m_hir_id);
             let traits::Normalized { value: predicate, obligations } =
                 traits::normalize(&mut selcx, param_env, normalize_cause, predicate);
 
-            inh.register_predicates(obligations);
+            ocx.register_obligations(obligations);
             let cause = ObligationCause::new(
                 span,
                 impl_m_hir_id,
-                ObligationCauseCode::CompareImplMethodObligation {
+                ObligationCauseCode::CompareImplItemObligation {
                     impl_item_def_id: impl_m.def_id.expect_local(),
                     trait_item_def_id: trait_m.def_id,
+                    kind: impl_m.kind,
                 },
             );
-            inh.register_predicate(traits::Obligation::new(cause, param_env, predicate));
+            ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
         }
 
         // We now need to check that the signature of the impl method is
@@ -260,32 +256,31 @@ fn compare_predicate_entailment<'tcx>(
             infer::HigherRankedType,
             tcx.fn_sig(impl_m.def_id),
         );
-        let impl_sig =
-            inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, impl_sig);
+
+        let norm_cause = ObligationCause::misc(impl_m_span, impl_m_hir_id);
+        let impl_sig = ocx.normalize(norm_cause.clone(), param_env, impl_sig);
         let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
         debug!("compare_impl_method: impl_fty={:?}", impl_fty);
 
         let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
         let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
-        let trait_sig =
-            inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
+        let trait_sig = ocx.normalize(norm_cause, param_env, trait_sig);
         // Add the resulting inputs and output as well-formed.
         wf_tys.extend(trait_sig.inputs_and_output.iter());
         let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
 
         debug!("compare_impl_method: trait_fty={:?}", trait_fty);
 
-        let sub_result = infcx.at(&cause, param_env).sup(trait_fty, impl_fty).map(
-            |InferOk { obligations, .. }| {
-                // FIXME: We'd want to keep more accurate spans than "the method signature" when
-                // processing the comparison between the trait and impl fn, but we sadly lose them
-                // and point at the whole signature when a trait bound or specific input or output
-                // type would be more appropriate. In other places we have a `Vec<Span>`
-                // corresponding to their `Vec<Predicate>`, but we don't have that here.
-                // Fixing this would improve the output of test `issue-83765.rs`.
-                inh.register_predicates(obligations);
-            },
-        );
+        // FIXME: We'd want to keep more accurate spans than "the method signature" when
+        // processing the comparison between the trait and impl fn, but we sadly lose them
+        // and point at the whole signature when a trait bound or specific input or output
+        // type would be more appropriate. In other places we have a `Vec<Span>`
+        // corresponding to their `Vec<Predicate>`, but we don't have that here.
+        // Fixing this would improve the output of test `issue-83765.rs`.
+        let sub_result = infcx
+            .at(&cause, param_env)
+            .sup(trait_fty, impl_fty)
+            .map(|infer_ok| ocx.register_infer_ok_obligations(infer_ok));
 
         if let Err(terr) = sub_result {
             debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
@@ -297,7 +292,7 @@ fn compare_predicate_entailment<'tcx>(
 
             let mut diag = struct_span_err!(
                 tcx.sess,
-                cause.span(tcx),
+                cause.span(),
                 E0053,
                 "method `{}` has an incompatible type for trait",
                 trait_m.name
@@ -391,7 +386,7 @@ fn compare_predicate_entailment<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        let errors = ocx.select_all_or_error();
         if !errors.is_empty() {
             let reported = infcx.report_fulfillment_errors(&errors, None, false);
             return Err(reported);
@@ -399,8 +394,12 @@ fn compare_predicate_entailment<'tcx>(
 
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
-        let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id);
-        fcx.regionck_item(impl_m_hir_id, impl_m_span, wf_tys);
+        let mut outlives_environment = OutlivesEnvironment::new(param_env);
+        outlives_environment.add_implied_bounds(infcx, wf_tys, impl_m_hir_id);
+        infcx.check_region_obligations_and_report_errors(
+            impl_m.def_id.expect_local(),
+            &outlives_environment,
+        );
 
         Ok(())
     })
@@ -408,7 +407,6 @@ fn compare_predicate_entailment<'tcx>(
 
 fn check_region_bounds_on_impl_item<'tcx>(
     tcx: TyCtxt<'tcx>,
-    span: Span,
     impl_m: &ty::AssocItem,
     trait_m: &ty::AssocItem,
     trait_generics: &ty::Generics,
@@ -434,25 +432,25 @@ fn check_region_bounds_on_impl_item<'tcx>(
     // are zero. Since I don't quite know how to phrase things at
     // the moment, give a kind of vague error message.
     if trait_params != impl_params {
-        let item_kind = assoc_item_kind_str(impl_m);
-        let def_span = tcx.sess.source_map().guess_head_span(span);
-        let span = impl_m
-            .def_id
-            .as_local()
-            .and_then(|did| tcx.hir().get_generics(did))
-            .map_or(def_span, |g| g.span);
-        let generics_span = tcx.hir().span_if_local(trait_m.def_id).map(|sp| {
-            let def_sp = tcx.sess.source_map().guess_head_span(sp);
-            trait_m
-                .def_id
-                .as_local()
-                .and_then(|did| tcx.hir().get_generics(did))
-                .map_or(def_sp, |g| g.span)
-        });
+        let span = tcx
+            .hir()
+            .get_generics(impl_m.def_id.expect_local())
+            .expect("expected impl item to have generics or else we can't compare them")
+            .span;
+        let generics_span = if let Some(local_def_id) = trait_m.def_id.as_local() {
+            Some(
+                tcx.hir()
+                    .get_generics(local_def_id)
+                    .expect("expected trait item to have generics or else we can't compare them")
+                    .span,
+            )
+        } else {
+            None
+        };
 
         let reported = tcx.sess.emit_err(LifetimesOrBoundsMismatchOnTrait {
             span,
-            item_kind,
+            item_kind: assoc_item_kind_str(impl_m),
             ident: impl_m.ident(tcx),
             generics_span,
         });
@@ -492,7 +490,7 @@ fn extract_spans_for_error_reporting<'a, 'tcx>(
         TypeError::ArgumentSorts(ExpectedFound { .. }, i) => {
             (impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i)))
         }
-        _ => (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id)),
+        _ => (cause.span(), tcx.hir().span_if_local(trait_m.def_id)),
     }
 }
 
@@ -513,8 +511,8 @@ fn compare_self_type<'tcx>(
 
     let self_string = |method: &ty::AssocItem| {
         let untransformed_self_ty = match method.container {
-            ty::ImplContainer(_) => impl_trait_ref.self_ty(),
-            ty::TraitContainer(_) => tcx.types.self_param,
+            ty::ImplContainer => impl_trait_ref.self_ty(),
+            ty::TraitContainer => tcx.types.self_param,
         };
         let self_arg_ty = tcx.fn_sig(method.def_id).input(0);
         let param_env = ty::ParamEnv::reveal_all();
@@ -548,7 +546,7 @@ fn compare_self_type<'tcx>(
             if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) {
                 err.span_label(span, format!("trait method declared without `{self_descr}`"));
             } else {
-                err.note_trait_signature(trait_m.name.to_string(), trait_m.signature(tcx));
+                err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
             }
             let reported = err.emit();
             return Err(reported);
@@ -568,7 +566,7 @@ fn compare_self_type<'tcx>(
             if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) {
                 err.span_label(span, format!("`{self_descr}` used in trait"));
             } else {
-                err.note_trait_signature(trait_m.name.to_string(), trait_m.signature(tcx));
+                err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
             }
             let reported = err.emit();
             return Err(reported);
@@ -807,7 +805,7 @@ fn compare_number_of_method_arguments<'tcx>(
                 ),
             );
         } else {
-            err.note_trait_signature(trait_m.name.to_string(), trait_m.signature(tcx));
+            err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
         }
         err.span_label(
             impl_span,
@@ -1041,8 +1039,7 @@ fn compare_generic_param_kinds<'tcx>(
             err.span_label(trait_header_span, "");
             err.span_label(param_trait_span, make_param_message("expected", param_trait));
 
-            let impl_header_span =
-                tcx.sess.source_map().guess_head_span(tcx.def_span(tcx.parent(impl_item.def_id)));
+            let impl_header_span = tcx.def_span(tcx.parent(impl_item.def_id));
             err.span_label(impl_header_span, "");
             err.span_label(param_impl_span, make_param_message("found", param_impl));
 
@@ -1065,8 +1062,7 @@ pub(crate) fn compare_const_impl<'tcx>(
 
     tcx.infer_ctxt().enter(|infcx| {
         let param_env = tcx.param_env(impl_c.def_id);
-        let inh = Inherited::new(infcx, impl_c.def_id.expect_local());
-        let infcx = &inh.infcx;
+        let ocx = ObligationCtxt::new(&infcx);
 
         // The below is for the most part highly similar to the procedure
         // for methods above. It is simpler in many respects, especially
@@ -1085,24 +1081,26 @@ pub(crate) fn compare_const_impl<'tcx>(
         let mut cause = ObligationCause::new(
             impl_c_span,
             impl_c_hir_id,
-            ObligationCauseCode::CompareImplConstObligation,
+            ObligationCauseCode::CompareImplItemObligation {
+                impl_item_def_id: impl_c.def_id.expect_local(),
+                trait_item_def_id: trait_c.def_id,
+                kind: impl_c.kind,
+            },
         );
 
         // There is no "body" here, so just pass dummy id.
-        let impl_ty =
-            inh.normalize_associated_types_in(impl_c_span, impl_c_hir_id, param_env, impl_ty);
+        let impl_ty = ocx.normalize(cause.clone(), param_env, impl_ty);
 
         debug!("compare_const_impl: impl_ty={:?}", impl_ty);
 
-        let trait_ty =
-            inh.normalize_associated_types_in(impl_c_span, impl_c_hir_id, param_env, trait_ty);
+        let trait_ty = ocx.normalize(cause.clone(), param_env, trait_ty);
 
         debug!("compare_const_impl: trait_ty={:?}", trait_ty);
 
         let err = infcx
             .at(&cause, param_env)
             .sup(trait_ty, impl_ty)
-            .map(|ok| inh.register_infer_ok_obligations(ok));
+            .map(|ok| ocx.register_infer_ok_obligations(ok));
 
         if let Err(terr) = err {
             debug!(
@@ -1149,14 +1147,17 @@ pub(crate) fn compare_const_impl<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        let errors = ocx.select_all_or_error();
         if !errors.is_empty() {
             infcx.report_fulfillment_errors(&errors, None, false);
             return;
         }
 
-        let fcx = FnCtxt::new(&inh, param_env, impl_c_hir_id);
-        fcx.regionck_item(impl_c_hir_id, impl_c_span, FxHashSet::default());
+        let outlives_environment = OutlivesEnvironment::new(param_env);
+        infcx.check_region_obligations_and_report_errors(
+            impl_c.def_id.expect_local(),
+            &outlives_environment,
+        );
     });
 }
 
@@ -1193,7 +1194,7 @@ fn compare_type_predicate_entailment<'tcx>(
 ) -> Result<(), ErrorGuaranteed> {
     let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
     let trait_to_impl_substs =
-        impl_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
+        impl_substs.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.substs);
 
     let impl_ty_generics = tcx.generics_of(impl_ty.def_id);
     let trait_ty_generics = tcx.generics_of(trait_ty.def_id);
@@ -1202,7 +1203,6 @@ fn compare_type_predicate_entailment<'tcx>(
 
     check_region_bounds_on_impl_item(
         tcx,
-        impl_ty_span,
         impl_ty,
         trait_ty,
         &trait_ty_generics,
@@ -1220,15 +1220,6 @@ fn compare_type_predicate_entailment<'tcx>(
     // `ObligationCause` (and the `FnCtxt`). This is what
     // `regionck_item` expects.
     let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
-    let cause = ObligationCause::new(
-        impl_ty_span,
-        impl_ty_hir_id,
-        ObligationCauseCode::CompareImplTypeObligation {
-            impl_item_def_id: impl_ty.def_id.expect_local(),
-            trait_item_def_id: trait_ty.def_id,
-        },
-    );
-
     debug!("compare_type_predicate_entailment: trait_to_impl_substs={:?}", trait_to_impl_substs);
 
     // The predicates declared by the impl definition, the trait and the
@@ -1247,31 +1238,38 @@ fn compare_type_predicate_entailment<'tcx>(
         Reveal::UserFacing,
         hir::Constness::NotConst,
     );
-    let param_env = traits::normalize_param_env_or_error(
-        tcx,
-        impl_ty.def_id,
-        param_env,
-        normalize_cause.clone(),
-    );
+    let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
     tcx.infer_ctxt().enter(|infcx| {
-        let inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
-        let infcx = &inh.infcx;
+        let ocx = ObligationCtxt::new(&infcx);
 
         debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
 
         let mut selcx = traits::SelectionContext::new(&infcx);
 
-        for predicate in impl_ty_own_bounds.predicates {
+        assert_eq!(impl_ty_own_bounds.predicates.len(), impl_ty_own_bounds.spans.len());
+        for (span, predicate) in
+            std::iter::zip(impl_ty_own_bounds.spans, impl_ty_own_bounds.predicates)
+        {
+            let cause = ObligationCause::misc(span, impl_ty_hir_id);
             let traits::Normalized { value: predicate, obligations } =
-                traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate);
+                traits::normalize(&mut selcx, param_env, cause, predicate);
 
-            inh.register_predicates(obligations);
-            inh.register_predicate(traits::Obligation::new(cause.clone(), param_env, predicate));
+            let cause = ObligationCause::new(
+                span,
+                impl_ty_hir_id,
+                ObligationCauseCode::CompareImplItemObligation {
+                    impl_item_def_id: impl_ty.def_id.expect_local(),
+                    trait_item_def_id: trait_ty.def_id,
+                    kind: impl_ty.kind,
+                },
+            );
+            ocx.register_obligations(obligations);
+            ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
         }
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        let errors = ocx.select_all_or_error();
         if !errors.is_empty() {
             let reported = infcx.report_fulfillment_errors(&errors, None, false);
             return Err(reported);
@@ -1279,8 +1277,11 @@ fn compare_type_predicate_entailment<'tcx>(
 
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
-        let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
-        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, FxHashSet::default());
+        let outlives_environment = OutlivesEnvironment::new(param_env);
+        infcx.check_region_obligations_and_report_errors(
+            impl_ty.def_id.expect_local(),
+            &outlives_environment,
+        );
 
         Ok(())
     })
@@ -1389,9 +1390,9 @@ pub fn check_type_bounds<'tcx>(
     });
     let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
     let impl_ty_substs = tcx.intern_substs(&substs);
+    let container_id = impl_ty.container_id(tcx);
 
-    let rebased_substs =
-        impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
+    let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
     let impl_ty_value = tcx.type_of(impl_ty.def_id);
 
     let param_env = tcx.param_env(impl_ty.def_id);
@@ -1440,14 +1441,12 @@ pub fn check_type_bounds<'tcx>(
     debug!(?normalize_param_env);
 
     let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
-    let rebased_substs =
-        impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
+    let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
 
     tcx.infer_ctxt().enter(move |infcx| {
-        let inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
-        let infcx = &inh.infcx;
-        let mut selcx = traits::SelectionContext::new(&infcx);
+        let ocx = ObligationCtxt::new(&infcx);
 
+        let mut selcx = traits::SelectionContext::new(&infcx);
         let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
         let normalize_cause = ObligationCause::new(
             impl_ty_span,
@@ -1472,6 +1471,7 @@ pub fn check_type_bounds<'tcx>(
             .map(|e| e.map_bound(|e| *e).transpose_tuple2())
             .map(|(bound, span)| {
                 debug!(?bound);
+                // this is where opaque type is found
                 let concrete_ty_bound = bound.subst(tcx, rebased_substs);
                 debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
 
@@ -1490,13 +1490,12 @@ pub fn check_type_bounds<'tcx>(
             debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
             obligation.predicate = normalized_predicate;
 
-            inh.register_predicates(obligations);
-            inh.register_predicate(obligation);
+            ocx.register_obligations(obligations);
+            ocx.register_obligation(obligation);
         }
-
         // Check that all obligations are satisfied by the implementation's
         // version.
-        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        let errors = ocx.select_all_or_error();
         if !errors.is_empty() {
             let reported = infcx.report_fulfillment_errors(&errors, None, false);
             return Err(reported);
@@ -1504,12 +1503,36 @@ pub fn check_type_bounds<'tcx>(
 
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
-        let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
         let implied_bounds = match impl_ty.container {
-            ty::TraitContainer(_) => FxHashSet::default(),
-            ty::ImplContainer(def_id) => fcx.impl_implied_bounds(def_id, impl_ty_span),
+            ty::TraitContainer => FxHashSet::default(),
+            ty::ImplContainer => wfcheck::impl_implied_bounds(
+                tcx,
+                param_env,
+                container_id.expect_local(),
+                impl_ty_span,
+            ),
         };
-        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, implied_bounds);
+        let mut outlives_environment = OutlivesEnvironment::new(param_env);
+        outlives_environment.add_implied_bounds(&infcx, implied_bounds, impl_ty_hir_id);
+        infcx.check_region_obligations_and_report_errors(
+            impl_ty.def_id.expect_local(),
+            &outlives_environment,
+        );
+
+        let constraints = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+        for (key, value) in constraints {
+            infcx
+                .report_mismatched_types(
+                    &ObligationCause::misc(
+                        value.hidden_type.span,
+                        tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local()),
+                    ),
+                    tcx.mk_opaque(key.def_id.to_def_id(), key.substs),
+                    value.hidden_type.ty,
+                    TypeError::Mismatch,
+                )
+                .emit();
+        }
 
         Ok(())
     })