summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_typeck/src/coercion.rs
diff options
context:
space:
mode:
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(),
);
}