//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::lang_items::LangItem;
-use rustc_hir::Constness;
use rustc_index::bit_set::GrowableBitSet;
use rustc_infer::infer::InferOk;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
+use rustc_middle::ty::{self, GenericParamDefKind, Ty};
use rustc_middle::ty::{ToPolyTraitRef, ToPredicate};
use rustc_span::def_id::DefId;
use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
use crate::traits::select::TraitObligationExt;
-use crate::traits::util;
-use crate::traits::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
-use crate::traits::ImplSource;
-use crate::traits::Normalized;
-use crate::traits::OutputTypeParameterMismatch;
-use crate::traits::Selection;
-use crate::traits::TraitNotObjectSafe;
-use crate::traits::VtblSegment;
-use crate::traits::{BuiltinDerivedObligation, ImplDerivedObligation};
+use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def};
use crate::traits::{
- ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, ImplSourceConstDropData,
- ImplSourceDiscriminantKindData, ImplSourceFnPointerData, ImplSourceGeneratorData,
- ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData,
- ImplSourceTraitUpcastingData, ImplSourceUserDefinedData,
+ BuiltinDerivedObligation, DerivedObligationCause, ImplDerivedObligation,
+ ImplDerivedObligationCause, ImplSource, ImplSourceAutoImplData, ImplSourceBuiltinData,
+ ImplSourceClosureData, ImplSourceConstDestructData, ImplSourceDiscriminantKindData,
+ ImplSourceFnPointerData, ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData,
+ ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized,
+ ObjectCastObligation, Obligation, ObligationCause, OutputTypeParameterMismatch,
+ PredicateObligation, Selection, SelectionError, TraitNotObjectSafe, TraitObligation,
+ Unimplemented, VtblSegment,
};
-use crate::traits::{ObjectCastObligation, PredicateObligation, TraitObligation};
-use crate::traits::{Obligation, ObligationCause};
-use crate::traits::{SelectionError, Unimplemented};
use super::BuiltinImplConditions;
use super::SelectionCandidate::{self, *};
Ok(ImplSource::TraitUpcasting(data))
}
- ConstDropCandidate(def_id) => {
- let data = self.confirm_const_drop_candidate(obligation, def_id)?;
- Ok(ImplSource::ConstDrop(data))
+ ConstDestructCandidate(def_id) => {
+ let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
+ Ok(ImplSource::ConstDestruct(data))
}
}
}
debug!(?nested, "vtable_auto_impl");
ensure_sufficient_stack(|| {
let cause = obligation.derived_cause(BuiltinDerivedObligation);
- let mut obligations = self.collect_predicates_for_types(
- obligation.param_env,
- cause,
- obligation.recursion_depth + 1,
- trait_def_id,
- nested,
- );
let trait_obligations: Vec<PredicateObligation<'_>> =
self.infcx.commit_unconditionally(|_| {
let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
let trait_ref = self.infcx.replace_bound_vars_with_placeholders(poly_trait_ref);
- let cause = obligation.derived_cause(ImplDerivedObligation);
self.impl_or_trait_obligations(
- cause,
+ &cause,
obligation.recursion_depth + 1,
obligation.param_env,
trait_def_id,
&trait_ref.substs,
+ obligation.predicate,
)
});
+ let mut obligations = self.collect_predicates_for_types(
+ obligation.param_env,
+ cause,
+ obligation.recursion_depth + 1,
+ trait_def_id,
+ nested,
+ );
+
// Adds the predicates from the trait. Note that this contains a `Self: Trait`
// predicate as usual. It won't have any effect since auto traits are coinductive.
obligations.extend(trait_obligations);
self.infcx.commit_unconditionally(|_| {
let substs = self.rematch_impl(impl_def_id, obligation);
debug!(?substs, "impl substs");
- let cause = obligation.derived_cause(ImplDerivedObligation);
ensure_sufficient_stack(|| {
self.vtable_impl(
impl_def_id,
substs,
- cause,
+ &obligation.cause,
obligation.recursion_depth + 1,
obligation.param_env,
+ obligation.predicate,
)
})
})
&mut self,
impl_def_id: DefId,
substs: Normalized<'tcx, SubstsRef<'tcx>>,
- cause: ObligationCause<'tcx>,
+ cause: &ObligationCause<'tcx>,
recursion_depth: usize,
param_env: ty::ParamEnv<'tcx>,
+ parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
debug!(?impl_def_id, ?substs, ?recursion_depth, "vtable_impl");
param_env,
impl_def_id,
&substs.value,
+ parent_trait_pred,
);
debug!(?impl_obligations, "vtable_impl");
.collect();
for assoc_type in assoc_types {
- if !tcx.generics_of(assoc_type).params.is_empty() {
+ let defs: &ty::Generics = tcx.generics_of(assoc_type);
+
+ if !defs.params.is_empty() && !tcx.features().generic_associated_types_extended {
tcx.sess.delay_span_bug(
obligation.cause.span,
"GATs in trait object shouldn't have been considered",
);
return Err(SelectionError::Unimplemented);
}
+
// This maybe belongs in wf, but that can't (doesn't) handle
// higher-ranked things.
// Prevent, e.g., `dyn Iterator<Item = str>`.
for bound in self.tcx().item_bounds(assoc_type) {
- let subst_bound = bound.subst(tcx, trait_predicate.trait_ref.substs);
+ let subst_bound =
+ if defs.count() == 0 {
+ bound.subst(tcx, trait_predicate.trait_ref.substs)
+ } else {
+ let mut substs = smallvec::SmallVec::with_capacity(defs.count());
+ substs.extend(trait_predicate.trait_ref.substs.iter());
+ let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
+ smallvec::SmallVec::with_capacity(
+ bound.kind().bound_vars().len() + defs.count(),
+ );
+ bound_vars.extend(bound.kind().bound_vars().into_iter());
+ InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param
+ .kind
+ {
+ GenericParamDefKind::Type { .. } => {
+ let kind = ty::BoundTyKind::Param(param.name);
+ let bound_var = ty::BoundVariableKind::Ty(kind);
+ bound_vars.push(bound_var);
+ tcx.mk_ty(ty::Bound(
+ ty::INNERMOST,
+ ty::BoundTy {
+ var: ty::BoundVar::from_usize(bound_vars.len() - 1),
+ kind,
+ },
+ ))
+ .into()
+ }
+ GenericParamDefKind::Lifetime => {
+ let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
+ let bound_var = ty::BoundVariableKind::Region(kind);
+ bound_vars.push(bound_var);
+ tcx.mk_region(ty::ReLateBound(
+ ty::INNERMOST,
+ ty::BoundRegion {
+ var: ty::BoundVar::from_usize(bound_vars.len() - 1),
+ kind,
+ },
+ ))
+ .into()
+ }
+ GenericParamDefKind::Const { .. } => {
+ let bound_var = ty::BoundVariableKind::Const;
+ bound_vars.push(bound_var);
+ tcx.mk_const(ty::ConstS {
+ ty: tcx.type_of(param.def_id),
+ val: ty::ConstKind::Bound(
+ ty::INNERMOST,
+ ty::BoundVar::from_usize(bound_vars.len() - 1),
+ ),
+ })
+ .into()
+ }
+ });
+ let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
+ let assoc_ty_substs = tcx.intern_substs(&substs);
+
+ let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
+ let bound = bound.kind().skip_binder().subst(tcx, assoc_ty_substs);
+ tcx.mk_predicate(ty::Binder::bind_with_vars(bound, bound_vars))
+ };
let normalized_bound = normalize_with_depth_to(
self,
obligation.param_env,
let substs = trait_ref.substs;
let trait_obligations = self.impl_or_trait_obligations(
- obligation.cause.clone(),
+ &obligation.cause,
obligation.recursion_depth,
obligation.param_env,
trait_def_id,
&substs,
+ obligation.predicate,
);
debug!(?trait_def_id, ?trait_obligations, "trait alias obligations");
Ok(ImplSourceBuiltinData { nested })
}
- fn confirm_const_drop_candidate(
+ fn confirm_const_destruct_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
impl_def_id: Option<DefId>,
- ) -> Result<ImplSourceConstDropData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
- // `~const Drop` in a non-const environment is always trivially true, since our type is `Drop`
- if obligation.param_env.constness() == Constness::NotConst {
- return Ok(ImplSourceConstDropData { nested: vec![] });
+ ) -> Result<ImplSourceConstDestructData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+ // `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop`
+ if !obligation.is_const() {
+ return Ok(ImplSourceConstDestructData { nested: vec![] });
}
+ let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None);
+
let tcx = self.tcx();
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
let cause = obligation.derived_cause(BuiltinDerivedObligation);
// If we have a custom `impl const Drop`, then
- // first check it like a regular impl candidate
+ // first check it like a regular impl candidate.
+ // This is copied from confirm_impl_candidate but remaps the predicate to `~const Drop` beforehand.
if let Some(impl_def_id) = impl_def_id {
- nested.extend(self.confirm_impl_candidate(obligation, impl_def_id).nested);
+ let obligations = self.infcx.commit_unconditionally(|_| {
+ let mut new_obligation = obligation.clone();
+ new_obligation.predicate = new_obligation.predicate.map_bound(|mut trait_pred| {
+ trait_pred.trait_ref.def_id = drop_trait;
+ trait_pred
+ });
+ let substs = self.rematch_impl(impl_def_id, &new_obligation);
+ debug!(?substs, "impl substs");
+
+ let derived = DerivedObligationCause {
+ parent_trait_pred: obligation.predicate,
+ parent_code: obligation.cause.clone_code(),
+ };
+ let derived_code = ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
+ derived,
+ impl_def_id,
+ span: obligation.cause.span,
+ }));
+
+ let cause = ObligationCause::new(
+ obligation.cause.span,
+ obligation.cause.body_id,
+ derived_code,
+ );
+ ensure_sufficient_stack(|| {
+ self.vtable_impl(
+ impl_def_id,
+ substs,
+ &cause,
+ new_obligation.recursion_depth + 1,
+ new_obligation.param_env,
+ obligation.predicate,
+ )
+ })
+ });
+ nested.extend(obligations.nested);
}
// We want to confirm the ADT's fields if we have an ADT
self_ty
.rebind(ty::TraitPredicate {
trait_ref: ty::TraitRef {
- def_id: self.tcx().require_lang_item(LangItem::Drop, None),
+ def_id: self
+ .tcx()
+ .require_lang_item(LangItem::Destruct, None),
substs: self.tcx().mk_substs_trait(nested_ty, &[]),
},
constness: ty::BoundConstness::ConstIfConst,
let predicate = self_ty
.rebind(ty::TraitPredicate {
trait_ref: ty::TraitRef {
- def_id: self.tcx().require_lang_item(LangItem::Drop, None),
+ def_id: self.tcx().require_lang_item(LangItem::Destruct, None),
substs: self.tcx().mk_substs_trait(nested_ty, &[]),
},
constness: ty::BoundConstness::ConstIfConst,
}
}
- Ok(ImplSourceConstDropData { nested })
+ Ok(ImplSourceConstDestructData { nested })
}
}