From 9f800457dda7ee9b8579394d1c07761f3008e573 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 26 Mar 2019 17:34:32 +0000 Subject: [PATCH] Ban multi-trait objects via trait aliases. --- src/liballoc/slice.rs | 8 +- src/librustc/hir/map/mod.rs | 2 +- src/librustc/hir/mod.rs | 8 +- src/librustc/infer/outlives/verify.rs | 4 +- src/librustc/traits/mod.rs | 3 +- src/librustc/traits/select.rs | 3 +- src/librustc/traits/util.rs | 209 +++++++++++++++------ src/librustc/ty/mod.rs | 4 +- src/librustc_save_analysis/dump_visitor.rs | 6 +- src/librustc_typeck/astconv.rs | 85 ++++----- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/wfcheck.rs | 2 +- src/libsyntax/ast.rs | 4 +- 13 files changed, 211 insertions(+), 129 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 6eac8487401..8768f1ff081 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -123,12 +123,12 @@ pub use core::slice::{RChunks, RChunksMut, RChunksExact, RChunksExactMut}; //////////////////////////////////////////////////////////////////////////////// // HACK(japaric) needed for the implementation of `vec!` macro during testing -// NB see the hack module in this file for more details +// N.B., see the `hack` module in this file for more details. #[cfg(test)] pub use hack::into_vec; // HACK(japaric) needed for the implementation of `Vec::clone` during testing -// NB see the hack module in this file for more details +// N.B., see the `hack` module in this file for more details. #[cfg(test)] pub use hack::to_vec; @@ -376,7 +376,7 @@ impl [T] { pub fn to_vec(&self) -> Vec where T: Clone { - // NB see hack module in this file + // N.B., see the `hack` module in this file for more details. hack::to_vec(self) } @@ -397,7 +397,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn into_vec(self: Box) -> Vec { - // NB see hack module in this file + // N.B., see the `hack` module in this file for more details. hack::into_vec(self) } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 4b94f772554..23f4d208571 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -957,7 +957,7 @@ impl<'hir> Map<'hir> { } } - /// Returns the name associated with the given NodeId's AST. + /// Returns the name associated with the given `NodeId`'s AST. pub fn name(&self, id: NodeId) -> Name { let hir_id = self.node_to_hir_id(id); self.name_by_hir_id(hir_id) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 22312e7459b..fafe1cf85a3 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2143,11 +2143,11 @@ pub enum UseKind { ListStem, } -/// TraitRef's appear in impls. +/// `TraitRef` are references to traits in impls. /// -/// resolve maps each TraitRef's ref_id to its defining trait; that's all -/// that the ref_id is for. Note that ref_id's value is not the NodeId of the -/// trait being referred to but just a unique NodeId that serves as a key +/// `resolve` maps each `TraitRef`'s `ref_id` to its defining trait; that's all +/// that the `ref_id` is for. Note that `ref_id`'s value is not the `NodeId` of the +/// trait being referred to but just a unique `NodeId` that serves as a key /// within the resolution map. #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct TraitRef { diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs index e1ad5aeea19..5b8d89c865a 100644 --- a/src/librustc/infer/outlives/verify.rs +++ b/src/librustc/infer/outlives/verify.rs @@ -141,9 +141,9 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> { } fn recursive_type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> { - let mut bounds = ty.walk_shallow() + let mut bounds: Vec<_> = ty.walk_shallow() .map(|subty| self.type_bound(subty)) - .collect::>(); + .collect(); let mut regions = smallvec![]; ty.push_regions(&mut regions); diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 846924fb591..627f923399b 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -62,6 +62,7 @@ pub use self::engine::{TraitEngine, TraitEngineExt}; pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; pub use self::util::{supertraits, supertrait_def_ids, transitive_bounds, Supertraits, SupertraitDefIds}; +pub use self::util::{expand_trait_refs, TraitRefExpander}; pub use self::chalk_fulfill::{ CanonicalGoal as ChalkCanonicalGoal, @@ -1043,7 +1044,7 @@ fn vtable_methods<'a, 'tcx>( ) } -impl<'tcx,O> Obligation<'tcx,O> { +impl<'tcx, O> Obligation<'tcx,O> { pub fn new(cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, predicate: O) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index c4be85050db..ec5e127a5ec 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1772,7 +1772,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { bounds ); - let matching_bound = util::elaborate_predicates(self.tcx(), bounds.predicates) + let elaborated_predicates = util::elaborate_predicates(self.tcx(), bounds.predicates); + let matching_bound = elaborated_predicates .filter_to_traits() .find(|bound| { self.infcx.probe(|_| { diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 578d8bbedf3..897681e538e 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -1,3 +1,5 @@ +use syntax_pos::Span; + use crate::hir; use crate::hir::def_id::DefId; use crate::traits::specialize::specialization_graph::NodeItem; @@ -41,7 +43,6 @@ fn anonymize_predicate<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } } - struct PredicateSet<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, set: FxHashSet>, @@ -73,12 +74,11 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { /// "Elaboration" is the process of identifying all the predicates that /// are implied by a source predicate. Currently this basically means -/// walking the "supertraits" and other similar assumptions. For -/// example, if we know that `T : Ord`, the elaborator would deduce -/// that `T : PartialOrd` holds as well. Similarly, if we have `trait -/// Foo : 'static`, and we know that `T : Foo`, then we know that `T : -/// 'static`. -pub struct Elaborator<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +/// walking the "supertraits" and other similar assumptions. For example, +/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd` +/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that +/// `T: Foo`, then we know that `T: 'static`. +pub struct Elaborator<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { stack: Vec>, visited: PredicateSet<'a, 'gcx, 'tcx>, } @@ -96,8 +96,7 @@ pub fn elaborate_trait_refs<'cx, 'gcx, 'tcx>( trait_refs: impl Iterator>) -> Elaborator<'cx, 'gcx, 'tcx> { - let predicates = trait_refs.map(|trait_ref| trait_ref.to_predicate()) - .collect(); + let predicates = trait_refs.map(|trait_ref| trait_ref.to_predicate()).collect(); elaborate_predicates(tcx, predicates) } @@ -120,7 +119,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { let tcx = self.visited.tcx; match *predicate { ty::Predicate::Trait(ref data) => { - // Predicates declared on the trait. + // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); let mut predicates: Vec<_> = predicates.predicates @@ -130,12 +129,11 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { debug!("super_predicates: data={:?} predicates={:?}", data, predicates); - // 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(|r| self.visited.insert(r)); + // 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(|p| self.visited.insert(p)); self.stack.extend(predicates); } @@ -161,11 +159,9 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { // Currently, we do not elaborate const-evaluatable // predicates. } - ty::Predicate::RegionOutlives(..) => { // Nothing to elaborate from `'a: 'b`. } - ty::Predicate::TypeOutlives(ref data) => { // We know that `T: 'a` for some type `T`. We can // often elaborate this. For example, if we know that @@ -192,34 +188,35 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { tcx.push_outlives_components(ty_max, &mut components); self.stack.extend( components - .into_iter() - .filter_map(|component| match component { - Component::Region(r) => if r.is_late_bound() { - None - } else { - Some(ty::Predicate::RegionOutlives( - ty::Binder::dummy(ty::OutlivesPredicate(r, r_min)))) - }, + .into_iter() + .filter_map(|component| match component { + Component::Region(r) => if r.is_late_bound() { + None + } else { + Some(ty::Predicate::RegionOutlives( + ty::Binder::dummy(ty::OutlivesPredicate(r, r_min)))) + } - Component::Param(p) => { - let ty = tcx.mk_ty_param(p.index, p.name); - Some(ty::Predicate::TypeOutlives( - ty::Binder::dummy(ty::OutlivesPredicate(ty, r_min)))) - }, + Component::Param(p) => { + let ty = tcx.mk_ty_param(p.index, p.name); + Some(ty::Predicate::TypeOutlives( + ty::Binder::dummy(ty::OutlivesPredicate(ty, r_min)))) + } - Component::UnresolvedInferenceVariable(_) => { - None - }, + Component::UnresolvedInferenceVariable(_) => { + None + } - Component::Projection(_) | - Component::EscapingProjection(_) => { - // We can probably do more here. This - // corresponds to a case like `>::U: 'b`. - None - }, - }) - .filter(|p| visited.insert(p))); + Component::Projection(_) | + Component::EscapingProjection(_) => { + // We can probably do more here. This + // corresponds to a case like `>::U: 'b`. + None + } + }) + .filter(|p| visited.insert(p)) + ); } } } @@ -233,16 +230,10 @@ impl<'cx, 'gcx, 'tcx> Iterator for Elaborator<'cx, 'gcx, 'tcx> { } fn next(&mut self) -> Option> { - // Extract next item from top-most stack frame, if any. - let next_predicate = match self.stack.pop() { - Some(predicate) => predicate, - None => { - // No more stack frames. Done. - return None; - } - }; - self.push(&next_predicate); - return Some(next_predicate); + self.stack.pop().map(|item| { + self.push(&item); + item + }) } } @@ -254,20 +245,124 @@ pub type Supertraits<'cx, 'gcx, 'tcx> = FilterToTraits(tcx: TyCtxt<'cx, 'gcx, 'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) - -> Supertraits<'cx, 'gcx, 'tcx> -{ + -> Supertraits<'cx, 'gcx, 'tcx> { elaborate_trait_ref(tcx, trait_ref).filter_to_traits() } pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>, bounds: impl Iterator>) - -> Supertraits<'cx, 'gcx, 'tcx> -{ + -> Supertraits<'cx, 'gcx, 'tcx> { elaborate_trait_refs(tcx, bounds).filter_to_traits() } +/////////////////////////////////////////////////////////////////////////// +// `TraitRefExpander` iterator +/////////////////////////////////////////////////////////////////////////// + +/// "Trait reference expansion" is the process of expanding a sequence of trait +/// references into another sequence by transitively following all trait +/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias +/// `trait Foo = Bar + Sync;`, and another trait alias +/// `trait Bar = Read + Write`, then the bounds would expand to +/// `Read + Write + Sync + Send`. +pub struct TraitRefExpander<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + stack: Vec>, + visited: PredicateSet<'a, 'gcx, 'tcx>, +} + +#[derive(Debug, Clone)] +pub struct TraitRefExpansionInfo<'tcx> { + pub top_level_trait_ref: ty::PolyTraitRef<'tcx>, + pub top_level_span: Span, + pub trait_ref: ty::PolyTraitRef<'tcx>, + pub span: Span, +} + +pub fn expand_trait_refs<'cx, 'gcx, 'tcx>( + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + trait_refs: impl IntoIterator, Span)> +) -> TraitRefExpander<'cx, 'gcx, 'tcx> { + let mut visited = PredicateSet::new(tcx); + let mut items: Vec<_> = + trait_refs + .into_iter() + .map(|(tr, sp)| TraitRefExpansionInfo { + top_level_trait_ref: tr.clone(), + top_level_span: sp, + trait_ref: tr, + span: sp, + }) + .collect(); + items.retain(|item| visited.insert(&item.trait_ref.to_predicate())); + TraitRefExpander { stack: items, visited: visited, } +} + +impl<'cx, 'gcx, 'tcx> TraitRefExpander<'cx, 'gcx, 'tcx> { + // Returns `true` if `item` refers to a trait. + fn push(&mut self, item: &TraitRefExpansionInfo<'tcx>) -> bool { + let tcx = self.visited.tcx; + + if !tcx.is_trait_alias(item.trait_ref.def_id()) { + return true; + } + + // Get predicates declared on the trait. + let predicates = tcx.super_predicates_of(item.trait_ref.def_id()); + + let mut items: Vec<_> = predicates.predicates + .iter() + .rev() + .filter_map(|(pred, sp)| { + pred.subst_supertrait(tcx, &item.trait_ref) + .to_opt_poly_trait_ref() + .map(|trait_ref| + TraitRefExpansionInfo { + trait_ref, + span: *sp, + ..*item + } + ) + }) + .collect(); + + debug!("expand_trait_refs: trait_ref={:?} items={:?}", + item.trait_ref, items); + + // Only keep those items that we haven't already seen. + items.retain(|i| self.visited.insert(&i.trait_ref.to_predicate())); + + self.stack.extend(items); + false + } +} + +impl<'cx, 'gcx, 'tcx> Iterator for TraitRefExpander<'cx, 'gcx, 'tcx> { + type Item = TraitRefExpansionInfo<'tcx>; + + fn size_hint(&self) -> (usize, Option) { + (self.stack.len(), None) + } + + fn next(&mut self) -> Option> { + loop { + let item = self.stack.pop(); + match item { + Some(item) => { + if self.push(&item) { + return Some(item); + } + } + None => { + return None; + } + } + } + } +} + /////////////////////////////////////////////////////////////////////////// // Iterator over def-ids of supertraits +/////////////////////////////////////////////////////////////////////////// pub struct SupertraitDefIds<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c55e508c8b5..6020a737853 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1234,7 +1234,7 @@ impl<'tcx> TraitPredicate<'tcx> { self.trait_ref.def_id } - pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { + pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { self.trait_ref.input_types() } @@ -2400,7 +2400,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { pub fn discriminants( &'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - ) -> impl Iterator)> + Captures<'gcx> + 'a { + ) -> impl Iterator)> + Captures<'gcx> + 'a { let repr_type = self.repr.discr_type(); let initial = repr_type.initial_discriminant(tcx.global_tcx()); let mut prev_discr = None::>; diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 1e65f868eba..5f184bf4a7d 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1177,13 +1177,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ); } ast::ImplItemKind::Type(ref ty) => { - // FIXME uses of the assoc type should ideally point to this + // FIXME: uses of the assoc type should ideally point to this // 'def' and the name here should be a ref to the def in the // trait. self.visit_ty(ty) } ast::ImplItemKind::Existential(ref bounds) => { - // FIXME uses of the assoc type should ideally point to this + // FIXME: uses of the assoc type should ideally point to this // 'def' and the name here should be a ref to the def in the // trait. for bound in bounds.iter() { @@ -1216,7 +1216,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let hir_id = self.tcx.hir().node_to_hir_id(id); let access = access_from!(self.save_ctxt, root_item, hir_id); - // The parent def id of a given use tree is always the enclosing item. + // The parent def-ID of a given use tree is always the enclosing item. let parent = self.save_ctxt.tcx.hir().opt_local_def_id(id) .and_then(|id| self.save_ctxt.tcx.parent(id)) .map(id_from_def_id); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 06605695630..fc6edc2627b 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -975,12 +975,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { if trait_bounds.is_empty() { span_err!(tcx.sess, span, E0224, - "at least one non-builtin trait is required for an object type"); + "at least one non-builtin trait is required for an object type"); return tcx.types.err; } let mut projection_bounds = Vec::new(); let dummy_self = self.tcx().types.trait_object_dummy_self; + let mut bound_trait_refs = Vec::with_capacity(trait_bounds.len()); let (principal, potential_assoc_types) = self.instantiate_poly_trait_ref( &trait_bounds[0], dummy_self, @@ -988,22 +989,29 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ); debug!("principal: {:?}", principal); - for trait_bound in trait_bounds[1..].iter() { - // sanity check for non-principal trait bounds - self.instantiate_poly_trait_ref(trait_bound, - dummy_self, - &mut vec![]); + for trait_bound in trait_bounds[1..].iter().rev() { + // Sanity check for non-principal trait bounds. + let (tr, _) = self.instantiate_poly_trait_ref( + trait_bound, + dummy_self, + &mut Vec::new() + ); + bound_trait_refs.push((tr, trait_bound.span)); } + bound_trait_refs.push((principal, trait_bounds[0].span)); - let (mut auto_traits, trait_bounds) = split_auto_traits(tcx, &trait_bounds[1..]); - - if !trait_bounds.is_empty() { - let b = &trait_bounds[0]; - let span = b.trait_ref.path.span; - struct_span_err!(self.tcx().sess, span, E0225, - "only auto traits can be used as additional traits in a trait object") - .span_label(span, "non-auto additional trait") - .emit(); + let expanded_traits = traits::expand_trait_refs(tcx, bound_trait_refs); + let (auto_traits, regular_traits): (Vec<_>, Vec<_>) = + expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref.def_id())); + if regular_traits.len() > 1 { + let extra_trait = ®ular_traits[1]; + let mut err = struct_span_err!(tcx.sess, extra_trait.top_level_span, E0225, + "only auto traits can be used as additional traits in a trait object"); + err.span_label(extra_trait.span, "non-auto additional trait"); + if extra_trait.span != extra_trait.top_level_span { + err.span_label(extra_trait.top_level_span, "expanded from this alias"); + } + err.emit(); } // Check that there are no gross object safety violations; @@ -1024,9 +1032,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", tr); match tr { ty::Predicate::Trait(pred) => { - associated_types.extend(tcx.associated_items(pred.def_id()) - .filter(|item| item.kind == ty::AssociatedKind::Type) - .map(|item| item.def_id)); + associated_types + .extend(tcx.associated_items(pred.def_id()) + .filter(|item| item.kind == ty::AssociatedKind::Type) + .map(|item| item.def_id)); } ty::Predicate::Projection(pred) => { // A `Self` within the original bound will be substituted with a @@ -1145,11 +1154,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { }) }); - // Dedup auto traits so that `dyn Trait + Send + Send` is the same as `dyn Trait + Send`. + // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as + // `dyn Trait + Send`. + let mut auto_traits: Vec<_> = + auto_traits.into_iter().map(|i| i.trait_ref.def_id()).collect(); auto_traits.sort(); auto_traits.dedup(); + debug!("auto_traits: {:?}", auto_traits); - // Calling `skip_binder` is okay, because the predicates are re-bound. + // Calling `skip_binder` is okay because the predicates are re-bound. let principal = if tcx.trait_is_auto(existential_principal.def_id()) { ty::ExistentialPredicate::AutoTrait(existential_principal.def_id()) } else { @@ -1175,14 +1188,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } else { self.re_infer(span, None).unwrap_or_else(|| { span_err!(tcx.sess, span, E0228, - "the lifetime bound for this object type cannot be deduced \ - from context; please supply an explicit bound"); + "the lifetime bound for this object type cannot be deduced \ + from context; please supply an explicit bound"); tcx.lifetimes.re_static }) } }) }; - debug!("region_bound: {:?}", region_bound); let ty = tcx.mk_dynamic(existential_predicates, region_bound); @@ -2097,33 +2109,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } } -/// Divides a list of general trait bounds into two groups: auto traits (e.g., Sync and Send) and -/// the remaining general trait bounds. -fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - trait_bounds: &'b [hir::PolyTraitRef]) - -> (Vec, Vec<&'b hir::PolyTraitRef>) -{ - let (auto_traits, trait_bounds): (Vec<_>, _) = trait_bounds.iter().partition(|bound| { - // Checks whether `trait_did` is an auto trait and adds it to `auto_traits` if so. - match bound.trait_ref.path.res { - Res::Def(DefKind::Trait, trait_did) if tcx.trait_is_auto(trait_did) => { - true - } - _ => false - } - }); - - let auto_traits = auto_traits.into_iter().map(|tr| { - if let Res::Def(DefKind::Trait, trait_did) = tr.trait_ref.path.res { - trait_did - } else { - unreachable!() - } - }).collect::>(); - - (auto_traits, trait_bounds) -} - // A helper struct for conveniently grouping a set of bounds which we pass to // and return from functions in multiple places. #[derive(PartialEq, Eq, Clone, Debug)] diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 251400e65f3..590ae9d46e8 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -758,7 +758,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) { - // FIXME -- Do we want to commit to this behavior for param bounds? + // FIXME: do we want to commit to this behavior for param bounds? let bounds = self.param_env .caller_bounds diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index b009c8ea6dc..7e7a8d59266 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -1019,7 +1019,7 @@ fn check_false_global_bounds<'a, 'gcx, 'tcx>( .iter() .map(|(p, _)| *p) .collect(); - // Check elaborated bounds + // Check elaborated bounds. let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates); for pred in implied_obligations { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d12240655e6..e299518af0b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2133,10 +2133,10 @@ pub struct TraitRef { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct PolyTraitRef { - /// The `'a` in `<'a> Foo<&'a T>` + /// The `'a` in `<'a> Foo<&'a T>`. pub bound_generic_params: Vec, - /// The `Foo<&'a T>` in `<'a> Foo<&'a T>` + /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`. pub trait_ref: TraitRef, pub span: Span,