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, EarlyBinder, GenericParamDefKind, Ty};
use rustc_middle::ty::{ToPolyTraitRef, ToPredicate};
use rustc_span::def_id::DefId;
_ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
};
- let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs);
+ let candidate_predicate =
+ tcx.bound_item_bounds(def_id).map_bound(|i| i[idx]).subst(tcx, substs);
let candidate = candidate_predicate
.to_opt_poly_trait_pred()
.expect("projection candidate is not a trait predicate")
.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);
+ for bound in self.tcx().bound_item_bounds(assoc_type).transpose_iter() {
+ 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.0.kind().bound_vars().len() + defs.count(),
+ );
+ bound_vars.extend(bound.0.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 =
+ EarlyBinder(bound.0.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,
/// and we desugared it so that the type of the expression is
/// `Closure`, and `Closure` expects `i32` as argument. Then it
/// is "as if" the compiler generated this impl:
- ///
- /// impl Fn(i32) for Closure { ... }
- ///
+ /// ```ignore (illustrative)
+ /// impl Fn(i32) for Closure { ... }
+ /// ```
/// Now imagine our obligation is `Closure: Fn(usize)`. So far
/// we have matched the self type `Closure`. At this point we'll
/// compare the `i32` to `usize` and generate an error.
// The last field of the structure has to exist and contain type/const parameters.
let (tail_field, prefix_fields) =
def.non_enum_variant().fields.split_last().ok_or(Unimplemented)?;
- let tail_field_ty = tcx.type_of(tail_field.did);
+ let tail_field_ty = tcx.bound_type_of(tail_field.did);
let mut unsizing_params = GrowableBitSet::new_empty();
- for arg in tail_field_ty.walk() {
+ for arg in tail_field_ty.0.walk() {
if let Some(i) = maybe_unsizing_param_idx(arg) {
unsizing_params.insert(i);
}
}
let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None);
- // FIXME: remove if statement below when beta is bumped
- #[cfg(bootstrap)]
- {}
-
- if obligation.predicate.skip_binder().def_id() == drop_trait {
- return Ok(ImplSourceConstDestructData { nested: vec![] });
- }
let tcx = self.tcx();
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());