Skip to content

Commit

Permalink
Rollup merge of rust-lang#38028 - Mark-Simulacrum:polish, r=nikomatsakis
Browse files Browse the repository at this point in the history
Refactor one_bound_for_assoc_type to take an Iterator instead of Vec

I doubt the performance implications will be serious, but it will avoid allocating one-element Vecs for the successful case (and avoid allocating vecs at all for any case, too).

`--stage 2` tests passed locally.
  • Loading branch information
frewsxcv authored Dec 3, 2016
2 parents 468ca2c + d21861d commit ca0c839
Showing 1 changed file with 33 additions and 33 deletions.
66 changes: 33 additions & 33 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -884,10 +884,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
// those that do.
self.ensure_super_predicates(binding.span, trait_ref.def_id())?;

let candidates: Vec<ty::PolyTraitRef> =
let candidates =
traits::supertraits(tcx, trait_ref.clone())
.filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name))
.collect();
.filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name));

let candidate = self.one_bound_for_assoc_type(candidates,
&trait_ref.to_string(),
Expand Down Expand Up @@ -1191,10 +1190,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {

// Check that there is exactly one way to find an associated type with the
// correct name.
let suitable_bounds: Vec<_> =
let suitable_bounds =
traits::transitive_bounds(tcx, &bounds)
.filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name))
.collect();
.filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name));

self.one_bound_for_assoc_type(suitable_bounds,
&ty_param_name.as_str(),
Expand All @@ -1205,54 +1203,57 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {

// Checks that bounds contains exactly one element and reports appropriate
// errors otherwise.
fn one_bound_for_assoc_type(&self,
bounds: Vec<ty::PolyTraitRef<'tcx>>,
fn one_bound_for_assoc_type<I>(&self,
mut bounds: I,
ty_param_name: &str,
assoc_name: &str,
span: Span)
-> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
where I: Iterator<Item=ty::PolyTraitRef<'tcx>>
{
if bounds.is_empty() {
struct_span_err!(self.tcx().sess, span, E0220,
"associated type `{}` not found for `{}`",
assoc_name,
ty_param_name)
.span_label(span, &format!("associated type `{}` not found", assoc_name))
.emit();
return Err(ErrorReported);
}

if bounds.len() > 1 {
let spans = bounds.iter().map(|b| {
self.tcx().associated_items(b.def_id()).find(|item| {
item.kind == ty::AssociatedKind::Type && item.name == assoc_name
})
.and_then(|item| self.tcx().map.span_if_local(item.def_id))
});
let bound = match bounds.next() {
Some(bound) => bound,
None => {
struct_span_err!(self.tcx().sess, span, E0220,
"associated type `{}` not found for `{}`",
assoc_name,
ty_param_name)
.span_label(span, &format!("associated type `{}` not found", assoc_name))
.emit();
return Err(ErrorReported);
}
};

if let Some(bound2) = bounds.next() {
let bounds = iter::once(bound).chain(iter::once(bound2)).chain(bounds);
let mut err = struct_span_err!(
self.tcx().sess, span, E0221,
"ambiguous associated type `{}` in bounds of `{}`",
assoc_name,
ty_param_name);
err.span_label(span, &format!("ambiguous associated type `{}`", assoc_name));

for span_and_bound in spans.zip(&bounds) {
if let Some(span) = span_and_bound.0 {
for bound in bounds {
let bound_span = self.tcx().associated_items(bound.def_id()).find(|item| {
item.kind == ty::AssociatedKind::Type && item.name == assoc_name
})
.and_then(|item| self.tcx().map.span_if_local(item.def_id));

if let Some(span) = bound_span {
err.span_label(span, &format!("ambiguous `{}` from `{}`",
assoc_name,
span_and_bound.1));
bound));
} else {
span_note!(&mut err, span,
"associated type `{}` could derive from `{}`",
ty_param_name,
span_and_bound.1);
bound);
}
}
err.emit();
}

Ok(bounds[0].clone())
return Ok(bound);
}

// Create a type from a path to an associated type.
Expand Down Expand Up @@ -1293,11 +1294,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
return (tcx.types.err, Def::Err);
}

let candidates: Vec<ty::PolyTraitRef> =
let candidates =
traits::supertraits(tcx, ty::Binder(trait_ref))
.filter(|r| self.trait_defines_associated_type_named(r.def_id(),
assoc_name))
.collect();
assoc_name));

match self.one_bound_for_assoc_type(candidates,
"Self",
Expand Down

0 comments on commit ca0c839

Please sign in to comment.