about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlexander Regueiro <alexreg@me.com>2019-05-13 19:51:33 +0100
committerAlexander Regueiro <alexreg@me.com>2019-05-20 16:12:49 +0100
commita0a61904f4b38c76fe32c7cda57626be94b9c65a (patch)
tree169a26efcedc0b19a3326f19be1c3f153109ccd8
parent783b713b5d90747dec1aabdbc8bfc348593a00c5 (diff)
downloadrust-a0a61904f4b38c76fe32c7cda57626be94b9c65a.tar.gz
rust-a0a61904f4b38c76fe32c7cda57626be94b9c65a.zip
Addressed more points raised in review.
-rw-r--r--src/librustc/traits/mod.rs4
-rw-r--r--src/librustc/traits/util.rs66
-rw-r--r--src/librustc_typeck/astconv.rs18
3 files changed, 38 insertions, 50 deletions
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index d950746f6e6..a4b9ed0a206 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -63,9 +63,7 @@ pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_
 pub use self::util::{
     supertraits, supertrait_def_ids, transitive_bounds, Supertraits, SupertraitDefIds,
 };
-pub use self::util::{
-    expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfoDignosticBuilder,
-};
+pub use self::util::{expand_trait_aliases, TraitAliasExpander};
 
 pub use self::chalk_fulfill::{
     CanonicalGoal as ChalkCanonicalGoal,
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index 77588d713df..5ba23a9c45a 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -132,18 +132,18 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
                 // 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);
             }
@@ -298,13 +298,21 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
         }
     }
 
-    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> {
@@ -318,33 +326,14 @@ impl<'tcx> TraitAliasExpansionInfo<'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
     }
 }
 
@@ -388,16 +377,15 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> {
         // 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);
 
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 7d4243c4842..ce5963e3ce5 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -11,7 +11,7 @@ use crate::lint;
 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};
@@ -976,6 +976,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
         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()
@@ -998,14 +1000,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
         if regular_traits.len() > 1 {
             let first_trait = &regular_traits[0];
             let additional_trait = &regular_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() {