diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_hir_typeck/src/coercion.rs (renamed from compiler/rustc_typeck/src/check/coercion.rs) | 83 |
1 files changed, 74 insertions, 9 deletions
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index def592c46..86597a703 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -35,8 +35,7 @@ //! // and are then unable to coerce `&7i32` to `&mut i32`. //! ``` -use crate::astconv::AstConv; -use crate::check::FnCtxt; +use crate::FnCtxt; use rustc_errors::{ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, }; @@ -44,6 +43,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Expr; +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}; @@ -61,7 +61,7 @@ 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::InferCtxtExt as _; +use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; use smallvec::{smallvec, SmallVec}; @@ -216,6 +216,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { ty::Ref(r_b, _, mutbl_b) => { return self.coerce_borrowed_pointer(a, b, r_b, mutbl_b); } + ty::Dynamic(predicates, region, ty::DynStar) if self.tcx.features().dyn_star => { + return self.coerce_dyn_star(a, b, predicates, region); + } _ => {} } @@ -702,7 +705,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Object safety violations or miscellaneous. Err(err) => { - self.report_selection_error(obligation.clone(), &obligation, &err, false); + self.err_ctxt().report_selection_error( + obligation.clone(), + &obligation, + &err, + false, + ); // Treat this like an obligation and follow through // with the unsizing - the lack of a coercion should // be silent, as it causes a type mismatch later. @@ -740,6 +748,63 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Ok(coercion) } + fn coerce_dyn_star( + &self, + a: Ty<'tcx>, + b: Ty<'tcx>, + predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>, + b_region: ty::Region<'tcx>, + ) -> CoerceResult<'tcx> { + if !self.tcx.features().dyn_star { + return Err(TypeError::Mismatch); + } + + if let ty::Dynamic(a_data, _, _) = a.kind() + && let ty::Dynamic(b_data, _, _) = b.kind() + { + 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(); + } + } + + // Check the obligations of the cast -- for example, when casting + // `usize` to `dyn* Clone + 'static`: + let obligations = predicates + .iter() + .map(|predicate| { + // For each existential predicate (e.g., `?Self: Clone`) substitute + // the type of the expression (e.g., `usize` in our example above) + // 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) + }) + // 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), + ))), + )]) + .collect(); + + Ok(InferOk { + value: (vec![Adjustment { kind: Adjust::DynStar, target: b }], b), + obligations, + }) + } + fn coerce_from_safe_fn<F, G>( &self, a: Ty<'tcx>, @@ -1549,7 +1614,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } } _ => { - err = fcx.report_mismatched_types( + err = fcx.err_ctxt().report_mismatched_types( cause, expected, found, @@ -1629,7 +1694,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { expression: Option<&'tcx hir::Expr<'tcx>>, blk_id: Option<hir::HirId>, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut err = fcx.report_mismatched_types(cause, expected, found, ty_err); + let mut err = fcx.err_ctxt().report_mismatched_types(cause, expected, found, ty_err); let mut pointing_at_return_type = false; let mut fn_output = None; @@ -1683,7 +1748,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { expected, found, can_suggest, - fcx.tcx.hir().local_def_id_to_hir_id(fcx.tcx.hir().get_parent_item(id)), + fcx.tcx.hir().get_parent_item(id).into(), ); } if !pointing_at_return_type { @@ -1692,7 +1757,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } let parent_id = fcx.tcx.hir().get_parent_item(id); - let parent_item = fcx.tcx.hir().get_by_def_id(parent_id); + let parent_item = fcx.tcx.hir().get_by_def_id(parent_id.def_id); if let (Some(expr), Some(_), Some((fn_decl, _, _))) = (expression, blk_id, fcx.get_node_fn_decl(parent_item)) @@ -1704,7 +1769,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { expected, found, id, - fcx.tcx.hir().local_def_id_to_hir_id(parent_id), + parent_id.into(), ); } |