1
Fork 0

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:
kadmin 2022-01-08 09:28:12 +00:00
parent fb57b7518d
commit 67f56671d0
51 changed files with 274 additions and 259 deletions

View file

@ -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,
})

View file

@ -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.

View file

@ -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)
}
}

View file

@ -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)
}

View file

@ -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,
)

View file

@ -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);

View file

@ -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()

View file

@ -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(&param.bounds),
GenericParamKind::Type { .. } | GenericParamKind::Const { .. }
if param.hir_id == param_id =>
{
Some(&param.bounds)
}
_ => None,
})
.flat_map(|bounds| bounds.iter())

View file

@ -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))
})
}

View file

@ -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;
}

View file

@ -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 {