Use Term in ProjectionPredicate
ProjectionPredicate should be able to handle both associated types and consts so this adds the first step of that. It mainly just pipes types all the way down, not entirely sure how to handle consts, but hopefully that'll come with time.
This commit is contained in:
parent
fb57b7518d
commit
67f56671d0
51 changed files with 274 additions and 259 deletions
|
@ -151,8 +151,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
.bindings
|
||||
.iter()
|
||||
.find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
|
||||
(true, hir::TypeBindingKind::Equality { ty }) => {
|
||||
sess.source_map().span_to_snippet(ty.span).ok()
|
||||
(true, hir::TypeBindingKind::Equality { term }) => {
|
||||
let span = match term {
|
||||
hir::Term::Ty(ty) => ty.span,
|
||||
hir::Term::Const(c) => self.tcx().hir().span(c.hir_id),
|
||||
};
|
||||
sess.source_map().span_to_snippet(span).ok()
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
|
|
|
@ -602,14 +602,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
.iter()
|
||||
.map(|binding| {
|
||||
let kind = match binding.kind {
|
||||
hir::TypeBindingKind::Equality { ty } => {
|
||||
ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty))
|
||||
}
|
||||
hir::TypeBindingKind::Const { ref c } => {
|
||||
let local_did = self.tcx().hir().local_def_id(c.hir_id);
|
||||
let c = Const::from_anon_const(self.tcx(), local_did);
|
||||
ConvertedBindingKind::Const(&c)
|
||||
}
|
||||
hir::TypeBindingKind::Equality { ref term } => match term {
|
||||
hir::Term::Ty(ref ty) => {
|
||||
ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty))
|
||||
}
|
||||
hir::Term::Const(ref c) => {
|
||||
let local_did = self.tcx().hir().local_def_id(c.hir_id);
|
||||
let c = Const::from_anon_const(self.tcx(), local_did);
|
||||
ConvertedBindingKind::Const(&c)
|
||||
}
|
||||
},
|
||||
hir::TypeBindingKind::Constraint { ref bounds } => {
|
||||
ConvertedBindingKind::Constraint(bounds)
|
||||
}
|
||||
|
@ -1227,21 +1229,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
//
|
||||
// `<T as Iterator>::Item = u32`
|
||||
bounds.projection_bounds.push((
|
||||
projection_ty.map_bound(|projection_ty| {
|
||||
debug!(
|
||||
"add_predicates_for_ast_type_binding: projection_ty {:?}, substs: {:?}",
|
||||
projection_ty, projection_ty.substs
|
||||
);
|
||||
ty::ProjectionPredicate { projection_ty, ty }
|
||||
projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate {
|
||||
projection_ty,
|
||||
term: ty.into(),
|
||||
}),
|
||||
binding.span,
|
||||
));
|
||||
}
|
||||
ConvertedBindingKind::Const(c) => {
|
||||
bounds.const_bounds.push((
|
||||
projection_ty.map_bound(|projection_ty| ty::ConstPredicate {
|
||||
projection: projection_ty,
|
||||
c,
|
||||
bounds.projection_bounds.push((
|
||||
projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate {
|
||||
projection_ty,
|
||||
term: c.into(),
|
||||
}),
|
||||
binding.span,
|
||||
));
|
||||
|
@ -1393,7 +1392,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
// A `Self` within the original bound will be substituted with a
|
||||
// `trait_object_dummy_self`, so check for that.
|
||||
let references_self =
|
||||
pred.skip_binder().ty.walk().any(|arg| arg == dummy_self.into());
|
||||
pred.skip_binder().term.ty().walk().any(|arg| arg == dummy_self.into());
|
||||
|
||||
// If the projection output contains `Self`, force the user to
|
||||
// elaborate it explicitly to avoid a lot of complexity.
|
||||
|
|
|
@ -37,12 +37,6 @@ pub struct Bounds<'tcx> {
|
|||
/// here.
|
||||
pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
|
||||
|
||||
/// A list of const equality bounds. So if you had `T:
|
||||
/// Iterator<N = 4>` this would include `<T as
|
||||
/// Iterator>::N => 4`. Note that the self-type is explicit
|
||||
/// here.
|
||||
pub const_bounds: Vec<(ty::Binder<'tcx, ty::ConstPredicate<'tcx>>, Span)>,
|
||||
|
||||
/// `Some` if there is *no* `?Sized` predicate. The `span`
|
||||
/// is the location in the source of the `T` declaration which can
|
||||
/// be cited as the source of the `T: Sized` requirement.
|
||||
|
@ -90,24 +84,7 @@ impl<'tcx> Bounds<'tcx> {
|
|||
.projection_bounds
|
||||
.iter()
|
||||
.map(move |&(projection, span)| (projection.to_predicate(tcx), span));
|
||||
let const_bounds = self.const_bounds.iter().map(move |&(bound, span)| {
|
||||
// FIXME(...): what about the projection's generics?
|
||||
// Is this the right local defid? Or should I get the self ty then
|
||||
let pred = bound
|
||||
.map_bound(|cp| {
|
||||
let got =
|
||||
ty::Const::from_anon_const(tcx, cp.projection.item_def_id.expect_local());
|
||||
ty::PredicateKind::ConstEquate(cp.c, got)
|
||||
})
|
||||
.to_predicate(tcx);
|
||||
(pred, span)
|
||||
});
|
||||
|
||||
sized_predicate
|
||||
.into_iter()
|
||||
.chain(region_preds)
|
||||
.chain(trait_bounds)
|
||||
.chain(projection_bounds)
|
||||
.chain(const_bounds)
|
||||
sized_predicate.into_iter().chain(region_preds).chain(trait_bounds).chain(projection_bounds)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -279,7 +279,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return None;
|
||||
};
|
||||
|
||||
let ret_param_ty = projection.skip_binder().ty;
|
||||
let ret_param_ty = projection.skip_binder().term.ty();
|
||||
let ret_param_ty = self.resolve_vars_if_possible(ret_param_ty);
|
||||
debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty);
|
||||
|
||||
|
@ -706,7 +706,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Extract the type from the projection. Note that there can
|
||||
// be no bound variables in this type because the "self type"
|
||||
// does not have any regions in it.
|
||||
let output_ty = self.resolve_vars_if_possible(predicate.ty);
|
||||
let output_ty = self.resolve_vars_if_possible(predicate.term.ty());
|
||||
debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty);
|
||||
Some(output_ty)
|
||||
}
|
||||
|
|
|
@ -1360,7 +1360,7 @@ pub fn check_type_bounds<'tcx>(
|
|||
item_def_id: trait_ty.def_id,
|
||||
substs: rebased_substs,
|
||||
},
|
||||
ty: impl_ty_value,
|
||||
term: impl_ty_value.into(),
|
||||
},
|
||||
bound_vars,
|
||||
)
|
||||
|
|
|
@ -789,7 +789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
item_def_id: projection_ty.item_def_id,
|
||||
};
|
||||
|
||||
let ty = pred.skip_binder().ty;
|
||||
let ty: Ty<'_> = pred.skip_binder().term.ty();
|
||||
|
||||
let obligation = format!("{} = {}", projection_ty, ty);
|
||||
let quiet = format!("{} = {}", quiet_projection_ty, ty);
|
||||
|
|
|
@ -691,7 +691,11 @@ fn bounds_from_generic_predicates<'tcx>(
|
|||
// insert the associated types where they correspond, but for now let's be "lazy" and
|
||||
// propose this instead of the following valid resugaring:
|
||||
// `T: Trait, Trait::Assoc = K` → `T: Trait<Assoc = K>`
|
||||
where_clauses.push(format!("{} = {}", tcx.def_path_str(p.projection_ty.item_def_id), p.ty));
|
||||
where_clauses.push(format!(
|
||||
"{} = {}",
|
||||
tcx.def_path_str(p.projection_ty.item_def_id),
|
||||
p.term.ty()
|
||||
));
|
||||
}
|
||||
let where_clauses = if where_clauses.is_empty() {
|
||||
String::new()
|
||||
|
|
|
@ -664,7 +664,11 @@ impl<'tcx> ItemCtxt<'tcx> {
|
|||
.params
|
||||
.iter()
|
||||
.filter_map(|param| match param.kind {
|
||||
GenericParamKind::Type { .. } if param.hir_id == param_id => Some(¶m.bounds),
|
||||
GenericParamKind::Type { .. } | GenericParamKind::Const { .. }
|
||||
if param.hir_id == param_id =>
|
||||
{
|
||||
Some(¶m.bounds)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.flat_map(|bounds| bounds.iter())
|
||||
|
|
|
@ -67,11 +67,7 @@ fn opaque_type_bounds<'tcx>(
|
|||
let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
|
||||
// Opaque types are implicitly sized unless a `?Sized` bound is found
|
||||
<dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
|
||||
let preds = bounds.predicates(tcx, item_ty);
|
||||
|
||||
let bounds = tcx.arena.alloc_from_iter(preds);
|
||||
debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds);
|
||||
bounds
|
||||
tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ pub fn setup_constraining_predicates<'tcx>(
|
|||
if !relies_only_on_inputs {
|
||||
continue;
|
||||
}
|
||||
input_parameters.extend(parameters_for(&projection.ty, false));
|
||||
input_parameters.extend(parameters_for(&projection.term, false));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ fn unconstrained_parent_impl_substs<'tcx>(
|
|||
for (predicate, _) in impl_generic_predicates.predicates.iter() {
|
||||
if let ty::PredicateKind::Projection(proj) = predicate.kind().skip_binder() {
|
||||
let projection_ty = proj.projection_ty;
|
||||
let projected_ty = proj.ty;
|
||||
let projected_ty = proj.term.ty();
|
||||
|
||||
let unbound_trait_ref = projection_ty.trait_ref(tcx);
|
||||
if Some(unbound_trait_ref) == impl_trait_ref {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue