Skip to content

Commit

Permalink
refactor LoweringContext::lower_generics_mut
Browse files Browse the repository at this point in the history
Further reduce nesting by using early exits and replacing
the innermost loop with `.find()`. Also eliminates the labeled
branch.

Add comments explaining why the copying of `?Sized` bounds is
necessary.
  • Loading branch information
tlyu committed Jul 25, 2021
1 parent d9aa287 commit 0771f9c
Showing 1 changed file with 36 additions and 25 deletions.
61 changes: 36 additions & 25 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1372,37 +1372,48 @@ impl<'hir> LoweringContext<'_, 'hir> {
generics: &Generics,
itctx: ImplTraitContext<'_, 'hir>,
) -> GenericsCtor<'hir> {
// Collect `?Trait` bounds in where clause and move them to parameter definitions.
// Collect `?Trait` bounds in where clause and move them to parameter
// definitions. Currently, the decision to add the predicate for the
// implicit `Sized` bound only examines the generic parameters, not the
// where clauses, to discover any `?Sized` bounds. (e.g.,
// `AstConv::is_unsized`)
let mut add_bounds: NodeMap<Vec<_>> = Default::default();
for pred in &generics.where_clause.predicates {
if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
'next_bound: for bound in &bound_pred.bounds {
if let GenericBound::Trait(_, TraitBoundModifier::Maybe) = *bound {
// Check if the where clause type is a plain type parameter.
match self
.resolver
.get_partial_res(bound_pred.bounded_ty.id)
.map(|d| (d.base_res(), d.unresolved_segments()))
let bound_pred = match *pred {
WherePredicate::BoundPredicate(ref bound_pred) => bound_pred,
_ => continue,
};
for bound in &bound_pred.bounds {
if !matches!(*bound, GenericBound::Trait(_, TraitBoundModifier::Maybe)) {
continue;
}
// Check if the where clause type is a plain type parameter.
match self
.resolver
.get_partial_res(bound_pred.bounded_ty.id)
.map(|d| (d.base_res(), d.unresolved_segments()))
{
Some((Res::Def(DefKind::TyParam, def_id), 0))
if bound_pred.bound_generic_params.is_empty() =>
{
if let Some(param) = generics
.params
.iter()
.find(|p| def_id == self.resolver.local_def_id(p.id).to_def_id())
{
Some((Res::Def(DefKind::TyParam, def_id), 0))
if bound_pred.bound_generic_params.is_empty() =>
{
for param in &generics.params {
if def_id == self.resolver.local_def_id(param.id).to_def_id() {
add_bounds.entry(param.id).or_default().push(bound.clone());
continue 'next_bound;
}
}
}
_ => {}
add_bounds.entry(param.id).or_default().push(bound.clone());
continue;
}
self.diagnostic().span_err(
bound_pred.bounded_ty.span,
"`?Trait` bounds are only permitted at the \
point where a type parameter is declared",
);
}
_ => {}
}
// Either the `bounded_ty` is not a plain type parameter, or
// it's not found in the generic type parameters list.
self.diagnostic().span_err(
bound_pred.bounded_ty.span,
"`?Trait` bounds are only permitted at the \
point where a type parameter is declared",
);
}
}

Expand Down

0 comments on commit 0771f9c

Please sign in to comment.