// Get predicates declared on the trait.
let predicates = tcx.super_predicates_of(data.def_id());
- let mut predicates: Vec<_> = predicates.predicates
+ let predicates = predicates.predicates
.iter()
- .map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref()))
- .collect();
+ .map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref()));
debug!("super_predicates: data={:?} predicates={:?}",
- data, predicates);
+ data, predicates.clone());
// Only keep those bounds that we haven't already seen.
// This is necessary to prevent infinite recursion in some
// cases. One common case is when people define
// `trait Sized: Sized { }` rather than `trait Sized { }`.
- predicates.retain(|pred| self.visited.insert(pred));
+ let visited = &mut self.visited;
+ let predicates = predicates.filter(|pred| visited.insert(pred));
self.stack.extend(predicates);
}
}
}
- fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
- let mut path = self.path.clone();
- path.push((trait_ref, span));
-
- Self {
- path
+ /// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate
+ /// trait aliases.
+ pub fn label_with_exp_info(&self,
+ diag: &mut DiagnosticBuilder<'_>,
+ top_label: &str,
+ use_desc: &str
+ ) {
+ diag.span_label(self.top().1, top_label);
+ if self.path.len() > 1 {
+ for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) {
+ diag.span_label(*sp, format!("referenced here ({})", use_desc));
+ }
}
+ diag.span_label(self.bottom().1,
+ format!("trait alias used in trait object type ({})", use_desc));
}
pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> {
pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
self.path.first().unwrap()
}
-}
-/// Emits diagnostic information relating to the expansion of a trait via trait aliases
-/// (see [`TraitAliasExpansionInfo`]).
-pub trait TraitAliasExpansionInfoDignosticBuilder {
- fn label_with_exp_info<'tcx>(&mut self,
- info: &TraitAliasExpansionInfo<'tcx>,
- top_label: &str,
- use_desc: &str
- ) -> &mut Self;
-}
+ fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
+ let mut path = self.path.clone();
+ path.push((trait_ref, span));
-impl<'a> TraitAliasExpansionInfoDignosticBuilder for DiagnosticBuilder<'a> {
- fn label_with_exp_info<'tcx>(&mut self,
- info: &TraitAliasExpansionInfo<'tcx>,
- top_label: &str,
- use_desc: &str
- ) -> &mut Self {
- self.span_label(info.top().1, top_label);
- if info.path.len() > 1 {
- for (_, sp) in info.path.iter().rev().skip(1).take(info.path.len() - 2) {
- self.span_label(*sp, format!("referenced here ({})", use_desc));
- }
+ Self {
+ path
}
- self.span_label(info.bottom().1,
- format!("trait alias used in trait object type ({})", use_desc));
- self
}
}
// Get components of trait alias.
let predicates = tcx.super_predicates_of(trait_ref.def_id());
- let items: Vec<_> = predicates.predicates
+ let items = predicates.predicates
.iter()
.rev()
.filter_map(|(pred, span)| {
pred.subst_supertrait(tcx, &trait_ref)
.to_opt_poly_trait_ref()
.map(|trait_ref| item.clone_and_push(trait_ref, *span))
- })
- .collect();
- debug!("expand_trait_aliases: items={:?}", items);
+ });
+ debug!("expand_trait_aliases: items={:?}", items.clone());
self.stack.extend(items);
use crate::middle::resolve_lifetime as rl;
use crate::namespace::Namespace;
use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
-use rustc::traits::{self, TraitAliasExpansionInfoDignosticBuilder};
+use rustc::traits;
use rustc::ty::{self, DefIdTree, Ty, TyCtxt, ToPredicate, TypeFoldable};
use rustc::ty::{GenericParamDef, GenericParamDefKind};
use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef};
let mut projection_bounds = Vec::new();
let mut potential_assoc_types = Vec::new();
let dummy_self = self.tcx().types.trait_object_dummy_self;
+ // FIXME: we want to avoid collecting into a `Vec` here, but simply cloning the iterator is
+ // not straightforward due to the borrow checker.
let bound_trait_refs: Vec<_> = trait_bounds
.iter()
.rev()
if regular_traits.len() > 1 {
let first_trait = ®ular_traits[0];
let additional_trait = ®ular_traits[1];
- struct_span_err!(tcx.sess, additional_trait.bottom().1, E0225,
+ let mut err = struct_span_err!(tcx.sess, additional_trait.bottom().1, E0225,
"only auto traits can be used as additional traits in a trait object"
- )
- .label_with_exp_info(additional_trait, "additional non-auto trait",
- "additional use")
- .label_with_exp_info(first_trait, "first non-auto trait",
- "first use")
- .emit();
+ );
+ additional_trait.label_with_exp_info(&mut err,
+ "additional non-auto trait", "additional use");
+ first_trait.label_with_exp_info(&mut err,
+ "first non-auto trait", "first use");
+ err.emit();
}
if regular_traits.is_empty() && auto_traits.is_empty() {