]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #95466 - Dylan-DPC:rollup-g7ddr8y, r=Dylan-DPC
authorbors <bors@rust-lang.org>
Wed, 30 Mar 2022 07:45:42 +0000 (07:45 +0000)
committerbors <bors@rust-lang.org>
Wed, 30 Mar 2022 07:45:42 +0000 (07:45 +0000)
Rollup of 5 pull requests

Successful merges:

 - #95294 (Document Linux kernel handoff in std::io::copy and std::fs::copy)
 - #95443 (Clarify how `src/tools/x` searches for python)
 - #95452 (fix since field version for termination stabilization)
 - #95460 (Spellchecking compiler code)
 - #95461 (Spellchecking some comments)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup

1  2 
compiler/rustc_borrowck/src/lib.rs
compiler/rustc_borrowck/src/region_infer/mod.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs

index 58b246ec873ca27a329ac72be71f0a7aae7f937f,13584048f09c9e2015bcf9f5bd13e597c4f9719b..a8fd5bb50a60f81c19426656a144023fa5a58c1b
@@@ -7,7 -7,6 +7,7 @@@
  #![feature(let_chains)]
  #![feature(let_else)]
  #![feature(min_specialization)]
 +#![feature(never_type)]
  #![feature(stmt_expr_attributes)]
  #![feature(trusted_step)]
  #![feature(try_blocks)]
@@@ -126,9 -125,8 +126,9 @@@ fn mir_borrowck<'tcx>
  ) -> &'tcx BorrowCheckResult<'tcx> {
      let (input_body, promoted) = tcx.mir_promoted(def);
      debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
 +    let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
  
 -    let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| {
 +    let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(hir_owner).enter(|infcx| {
          let input_body: &Body<'_> = &input_body.borrow();
          let promoted: &IndexVec<_, _> = &promoted.borrow();
          do_mir_borrowck(&infcx, input_body, promoted, false).0
  /// If `return_body_with_facts` is true, then return the body with non-erased
  /// region ids on which the borrow checking was performed together with Polonius
  /// facts.
 -#[instrument(skip(infcx, input_body, input_promoted), level = "debug")]
 +#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")]
  fn do_mir_borrowck<'a, 'tcx>(
      infcx: &InferCtxt<'a, 'tcx>,
      input_body: &Body<'tcx>,
@@@ -1048,7 -1046,7 +1048,7 @@@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 't
                  // borrow); so don't check if they interfere.
                  //
                  // NOTE: *reservations* do conflict with themselves;
-                 // thus aren't injecting unsoundenss w/ this check.)
+                 // thus aren't injecting unsoundness w/ this check.)
                  (Activation(_, activating), _) if activating == borrow_index => {
                      debug!(
                          "check_access_for_conflict place_span: {:?} sd: {:?} rw: {:?} \
                      );
                      // rust-lang/rust#56254 - This was previously permitted on
                      // the 2018 edition so we emit it as a warning. We buffer
-                     // these sepately so that we only emit a warning if borrow
+                     // these separately so that we only emit a warning if borrow
                      // checking was otherwise successful.
                      this.reservation_warnings
                          .insert(bi, (place_span.0, place_span.1, location, bk, borrow.clone()));
      ) {
          debug!("check_if_reassignment_to_immutable_state({:?})", local);
  
-         // Check if any of the initializiations of `local` have happened yet:
+         // Check if any of the initializations of `local` have happened yet:
          if let Some(init_index) = self.is_local_ever_initialized(local, flow_state) {
              // And, if so, report an error.
              let init = &self.move_data.inits[init_index];
index 1f81f7dda1334f85fcb95a313b71ba83ef4836ce,47da1da978c764afd4a47aeef4f7ef18e6b6f4cd..dabf61715ce58fb78bb4239dd40ab501932c061e
@@@ -45,7 -45,6 +45,7 @@@ mod reverse_sccs
  pub mod values;
  
  pub struct RegionInferenceContext<'tcx> {
 +    pub var_infos: VarInfos,
      /// Contains the definition for every region variable. Region
      /// variables are identified by their index (`RegionVid`). The
      /// definition contains information about where the region came
@@@ -268,7 -267,7 +268,7 @@@ impl<'tcx> RegionInferenceContext<'tcx
      ) -> Self {
          // Create a RegionDefinition for each inference variable.
          let definitions: IndexVec<_, _> = var_infos
 -            .into_iter()
 +            .iter()
              .map(|info| RegionDefinition::new(info.universe, info.origin))
              .collect();
  
              Rc::new(member_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
  
          let mut result = Self {
 +            var_infos,
              definitions,
              liveness_constraints,
              constraints,
          let universe_a = self.scc_universes[scc_a];
  
          // Quick check: if scc_b's declared universe is a subset of
-         // scc_a's declared univese (typically, both are ROOT), then
+         // scc_a's declared universe (typically, both are ROOT), then
          // it cannot contain any problematic universe elements.
          if universe_a.can_name(self.scc_universes[scc_b]) {
              return true;
              .iter()
              .find_map(|constraint| {
                  if let ConstraintCategory::Predicate(predicate_span) = constraint.category {
-                     // We currentl'y doesn't store the `DefId` in the `ConstraintCategory`
+                     // We currently do not store the `DefId` in the `ConstraintCategory`
                      // for performances reasons. The error reporting code used by NLL only
                      // uses the span, so this doesn't cause any problems at the moment.
                      Some(ObligationCauseCode::BindingObligation(
index 9d7dcc5379c5d41f07a44a1e0298a4af291271fb,47c7ac3094f27f33ac89c8693c4ba98392e3b9e5..7dc292ffb6579dfc9dcaaa11b75735ab90062f12
@@@ -5,7 -5,6 +5,7 @@@ use std::{fmt, iter, mem}
  
  use either::Either;
  
 +use hir::OpaqueTyOrigin;
  use rustc_data_structures::frozen::Frozen;
  use rustc_data_structures::fx::{FxHashMap, FxHashSet};
  use rustc_data_structures::vec_map::VecMap;
@@@ -16,8 -15,8 +16,8 @@@ use rustc_hir::def_id::LocalDefId
  use rustc_hir::lang_items::LangItem;
  use rustc_index::vec::{Idx, IndexVec};
  use rustc_infer::infer::canonical::QueryRegionConstraints;
 -use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
  use rustc_infer::infer::outlives::env::RegionBoundPairs;
 +use rustc_infer::infer::region_constraints::RegionConstraintData;
  use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
  use rustc_infer::infer::{
      InferCtxt, InferOk, LateBoundRegionConversionTime, NllRegionVariableOrigin,
@@@ -31,8 -30,8 +31,8 @@@ use rustc_middle::ty::cast::CastTy
  use rustc_middle::ty::fold::TypeFoldable;
  use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
  use rustc_middle::ty::{
 -    self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid,
 -    ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
 +    self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueHiddenType,
 +    OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
  };
  use rustc_span::def_id::CRATE_DEF_ID;
  use rustc_span::{Span, DUMMY_SP};
@@@ -40,11 -39,9 +40,11 @@@ use rustc_target::abi::VariantIdx
  use rustc_trait_selection::infer::InferCtxtExt as _;
  use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
  use rustc_trait_selection::traits::query::type_op;
 +use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
  use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
 +use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
  use rustc_trait_selection::traits::query::Fallible;
 -use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations};
 +use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation};
  
  use rustc_const_eval::transform::{
      check_consts::ConstCx, promote_consts::is_const_fn_in_array_repeat_expression,
@@@ -78,7 -75,7 +78,7 @@@ macro_rules! span_mirbug 
              $context.last_span,
              &format!(
                  "broken MIR in {:?} ({:?}): {}",
 -                $context.body.source.def_id(),
 +                $context.body().source.def_id(),
                  $elem,
                  format_args!($($message)*),
              ),
@@@ -202,44 -199,59 +202,44 @@@ pub(crate) fn type_check<'mir, 'tcx>
              );
  
              translate_outlives_facts(&mut cx);
 -            let opaque_type_values = mem::take(&mut infcx.inner.borrow_mut().opaque_types);
 +            let opaque_type_values =
 +                infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
  
              opaque_type_values
                  .into_iter()
 -                .filter_map(|(opaque_type_key, mut decl)| {
 -                    decl.concrete_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
 +                .map(|(opaque_type_key, decl)| {
 +                    cx.fully_perform_op(
 +                        Locations::All(body.span),
 +                        ConstraintCategory::OpaqueType,
 +                        CustomTypeOp::new(
 +                            |infcx| {
 +                                infcx.register_member_constraints(
 +                                    param_env,
 +                                    opaque_type_key,
 +                                    decl.hidden_type.ty,
 +                                    decl.hidden_type.span,
 +                                );
 +                                Ok(InferOk { value: (), obligations: vec![] })
 +                            },
 +                            || "opaque_type_map".to_string(),
 +                        ),
 +                    )
 +                    .unwrap();
 +                    let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
                      trace!(
                          "finalized opaque type {:?} to {:#?}",
                          opaque_type_key,
 -                        decl.concrete_ty.kind()
 +                        hidden_type.ty.kind()
                      );
 -                    if decl.concrete_ty.has_infer_types_or_consts() {
 +                    if hidden_type.has_infer_types_or_consts() {
                          infcx.tcx.sess.delay_span_bug(
 -                            body.span,
 -                            &format!("could not resolve {:#?}", decl.concrete_ty.kind()),
 +                            decl.hidden_type.span,
 +                            &format!("could not resolve {:#?}", hidden_type.ty.kind()),
                          );
 -                        decl.concrete_ty = infcx.tcx.ty_error();
 +                        hidden_type.ty = infcx.tcx.ty_error();
                      }
 -                    let concrete_is_opaque = if let ty::Opaque(def_id, _) = decl.concrete_ty.kind()
 -                    {
 -                        *def_id == opaque_type_key.def_id
 -                    } else {
 -                        false
 -                    };
  
 -                    if concrete_is_opaque {
 -                        // We're using an opaque `impl Trait` type without
 -                        // 'revealing' it. For example, code like this:
 -                        //
 -                        // type Foo = impl Debug;
 -                        // fn foo1() -> Foo { ... }
 -                        // fn foo2() -> Foo { foo1() }
 -                        //
 -                        // In `foo2`, we're not revealing the type of `Foo` - we're
 -                        // just treating it as the opaque type.
 -                        //
 -                        // When this occurs, we do *not* want to try to equate
 -                        // the concrete type with the underlying defining type
 -                        // of the opaque type - this will always fail, since
 -                        // the defining type of an opaque type is always
 -                        // some other type (e.g. not itself)
 -                        // Essentially, none of the normal obligations apply here -
 -                        // we're just passing around some unknown opaque type,
 -                        // without actually looking at the underlying type it
 -                        // gets 'revealed' into
 -                        debug!(
 -                            "eq_opaque_type_and_type: non-defining use of {:?}",
 -                            opaque_type_key.def_id,
 -                        );
 -                        None
 -                    } else {
 -                        Some((opaque_type_key, decl))
 -                    }
 +                    (opaque_type_key, (hidden_type, decl.origin))
                  })
                  .collect()
          },
@@@ -271,7 -283,7 +271,7 @@@ fn type_check_internal<'a, 'tcx, R>
          borrowck_context,
      );
      let errors_reported = {
 -        let mut verifier = TypeVerifier::new(&mut checker, body, promoted);
 +        let mut verifier = TypeVerifier::new(&mut checker, promoted);
          verifier.visit_body(&body);
          verifier.errors_reported
      };
@@@ -328,6 -340,7 +328,6 @@@ enum FieldAccessError 
  /// is a problem.
  struct TypeVerifier<'a, 'b, 'tcx> {
      cx: &'a mut TypeChecker<'b, 'tcx>,
 -    body: &'b Body<'tcx>,
      promoted: &'b IndexVec<Promoted, Body<'tcx>>,
      last_span: Span,
      errors_reported: bool,
@@@ -463,7 -476,7 +463,7 @@@ impl<'a, 'b, 'tcx> Visitor<'tcx> for Ty
  
      fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
          self.super_rvalue(rvalue, location);
 -        let rval_ty = rvalue.ty(self.body, self.tcx());
 +        let rval_ty = rvalue.ty(self.body(), self.tcx());
          self.sanitize_type(rvalue, rval_ty);
      }
  
  impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
      fn new(
          cx: &'a mut TypeChecker<'b, 'tcx>,
 -        body: &'b Body<'tcx>,
          promoted: &'b IndexVec<Promoted, Body<'tcx>>,
      ) -> Self {
 -        TypeVerifier { body, promoted, cx, last_span: body.span, errors_reported: false }
 +        TypeVerifier { promoted, last_span: cx.body.span, cx, errors_reported: false }
 +    }
 +
 +    fn body(&self) -> &Body<'tcx> {
 +        self.cx.body
      }
  
      fn tcx(&self) -> TyCtxt<'tcx> {
      ) -> PlaceTy<'tcx> {
          debug!("sanitize_place: {:?}", place);
  
 -        let mut place_ty = PlaceTy::from_ty(self.body.local_decls[place.local].ty);
 +        let mut place_ty = PlaceTy::from_ty(self.body().local_decls[place.local].ty);
  
          for elem in place.projection.iter() {
              if place_ty.variant_index.is_none() {
          // checker on the promoted MIR, then transfer the constraints back to
          // the main MIR, changing the locations to the provided location.
  
 -        let parent_body = mem::replace(&mut self.body, promoted_body);
 +        let parent_body = mem::replace(&mut self.cx.body, promoted_body);
  
          // Use new sets of constraints and closure bounds so that we can
          // modify their locations.
              self.cx.typeck_mir(promoted_body);
          }
  
 -        self.body = parent_body;
 +        self.cx.body = parent_body;
          // Merge the outlives constraints back in, at the given location.
          swap_constraints(self);
  
                  }))
              }
              ProjectionElem::Index(i) => {
 -                let index_ty = Place::from(i).ty(self.body, tcx).ty;
 +                let index_ty = Place::from(i).ty(self.body(), tcx).ty;
                  if index_ty != tcx.types.usize {
                      PlaceTy::from_ty(span_mirbug_and_err!(self, i, "index by non-usize {:?}", i))
                  } else {
@@@ -905,7 -915,7 +905,7 @@@ struct BorrowCheckContext<'a, 'tcx> 
  crate struct MirTypeckResults<'tcx> {
      crate constraints: MirTypeckRegionConstraints<'tcx>,
      crate universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
 -    crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
 +    crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
  }
  
  /// A collection of region constraints that must be satisfied for the
@@@ -1055,19 -1065,17 +1055,19 @@@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> 
          checker
      }
  
 +    fn body(&self) -> &Body<'tcx> {
 +        self.body
 +    }
 +
      fn unsized_feature_enabled(&self) -> bool {
          let features = self.tcx().features();
          features.unsized_locals || features.unsized_fn_params
      }
  
      /// Equate the inferred type and the annotated type for user type annotations
 +    #[instrument(skip(self), level = "debug")]
      fn check_user_type_annotations(&mut self) {
 -        debug!(
 -            "check_user_type_annotations: user_type_annotations={:?}",
 -            self.user_type_annotations
 -        );
 +        debug!(?self.user_type_annotations);
          for user_annotation in self.user_type_annotations {
              let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
              let inferred_ty = self.normalize(inferred_ty, Locations::All(span));
          Ok(())
      }
  
 -    /// Equates a type `anon_ty` that may contain opaque types whose
 -    /// values are to be inferred by the MIR.
 -    ///
 -    /// The type `revealed_ty` contains the same type as `anon_ty`, but with the
 -    /// hidden types for impl traits revealed.
 -    ///
 -    /// # Example
 -    ///
 -    /// Consider a piece of code like
 -    ///
 -    /// ```rust
 -    /// type Foo<U> = impl Debug;
 -    ///
 -    /// fn foo<T: Debug>(t: T) -> Box<Foo<T>> {
 -    ///      Box::new((t, 22_u32))
 -    /// }
 -    /// ```
 -    ///
 -    /// Here, the function signature would be something like
 -    /// `fn(T) -> Box<impl Debug>`. The MIR return slot would have
 -    /// the type with the opaque type revealed, so `Box<(T, u32)>`.
 -    ///
 -    /// In terms of our function parameters:
 -    ///
 -    /// * `anon_ty` would be `Box<Foo<T>>` where `Foo<T>` is an opaque type
 -    ///   scoped to this function (note that it is parameterized by the
 -    ///   generics of `foo`). Note that `anon_ty` is not just the opaque type,
 -    ///   but the entire return type (which may contain opaque types within it).
 -    /// * `revealed_ty` would be `Box<(T, u32)>`
 -    #[instrument(skip(self), level = "debug")]
 -    fn eq_opaque_type_and_type(
 -        &mut self,
 -        revealed_ty: Ty<'tcx>,
 -        anon_ty: Ty<'tcx>,
 -        locations: Locations,
 -        category: ConstraintCategory,
 -    ) -> Fallible<()> {
 -        // Fast path for the common case.
 -        if !anon_ty.has_opaque_types() {
 -            if let Err(terr) = self.eq_types(anon_ty, revealed_ty, locations, category) {
 -                span_mirbug!(
 -                    self,
 -                    locations,
 -                    "eq_opaque_type_and_type: `{:?}=={:?}` failed with `{:?}`",
 -                    revealed_ty,
 -                    anon_ty,
 -                    terr
 -                );
 -            }
 -            return Ok(());
 -        }
 -
 -        let param_env = self.param_env;
 -        let body = self.body;
 -        let mir_def_id = body.source.def_id().expect_local();
 -
 -        debug!(?mir_def_id);
 -        self.fully_perform_op(
 -            locations,
 -            category,
 -            CustomTypeOp::new(
 -                |infcx| {
 -                    let mut obligations = ObligationAccumulator::default();
 -
 -                    let dummy_body_id = hir::CRATE_HIR_ID;
 -
 -                    // Replace the opaque types defined by this function with
 -                    // inference variables, creating a map. In our example above,
 -                    // this would transform the type `Box<Foo<T>>` (where `Foo` is an opaque type)
 -                    // to `Box<?T>`, returning an `opaque_type_map` mapping `{Foo<T> -> ?T}`.
 -                    // (Note that the key of the map is both the def-id of `Foo` along with
 -                    // any generic parameters.)
 -                    let output_ty = obligations.add(infcx.instantiate_opaque_types(
 -                        dummy_body_id,
 -                        param_env,
 -                        anon_ty,
 -                        locations.span(body),
 -                    ));
 -                    debug!(?output_ty, ?revealed_ty);
 -
 -                    // Make sure that the inferred types are well-formed. I'm
 -                    // not entirely sure this is needed (the HIR type check
 -                    // didn't do this) but it seems sensible to prevent opaque
 -                    // types hiding ill-formed types.
 -                    obligations.obligations.push(traits::Obligation::new(
 -                        ObligationCause::dummy(),
 -                        param_env,
 -                        ty::Binder::dummy(ty::PredicateKind::WellFormed(revealed_ty.into()))
 -                            .to_predicate(infcx.tcx),
 -                    ));
 -                    obligations.add(
 -                        infcx
 -                            .at(&ObligationCause::dummy(), param_env)
 -                            .eq(output_ty, revealed_ty)?,
 -                    );
 -
 -                    debug!("equated");
 -
 -                    Ok(InferOk { value: (), obligations: obligations.into_vec() })
 -                },
 -                || "input_output".to_string(),
 -            ),
 -        )?;
 -
 -        // Finally, if we instantiated the anon types successfully, we
 -        // have to solve any bounds (e.g., `-> impl Iterator` needs to
 -        // prove that `T: Iterator` where `T` is the type we
 -        // instantiated it with).
 -        let opaque_type_map = self.infcx.inner.borrow().opaque_types.clone();
 -        for (opaque_type_key, opaque_decl) in opaque_type_map {
 -            self.fully_perform_op(
 -                locations,
 -                ConstraintCategory::OpaqueType,
 -                CustomTypeOp::new(
 -                    |infcx| {
 -                        infcx.constrain_opaque_type(opaque_type_key, &opaque_decl);
 -                        Ok(InferOk { value: (), obligations: vec![] })
 -                    },
 -                    || "opaque_type_map".to_string(),
 -                ),
 -            )?;
 -        }
 -        Ok(())
 -    }
 -
      fn tcx(&self) -> TyCtxt<'tcx> {
          self.infcx.tcx
      }
              // we have to solve them here where we instantiate the
              // closure.
              //
-             // Despite the opacity of the previous parapgrah, this is
+             // Despite the opacity of the previous paragraph, this is
              // actually relatively easy to understand in terms of the
              // desugaring. A closure gets desugared to a struct, and
              // these extra requirements are basically like where
@@@ -2639,31 -2772,19 +2639,31 @@@ impl NormalizeLocation for Location 
      }
  }
  
 -#[derive(Debug, Default)]
 -struct ObligationAccumulator<'tcx> {
 -    obligations: PredicateObligations<'tcx>,
 +/// Runs `infcx.instantiate_opaque_types`. Unlike other `TypeOp`s,
 +/// this is not canonicalized - it directly affects the main `InferCtxt`
 +/// that we use during MIR borrowchecking.
 +#[derive(Debug)]
 +pub(super) struct InstantiateOpaqueType<'tcx> {
 +    pub base_universe: Option<ty::UniverseIndex>,
 +    pub region_constraints: Option<RegionConstraintData<'tcx>>,
 +    pub obligations: Vec<PredicateObligation<'tcx>>,
  }
  
 -impl<'tcx> ObligationAccumulator<'tcx> {
 -    fn add<T>(&mut self, value: InferOk<'tcx, T>) -> T {
 -        let InferOk { value, obligations } = value;
 -        self.obligations.extend(obligations);
 -        value
 -    }
 -
 -    fn into_vec(self) -> PredicateObligations<'tcx> {
 -        self.obligations
 +impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
 +    type Output = ();
 +    /// We use this type itself to store the information used
 +    /// when reporting errors. Since this is not a query, we don't
 +    /// re-run anything during error reporting - we just use the information
 +    /// we saved to help extract an error from the already-existing region
 +    /// constraints in our `InferCtxt`
 +    type ErrorInfo = InstantiateOpaqueType<'tcx>;
 +
 +    fn fully_perform(mut self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
 +        let (mut output, region_constraints) = scrape_region_constraints(infcx, || {
 +            Ok(InferOk { value: (), obligations: self.obligations.clone() })
 +        })?;
 +        self.region_constraints = Some(region_constraints);
 +        output.error_info = Some(self);
 +        Ok(output)
      }
  }
index 8790baa010c122c00bf411557804e1c71f356780,5e31e075e7395d70735c7b3a4fc8a6c2627b362a..e203c79030d20a5fd98d7e5fcc8e80d127d6d7e4
@@@ -11,7 -11,7 +11,7 @@@ use rustc_middle::mir::*
  use rustc_middle::ty::cast::CastTy;
  use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
  use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
 -use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
 +use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeFoldable};
  use rustc_mir_dataflow::{self, Analysis};
  use rustc_span::{sym, Span, Symbol};
  use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
@@@ -47,10 -47,7 +47,10 @@@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> 
          location: Location,
      ) -> bool {
          let ty = ccx.body.local_decls[local].ty;
 -        if !NeedsDrop::in_any_value_of_ty(ccx, ty) {
 +        // Peeking into opaque types causes cycles if the current function declares said opaque
 +        // type. Thus we avoid short circuiting on the type and instead run the more expensive
 +        // analysis that looks at the actual usage within this function
 +        if !ty.has_opaque_types() && !NeedsDrop::in_any_value_of_ty(ccx, ty) {
              return false;
          }
  
          location: Location,
      ) -> bool {
          let ty = ccx.body.local_decls[local].ty;
 -        if !HasMutInterior::in_any_value_of_ty(ccx, ty) {
 +        // Peeking into opaque types causes cycles if the current function declares said opaque
 +        // type. Thus we avoid short circuiting on the type and instead run the more expensive
 +        // analysis that looks at the actual usage within this function
 +        if !ty.has_opaque_types() && !HasMutInterior::in_any_value_of_ty(ccx, ty) {
              return false;
          }
  
  
              // If we know that all values of the return type are structurally matchable, there's no
              // need to run dataflow.
 -            _ if !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) => false,
 +            // Opaque types do not participate in const generics or pattern matching, so we can safely count them out.
 +            _ if ccx.body.return_ty().has_opaque_types()
 +                || !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) =>
 +            {
 +                false
 +            }
  
              hir::ConstContext::Const | hir::ConstContext::Static(_) => {
                  let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx)
@@@ -953,7 -942,7 +953,7 @@@ impl<'tcx> Visitor<'tcx> for Checker<'_
                  if callee_is_unstable_unmarked {
                      trace!("callee_is_unstable_unmarked");
                      // We do not use `const` modifiers for intrinsic "functions", as intrinsics are
-                     // `extern` funtions, and these have no way to get marked `const`. So instead we
+                     // `extern` functions, and these have no way to get marked `const`. So instead we
                      // use `rustc_const_(un)stable` attributes to mean that the intrinsic is `const`
                      if self.ccx.is_const_stable_const_fn() || is_intrinsic {
                          self.check_op(ops::FnCallUnstable(callee, None));