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 smallvec::{smallvec, SmallVec};
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()),
+ })),
));
}
}
cause,
coerce_unsized_did,
0,
- coerce_source,
- &[coerce_target.into()]
+ [coerce_source, coerce_target]
)];
let mut has_unsized_tuple_coercion = false;
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 {
&self,
a: Ty<'tcx>,
b: Ty<'tcx>,
- predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
+ predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
b_region: ty::Region<'tcx>,
) -> CoerceResult<'tcx> {
if !self.tcx.features().dyn_star {
// 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
// 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(
+ .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. For now, only those
+ // can be coerced to `dyn*`, except for `dyn* -> dyn*` upcasts.
+ if !a.is_dyn_star() {
+ obligations.push(Obligation::new(
+ self.tcx,
self.cause.clone(),
self.param_env,
- self.tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::TypeOutlives(
- ty::OutlivesPredicate(a, b_region),
- ))),
- )])
- .collect();
+ 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),
let Ok(ok) = coerce.coerce(source, target) else {
return false;
};
- let mut fcx = traits::FulfillmentContext::new_in_snapshot();
+ let mut fcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.tcx);
fcx.register_predicate_obligations(self, ok.obligations);
fcx.select_where_possible(&self).is_empty()
})
self.infcx
.type_implements_trait(
self.tcx.lang_items().deref_mut_trait()?,
- expr_ty,
- ty::List::empty(),
+ [expr_ty],
self.param_env,
)
.may_apply()
// 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"