X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_hir_typeck%2Fsrc%2Fcoercion.rs;h=af0b7f62ae3195f6ce058bde7b0cf97be631efc1;hb=84ff4ab5a238558a009e1cc6f375b0922053b95b;hp=71949b4211819b79d08c09b5b32872504294a3a7;hpb=91963cc244f4986818dadbb2c73dd6f67e779802;p=rust.git diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 71949b42118..82784bb8a66 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -46,7 +46,7 @@ use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{Coercion, InferOk, InferResult}; -use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt}; +use rustc_infer::traits::Obligation; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast, @@ -55,15 +55,14 @@ use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::visit::TypeVisitable; -use rustc_middle::ty::{self, ToPredicate, Ty, TypeAndMut}; +use rustc_middle::ty::{self, Ty, TypeAndMut}; use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::{self, BytePos, DesugaringKind, Span}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::TraitEngineExt as _; -use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt}; use smallvec::{smallvec, SmallVec}; use std::ops::Deref; @@ -278,13 +277,13 @@ fn coerce_from_inference_variable( for &source_ty in &[a, b] { if source_ty != target_ty { obligations.push(Obligation::new( + self.tcx(), self.cause.clone(), self.param_env, ty::Binder::dummy(ty::PredicateKind::Coerce(ty::CoercePredicate { a: source_ty, b: target_ty, - })) - .to_predicate(self.tcx()), + })), )); } } @@ -589,7 +588,7 @@ fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceRe } _ => None, }; - let coerce_source = reborrow.as_ref().map_or(source, |&(_, ref r)| r.target); + let coerce_source = reborrow.as_ref().map_or(source, |(_, r)| r.target); // Setup either a subtyping or a LUB relationship between // the `CoerceUnsized` target type and the expected type. @@ -630,8 +629,7 @@ fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceRe cause, coerce_unsized_did, 0, - coerce_source, - &[coerce_target.into()] + [coerce_source, coerce_target] )]; let mut has_unsized_tuple_coercion = false; @@ -669,7 +667,7 @@ fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceRe continue; } }; - match selcx.select(&obligation.with(trait_pred)) { + match selcx.select(&obligation.with(selcx.tcx(), trait_pred)) { // Uncertain or unimplemented. Ok(None) => { if trait_pred.def_id() == unsize_did { @@ -748,7 +746,7 @@ fn coerce_dyn_star( &self, a: Ty<'tcx>, b: Ty<'tcx>, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>, b_region: ty::Region<'tcx>, ) -> CoerceResult<'tcx> { if !self.tcx.features().dyn_star { @@ -757,25 +755,14 @@ fn coerce_dyn_star( if let ty::Dynamic(a_data, _, _) = a.kind() && let ty::Dynamic(b_data, _, _) = b.kind() + && a_data.principal_def_id() == b_data.principal_def_id() { - if a_data.principal_def_id() == b_data.principal_def_id() { - return self.unify_and(a, b, |_| vec![]); - } else if !self.tcx().features().trait_upcasting { - let mut err = feature_err( - &self.tcx.sess.parse_sess, - sym::trait_upcasting, - self.cause.span, - &format!( - "cannot cast `{a}` to `{b}`, trait upcasting coercion is experimental" - ), - ); - err.emit(); - } + return self.unify_and(a, b, |_| vec![]); } // Check the obligations of the cast -- for example, when casting // `usize` to `dyn* Clone + 'static`: - let obligations = predicates + let mut obligations: Vec<_> = predicates .iter() .map(|predicate| { // For each existential predicate (e.g., `?Self: Clone`) substitute @@ -783,18 +770,32 @@ fn coerce_dyn_star( // and then require that the resulting predicate (e.g., `usize: Clone`) // holds (it does). let predicate = predicate.with_self_ty(self.tcx, a); - Obligation::new(self.cause.clone(), self.param_env, predicate) + Obligation::new(self.tcx, self.cause.clone(), self.param_env, predicate) }) - // Enforce the region bound (e.g., `usize: 'static`, in our example). - .chain([Obligation::new( - self.cause.clone(), - self.param_env, - self.tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::TypeOutlives( - ty::OutlivesPredicate(a, b_region), - ))), - )]) + .chain([ + // Enforce the region bound (e.g., `usize: 'static`, in our example). + Obligation::new( + self.tcx, + self.cause.clone(), + self.param_env, + ty::Binder::dummy(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( + a, b_region, + ))), + ), + ]) .collect(); + // Enforce that the type is `usize`/pointer-sized. + obligations.push(Obligation::new( + self.tcx, + self.cause.clone(), + self.param_env, + ty::Binder::dummy( + self.tcx.at(self.cause.span).mk_trait_ref(hir::LangItem::PointerSized, [a]), + ) + .to_poly_trait_predicate(), + )); + Ok(InferOk { value: (vec![Adjustment { kind: Adjust::DynStar, target: b }], b), obligations, @@ -1039,9 +1040,9 @@ pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool { let Ok(ok) = coerce.coerce(source, target) else { return false; }; - let mut fcx = >::new_in_snapshot(self.tcx); - fcx.register_predicate_obligations(self, ok.obligations); - fcx.select_where_possible(&self).is_empty() + let ocx = ObligationCtxt::new_in_snapshot(self); + ocx.register_obligations(ok.obligations); + ocx.select_where_possible().is_empty() }) } @@ -1068,8 +1069,7 @@ pub fn deref_once_mutably_for_diagnostic(&self, expr_ty: Ty<'tcx>) -> Option( // Mark that we've failed to coerce the types here to suppress // any superfluous errors we might encounter while trying to // emit or provide suggestions on how to fix the initial error. - fcx.set_tainted_by_errors(); + fcx.set_tainted_by_errors( + fcx.tcx.sess.delay_span_bug(cause.span, "coercion error but no error emitted"), + ); let (expected, found) = if label_expression_as_expected { // In the case where this is a "forced unit", like // `break`, we want to call the `()` "expected"