From a0a61904f4b38c76fe32c7cda57626be94b9c65a Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Mon, 13 May 2019 19:51:33 +0100 Subject: [PATCH] Addressed more points raised in review. --- src/librustc/traits/mod.rs | 4 +-- src/librustc/traits/util.rs | 66 ++++++++++++++-------------------- src/librustc_typeck/astconv.rs | 18 +++++----- 3 files changed, 38 insertions(+), 50 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index d950746f6e6d9..a4b9ed0a206b9 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 77588d713dfc5..5ba23a9c45a4f 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 7d4243c4842ed..ce5963e3ce5c2 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 = ®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() {