X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_borrowck%2Fsrc%2Ftype_check%2Fcanonical.rs;h=02222c0a03cb350f9dcfdebc2b963db3f1edfcd5;hb=73476554e9f89245be50195d5ff8e66cc5e64c82;hp=3617bf58be9dd48dd17c18c8738eb566024e18c9;hpb=8ed0384ca4651e914793dd8a05c9cdec9b2089b4;p=rust.git diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 3617bf58be9..02222c0a03c 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -1,13 +1,13 @@ use std::fmt; -use rustc_infer::infer::canonical::Canonical; -use rustc_infer::traits::query::NoSolution; +use rustc_infer::infer::{canonical::Canonical, InferOk}; use rustc_middle::mir::ConstraintCategory; -use rustc_middle::ty::{self, ToPredicate, TypeFoldable}; +use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable}; use rustc_span::def_id::DefId; use rustc_span::Span; use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput}; -use rustc_trait_selection::traits::query::Fallible; +use rustc_trait_selection::traits::query::{Fallible, NoSolution}; +use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; use crate::diagnostics::{ToUniverseInfo, UniverseInfo}; @@ -177,4 +177,74 @@ pub(super) fn normalize_with_category( value }) } + + #[instrument(skip(self), level = "debug")] + pub(super) fn ascribe_user_type( + &mut self, + mir_ty: Ty<'tcx>, + user_ty: ty::UserType<'tcx>, + span: Span, + ) { + // FIXME: Ideally MIR types are normalized, but this is not always true. + let mir_ty = self.normalize(mir_ty, Locations::All(span)); + + self.fully_perform_op( + Locations::All(span), + ConstraintCategory::Boring, + self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(mir_ty, user_ty)), + ) + .unwrap_or_else(|err| { + span_mirbug!( + self, + span, + "ascribe_user_type `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`", + ); + }); + } + + /// *Incorrectly* skips the WF checks we normally do in `ascribe_user_type`. + /// + /// FIXME(#104478, #104477): This is a hack for backward-compatibility. + #[instrument(skip(self), level = "debug")] + pub(super) fn ascribe_user_type_skip_wf( + &mut self, + mir_ty: Ty<'tcx>, + user_ty: ty::UserType<'tcx>, + span: Span, + ) { + let ty::UserType::Ty(user_ty) = user_ty else { bug!() }; + + // A fast path for a common case with closure input/output types. + if let ty::Infer(_) = user_ty.kind() { + self.eq_types(user_ty, mir_ty, Locations::All(span), ConstraintCategory::Boring) + .unwrap(); + return; + } + + let mir_ty = self.normalize(mir_ty, Locations::All(span)); + let cause = ObligationCause::dummy_with_span(span); + let param_env = self.param_env; + let op = |infcx: &'_ _| { + let ocx = ObligationCtxt::new_in_snapshot(infcx); + let user_ty = ocx.normalize(&cause, param_env, user_ty); + ocx.eq(&cause, param_env, user_ty, mir_ty)?; + if !ocx.select_all_or_error().is_empty() { + return Err(NoSolution); + } + Ok(InferOk { value: (), obligations: vec![] }) + }; + + self.fully_perform_op( + Locations::All(span), + ConstraintCategory::Boring, + type_op::custom::CustomTypeOp::new(op, || "ascribe_user_type_skip_wf".to_string()), + ) + .unwrap_or_else(|err| { + span_mirbug!( + self, + span, + "ascribe_user_type_skip_wf `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`", + ); + }); + } }