From 16ef2957705392abd6a7d9ac46619863ac339ef1 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Mon, 29 Apr 2019 03:54:03 +0100 Subject: [PATCH 01/12] Accumulation of various drive-by cosmetic changes. --- src/librustc/query/mod.rs | 42 +++++++++---------- src/librustc/traits/util.rs | 14 +++---- src/librustc/ty/mod.rs | 10 ++--- src/librustc/ty/query/mod.rs | 3 +- .../borrow_check/error_reporting.rs | 1 - src/librustc_typeck/astconv.rs | 14 +++---- src/librustc_typeck/collect.rs | 12 +++--- 7 files changed, 45 insertions(+), 51 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 2fff4c3f109b..d043a32f06bd 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -168,7 +168,7 @@ rustc_queries! { query predicates_defined_on(_: DefId) -> Lrc> {} - /// Returns the predicates written explicit by the user. + /// Returns the predicates written explicitly by the user. query explicit_predicates_of(_: DefId) -> Lrc> {} @@ -216,9 +216,9 @@ rustc_queries! { _: DefId ) -> Result, NoSolution> {} - /// True if this is a const fn, use the `is_const_fn` to know whether your crate actually - /// sees it as const fn (e.g., the const-fn-ness might be unstable and you might not have - /// the feature gate active) + /// Returns `true` if this is a const fn, use the `is_const_fn` to know whether your crate + /// actually sees it as const fn (e.g., the const-fn-ness might be unstable and you might + /// not have the feature gate active). /// /// **Do not call this function manually.** It is only meant to cache the base data for the /// `is_const_fn` function. @@ -226,7 +226,7 @@ rustc_queries! { desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) } } - /// Returns true if calls to the function may be promoted + /// Returns `true` if calls to the function may be promoted. /// /// This is either because the function is e.g., a tuple-struct or tuple-variant /// constructor, or because it has the `#[rustc_promotable]` attribute. The attribute should @@ -237,25 +237,23 @@ rustc_queries! { query const_fn_is_allowed_fn_ptr(_: DefId) -> bool {} - /// True if this is a foreign item (i.e., linked via `extern { ... }`). + /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`). query is_foreign_item(_: DefId) -> bool {} /// Returns `Some(mutability)` if the node pointed to by `def_id` is a static item. query static_mutability(_: DefId) -> Option {} - /// Get a map with the variance of every item; use `item_variance` - /// instead. + /// Gets a map with the variance of every item; use `item_variance` instead. query crate_variances(_: CrateNum) -> Lrc> { desc { "computing the variances for items in this crate" } } - /// Maps from def-id of a type or region parameter to its - /// (inferred) variance. + /// Maps from def-ID of a type or region parameter to its (inferred) variance. query variances_of(_: DefId) -> &'tcx [ty::Variance] {} } TypeChecking { - /// Maps from def-id of a type to its (inferred) outlives. + /// Maps from def-ID of a type to its (inferred) outlives. query inferred_outlives_crate(_: CrateNum) -> Lrc> { desc { "computing the inferred outlives predicates for items in this crate" } @@ -263,10 +261,10 @@ rustc_queries! { } Other { - /// Maps from an impl/trait def-id to a list of the def-ids of its items + /// Maps from an impl/trait def-ID to a list of the def-ids of its items. query associated_item_def_ids(_: DefId) -> Lrc> {} - /// Maps from a trait item to the trait item "descriptor" + /// Maps from a trait item to the trait item "descriptor". query associated_item(_: DefId) -> ty::AssociatedItem {} query impl_trait_ref(_: DefId) -> Option> {} @@ -276,7 +274,7 @@ rustc_queries! { } TypeChecking { - /// Maps a DefId of a type to a list of its inherent impls. + /// Maps a def-ID of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. query inherent_impls(_: DefId) -> Lrc> { @@ -300,7 +298,7 @@ rustc_queries! { desc { |tcx| "linting {}", key.describe_as_module(tcx) } } - /// Checks the attributes in the module + /// Checks the attributes in the module. query check_mod_attrs(key: DefId) -> () { desc { |tcx| "checking attributes in {}", key.describe_as_module(tcx) } } @@ -309,7 +307,7 @@ rustc_queries! { desc { |tcx| "checking for unstable API usage in {}", key.describe_as_module(tcx) } } - /// Checks the loops in the module + /// Checks the loops in the module. query check_mod_loops(key: DefId) -> () { desc { |tcx| "checking loops in {}", key.describe_as_module(tcx) } } @@ -338,7 +336,7 @@ rustc_queries! { desc { |tcx| "collecting item types in {}", key.describe_as_module(tcx) } } - /// Caches CoerceUnsized kinds for impls on custom types. + /// Caches `CoerceUnsized` kinds for impls on custom types. query coerce_unsized_info(_: DefId) -> ty::adjustment::CoerceUnsizedInfo {} } @@ -375,7 +373,7 @@ rustc_queries! { BorrowChecking { query borrowck(_: DefId) -> Lrc {} - /// Borrow checks the function body. If this is a closure, returns + /// Borrow-checks the function body. If this is a closure, returns /// additional requirements that the closure's creator must verify. query mir_borrowck(_: DefId) -> mir::BorrowCheckResult<'tcx> {} } @@ -401,11 +399,11 @@ rustc_queries! { } Other { - /// Evaluate a constant without running sanity checks + /// Evaluates a constant without running sanity checks. /// /// **Do not use this** outside const eval. Const eval uses this to break query cycles /// during validation. Please add a comment to every use site explaining why using - /// `const_eval` isn't sufficient + /// `const_eval` isn't sufficient. query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> ConstEvalRawResult<'tcx> { no_force @@ -660,12 +658,12 @@ rustc_queries! { } Linking { - // The DefIds of all non-generic functions and statics in the given crate + // The `DefId`s of all non-generic functions and statics in the given crate // that can be reached from outside the crate. // // We expect this items to be available for being linked to. // - // This query can also be called for LOCAL_CRATE. In this case it will + // This query can also be called for `LOCAL_CRATE`. In this case it will // compute which items will be reachable to other crates, taking into account // the kind of crate that is currently compiled. Crates with only a // C interface have fewer reachable things. diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index be29ea5701b2..578d8bbedf39 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -123,12 +123,10 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { // Predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); - let mut predicates: Vec<_> = - predicates.predicates - .iter() - .map(|(p, _)| p.subst_supertrait(tcx, &data.to_poly_trait_ref())) - .collect(); - + let mut predicates: Vec<_> = predicates.predicates + .iter() + .map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref())) + .collect(); debug!("super_predicates: data={:?} predicates={:?}", data, predicates); @@ -150,8 +148,8 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { // predicates. } ty::Predicate::Subtype(..) => { - // Currently, we do not "elaborate" predicates like `X - // <: Y`, though conceivably we might. + // Currently, we do not "elaborate" predicates like `X <: Y`, + // though conceivably we might. } ty::Predicate::Projection(..) => { // Nothing to elaborate in a projection predicate. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index e1c432d5b6da..c55e508c8b52 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1075,25 +1075,25 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub enum Predicate<'tcx> { - /// Corresponds to `where Foo: Bar`. `Foo` here would be + /// Corresponds to `where Foo: Bar`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` /// would be the type parameters. Trait(PolyTraitPredicate<'tcx>), - /// where `'a: 'b` + /// `where 'a: 'b` RegionOutlives(PolyRegionOutlivesPredicate<'tcx>), - /// where `T: 'a` + /// `where T: 'a` TypeOutlives(PolyTypeOutlivesPredicate<'tcx>), - /// where `::Name == X`, approximately. + /// `where ::Name == X`, approximately. /// See the `ProjectionPredicate` struct for details. Projection(PolyProjectionPredicate<'tcx>), /// no syntax: `T` well-formed WellFormed(Ty<'tcx>), - /// trait must be object-safe + /// Trait must be object-safe. ObjectSafe(DefId), /// No direct syntax. May be thought of as `where T: FnFoo<...>` diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 18d575f73645..be52b7e64519 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -100,8 +100,7 @@ pub use self::on_disk_cache::OnDiskCache; rustc_query_append! { [define_queries!][ <'tcx> Other { - /// Run analysis passes on the crate + /// Runs analysis passes on the crate. [] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>, - }, ]} diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 1a1000f0bb41..32d182edfdcd 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1502,7 +1502,6 @@ enum StorageDeadOrDrop<'tcx> { } impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { - /// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure /// is moved after being invoked. /// diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 4b052aec5fc2..06605695630f 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -702,7 +702,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } /// Instantiates the path for the given trait reference, assuming that it's - /// bound to a valid trait type. Returns the def_id for the defining trait. + /// bound to a valid trait type. Returns the def-ID for the defining trait. /// The type _cannot_ be a type other than a trait type. /// /// If the `projections` argument is `None`, then assoc type bindings like `Foo` @@ -1035,7 +1035,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { pred.skip_binder().ty.walk().any(|t| t == dummy_self); // If the projection output contains `Self`, force the user to - // elaborate it explicitly to avoid a bunch of complexity. + // elaborate it explicitly to avoid a lot of complexity. // // The "classicaly useful" case is the following: // ``` @@ -1044,14 +1044,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { // } // ``` // - // Here, the user could theoretically write `dyn MyTrait`, + // Here, the user could theoretically write `dyn MyTrait`, // but actually supporting that would "expand" to an infinitely-long type - // `fix $ τ → dyn MyTrait::MyOutput`. + // `fix $ τ → dyn MyTrait::MyOutput`. // - // Instead, we force the user to write `dyn MyTrait`, + // Instead, we force the user to write `dyn MyTrait`, // which is uglier but works. See the discussion in #56288 for alternatives. if !references_self { - // Include projections defined on supertraits, + // Include projections defined on supertraits. projection_bounds.push((pred, DUMMY_SP)) } } @@ -2138,7 +2138,7 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> { pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>) -> Vec<(ty::Predicate<'tcx>, Span)> { - // If it could be sized, and is, add the sized predicate. + // If it could be sized, and is, add the `Sized` predicate. let sized_predicate = self.implicitly_sized.and_then(|span| { tcx.lang_items().sized_trait().map(|sized| { let trait_ref = ty::TraitRef { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 711d79f95f53..104c8e25d138 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -684,9 +684,9 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad tcx.alloc_adt_def(def_id, kind, variants, repr) } -/// Ensures that the super-predicates of the trait with `DefId` -/// trait_def_id are converted and stored. This also ensures that -/// the transitive super-predicates are converted; +/// Ensures that the super-predicates of the trait with a `DefId` +/// of `trait_def_id` are converted and stored. This also ensures that +/// the transitive super-predicates are converted. fn super_predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId, @@ -707,14 +707,14 @@ fn super_predicates_of<'a, 'tcx>( let icx = ItemCtxt::new(tcx, trait_def_id); - // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo : Bar + Zed`. + // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`. let self_param_ty = tcx.mk_self_type(); let superbounds1 = compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span); let superbounds1 = superbounds1.predicates(tcx, self_param_ty); - // Convert any explicit superbounds in the where clause, - // e.g., `trait Foo where Self : Bar`. + // Convert any explicit superbounds in the wheree-clause, + // e.g., `trait Foo where Self: Bar`. // In the case of trait aliases, however, we include all bounds in the where clause, // so e.g., `trait Foo = where u32: PartialEq` would include `u32: PartialEq` // as one of its "superpredicates". From 9f800457dda7ee9b8579394d1c07761f3008e573 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 26 Mar 2019 17:34:32 +0000 Subject: [PATCH 02/12] 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 | 215 +++++++++++++++------ src/librustc/ty/mod.rs | 4 +- src/librustc_save_analysis/dump_visitor.rs | 6 +- src/librustc_typeck/astconv.rs | 87 ++++----- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/wfcheck.rs | 2 +- src/libsyntax/ast.rs | 4 +- 13 files changed, 215 insertions(+), 133 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 6eac84874010..8768f1ff081c 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 4b94f772554e..23f4d2085713 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 22312e7459be..fafe1cf85a3e 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 e1ad5aeea19f..5b8d89c865a5 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 846924fb591e..627f923399b5 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 c4be85050dbc..ec5e127a5ec4 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 578d8bbedf39..897681e538e3 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)))) - }, - - 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::Projection(_) | - Component::EscapingProjection(_) => { - // We can probably do more here. This - // corresponds to a case like `>::U: 'b`. - None - }, - }) - .filter(|p| visited.insert(p))); + .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::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)) + ); } } } @@ -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 c55e508c8b52..6020a737853e 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 1e65f868ebac..5f184bf4a7d4 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 06605695630f..fc6edc2627bc 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)); } - - 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(); + bound_trait_refs.push((principal, trait_bounds[0].span)); + + 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 251400e65f38..590ae9d46e8d 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 b009c8ea6dce..7e7a8d592667 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 d12240655e62..e299518af0be 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, From 72e5e8bfa731a3b7e5a9363eced44e76d962c794 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 26 Mar 2019 17:23:09 +0000 Subject: [PATCH 03/12] Update tests. --- src/test/ui/error-codes/E0225.rs | 6 ++++++ src/test/ui/error-codes/E0225.stderr | 13 +++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/test/ui/error-codes/E0225.rs b/src/test/ui/error-codes/E0225.rs index 1789be1559d8..e3ac680f4415 100644 --- a/src/test/ui/error-codes/E0225.rs +++ b/src/test/ui/error-codes/E0225.rs @@ -1,4 +1,10 @@ +#![feature(trait_alias)] + +trait Foo = std::io::Read + std::io::Write; + fn main() { let _: Box; //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + let _: Box; + //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] } diff --git a/src/test/ui/error-codes/E0225.stderr b/src/test/ui/error-codes/E0225.stderr index 85a04708cb25..c8d8f07db8ae 100644 --- a/src/test/ui/error-codes/E0225.stderr +++ b/src/test/ui/error-codes/E0225.stderr @@ -1,9 +1,18 @@ error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/E0225.rs:2:32 + --> $DIR/E0225.rs:6:32 | LL | let _: Box; | ^^^^^^^^^^^^^^ non-auto additional trait -error: aborting due to previous error +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/E0225.rs:8:16 + | +LL | trait Foo = std::io::Read + std::io::Write; + | -------------- non-auto additional trait +... +LL | let _: Box; + | ^^^ expanded from this alias + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0225`. From 16692f7b1ad8623f784d3d3b60814ebfa468fe62 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Wed, 27 Mar 2019 15:14:41 +0000 Subject: [PATCH 04/12] Addressed review points. --- src/librustc/traits/mod.rs | 2 +- src/librustc/traits/util.rs | 45 +++++++++++++++------------------- src/librustc_typeck/astconv.rs | 4 +-- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 627f923399b5..a792c439f5b8 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -1044,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/util.rs b/src/librustc/traits/util.rs index 897681e538e3..4cb3f551123d 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -107,7 +107,7 @@ pub fn elaborate_predicates<'cx, 'gcx, 'tcx>( { let mut visited = PredicateSet::new(tcx); predicates.retain(|pred| visited.insert(pred)); - Elaborator { stack: predicates, visited: visited } + Elaborator { stack: predicates, visited } } impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { @@ -286,19 +286,21 @@ pub fn expand_trait_refs<'cx, 'gcx, '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, + .map(|(trait_ref, span)| TraitRefExpansionInfo { + top_level_trait_ref: trait_ref.clone(), + top_level_span: span, + trait_ref, + span, }) .collect(); items.retain(|item| visited.insert(&item.trait_ref.to_predicate())); - TraitRefExpander { stack: items, visited: visited, } + TraitRefExpander { stack: items, visited } } impl<'cx, 'gcx, 'tcx> TraitRefExpander<'cx, 'gcx, 'tcx> { - // Returns `true` if `item` refers to a trait. + /// If `item` refers to a trait alias, adds the components of the trait alias to the stack, + /// and returns `false`. + /// If `item` refers to an ordinary trait, simply returns `true`. fn push(&mut self, item: &TraitRefExpansionInfo<'tcx>) -> bool { let tcx = self.visited.tcx; @@ -306,27 +308,27 @@ impl<'cx, 'gcx, 'tcx> TraitRefExpander<'cx, 'gcx, 'tcx> { return true; } - // Get predicates declared on the trait. + // Get components of the trait alias. let predicates = tcx.super_predicates_of(item.trait_ref.def_id()); let mut items: Vec<_> = predicates.predicates .iter() .rev() - .filter_map(|(pred, sp)| { + .filter_map(|(pred, span)| { pred.subst_supertrait(tcx, &item.trait_ref) .to_opt_poly_trait_ref() .map(|trait_ref| TraitRefExpansionInfo { trait_ref, - span: *sp, + span: *span, ..*item } ) }) .collect(); - debug!("expand_trait_refs: trait_ref={:?} items={:?}", - item.trait_ref, items); + debug!("trait_ref_expander: 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())); @@ -344,24 +346,17 @@ impl<'cx, 'gcx, 'tcx> Iterator for TraitRefExpander<'cx, 'gcx, 'tcx> { } 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; - } + while let Some(item) = self.stack.pop() { + if self.push(&item) { + return Some(item); } } + None } } /////////////////////////////////////////////////////////////////////////// -// Iterator over def-ids of supertraits +// Iterator over def-IDs of supertraits /////////////////////////////////////////////////////////////////////////// pub struct SupertraitDefIds<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index fc6edc2627bc..e5410defb7aa 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -981,7 +981,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { 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, @@ -989,6 +988,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ); debug!("principal: {:?}", principal); + let mut bound_trait_refs = Vec::with_capacity(trait_bounds.len()); for trait_bound in trait_bounds[1..].iter().rev() { // Sanity check for non-principal trait bounds. let (tr, _) = self.instantiate_poly_trait_ref( @@ -1009,7 +1009,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { "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.span_label(extra_trait.top_level_span, "expanded from this trait alias"); } err.emit(); } From 5f6c2127d792b0f2f2eb82e160e02cae3b238f14 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Thu, 28 Mar 2019 01:29:31 +0000 Subject: [PATCH 05/12] Factored out part of `conv_object_ty_poly_trait_ref` method. --- src/librustc_typeck/astconv.rs | 40 +++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index e5410defb7aa..e1dc0b10c9f9 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -965,6 +965,30 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref) } + fn expand_trait_refs(&self, + trait_refs: impl IntoIterator, Span)> + ) -> Vec { + let tcx = self.tcx(); + + // Expand trait aliases recursively and check that only one regular (non-auto) trait + // is used. + let expanded_traits = traits::expand_trait_refs(tcx, 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 trait alias"); + } + err.emit(); + } + + auto_traits.into_iter().map(|i| i.trait_ref.def_id()).collect() + } + fn conv_object_ty_poly_trait_ref(&self, span: Span, trait_bounds: &[hir::PolyTraitRef], @@ -1000,19 +1024,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } bound_trait_refs.push((principal, trait_bounds[0].span)); - 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 trait alias"); - } - err.emit(); - } + let mut auto_traits = self.expand_trait_refs(bound_trait_refs); // Check that there are no gross object safety violations; // most importantly, that the supertraits don't contain `Self`, @@ -1156,8 +1168,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { // 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); From aea954b74de16888f09ff003ebfdf97f9f7ef001 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Mon, 29 Apr 2019 03:58:24 +0100 Subject: [PATCH 06/12] Fixed detection of multiple non-auto traits. --- src/librustc/traits/mod.rs | 9 +- src/librustc/traits/util.rs | 195 +++++++++++++++++--------- src/librustc_passes/ast_validation.rs | 1 - src/librustc_typeck/astconv.rs | 155 ++++++++++---------- 4 files changed, 208 insertions(+), 152 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index a792c439f5b8..d950746f6e6d 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -60,9 +60,12 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapError; pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; 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::util::{ + supertraits, supertrait_def_ids, transitive_bounds, Supertraits, SupertraitDefIds, +}; +pub use self::util::{ + expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfoDignosticBuilder, +}; pub use self::chalk_fulfill::{ CanonicalGoal as ChalkCanonicalGoal, diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 4cb3f551123d..d765827e3d56 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -1,3 +1,5 @@ +use errors::DiagnosticBuilder; +use smallvec::SmallVec; use syntax_pos::Span; use crate::hir; @@ -43,7 +45,7 @@ fn anonymize_predicate<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } } -struct PredicateSet<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +struct PredicateSet<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, set: FxHashSet>, } @@ -53,6 +55,10 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { PredicateSet { tcx: tcx, set: Default::default() } } + fn contains(&mut self, pred: &ty::Predicate<'tcx>) -> bool { + self.set.contains(&anonymize_predicate(self.tcx, pred)) + } + fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool { // We have to be careful here because we want // @@ -66,6 +72,18 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { // regions before we throw things into the underlying set. self.set.insert(anonymize_predicate(self.tcx, pred)) } + + fn remove(&mut self, pred: &ty::Predicate<'tcx>) -> bool { + self.set.remove(&anonymize_predicate(self.tcx, pred)) + } +} + +impl<'a, 'gcx, 'tcx, T: AsRef>> Extend for PredicateSet<'a, 'gcx, 'tcx> { + fn extend>(&mut self, iter: I) { + for pred in iter.into_iter() { + self.insert(pred.as_ref()); + } + } } /////////////////////////////////////////////////////////////////////////// @@ -230,10 +248,16 @@ impl<'cx, 'gcx, 'tcx> Iterator for Elaborator<'cx, 'gcx, 'tcx> { } fn next(&mut self) -> Option> { - self.stack.pop().map(|item| { - self.push(&item); - item - }) + // 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); } } @@ -256,96 +280,140 @@ pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>, } /////////////////////////////////////////////////////////////////////////// -// `TraitRefExpander` iterator +// `TraitAliasExpander` iterator /////////////////////////////////////////////////////////////////////////// -/// "Trait reference expansion" is the process of expanding a sequence of trait +/// "Trait alias 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>, +pub struct TraitAliasExpander<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + stack: Vec>, + /// The set of predicates visited from the root directly to the current point in the + /// expansion tree. 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 struct TraitAliasExpansionInfo<'tcx> { + pub items: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, } -pub fn expand_trait_refs<'cx, 'gcx, 'tcx>( +impl<'tcx> TraitAliasExpansionInfo<'tcx> { + fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> TraitAliasExpansionInfo<'tcx> { + TraitAliasExpansionInfo { + items: smallvec![(trait_ref, span)] + } + } + + fn push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> TraitAliasExpansionInfo<'tcx> { + let mut items = self.items.clone(); + items.push((trait_ref, span)); + + TraitAliasExpansionInfo { + items + } + } + + pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> { + &self.top().0 + } + + pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { + self.items.last().unwrap() + } + + pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { + self.items.first().unwrap() + } +} + +pub trait TraitAliasExpansionInfoDignosticBuilder { + fn label_with_exp_info<'tcx>(&mut self, + info: &TraitAliasExpansionInfo<'tcx>, + top_label: &str + ) -> &mut Self; +} + +impl<'a> TraitAliasExpansionInfoDignosticBuilder for DiagnosticBuilder<'a> { + fn label_with_exp_info<'tcx>(&mut self, + info: &TraitAliasExpansionInfo<'tcx>, + top_label: &str + ) -> &mut Self { + self.span_label(info.top().1, top_label); + if info.items.len() > 1 { + for (_, sp) in info.items[1..(info.items.len() - 1)].iter().rev() { + self.span_label(*sp, "referenced here"); + } + } + self + } +} + +pub fn expand_trait_aliases<'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(|(trait_ref, span)| TraitRefExpansionInfo { - top_level_trait_ref: trait_ref.clone(), - top_level_span: span, - trait_ref, - span, - }) - .collect(); - items.retain(|item| visited.insert(&item.trait_ref.to_predicate())); - TraitRefExpander { stack: items, visited } +) -> TraitAliasExpander<'cx, 'gcx, 'tcx> { + let items: Vec<_> = trait_refs + .into_iter() + .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)) + .collect(); + TraitAliasExpander { stack: items, visited: PredicateSet::new(tcx) } } -impl<'cx, 'gcx, 'tcx> TraitRefExpander<'cx, 'gcx, 'tcx> { - /// If `item` refers to a trait alias, adds the components of the trait alias to the stack, - /// and returns `false`. - /// If `item` refers to an ordinary trait, simply returns `true`. - fn push(&mut self, item: &TraitRefExpansionInfo<'tcx>) -> bool { +impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> { + /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item` + /// to the definition and pushes the resulting expansion onto `self.stack`, and returns `false`. + /// Otherwise, immediately returns `true` if `item` is a regular trait and `false` if it is a + /// trait alias. + /// The return value indicates whether `item` should not be yielded to the user. + fn push(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { let tcx = self.visited.tcx; + let trait_ref = item.trait_ref(); + let pred = trait_ref.to_predicate(); + + debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); + + self.visited.remove(&pred); - if !tcx.is_trait_alias(item.trait_ref.def_id()) { - return true; + let is_alias = tcx.is_trait_alias(trait_ref.def_id()); + if !is_alias || self.visited.contains(&pred) { + return !is_alias; } - // Get components of the trait alias. - let predicates = tcx.super_predicates_of(item.trait_ref.def_id()); + // Get components of trait alias. + let predicates = tcx.super_predicates_of(trait_ref.def_id()); - let mut items: Vec<_> = predicates.predicates + let items: Vec<_> = predicates.predicates .iter() .rev() .filter_map(|(pred, span)| { - pred.subst_supertrait(tcx, &item.trait_ref) + pred.subst_supertrait(tcx, &trait_ref) .to_opt_poly_trait_ref() - .map(|trait_ref| - TraitRefExpansionInfo { - trait_ref, - span: *span, - ..*item - } - ) + .map(|trait_ref| item.push(trait_ref, *span)) }) .collect(); + debug!("expand_trait_aliases: items={:?}", items); - debug!("trait_ref_expander: trait_ref={:?} items={:?}", - item.trait_ref, items); + self.stack.extend(items); - // Only keep those items that we haven't already seen. - items.retain(|i| self.visited.insert(&i.trait_ref.to_predicate())); + // Record predicate into set of already-visited. + self.visited.insert(&pred); - self.stack.extend(items); false } } -impl<'cx, 'gcx, 'tcx> Iterator for TraitRefExpander<'cx, 'gcx, 'tcx> { - type Item = TraitRefExpansionInfo<'tcx>; +impl<'cx, 'gcx, 'tcx> Iterator for TraitAliasExpander<'cx, 'gcx, 'tcx> { + type Item = TraitAliasExpansionInfo<'tcx>; fn size_hint(&self) -> (usize, Option) { (self.stack.len(), None) } - fn next(&mut self) -> Option> { + fn next(&mut self) -> Option> { while let Some(item) = self.stack.pop() { if self.push(&item) { return Some(item); @@ -386,8 +454,8 @@ impl<'cx, 'gcx, 'tcx> Iterator for SupertraitDefIds<'cx, 'gcx, 'tcx> { self.stack.extend( predicates.predicates .iter() - .filter_map(|(p, _)| p.to_opt_poly_trait_ref()) - .map(|t| t.def_id()) + .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref()) + .map(|trait_ref| trait_ref.def_id()) .filter(|&super_def_id| visited.insert(super_def_id))); Some(def_id) } @@ -413,17 +481,12 @@ impl<'tcx, I: Iterator>> Iterator for FilterToTraits< type Item = ty::PolyTraitRef<'tcx>; fn next(&mut self) -> Option> { - loop { - match self.base_iterator.next() { - None => { - return None; - } - Some(ty::Predicate::Trait(data)) => { - return Some(data.to_poly_trait_ref()); - } - Some(_) => {} + while let Some(pred) = self.base_iterator.next() { + if let ty::Predicate::Trait(data) = pred { + return Some(data.to_poly_trait_ref()); } } + None } fn size_hint(&self) -> (usize, Option) { diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 2bea1db841ae..d70c81854955 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -504,7 +504,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { any_lifetime_bounds = true; } } - self.no_questions_in_bounds(bounds, "trait object types", false); } TyKind::ImplTrait(_, ref bounds) => { if self.is_impl_trait_banned { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index e1dc0b10c9f9..428fa66101ac 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; +use rustc::traits::{self, TraitAliasExpansionInfoDignosticBuilder}; use rustc::ty::{self, DefIdTree, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef}; @@ -965,84 +965,77 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref) } - fn expand_trait_refs(&self, - trait_refs: impl IntoIterator, Span)> - ) -> Vec { + fn conv_object_ty_poly_trait_ref(&self, + span: Span, + trait_bounds: &[hir::PolyTraitRef], + lifetime: &hir::Lifetime) + -> Ty<'tcx> + { let tcx = self.tcx(); + let mut projection_bounds = Vec::new(); + let mut potential_assoc_types = Vec::new(); + let dummy_self = self.tcx().types.trait_object_dummy_self; + let bound_trait_refs: Vec<_> = trait_bounds + .iter() + .rev() + .map(|trait_bound| { + let (trait_ref, cur_potential_assoc_types) = self.instantiate_poly_trait_ref( + trait_bound, + dummy_self, + &mut projection_bounds + ); + potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten()); + (trait_ref, trait_bound.span) + }).collect(); + // Expand trait aliases recursively and check that only one regular (non-auto) trait - // is used. - let expanded_traits = traits::expand_trait_refs(tcx, trait_refs); - let (auto_traits, regular_traits): (Vec<_>, Vec<_>) = - expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref.def_id())); + // is used and no 'maybe' bounds are used. + let expanded_traits = traits::expand_trait_aliases(tcx, bound_trait_refs.clone()); + let (mut 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, + let mut err = struct_span_err!(tcx.sess, extra_trait.bottom().1, 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 trait alias"); - } + err.label_with_exp_info(extra_trait, "additional non-auto trait"); + err.span_label(regular_traits[0].top().1, "first non-auto trait"); err.emit(); } - auto_traits.into_iter().map(|i| i.trait_ref.def_id()).collect() - } - - fn conv_object_ty_poly_trait_ref(&self, - span: Span, - trait_bounds: &[hir::PolyTraitRef], - lifetime: &hir::Lifetime) - -> Ty<'tcx> - { - let tcx = self.tcx(); - - if trait_bounds.is_empty() { + if regular_traits.is_empty() && auto_traits.is_empty() { span_err!(tcx.sess, span, E0224, "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 (principal, potential_assoc_types) = self.instantiate_poly_trait_ref( - &trait_bounds[0], - dummy_self, - &mut projection_bounds, - ); - debug!("principal: {:?}", principal); - - let mut bound_trait_refs = Vec::with_capacity(trait_bounds.len()); - 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 = self.expand_trait_refs(bound_trait_refs); - // Check that there are no gross object safety violations; // most importantly, that the supertraits don't contain `Self`, // to avoid ICEs. - let object_safety_violations = - tcx.global_tcx().astconv_object_safety_violations(principal.def_id()); - if !object_safety_violations.is_empty() { - tcx.report_object_safety_error(span, principal.def_id(), object_safety_violations) - .map(|mut err| err.emit()); - return tcx.types.err; + for item in ®ular_traits { + let object_safety_violations = + tcx.global_tcx().astconv_object_safety_violations(item.trait_ref().def_id()); + if !object_safety_violations.is_empty() { + tcx.report_object_safety_error( + span, + item.trait_ref().def_id(), + object_safety_violations + ) + .map(|mut err| err.emit()); + return tcx.types.err; + } } // Use a `BTreeSet` to keep output in a more consistent order. let mut associated_types = BTreeSet::default(); - for tr in traits::elaborate_trait_ref(tcx, principal) { - debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", tr); - match tr { + let regular_traits_refs = bound_trait_refs + .into_iter() + .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())) + .map(|(trait_ref, _)| trait_ref); + for trait_ref in traits::elaborate_trait_refs(tcx, regular_traits_refs) { + debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", trait_ref); + match trait_ref { ty::Predicate::Trait(pred) => { associated_types .extend(tcx.associated_items(pred.def_id()) @@ -1102,20 +1095,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { if associated_types.len() == 1 { "" } else { "s" }, names, ); - let mut suggest = false; - let mut potential_assoc_types_spans = vec![]; - if let Some(potential_assoc_types) = potential_assoc_types { + let (suggest, potential_assoc_types_spans) = if potential_assoc_types.len() == associated_types.len() { - // Only suggest when the amount of missing associated types is equals to the + // Only suggest when the amount of missing associated types equals the number of // extra type arguments present, as that gives us a relatively high confidence // that the user forgot to give the associtated type's name. The canonical // example would be trying to use `Iterator` instead of - // `Iterator`. - suggest = true; - potential_assoc_types_spans = potential_assoc_types; - } - } - let mut suggestions = vec![]; + // `Iterator`. + (true, potential_assoc_types) + } else { + (false, Vec::new()) + }; + let mut suggestions = Vec::new(); for (i, item_def_id) in associated_types.iter().enumerate() { let assoc_item = tcx.associated_item(*item_def_id); err.span_label( @@ -1151,9 +1142,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { err.emit(); } + // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as + // `dyn Trait + Send`. + auto_traits.sort_by_key(|i| i.trait_ref().def_id()); + auto_traits.dedup_by_key(|i| i.trait_ref().def_id()); + debug!("regular_traits: {:?}", regular_traits); + debug!("auto_traits: {:?}", auto_traits); + // Erase the `dummy_self` (`trait_object_dummy_self`) used above. - let existential_principal = principal.map_bound(|trait_ref| { - self.trait_ref_to_existential(trait_ref) + let existential_trait_refs = regular_traits.iter().map(|i| { + i.trait_ref().map_bound(|trait_ref| self.trait_ref_to_existential(trait_ref)) }); let existential_projections = projection_bounds.iter().map(|(bound, _)| { bound.map_bound(|b| { @@ -1166,21 +1164,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { }) }); - // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as - // `dyn Trait + Send`. - auto_traits.sort(); - auto_traits.dedup(); - debug!("auto_traits: {:?}", auto_traits); - // 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 { - ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()) - }; + let regular_trait_predicates = existential_trait_refs.map( + |trait_ref| ty::ExistentialPredicate::Trait(*trait_ref.skip_binder())); + let auto_trait_predicates = auto_traits.into_iter().map( + |trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())); let mut v = - iter::once(principal) - .chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait)) + regular_trait_predicates + .chain(auto_trait_predicates) .chain(existential_projections .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder()))) .collect::>(); From fd7c253accd46ea8340feb79ecaf18d99f518bb8 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Sat, 30 Mar 2019 22:06:09 +0000 Subject: [PATCH 07/12] Update tests. --- ...sociated-types-overridden-binding-2.stderr | 2 +- src/test/ui/bad/bad-sized.stderr | 4 +- src/test/ui/error-codes/E0225.stderr | 10 +- src/test/ui/issues/issue-22560.stderr | 22 +- src/test/ui/issues/issue-32963.stderr | 4 +- src/test/ui/maybe-bounds.rs | 4 +- src/test/ui/maybe-bounds.stderr | 14 +- .../ui/parser/trait-object-trait-parens.rs | 4 +- .../parser/trait-object-trait-parens.stderr | 16 +- src/test/ui/traits/trait-alias-object.rs | 9 - .../auxiliary/trait_alias.rs | 0 .../traits/trait-alias}/trait-alias-bounds.rs | 2 + .../trait-alias-cross-crate.rs | 0 .../trait-alias-cross-crate.stderr | 0 .../{ => trait-alias}/trait-alias-impl.rs | 0 .../{ => trait-alias}/trait-alias-impl.stderr | 0 .../trait-alias/trait-alias-maybe-bound.rs | 27 ++ .../trait-alias-maybe-bound.stderr | 14 + .../trait-alias/trait-alias-no-duplicates.rs | 126 ++++++ .../trait-alias-no-duplicates.stderr | 358 +++++++++++++++++ .../trait-alias-no-extra-traits.rs | 121 ++++++ .../trait-alias-no-extra-traits.stderr | 371 ++++++++++++++++++ .../trait-alias/trait-alias-object-fail.rs | 11 + .../trait-alias-object-fail.stderr} | 8 +- .../trait-alias/trait-alias-object-wf.rs | 71 ++++ .../traits/trait-alias}/trait-alias-object.rs | 2 + .../trait-alias-syntax-fail.rs} | 0 .../trait-alias-syntax-fail.stderr} | 4 +- .../traits/trait-alias}/trait-alias-syntax.rs | 2 + .../{ => trait-alias}/trait-alias-wf.rs | 0 .../{ => trait-alias}/trait-alias-wf.stderr | 0 .../trait-alias}/trait-alias.rs | 1 + .../traits-static-outlives-a-where-clause.rs | 0 .../ui/traits/wf-trait-object-maybe-bound.rs | 13 + .../traits/wf-trait-object-maybe-bound.stderr | 8 + .../traits/wf-trait-object-no-duplicates.rs | 33 ++ .../wf-trait-object-no-duplicates.stderr | 43 ++ .../traits/wf-trait-object-reverse-order.rs | 15 + 38 files changed, 1259 insertions(+), 60 deletions(-) delete mode 100644 src/test/ui/traits/trait-alias-object.rs rename src/test/ui/traits/{ => trait-alias}/auxiliary/trait_alias.rs (100%) rename src/test/{run-pass/traits => ui/traits/trait-alias}/trait-alias-bounds.rs (98%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-cross-crate.rs (100%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-cross-crate.stderr (100%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-impl.rs (100%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-impl.stderr (100%) create mode 100644 src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs create mode 100644 src/test/ui/traits/trait-alias/trait-alias-maybe-bound.stderr create mode 100644 src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs create mode 100644 src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr create mode 100644 src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs create mode 100644 src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr create mode 100644 src/test/ui/traits/trait-alias/trait-alias-object-fail.rs rename src/test/ui/traits/{trait-alias-object.stderr => trait-alias/trait-alias-object-fail.stderr} (70%) create mode 100644 src/test/ui/traits/trait-alias/trait-alias-object-wf.rs rename src/test/{run-pass/traits => ui/traits/trait-alias}/trait-alias-object.rs (96%) rename src/test/ui/traits/{trait-alias-syntax.rs => trait-alias/trait-alias-syntax-fail.rs} (100%) rename src/test/ui/traits/{trait-alias-syntax.stderr => trait-alias/trait-alias-syntax-fail.stderr} (77%) rename src/test/{run-pass/traits => ui/traits/trait-alias}/trait-alias-syntax.rs (97%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-wf.rs (100%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-wf.stderr (100%) rename src/test/ui/{run-pass/traits => traits/trait-alias}/trait-alias.rs (98%) rename src/test/ui/{run-pass => }/traits/traits-static-outlives-a-where-clause.rs (100%) create mode 100644 src/test/ui/traits/wf-trait-object-maybe-bound.rs create mode 100644 src/test/ui/traits/wf-trait-object-maybe-bound.stderr create mode 100644 src/test/ui/traits/wf-trait-object-no-duplicates.rs create mode 100644 src/test/ui/traits/wf-trait-object-no-duplicates.stderr create mode 100644 src/test/ui/traits/wf-trait-object-reverse-order.rs diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr index ad0b6515490b..85724cb7c6e8 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr @@ -6,7 +6,7 @@ LL | let _: &I32Iterator = &vec![42].into_iter(); | = note: expected type `u32` found type `i32` - = note: required for the cast to the object type `dyn I32Iterator` + = note: required for the cast to the object type `dyn std::iter::Iterator` error: aborting due to previous error diff --git a/src/test/ui/bad/bad-sized.stderr b/src/test/ui/bad/bad-sized.stderr index 321f97541587..671840acdbfe 100644 --- a/src/test/ui/bad/bad-sized.stderr +++ b/src/test/ui/bad/bad-sized.stderr @@ -2,7 +2,9 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/bad-sized.rs:4:24 | LL | let x: Vec = Vec::new(); - | ^^^^^ non-auto additional trait + | ----- ^^^^^ additional non-auto trait + | | + | first non-auto trait error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time --> $DIR/bad-sized.rs:4:12 diff --git a/src/test/ui/error-codes/E0225.stderr b/src/test/ui/error-codes/E0225.stderr index c8d8f07db8ae..183cf0aad643 100644 --- a/src/test/ui/error-codes/E0225.stderr +++ b/src/test/ui/error-codes/E0225.stderr @@ -2,16 +2,20 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/E0225.rs:6:32 | LL | let _: Box; - | ^^^^^^^^^^^^^^ non-auto additional trait + | ------------- ^^^^^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/E0225.rs:8:16 | LL | trait Foo = std::io::Read + std::io::Write; - | -------------- non-auto additional trait + | ------------- -------------- additional non-auto trait + | | + | first non-auto trait ... LL | let _: Box; - | ^^^ expanded from this alias + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-22560.stderr b/src/test/ui/issues/issue-22560.stderr index 5a056dff590f..2c6f4d9d45f7 100644 --- a/src/test/ui/issues/issue-22560.stderr +++ b/src/test/ui/issues/issue-22560.stderr @@ -1,15 +1,15 @@ error[E0393]: the type parameter `Rhs` must be explicitly specified - --> $DIR/issue-22560.rs:3:13 + --> $DIR/issue-22560.rs:6:13 | -LL | type Test = Add + +LL | Sub; | ^^^ missing reference to `Rhs` | = note: because of the default `Self` reference, type parameters must be specified on object types error[E0393]: the type parameter `Rhs` must be explicitly specified - --> $DIR/issue-22560.rs:6:13 + --> $DIR/issue-22560.rs:3:13 | -LL | Sub; +LL | type Test = Add + | ^^^ missing reference to `Rhs` | = note: because of the default `Self` reference, type parameters must be specified on object types @@ -17,18 +17,26 @@ LL | Sub; error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/issue-22560.rs:6:13 | +LL | type Test = Add + + | --- first non-auto trait +... LL | Sub; - | ^^^ non-auto additional trait + | ^^^ additional non-auto trait -error[E0191]: the value of the associated type `Output` (from the trait `std::ops::Add`) must be specified +error[E0191]: the value of the associated types `Output` (from the trait `std::ops::Add`), `Output` (from the trait `std::ops::Sub`) must be specified --> $DIR/issue-22560.rs:3:13 | LL | type Test = Add + | _____________^ + | |_____________| + | | LL | | LL | | LL | | Sub; - | |_______________^ associated type `Output` must be specified + | | ^ + | |_______________| + | |_______________associated type `Output` must be specified + | associated type `Output` must be specified error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-32963.stderr b/src/test/ui/issues/issue-32963.stderr index 70fda313170d..381ccdbeb999 100644 --- a/src/test/ui/issues/issue-32963.stderr +++ b/src/test/ui/issues/issue-32963.stderr @@ -2,7 +2,9 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/issue-32963.rs:8:25 | LL | size_of_copy::(); - | ^^^^ non-auto additional trait + | ---- ^^^^ additional non-auto trait + | | + | first non-auto trait error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied --> $DIR/issue-32963.rs:8:5 diff --git a/src/test/ui/maybe-bounds.rs b/src/test/ui/maybe-bounds.rs index 3e07026fb7d7..7defd8d3943b 100644 --- a/src/test/ui/maybe-bounds.rs +++ b/src/test/ui/maybe-bounds.rs @@ -1,6 +1,6 @@ trait Tr: ?Sized {} //~ ERROR `?Trait` is not permitted in supertraits -type A1 = Tr + (?Sized); //~ ERROR `?Trait` is not permitted in trait object types -type A2 = for<'a> Tr + (?Sized); //~ ERROR `?Trait` is not permitted in trait object types +type A1 = Tr + (?Sized); +type A2 = for<'a> Tr + (?Sized); fn main() {} diff --git a/src/test/ui/maybe-bounds.stderr b/src/test/ui/maybe-bounds.stderr index 20446c257df0..d8c2adfc61c5 100644 --- a/src/test/ui/maybe-bounds.stderr +++ b/src/test/ui/maybe-bounds.stderr @@ -6,17 +6,5 @@ LL | trait Tr: ?Sized {} | = note: traits are `?Sized` by default -error: `?Trait` is not permitted in trait object types - --> $DIR/maybe-bounds.rs:3:16 - | -LL | type A1 = Tr + (?Sized); - | ^^^^^^^^ - -error: `?Trait` is not permitted in trait object types - --> $DIR/maybe-bounds.rs:4:24 - | -LL | type A2 = for<'a> Tr + (?Sized); - | ^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to previous error diff --git a/src/test/ui/parser/trait-object-trait-parens.rs b/src/test/ui/parser/trait-object-trait-parens.rs index 2bbc5800015b..49373564f673 100644 --- a/src/test/ui/parser/trait-object-trait-parens.rs +++ b/src/test/ui/parser/trait-object-trait-parens.rs @@ -4,9 +4,7 @@ fn f Trait<'a>)>() {} fn main() { let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>; - //~^ ERROR `?Trait` is not permitted in trait object types let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>; let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; - //~^ ERROR `?Trait` is not permitted in trait object types - //~| ERROR use of undeclared lifetime name `'a` + //~^ ERROR use of undeclared lifetime name `'a` } diff --git a/src/test/ui/parser/trait-object-trait-parens.stderr b/src/test/ui/parser/trait-object-trait-parens.stderr index 36494b765394..1cf40b30406c 100644 --- a/src/test/ui/parser/trait-object-trait-parens.stderr +++ b/src/test/ui/parser/trait-object-trait-parens.stderr @@ -1,21 +1,9 @@ -error: `?Trait` is not permitted in trait object types - --> $DIR/trait-object-trait-parens.rs:6:25 - | -LL | let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>; - | ^^^^^^^^ - -error: `?Trait` is not permitted in trait object types - --> $DIR/trait-object-trait-parens.rs:9:47 - | -LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; - | ^^^^^^^^ - error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/trait-object-trait-parens.rs:9:31 + --> $DIR/trait-object-trait-parens.rs:8:31 | LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; | ^^ undeclared lifetime -error: aborting due to 3 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/traits/trait-alias-object.rs b/src/test/ui/traits/trait-alias-object.rs deleted file mode 100644 index 379637401179..000000000000 --- a/src/test/ui/traits/trait-alias-object.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(trait_alias)] - -trait EqAlias = Eq; -trait IteratorAlias = Iterator; - -fn main() { - let _: &dyn EqAlias = &123; //~ ERROR `EqAlias` cannot be made into an object - let _: &dyn IteratorAlias = &vec![123].into_iter(); //~ ERROR must be specified -} diff --git a/src/test/ui/traits/auxiliary/trait_alias.rs b/src/test/ui/traits/trait-alias/auxiliary/trait_alias.rs similarity index 100% rename from src/test/ui/traits/auxiliary/trait_alias.rs rename to src/test/ui/traits/trait-alias/auxiliary/trait_alias.rs diff --git a/src/test/run-pass/traits/trait-alias-bounds.rs b/src/test/ui/traits/trait-alias/trait-alias-bounds.rs similarity index 98% rename from src/test/run-pass/traits/trait-alias-bounds.rs rename to src/test/ui/traits/trait-alias/trait-alias-bounds.rs index d3dd5cee0c33..428ce5102bad 100644 --- a/src/test/run-pass/traits/trait-alias-bounds.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-bounds.rs @@ -1,3 +1,5 @@ +// run-pass + #![feature(trait_alias)] use std::marker::PhantomData; diff --git a/src/test/ui/traits/trait-alias-cross-crate.rs b/src/test/ui/traits/trait-alias/trait-alias-cross-crate.rs similarity index 100% rename from src/test/ui/traits/trait-alias-cross-crate.rs rename to src/test/ui/traits/trait-alias/trait-alias-cross-crate.rs diff --git a/src/test/ui/traits/trait-alias-cross-crate.stderr b/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr similarity index 100% rename from src/test/ui/traits/trait-alias-cross-crate.stderr rename to src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr diff --git a/src/test/ui/traits/trait-alias-impl.rs b/src/test/ui/traits/trait-alias/trait-alias-impl.rs similarity index 100% rename from src/test/ui/traits/trait-alias-impl.rs rename to src/test/ui/traits/trait-alias/trait-alias-impl.rs diff --git a/src/test/ui/traits/trait-alias-impl.stderr b/src/test/ui/traits/trait-alias/trait-alias-impl.stderr similarity index 100% rename from src/test/ui/traits/trait-alias-impl.stderr rename to src/test/ui/traits/trait-alias/trait-alias-impl.stderr diff --git a/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs new file mode 100644 index 000000000000..f444dba5d289 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs @@ -0,0 +1,27 @@ +// Test that `dyn ... + ?Sized + ...` resulting from the expansion of trait aliases is okay. + +#![feature(trait_alias)] + +trait S = ?Sized; + +// Nest a couple of levels deep: +trait _0 = S; +trait _1 = _0; + +// Straight list expansion: +type _T0 = dyn _1; +//~^ ERROR at least one non-builtin trait is required for an object type [E0224] + +// In second position: +type _T1 = dyn Copy + _1; + +// ... and with an auto trait: +type _T2 = dyn Copy + Send + _1; + +// Twice: +trait _2 = _1 + _1; + +type _T3 = dyn _2; +//~^ ERROR at least one non-builtin trait is required for an object type [E0224] + +fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.stderr b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.stderr new file mode 100644 index 000000000000..52e90c00c374 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.stderr @@ -0,0 +1,14 @@ +error[E0224]: at least one non-builtin trait is required for an object type + --> $DIR/trait-alias-maybe-bound.rs:12:12 + | +LL | type _T0 = dyn _1; + | ^^^^^^ + +error[E0224]: at least one non-builtin trait is required for an object type + --> $DIR/trait-alias-maybe-bound.rs:24:12 + | +LL | type _T3 = dyn _2; + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs new file mode 100644 index 000000000000..95525883c643 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs @@ -0,0 +1,126 @@ +// The purpose of this test is to demonstrate that duplicating object safe traits +// that are not auto traits is rejected with trait aliases even though one could +// reasonably accept this. + +#![feature(trait_alias)] + +use std::marker::Unpin; + +// Some arbitray object-safe trait: +trait Obj {} + +// Nest a few levels deep: +trait _0 = Obj; +trait _1 = _0; + +type _T00 = dyn _0 + _0; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T01 = dyn _1 + _0; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T02 = dyn _1 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T03 = dyn Obj + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T04 = dyn _1 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more and in weird ways: + +trait _2 = _0 + _1; +trait _3 = Obj; +trait _4 = _3; + +type _T10 = dyn _2 + _3; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T11 = dyn _3 + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T12 = dyn Obj + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T13 = dyn _2 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T14 = dyn _1 + _3; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T15 = dyn _3 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T16 = dyn _1 + _4; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T17 = dyn _4 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Include auto traits: + +trait _5 = Obj + Send; + +type _T20 = dyn _5 + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T21 = dyn Obj + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T22 = dyn _5 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T23 = dyn _5 + Send + Sync + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Also nest: + +trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + +type _T30 = dyn _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T31 = dyn _6 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T32 = dyn Send + _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more: + +trait _7 = _5 + Sync; +trait _8 = Unpin + _7; + +type _T40 = dyn _8 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T41 = dyn Obj + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T42 = dyn _8 + _4; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T43 = dyn _4 + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T44 = dyn _4 + Send + Sync + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Take higher ranked types into account. + +// Note that `'a` and `'b` are intentionally different to make sure we consider +// them semantically the same. +trait ObjL<'l> {} +trait _9 = for<'a> ObjL<'a>; +trait _10 = for<'b> ObjL<'b>; +type _T50 = _9 + _10; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +trait ObjT {} +trait _11 = ObjT fn(&'a u8)>; +trait _12 = ObjT fn(&'b u8)>; +type _T60 = _11 + _12; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr new file mode 100644 index 000000000000..3cdf1582ab9c --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr @@ -0,0 +1,358 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:16:22 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | type _T00 = dyn _0 + _0; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:19:22 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | type _T01 = dyn _1 + _0; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:22:22 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | type _T02 = dyn _1 + _1; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:25:23 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | type _T03 = dyn Obj + _1; + | --- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:28:22 + | +LL | trait _0 = Obj; + | --- first non-auto trait +... +LL | type _T04 = dyn _1 + Obj; + | ^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:37:17 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _2 = _0 + _1; + | -- referenced here +... +LL | type _T10 = dyn _2 + _3; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:40:22 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +... +LL | trait _2 = _0 + _1; + | -- referenced here +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | type _T11 = dyn _3 + _2; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:43:23 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +... +LL | trait _2 = _0 + _1; + | -- referenced here +... +LL | type _T12 = dyn Obj + _2; + | --- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:46:17 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _2 = _0 + _1; + | -- referenced here +... +LL | type _T13 = dyn _2 + Obj; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:49:22 + | +LL | trait _0 = Obj; + | --- first non-auto trait +... +LL | trait _3 = Obj; + | --- additional non-auto trait +... +LL | type _T14 = dyn _1 + _3; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:52:22 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | type _T15 = dyn _3 + _1; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:55:22 + | +LL | trait _0 = Obj; + | --- first non-auto trait +... +LL | trait _3 = Obj; + | --- additional non-auto trait +LL | trait _4 = _3; + | -- referenced here +... +LL | type _T16 = dyn _1 + _4; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:58:22 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | type _T17 = dyn _4 + _1; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:65:22 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | +LL | type _T20 = dyn _5 + _5; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:68:23 + | +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | type _T21 = dyn Obj + _5; + | --- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:71:22 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T22 = dyn _5 + Obj; + | ^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:74:36 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T23 = dyn _5 + Send + Sync + Obj; + | ^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:81:17 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- referenced here +LL | +LL | type _T30 = dyn _6; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:84:17 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- referenced here +... +LL | type _T31 = dyn _6 + Send; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:87:24 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- referenced here +... +LL | type _T32 = dyn Send + _6; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:95:22 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T40 = dyn _8 + Obj; + | ^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:98:23 + | +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here +LL | trait _8 = Unpin + _7; + | -- referenced here +... +LL | type _T41 = dyn Obj + _8; + | --- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:101:22 + | +LL | trait _3 = Obj; + | --- additional non-auto trait +LL | trait _4 = _3; + | -- referenced here +... +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T42 = dyn _8 + _4; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:104:22 + | +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here +LL | trait _8 = Unpin + _7; + | -- referenced here +... +LL | type _T43 = dyn _4 + _8; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:107:36 + | +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here +LL | trait _8 = Unpin + _7; + | -- referenced here +... +LL | type _T44 = dyn _4 + Send + Sync + _8; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:117:18 + | +LL | trait _9 = for<'a> ObjL<'a>; + | ---------------- first non-auto trait +LL | trait _10 = for<'b> ObjL<'b>; + | ---------------- additional non-auto trait +LL | type _T50 = _9 + _10; + | ^^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:123:19 + | +LL | trait _11 = ObjT fn(&'a u8)>; + | ------------------------ first non-auto trait +LL | trait _12 = ObjT fn(&'b u8)>; + | ------------------------ additional non-auto trait +LL | type _T60 = _11 + _12; + | ^^^ + +error: aborting due to 27 previous errors + +For more information about this error, try `rustc --explain E0225`. diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs new file mode 100644 index 000000000000..54c177f0db80 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs @@ -0,0 +1,121 @@ +// The purpose of this test is to demonstrate that trait alias expansion +// preserves the rule that `dyn Trait` may only reference one non-auto trait. + +#![feature(trait_alias)] + +use std::marker::Unpin; + +// Some arbitray object-safe traits: +trait ObjA {} +trait ObjB {} + +// Nest a few levels deep: +trait _0 = ObjA; +trait _1 = _0; + +type _T00 = dyn _0 + ObjB; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T01 = dyn ObjB + _0; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T02 = dyn ObjB + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T03 = dyn _1 + ObjB; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more and in weird ways: + +trait _2 = ObjB; +trait _3 = _2; +trait _4 = _3; + +type _T10 = dyn _2 + _3; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T11 = dyn _3 + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T12 = dyn _2 + _4; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T13 = dyn _4 + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Include auto traits: + +trait _5 = Sync + ObjB + Send; + +type _T20 = dyn _5 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T21 = dyn _1 + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T22 = dyn _5 + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T23 = dyn ObjA + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T24 = dyn Send + _5 + _1 + Sync; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T25 = dyn _1 + Sync + _5 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T26 = dyn Sync + Send + _5 + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T27 = dyn Send + Sync + ObjA + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Also nest: + +trait _6 = _1 + _5; +trait _7 = _6; +trait _8 = _7; + +type _T30 = dyn _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T31 = dyn _6 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T32 = dyn Send + _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T33 = dyn _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T34 = dyn _8 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T35 = dyn Send + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more: + +trait _9 = _5 + Sync; +trait _10 = Unpin + _9; + +type _T40 = dyn _10 + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T41 = dyn ObjA + _10; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T42 = dyn _10 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T43 = dyn Send + _10 + Sync + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T44 = dyn ObjA + _10 + Send + Sync; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T45 = dyn Sync + Send + _10 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr new file mode 100644 index 000000000000..d73667a07097 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr @@ -0,0 +1,371 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:16:22 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | type _T00 = dyn _0 + ObjB; + | ^^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:19:24 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +... +LL | type _T01 = dyn ObjB + _0; + | ---- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:22:24 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | type _T02 = dyn ObjB + _1; + | ---- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:25:22 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | type _T03 = dyn _1 + ObjB; + | ^^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:34:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- referenced here +... +LL | type _T10 = dyn _2 + _3; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:37:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +... +LL | type _T11 = dyn _3 + _2; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:40:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- referenced here +LL | trait _4 = _3; + | -- referenced here +... +LL | type _T12 = dyn _2 + _4; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:43:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +... +LL | type _T13 = dyn _4 + _2; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:50:22 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +LL | +LL | type _T20 = dyn _5 + _1; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:53:22 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T21 = dyn _1 + _5; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:56:22 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T22 = dyn _5 + ObjA; + | ^^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:59:24 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T23 = dyn ObjA + _5; + | ---- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:62:29 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T24 = dyn Send + _5 + _1 + Sync; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:65:29 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T25 = dyn _1 + Sync + _5 + Send; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:68:36 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T26 = dyn Sync + Send + _5 + ObjA; + | ^^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:71:38 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T27 = dyn Send + Sync + ObjA + _5; + | ---- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:80:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- referenced here +... +LL | type _T30 = dyn _6; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:83:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- referenced here +... +LL | type _T31 = dyn _6 + Send; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:86:24 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- referenced here +... +LL | type _T32 = dyn Send + _6; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:89:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- referenced here +LL | trait _7 = _6; + | -- referenced here +LL | trait _8 = _7; + | -- referenced here +... +LL | type _T33 = dyn _8; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:92:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- referenced here +LL | trait _7 = _6; + | -- referenced here +LL | trait _8 = _7; + | -- referenced here +... +LL | type _T34 = dyn _8 + Send; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:95:24 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- referenced here +LL | trait _7 = _6; + | -- referenced here +LL | trait _8 = _7; + | -- referenced here +... +LL | type _T35 = dyn Send + _8; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:103:23 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T40 = dyn _10 + ObjA; + | ^^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:106:24 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here +LL | trait _10 = Unpin + _9; + | -- referenced here +... +LL | type _T41 = dyn ObjA + _10; + | ---- ^^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:109:23 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T42 = dyn _10 + _1; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:112:37 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T43 = dyn Send + _10 + Sync + ObjA; + | ^^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:115:24 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here +LL | trait _10 = Unpin + _9; + | -- referenced here +... +LL | type _T44 = dyn ObjA + _10 + Send + Sync; + | ---- ^^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:118:37 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T45 = dyn Sync + Send + _10 + _1; + | ^^ + +error: aborting due to 28 previous errors + +For more information about this error, try `rustc --explain E0225`. diff --git a/src/test/ui/traits/trait-alias/trait-alias-object-fail.rs b/src/test/ui/traits/trait-alias/trait-alias-object-fail.rs new file mode 100644 index 000000000000..d62fd7e59c92 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-object-fail.rs @@ -0,0 +1,11 @@ +#![feature(trait_alias)] + +trait EqAlias = Eq; +trait IteratorAlias = Iterator; + +fn main() { + let _: &dyn EqAlias = &123; + //~^ ERROR the trait `std::cmp::Eq` cannot be made into an object [E0038] + let _: &dyn IteratorAlias = &vec![123].into_iter(); + //~^ ERROR must be specified +} diff --git a/src/test/ui/traits/trait-alias-object.stderr b/src/test/ui/traits/trait-alias/trait-alias-object-fail.stderr similarity index 70% rename from src/test/ui/traits/trait-alias-object.stderr rename to src/test/ui/traits/trait-alias/trait-alias-object-fail.stderr index 353aea311e90..9a9b91770308 100644 --- a/src/test/ui/traits/trait-alias-object.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-object-fail.stderr @@ -1,13 +1,13 @@ -error[E0038]: the trait `EqAlias` cannot be made into an object - --> $DIR/trait-alias-object.rs:7:13 +error[E0038]: the trait `std::cmp::Eq` cannot be made into an object + --> $DIR/trait-alias-object-fail.rs:7:13 | LL | let _: &dyn EqAlias = &123; - | ^^^^^^^^^^^ the trait `EqAlias` cannot be made into an object + | ^^^^^^^^^^^ the trait `std::cmp::Eq` cannot be made into an object | = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses error[E0191]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified - --> $DIR/trait-alias-object.rs:8:13 + --> $DIR/trait-alias-object-fail.rs:9:13 | LL | let _: &dyn IteratorAlias = &vec![123].into_iter(); | ^^^^^^^^^^^^^^^^^ associated type `Item` must be specified diff --git a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs new file mode 100644 index 000000000000..6383e8b6e10f --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs @@ -0,0 +1,71 @@ +// run-pass + +// This test checks that trait objects involving trait aliases are well-formed. + +#![feature(trait_alias)] + +trait Obj {} + +trait _0 = Send + Sync; + +// Just auto traits: + +trait _1 = _0 + Send + Sync; + +use std::marker::Unpin; + +type _T01 = dyn _0; +type _T02 = dyn _1; +type _T03 = dyn Unpin + _1 + Send + Sync; + +// Include object safe traits: + +type _T10 = dyn Obj + _0; +type _T11 = dyn Obj + _1; +type _T12 = dyn Obj + _1 + _0; + +// And when the object safe trait is in a trait alias: + +trait _2 = Obj; + +type _T20 = dyn _2 + _0; +type _T21 = dyn _2 + _1; +type _T22 = dyn _2 + _1 + _0; + +// And it should also work when that trait is has auto traits to the right of it. + +trait _3 = Obj + Unpin; + +type _T30 = dyn _3 + _0; +type _T31 = dyn _3 + _1; +type _T32 = dyn _3 + _1 + _0; + +// Nest the trait deeply: + +trait _4 = _3; +trait _5 = _4 + Sync + _0 + Send; +trait _6 = _5 + Send + _1 + Sync; + +type _T60 = dyn _6 + _0; +type _T61 = dyn _6 + _1; +type _T62 = dyn _6 + _1 + _0; + +// Just nest the trait alone: + +trait _7 = _2; +trait _8 = _7; +trait _9 = _8; + +type _T9 = dyn _9; + +// First bound is auto trait: + +trait _10 = Send + Obj; +trait _11 = Obj + Send; +trait _12 = Sync + _11; +trait _13 = Send + _12; + +type _T70 = dyn _0; +type _T71 = dyn _3; + +fn main() {} diff --git a/src/test/run-pass/traits/trait-alias-object.rs b/src/test/ui/traits/trait-alias/trait-alias-object.rs similarity index 96% rename from src/test/run-pass/traits/trait-alias-object.rs rename to src/test/ui/traits/trait-alias/trait-alias-object.rs index 1cf9e34edf30..12177cd827fd 100644 --- a/src/test/run-pass/traits/trait-alias-object.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-object.rs @@ -1,3 +1,5 @@ +// run-pass + #![feature(trait_alias)] trait Foo = PartialEq + Send; diff --git a/src/test/ui/traits/trait-alias-syntax.rs b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.rs similarity index 100% rename from src/test/ui/traits/trait-alias-syntax.rs rename to src/test/ui/traits/trait-alias/trait-alias-syntax-fail.rs diff --git a/src/test/ui/traits/trait-alias-syntax.stderr b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr similarity index 77% rename from src/test/ui/traits/trait-alias-syntax.stderr rename to src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr index f99cc45d8ae9..f456a2d778c2 100644 --- a/src/test/ui/traits/trait-alias-syntax.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr @@ -1,11 +1,11 @@ error: trait aliases cannot be `auto` - --> $DIR/trait-alias-syntax.rs:4:19 + --> $DIR/trait-alias-syntax-fail.rs:4:19 | LL | auto trait A = Foo; | ^ trait aliases cannot be `auto` error: trait aliases cannot be `unsafe` - --> $DIR/trait-alias-syntax.rs:5:21 + --> $DIR/trait-alias-syntax-fail.rs:5:21 | LL | unsafe trait B = Foo; | ^ trait aliases cannot be `unsafe` diff --git a/src/test/run-pass/traits/trait-alias-syntax.rs b/src/test/ui/traits/trait-alias/trait-alias-syntax.rs similarity index 97% rename from src/test/run-pass/traits/trait-alias-syntax.rs rename to src/test/ui/traits/trait-alias/trait-alias-syntax.rs index 7cdd9184d3f5..17557a51aa72 100644 --- a/src/test/run-pass/traits/trait-alias-syntax.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-syntax.rs @@ -1,3 +1,5 @@ +// run-pass + #![feature(trait_alias)] trait SimpleAlias = Default; diff --git a/src/test/ui/traits/trait-alias-wf.rs b/src/test/ui/traits/trait-alias/trait-alias-wf.rs similarity index 100% rename from src/test/ui/traits/trait-alias-wf.rs rename to src/test/ui/traits/trait-alias/trait-alias-wf.rs diff --git a/src/test/ui/traits/trait-alias-wf.stderr b/src/test/ui/traits/trait-alias/trait-alias-wf.stderr similarity index 100% rename from src/test/ui/traits/trait-alias-wf.stderr rename to src/test/ui/traits/trait-alias/trait-alias-wf.stderr diff --git a/src/test/ui/run-pass/traits/trait-alias.rs b/src/test/ui/traits/trait-alias/trait-alias.rs similarity index 98% rename from src/test/ui/run-pass/traits/trait-alias.rs rename to src/test/ui/traits/trait-alias/trait-alias.rs index 9be5664869e0..d8168f2990c4 100644 --- a/src/test/ui/run-pass/traits/trait-alias.rs +++ b/src/test/ui/traits/trait-alias/trait-alias.rs @@ -1,4 +1,5 @@ // run-pass + #![feature(trait_alias)] pub trait Foo {} diff --git a/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs b/src/test/ui/traits/traits-static-outlives-a-where-clause.rs similarity index 100% rename from src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs rename to src/test/ui/traits/traits-static-outlives-a-where-clause.rs diff --git a/src/test/ui/traits/wf-trait-object-maybe-bound.rs b/src/test/ui/traits/wf-trait-object-maybe-bound.rs new file mode 100644 index 000000000000..68f0155faf9b --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-maybe-bound.rs @@ -0,0 +1,13 @@ +// The purpose of this test is to demonstrate that `?Sized` is allowed in trait objects +// (thought it has no effect). + +type _0 = dyn ?Sized; +//~^ ERROR at least one non-builtin trait is required for an object type [E0224] + +type _1 = dyn Clone + ?Sized; + +type _2 = dyn Clone + ?Sized + ?Sized; + +type _3 = dyn ?Sized + Clone; + +fn main() {} diff --git a/src/test/ui/traits/wf-trait-object-maybe-bound.stderr b/src/test/ui/traits/wf-trait-object-maybe-bound.stderr new file mode 100644 index 000000000000..ba24b8342118 --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-maybe-bound.stderr @@ -0,0 +1,8 @@ +error[E0224]: at least one non-builtin trait is required for an object type + --> $DIR/wf-trait-object-maybe-bound.rs:4:11 + | +LL | type _0 = dyn ?Sized; + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/traits/wf-trait-object-no-duplicates.rs b/src/test/ui/traits/wf-trait-object-no-duplicates.rs new file mode 100644 index 000000000000..dd6d73619bce --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-no-duplicates.rs @@ -0,0 +1,33 @@ +// The purpose of this test is to demonstrate that duplicating object safe traits +// that are not auto-traits is rejected even though one could reasonably accept this. + +// Some arbitray object-safe trait: +trait Obj {} + +// Demonstrate that recursive expansion of trait aliases doesn't affect stable behavior: +type _0 = dyn Obj + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Some variations: + +type _1 = dyn Send + Obj + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _2 = dyn Obj + Send + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _3 = dyn Obj + Send + Send; // But it is OK to duplicate auto traits. + +// Take higher ranked types into account. + +// Note that `'a` and `'b` are intentionally different to make sure we consider +// them semantically the same. +trait ObjL<'l> {} +type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +trait ObjT {} +type _5 = dyn ObjT fn(&'a u8)> + ObjT fn(&'b u8)>; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +fn main() {} diff --git a/src/test/ui/traits/wf-trait-object-no-duplicates.stderr b/src/test/ui/traits/wf-trait-object-no-duplicates.stderr new file mode 100644 index 000000000000..75dacb2e1565 --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-no-duplicates.stderr @@ -0,0 +1,43 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/wf-trait-object-no-duplicates.rs:8:21 + | +LL | type _0 = dyn Obj + Obj; + | --- ^^^ additional non-auto trait + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/wf-trait-object-no-duplicates.rs:13:28 + | +LL | type _1 = dyn Send + Obj + Obj; + | --- ^^^ additional non-auto trait + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/wf-trait-object-no-duplicates.rs:16:28 + | +LL | type _2 = dyn Obj + Send + Obj; + | --- ^^^ additional non-auto trait + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/wf-trait-object-no-duplicates.rs:26:34 + | +LL | type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>; + | ---------------- ^^^^^^^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/wf-trait-object-no-duplicates.rs:30:42 + | +LL | type _5 = dyn ObjT fn(&'a u8)> + ObjT fn(&'b u8)>; + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0225`. diff --git a/src/test/ui/traits/wf-trait-object-reverse-order.rs b/src/test/ui/traits/wf-trait-object-reverse-order.rs new file mode 100644 index 000000000000..f9c584ace5b2 --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-reverse-order.rs @@ -0,0 +1,15 @@ +// run-pass + +// Ensure that `dyn $($AutoTrait) + ObjSafe` is well-formed. + +use std::marker::Unpin; + +// Some arbitray object-safe trait: +trait Obj {} + +type _0 = Unpin; +type _1 = Send + Obj; +type _2 = Send + Unpin + Obj; +type _3 = Send + Unpin + Sync + Obj; + +fn main() {} From 20096628c6ce13654e79970b8c56baf1efcbff8e Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Thu, 2 May 2019 02:21:20 +0100 Subject: [PATCH 08/12] Addressed points raised in review. --- src/librustc/traits/util.rs | 33 ++++++++---- src/librustc_typeck/astconv.rs | 11 ++-- src/test/ui/error-codes/E0225.rs | 4 +- src/test/ui/maybe-bounds.rs | 4 +- .../trait-alias/trait-alias-maybe-bound.rs | 14 ++--- .../trait-alias/trait-alias-no-duplicates.rs | 2 +- .../trait-alias-no-extra-traits.rs | 2 +- .../trait-alias/trait-alias-object-wf.rs | 52 ++++++++++++------- .../trait-alias-only-maybe-bound.rs | 22 ++++++++ ...rr => trait-alias-only-maybe-bound.stderr} | 0 .../ui/traits/wf-trait-object-maybe-bound.rs | 16 +++--- .../traits/wf-trait-object-no-duplicates.rs | 2 +- .../wf-trait-object-only-maybe-bound.rs | 6 +++ ...> wf-trait-object-only-maybe-bound.stderr} | 0 .../traits/wf-trait-object-reverse-order.rs | 12 ++--- 15 files changed, 119 insertions(+), 61 deletions(-) create mode 100644 src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.rs rename src/test/ui/traits/trait-alias/{trait-alias-maybe-bound.stderr => trait-alias-only-maybe-bound.stderr} (100%) create mode 100644 src/test/ui/traits/wf-trait-object-only-maybe-bound.rs rename src/test/ui/traits/{wf-trait-object-maybe-bound.stderr => wf-trait-object-only-maybe-bound.stderr} (100%) diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index d765827e3d56..4e5aa6b915b5 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -56,6 +56,7 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { } fn contains(&mut self, pred: &ty::Predicate<'tcx>) -> bool { + // See the `insert` method for why we use `anonymize_predicate` here. self.set.contains(&anonymize_predicate(self.tcx, pred)) } @@ -74,13 +75,14 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { } fn remove(&mut self, pred: &ty::Predicate<'tcx>) -> bool { + // See the `insert` method for why we use `anonymize_predicate` here. self.set.remove(&anonymize_predicate(self.tcx, pred)) } } impl<'a, 'gcx, 'tcx, T: AsRef>> Extend for PredicateSet<'a, 'gcx, 'tcx> { fn extend>(&mut self, iter: I) { - for pred in iter.into_iter() { + for pred in iter { self.insert(pred.as_ref()); } } @@ -289,30 +291,33 @@ pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>, /// `trait Foo = Bar + Sync;`, and another trait alias /// `trait Bar = Read + Write`, then the bounds would expand to /// `Read + Write + Sync + Send`. +/// Expansion is done via a DFS (depth-first search), and the `visited` field +/// is used to avoid cycles. pub struct TraitAliasExpander<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { stack: Vec>, /// The set of predicates visited from the root directly to the current point in the - /// expansion tree. + /// expansion tree (only containing trait aliases). visited: PredicateSet<'a, 'gcx, 'tcx>, } +/// Stores information about the expansion of a trait via a path of zero or more trait aliases. #[derive(Debug, Clone)] pub struct TraitAliasExpansionInfo<'tcx> { pub items: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, } impl<'tcx> TraitAliasExpansionInfo<'tcx> { - fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> TraitAliasExpansionInfo<'tcx> { - TraitAliasExpansionInfo { + fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { + Self { items: smallvec![(trait_ref, span)] } } - fn push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> TraitAliasExpansionInfo<'tcx> { + fn push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { let mut items = self.items.clone(); items.push((trait_ref, span)); - TraitAliasExpansionInfo { + Self { items } } @@ -330,6 +335,8 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> { } } +/// 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>, @@ -365,10 +372,10 @@ pub fn expand_trait_aliases<'cx, 'gcx, 'tcx>( impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> { /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item` - /// to the definition and pushes the resulting expansion onto `self.stack`, and returns `false`. - /// Otherwise, immediately returns `true` if `item` is a regular trait and `false` if it is a + /// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`. + /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a /// trait alias. - /// The return value indicates whether `item` should not be yielded to the user. + /// The return value indicates whether `item` should be yielded to the user. fn push(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { let tcx = self.visited.tcx; let trait_ref = item.trait_ref(); @@ -376,13 +383,17 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> { debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); - self.visited.remove(&pred); - + // Don't recurse unless this bound is a trait alias and isn't currently in the DFS stack of + // already-visited predicates. let is_alias = tcx.is_trait_alias(trait_ref.def_id()); if !is_alias || self.visited.contains(&pred) { return !is_alias; } + // Remove the current predicate from the stack of already-visited ones, since we're doing + // a DFS. + self.visited.remove(&pred); + // Get components of trait alias. let predicates = tcx.super_predicates_of(trait_ref.def_id()); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 428fa66101ac..31aba9ed239c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -996,11 +996,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { 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.bottom().1, E0225, - "only auto traits can be used as additional traits in a trait object"); - err.label_with_exp_info(extra_trait, "additional non-auto trait"); - err.span_label(regular_traits[0].top().1, "first non-auto trait"); - err.emit(); + struct_span_err!(tcx.sess, extra_trait.bottom().1, E0225, + "only auto traits can be used as additional traits in a trait object" + ) + .label_with_exp_info(extra_trait, "additional non-auto trait") + .span_label(regular_traits[0].top().1, "first non-auto trait") + .emit(); } if regular_traits.is_empty() && auto_traits.is_empty() { diff --git a/src/test/ui/error-codes/E0225.rs b/src/test/ui/error-codes/E0225.rs index e3ac680f4415..b50f68e64516 100644 --- a/src/test/ui/error-codes/E0225.rs +++ b/src/test/ui/error-codes/E0225.rs @@ -3,8 +3,8 @@ trait Foo = std::io::Read + std::io::Write; fn main() { - let _: Box; + let _: Box; //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] - let _: Box; + let _: Box; //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] } diff --git a/src/test/ui/maybe-bounds.rs b/src/test/ui/maybe-bounds.rs index 7defd8d3943b..95d14f6d1da3 100644 --- a/src/test/ui/maybe-bounds.rs +++ b/src/test/ui/maybe-bounds.rs @@ -1,6 +1,6 @@ trait Tr: ?Sized {} //~ ERROR `?Trait` is not permitted in supertraits -type A1 = Tr + (?Sized); -type A2 = for<'a> Tr + (?Sized); +type A1 = dyn Tr + (?Sized); +type A2 = dyn for<'a> Tr + (?Sized); fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs index f444dba5d289..3dfcf03ce79d 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs @@ -1,7 +1,11 @@ +// compile-pass + // Test that `dyn ... + ?Sized + ...` resulting from the expansion of trait aliases is okay. #![feature(trait_alias)] +trait Foo {} + trait S = ?Sized; // Nest a couple of levels deep: @@ -9,19 +13,17 @@ trait _0 = S; trait _1 = _0; // Straight list expansion: -type _T0 = dyn _1; -//~^ ERROR at least one non-builtin trait is required for an object type [E0224] +type _T0 = dyn _1 + Foo; // In second position: -type _T1 = dyn Copy + _1; +type _T1 = dyn Foo + _1; // ... and with an auto trait: -type _T2 = dyn Copy + Send + _1; +type _T2 = dyn Foo + Send + _1; // Twice: trait _2 = _1 + _1; -type _T3 = dyn _2; -//~^ ERROR at least one non-builtin trait is required for an object type [E0224] +type _T3 = dyn _2 + Foo; fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs index 95525883c643..afd8400e2305 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs @@ -6,7 +6,7 @@ use std::marker::Unpin; -// Some arbitray object-safe trait: +// Some arbitrary object-safe trait: trait Obj {} // Nest a few levels deep: diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs index 54c177f0db80..4dad8c0f8734 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs @@ -5,7 +5,7 @@ use std::marker::Unpin; -// Some arbitray object-safe traits: +// Some arbitrary object-safe traits: trait ObjA {} trait ObjB {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs index 6383e8b6e10f..f7c410c6362f 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs @@ -1,6 +1,6 @@ // run-pass -// This test checks that trait objects involving trait aliases are well-formed. +// This test hecks that trait objects involving trait aliases are well-formed. #![feature(trait_alias)] @@ -14,31 +14,39 @@ trait _1 = _0 + Send + Sync; use std::marker::Unpin; -type _T01 = dyn _0; -type _T02 = dyn _1; -type _T03 = dyn Unpin + _1 + Send + Sync; +fn _f0() { + let _: Box; + let _: Box; + let _: Box; +} // Include object safe traits: -type _T10 = dyn Obj + _0; -type _T11 = dyn Obj + _1; -type _T12 = dyn Obj + _1 + _0; +fn _f1() { + let _: Box; + let _: Box; + let _: Box; +} // And when the object safe trait is in a trait alias: trait _2 = Obj; -type _T20 = dyn _2 + _0; -type _T21 = dyn _2 + _1; -type _T22 = dyn _2 + _1 + _0; +fn _f2() { + let _: Box; + let _: Box; + let _: Box; +} // And it should also work when that trait is has auto traits to the right of it. trait _3 = Obj + Unpin; -type _T30 = dyn _3 + _0; -type _T31 = dyn _3 + _1; -type _T32 = dyn _3 + _1 + _0; +fn _f3() { + let _: Box; + let _: Box; + let _: Box; +} // Nest the trait deeply: @@ -46,9 +54,11 @@ trait _4 = _3; trait _5 = _4 + Sync + _0 + Send; trait _6 = _5 + Send + _1 + Sync; -type _T60 = dyn _6 + _0; -type _T61 = dyn _6 + _1; -type _T62 = dyn _6 + _1 + _0; +fn _f4() { + let _: Box; + let _: Box; + let _: Box; +} // Just nest the trait alone: @@ -56,7 +66,9 @@ trait _7 = _2; trait _8 = _7; trait _9 = _8; -type _T9 = dyn _9; +fn _f5() { + let _: Box; +} // First bound is auto trait: @@ -65,7 +77,9 @@ trait _11 = Obj + Send; trait _12 = Sync + _11; trait _13 = Send + _12; -type _T70 = dyn _0; -type _T71 = dyn _3; +fn f6() { + let _: Box; + let _: Box; +} fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.rs b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.rs new file mode 100644 index 000000000000..d6c611d2a4d9 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.rs @@ -0,0 +1,22 @@ +// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed, when just +// `?Sized` results from trait alias expansion. + +#![feature(trait_alias)] + +trait S = ?Sized; + +// Nest a couple of levels deep: +trait _0 = S; +trait _1 = _0; + +// Straight list expansion: +type _T0 = dyn _1; +//~^ ERROR at least one non-builtin trait is required for an object type [E0224] + +// Twice: +trait _2 = _1 + _1; + +type _T1 = dyn _2; +//~^ ERROR at least one non-builtin trait is required for an object type [E0224] + +fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.stderr b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr similarity index 100% rename from src/test/ui/traits/trait-alias/trait-alias-maybe-bound.stderr rename to src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr diff --git a/src/test/ui/traits/wf-trait-object-maybe-bound.rs b/src/test/ui/traits/wf-trait-object-maybe-bound.rs index 68f0155faf9b..405104fe0814 100644 --- a/src/test/ui/traits/wf-trait-object-maybe-bound.rs +++ b/src/test/ui/traits/wf-trait-object-maybe-bound.rs @@ -1,13 +1,15 @@ -// The purpose of this test is to demonstrate that `?Sized` is allowed in trait objects -// (thought it has no effect). +// compile-pass -type _0 = dyn ?Sized; -//~^ ERROR at least one non-builtin trait is required for an object type [E0224] +// Test that `dyn ... + ?Sized + ...` is okay (though `?Sized` has no effect in trait objects). -type _1 = dyn Clone + ?Sized; +trait Foo {} -type _2 = dyn Clone + ?Sized + ?Sized; +type _0 = dyn ?Sized + Foo; -type _3 = dyn ?Sized + Clone; +type _1 = dyn Foo + ?Sized; + +type _2 = dyn Foo + ?Sized + ?Sized; + +type _3 = dyn ?Sized + Foo; fn main() {} diff --git a/src/test/ui/traits/wf-trait-object-no-duplicates.rs b/src/test/ui/traits/wf-trait-object-no-duplicates.rs index dd6d73619bce..678ede58296a 100644 --- a/src/test/ui/traits/wf-trait-object-no-duplicates.rs +++ b/src/test/ui/traits/wf-trait-object-no-duplicates.rs @@ -1,7 +1,7 @@ // The purpose of this test is to demonstrate that duplicating object safe traits // that are not auto-traits is rejected even though one could reasonably accept this. -// Some arbitray object-safe trait: +// Some arbitrary object-safe trait: trait Obj {} // Demonstrate that recursive expansion of trait aliases doesn't affect stable behavior: diff --git a/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs b/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs new file mode 100644 index 000000000000..c8e6ac38b5a3 --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs @@ -0,0 +1,6 @@ +// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed. + +type _0 = dyn ?Sized; +//~^ ERROR at least one non-builtin trait is required for an object type [E0224] + +fn main() {} diff --git a/src/test/ui/traits/wf-trait-object-maybe-bound.stderr b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr similarity index 100% rename from src/test/ui/traits/wf-trait-object-maybe-bound.stderr rename to src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr diff --git a/src/test/ui/traits/wf-trait-object-reverse-order.rs b/src/test/ui/traits/wf-trait-object-reverse-order.rs index f9c584ace5b2..4f676cbe3384 100644 --- a/src/test/ui/traits/wf-trait-object-reverse-order.rs +++ b/src/test/ui/traits/wf-trait-object-reverse-order.rs @@ -1,15 +1,15 @@ // run-pass -// Ensure that `dyn $($AutoTrait) + ObjSafe` is well-formed. +// Ensure that `dyn $($AutoTrait)+ ObjSafe` is well-formed. use std::marker::Unpin; -// Some arbitray object-safe trait: +// Some arbitrary object-safe trait: trait Obj {} -type _0 = Unpin; -type _1 = Send + Obj; -type _2 = Send + Unpin + Obj; -type _3 = Send + Unpin + Sync + Obj; +type _0 = dyn Unpin; +type _1 = dyn Send + Obj; +type _2 = dyn Send + Unpin + Obj; +type _3 = dyn Send + Unpin + Sync + Obj; fn main() {} From 783b713b5d90747dec1aabdbc8bfc348593a00c5 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Thu, 2 May 2019 18:03:29 +0100 Subject: [PATCH 09/12] Addressed more points raised in review. --- src/librustc/traits/util.rs | 96 ++++--- src/librustc_typeck/astconv.rs | 30 ++- src/test/ui/bad/bad-sized.stderr | 7 +- src/test/ui/error-codes/E0225.stderr | 22 +- src/test/ui/issues/issue-22560.stderr | 10 +- src/test/ui/issues/issue-32963.stderr | 7 +- .../trait-alias-no-duplicates.stderr | 186 ++++++++++---- .../trait-alias-no-extra-traits.stderr | 234 ++++++++++++++---- .../trait-alias/trait-alias-object-wf.rs | 2 +- .../trait-alias-only-maybe-bound.stderr | 6 +- .../wf-trait-object-no-duplicates.stderr | 35 ++- .../wf-trait-object-only-maybe-bound.stderr | 2 +- 12 files changed, 452 insertions(+), 185 deletions(-) diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 4e5aa6b915b5..77588d713dfc 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -51,13 +51,8 @@ struct PredicateSet<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { - fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PredicateSet<'a, 'gcx, 'tcx> { - PredicateSet { tcx: tcx, set: Default::default() } - } - - fn contains(&mut self, pred: &ty::Predicate<'tcx>) -> bool { - // See the `insert` method for why we use `anonymize_predicate` here. - self.set.contains(&anonymize_predicate(self.tcx, pred)) + fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self { + Self { tcx: tcx, set: Default::default() } } fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool { @@ -73,11 +68,6 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { // regions before we throw things into the underlying set. self.set.insert(anonymize_predicate(self.tcx, pred)) } - - fn remove(&mut self, pred: &ty::Predicate<'tcx>) -> bool { - // See the `insert` method for why we use `anonymize_predicate` here. - self.set.remove(&anonymize_predicate(self.tcx, pred)) - } } impl<'a, 'gcx, 'tcx, T: AsRef>> Extend for PredicateSet<'a, 'gcx, 'tcx> { @@ -135,7 +125,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { FilterToTraits::new(self) } - fn push(&mut self, predicate: &ty::Predicate<'tcx>) { + fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) { let tcx = self.visited.tcx; match *predicate { ty::Predicate::Trait(ref data) => { @@ -153,7 +143,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { // 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)); + predicates.retain(|pred| self.visited.insert(pred)); self.stack.extend(predicates); } @@ -251,15 +241,12 @@ 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); + if let Some(pred) = self.stack.pop() { + self.elaborate(&pred); + Some(pred) + } else { + None + } } } @@ -294,31 +281,29 @@ pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>, /// Expansion is done via a DFS (depth-first search), and the `visited` field /// is used to avoid cycles. pub struct TraitAliasExpander<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, stack: Vec>, - /// The set of predicates visited from the root directly to the current point in the - /// expansion tree (only containing trait aliases). - visited: PredicateSet<'a, 'gcx, 'tcx>, } /// Stores information about the expansion of a trait via a path of zero or more trait aliases. #[derive(Debug, Clone)] pub struct TraitAliasExpansionInfo<'tcx> { - pub items: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, + pub path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, } impl<'tcx> TraitAliasExpansionInfo<'tcx> { fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { Self { - items: smallvec![(trait_ref, span)] + path: smallvec![(trait_ref, span)] } } - fn push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { - let mut items = self.items.clone(); - items.push((trait_ref, span)); + 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 { - items + path } } @@ -327,11 +312,11 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> { } pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { - self.items.last().unwrap() + self.path.last().unwrap() } pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { - self.items.first().unwrap() + self.path.first().unwrap() } } @@ -340,21 +325,25 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> { pub trait TraitAliasExpansionInfoDignosticBuilder { fn label_with_exp_info<'tcx>(&mut self, info: &TraitAliasExpansionInfo<'tcx>, - top_label: &str + top_label: &str, + use_desc: &str ) -> &mut Self; } impl<'a> TraitAliasExpansionInfoDignosticBuilder for DiagnosticBuilder<'a> { fn label_with_exp_info<'tcx>(&mut self, info: &TraitAliasExpansionInfo<'tcx>, - top_label: &str + top_label: &str, + use_desc: &str ) -> &mut Self { self.span_label(info.top().1, top_label); - if info.items.len() > 1 { - for (_, sp) in info.items[1..(info.items.len() - 1)].iter().rev() { - self.span_label(*sp, "referenced here"); + 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.span_label(info.bottom().1, + format!("trait alias used in trait object type ({})", use_desc)); self } } @@ -367,7 +356,7 @@ pub fn expand_trait_aliases<'cx, 'gcx, 'tcx>( .into_iter() .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)) .collect(); - TraitAliasExpander { stack: items, visited: PredicateSet::new(tcx) } + TraitAliasExpander { tcx, stack: items } } impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> { @@ -376,23 +365,25 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> { /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a /// trait alias. /// The return value indicates whether `item` should be yielded to the user. - fn push(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { - let tcx = self.visited.tcx; + fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { + let tcx = self.tcx; let trait_ref = item.trait_ref(); let pred = trait_ref.to_predicate(); debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); - // Don't recurse unless this bound is a trait alias and isn't currently in the DFS stack of - // already-visited predicates. + // Don't recurse if this bound is not a trait alias. let is_alias = tcx.is_trait_alias(trait_ref.def_id()); - if !is_alias || self.visited.contains(&pred) { - return !is_alias; + if !is_alias { + return true; } - // Remove the current predicate from the stack of already-visited ones, since we're doing - // a DFS. - self.visited.remove(&pred); + // Don't recurse if this trait alias is already on the stack for the DFS search. + let anon_pred = anonymize_predicate(tcx, &pred); + if item.path.iter().rev().skip(1) + .any(|(tr, _)| anonymize_predicate(tcx, &tr.to_predicate()) == anon_pred) { + return false; + } // Get components of trait alias. let predicates = tcx.super_predicates_of(trait_ref.def_id()); @@ -403,16 +394,13 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> { .filter_map(|(pred, span)| { pred.subst_supertrait(tcx, &trait_ref) .to_opt_poly_trait_ref() - .map(|trait_ref| item.push(trait_ref, *span)) + .map(|trait_ref| item.clone_and_push(trait_ref, *span)) }) .collect(); debug!("expand_trait_aliases: items={:?}", items); self.stack.extend(items); - // Record predicate into set of already-visited. - self.visited.insert(&pred); - false } } @@ -426,7 +414,7 @@ impl<'cx, 'gcx, 'tcx> Iterator for TraitAliasExpander<'cx, 'gcx, 'tcx> { fn next(&mut self) -> Option> { while let Some(item) = self.stack.pop() { - if self.push(&item) { + if self.expand(&item) { return Some(item); } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 31aba9ed239c..7d4243c4842e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -648,14 +648,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { // careful! if default_needs_object_self(param) { struct_span_err!(tcx.sess, span, E0393, - "the type parameter `{}` must be explicitly \ - specified", - param.name) - .span_label(span, - format!("missing reference to `{}`", param.name)) - .note(&format!("because of the default `Self` reference, \ - type parameters must be specified on object \ - types")) + "the type parameter `{}` must be explicitly specified", + param.name + ) + .span_label(span, format!( + "missing reference to `{}`", param.name)) + .note(&format!( + "because of the default `Self` reference, type parameters \ + must be specified on object types")) .emit(); tcx.types.err.into() } else { @@ -987,7 +987,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ); potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten()); (trait_ref, trait_bound.span) - }).collect(); + }) + .collect(); // Expand trait aliases recursively and check that only one regular (non-auto) trait // is used and no 'maybe' bounds are used. @@ -995,12 +996,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let (mut 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]; - struct_span_err!(tcx.sess, extra_trait.bottom().1, E0225, + let first_trait = ®ular_traits[0]; + let additional_trait = ®ular_traits[1]; + 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(extra_trait, "additional non-auto trait") - .span_label(regular_traits[0].top().1, "first non-auto trait") + .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(); } diff --git a/src/test/ui/bad/bad-sized.stderr b/src/test/ui/bad/bad-sized.stderr index 671840acdbfe..6307af5d725d 100644 --- a/src/test/ui/bad/bad-sized.stderr +++ b/src/test/ui/bad/bad-sized.stderr @@ -2,9 +2,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/bad-sized.rs:4:24 | LL | let x: Vec = Vec::new(); - | ----- ^^^^^ additional non-auto trait - | | + | ----- ^^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time --> $DIR/bad-sized.rs:4:12 diff --git a/src/test/ui/error-codes/E0225.stderr b/src/test/ui/error-codes/E0225.stderr index 183cf0aad643..c7a66c327f1c 100644 --- a/src/test/ui/error-codes/E0225.stderr +++ b/src/test/ui/error-codes/E0225.stderr @@ -1,21 +1,27 @@ error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/E0225.rs:6:32 + --> $DIR/E0225.rs:6:36 | -LL | let _: Box; - | ------------- ^^^^^^^^^^^^^^ additional non-auto trait - | | - | first non-auto trait +LL | let _: Box; + | ------------- ^^^^^^^^^^^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/E0225.rs:8:16 + --> $DIR/E0225.rs:8:20 | LL | trait Foo = std::io::Read + std::io::Write; | ------------- -------------- additional non-auto trait | | | first non-auto trait ... -LL | let _: Box; - | ^^^ +LL | let _: Box; + | ^^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-22560.stderr b/src/test/ui/issues/issue-22560.stderr index 2c6f4d9d45f7..322136d35cad 100644 --- a/src/test/ui/issues/issue-22560.stderr +++ b/src/test/ui/issues/issue-22560.stderr @@ -18,10 +18,16 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/issue-22560.rs:6:13 | LL | type Test = Add + - | --- first non-auto trait + | --- + | | + | first non-auto trait + | trait alias used in trait object type (first use) ... LL | Sub; - | ^^^ additional non-auto trait + | ^^^ + | | + | additional non-auto trait + | trait alias used in trait object type (additional use) error[E0191]: the value of the associated types `Output` (from the trait `std::ops::Add`), `Output` (from the trait `std::ops::Sub`) must be specified --> $DIR/issue-22560.rs:3:13 diff --git a/src/test/ui/issues/issue-32963.stderr b/src/test/ui/issues/issue-32963.stderr index 381ccdbeb999..cde4123dc3f4 100644 --- a/src/test/ui/issues/issue-32963.stderr +++ b/src/test/ui/issues/issue-32963.stderr @@ -2,9 +2,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/issue-32963.rs:8:25 | LL | size_of_copy::(); - | ---- ^^^^ additional non-auto trait - | | + | ---- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied --> $DIR/issue-32963.rs:8:5 diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr index 3cdf1582ab9c..eb667c9522ce 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr @@ -8,7 +8,9 @@ LL | trait _0 = Obj; | first non-auto trait ... LL | type _T00 = dyn _0 + _0; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:19:22 @@ -18,9 +20,13 @@ LL | trait _0 = Obj; | | | additional non-auto trait | first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | type _T01 = dyn _1 + _0; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:22:22 @@ -31,10 +37,15 @@ LL | trait _0 = Obj; | additional non-auto trait | first non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) ... LL | type _T02 = dyn _1 + _1; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:25:23 @@ -42,21 +53,28 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T03 = dyn Obj + _1; - | --- ^^ + | --- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:28:22 | LL | trait _0 = Obj; | --- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | type _T04 = dyn _1 + Obj; - | ^^^ additional non-auto trait + | -- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:37:17 @@ -67,13 +85,18 @@ LL | trait _0 = Obj; | additional non-auto trait | first non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _2 = _0 + _1; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T10 = dyn _2 + _3; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:40:22 @@ -82,12 +105,14 @@ LL | trait _0 = Obj; | --- additional non-auto trait ... LL | trait _2 = _0 + _1; - | -- referenced here + | -- referenced here (additional use) LL | trait _3 = Obj; | --- first non-auto trait ... LL | type _T11 = dyn _3 + _2; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:43:23 @@ -96,12 +121,13 @@ LL | trait _0 = Obj; | --- additional non-auto trait ... LL | trait _2 = _0 + _1; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T12 = dyn Obj + _2; - | --- ^^ + | --- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:46:17 @@ -112,25 +138,34 @@ LL | trait _0 = Obj; | additional non-auto trait | first non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _2 = _0 + _1; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T13 = dyn _2 + Obj; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:49:22 | LL | trait _0 = Obj; | --- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _3 = Obj; | --- additional non-auto trait ... LL | type _T14 = dyn _1 + _3; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:52:22 @@ -138,27 +173,33 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _3 = Obj; | --- first non-auto trait ... LL | type _T15 = dyn _3 + _1; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:55:22 | LL | trait _0 = Obj; | --- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _3 = Obj; | --- additional non-auto trait LL | trait _4 = _3; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T16 = dyn _1 + _4; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:58:22 @@ -166,13 +207,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _3 = Obj; | --- first non-auto trait +LL | trait _4 = _3; + | -- referenced here (first use) ... LL | type _T17 = dyn _4 + _1; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:65:22 @@ -184,7 +229,9 @@ LL | trait _5 = Obj + Send; | first non-auto trait LL | LL | type _T20 = dyn _5 + _5; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:68:23 @@ -193,9 +240,10 @@ LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | type _T21 = dyn Obj + _5; - | --- ^^ + | --- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:71:22 @@ -204,7 +252,11 @@ LL | trait _5 = Obj + Send; | --- first non-auto trait ... LL | type _T22 = dyn _5 + Obj; - | ^^^ additional non-auto trait + | -- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:74:36 @@ -213,7 +265,11 @@ LL | trait _5 = Obj + Send; | --- first non-auto trait ... LL | type _T23 = dyn _5 + Send + Sync + Obj; - | ^^^ additional non-auto trait + | -- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:81:17 @@ -225,10 +281,15 @@ LL | trait _5 = Obj + Send; | first non-auto trait ... LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) LL | LL | type _T30 = dyn _6; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:84:17 @@ -240,10 +301,15 @@ LL | trait _5 = Obj + Send; | first non-auto trait ... LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T31 = dyn _6 + Send; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:87:24 @@ -255,10 +321,15 @@ LL | trait _5 = Obj + Send; | first non-auto trait ... LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T32 = dyn Send + _6; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:95:22 @@ -266,8 +337,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Obj + Send; | --- first non-auto trait ... +LL | trait _7 = _5 + Sync; + | -- referenced here (first use) +LL | trait _8 = Unpin + _7; + | -- referenced here (first use) +LL | LL | type _T40 = dyn _8 + Obj; - | ^^^ additional non-auto trait + | -- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:98:23 @@ -276,14 +356,15 @@ LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here + | -- referenced here (additional use) LL | trait _8 = Unpin + _7; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T41 = dyn Obj + _8; - | --- ^^ + | --- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:101:22 @@ -291,47 +372,62 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _3 = Obj; | --- additional non-auto trait LL | trait _4 = _3; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _5 = Obj + Send; | --- first non-auto trait ... +LL | trait _7 = _5 + Sync; + | -- referenced here (first use) +LL | trait _8 = Unpin + _7; + | -- referenced here (first use) +... LL | type _T42 = dyn _8 + _4; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:104:22 | LL | trait _3 = Obj; | --- first non-auto trait +LL | trait _4 = _3; + | -- referenced here (first use) ... LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here + | -- referenced here (additional use) LL | trait _8 = Unpin + _7; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T43 = dyn _4 + _8; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:107:36 | LL | trait _3 = Obj; | --- first non-auto trait +LL | trait _4 = _3; + | -- referenced here (first use) ... LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here + | -- referenced here (additional use) LL | trait _8 = Unpin + _7; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T44 = dyn _4 + Send + Sync + _8; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:117:18 @@ -341,7 +437,9 @@ LL | trait _9 = for<'a> ObjL<'a>; LL | trait _10 = for<'b> ObjL<'b>; | ---------------- additional non-auto trait LL | type _T50 = _9 + _10; - | ^^^ + | -- ^^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:123:19 @@ -351,7 +449,9 @@ LL | trait _11 = ObjT fn(&'a u8)>; LL | trait _12 = ObjT fn(&'b u8)>; | ------------------------ additional non-auto trait LL | type _T60 = _11 + _12; - | ^^^ + | --- ^^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error: aborting due to 27 previous errors diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr index d73667a07097..15685a228833 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr @@ -5,7 +5,11 @@ LL | trait _0 = ObjA; | ---- first non-auto trait ... LL | type _T00 = dyn _0 + ObjB; - | ^^^^ additional non-auto trait + | -- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:19:24 @@ -14,9 +18,10 @@ LL | trait _0 = ObjA; | ---- additional non-auto trait ... LL | type _T01 = dyn ObjB + _0; - | ---- ^^ + | ---- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:22:24 @@ -24,21 +29,28 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T02 = dyn ObjB + _1; - | ---- ^^ + | ---- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:25:22 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | type _T03 = dyn _1 + ObjB; - | ^^^^ additional non-auto trait + | -- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:34:22 @@ -49,10 +61,12 @@ LL | trait _2 = ObjB; | additional non-auto trait | first non-auto trait LL | trait _3 = _2; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T10 = dyn _2 + _3; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:37:22 @@ -62,9 +76,13 @@ LL | trait _2 = ObjB; | | | additional non-auto trait | first non-auto trait +LL | trait _3 = _2; + | -- referenced here (first use) ... LL | type _T11 = dyn _3 + _2; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:40:22 @@ -75,12 +93,14 @@ LL | trait _2 = ObjB; | additional non-auto trait | first non-auto trait LL | trait _3 = _2; - | -- referenced here + | -- referenced here (additional use) LL | trait _4 = _3; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T12 = dyn _2 + _4; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:43:22 @@ -90,9 +110,15 @@ LL | trait _2 = ObjB; | | | additional non-auto trait | first non-auto trait +LL | trait _3 = _2; + | -- referenced here (first use) +LL | trait _4 = _3; + | -- referenced here (first use) ... LL | type _T13 = dyn _4 + _2; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:50:22 @@ -100,25 +126,31 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait LL | LL | type _T20 = dyn _5 + _1; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:53:22 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | type _T21 = dyn _1 + _5; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:56:22 @@ -127,7 +159,11 @@ LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... LL | type _T22 = dyn _5 + ObjA; - | ^^^^ additional non-auto trait + | -- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:59:24 @@ -136,9 +172,10 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | type _T23 = dyn ObjA + _5; - | ---- ^^ + | ---- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:62:29 @@ -146,25 +183,31 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... LL | type _T24 = dyn Send + _5 + _1 + Sync; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:65:29 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | type _T25 = dyn _1 + Sync + _5 + Send; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:68:36 @@ -173,7 +216,11 @@ LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... LL | type _T26 = dyn Sync + Send + _5 + ObjA; - | ^^^^ additional non-auto trait + | -- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:71:38 @@ -182,111 +229,172 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | type _T27 = dyn Send + Sync + ObjA + _5; - | ---- ^^ + | ---- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:80:17 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _6 = _1 + _5; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T30 = dyn _6; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:83:17 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _6 = _1 + _5; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T31 = dyn _6 + Send; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:86:24 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _6 = _1 + _5; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T32 = dyn Send + _6; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:89:17 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _6 = _1 + _5; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) LL | trait _7 = _6; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) LL | trait _8 = _7; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) ... LL | type _T33 = dyn _8; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:92:17 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _6 = _1 + _5; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) LL | trait _7 = _6; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) LL | trait _8 = _7; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) ... LL | type _T34 = dyn _8 + Send; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:95:24 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _6 = _1 + _5; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) LL | trait _7 = _6; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) LL | trait _8 = _7; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) ... LL | type _T35 = dyn Send + _8; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:103:23 @@ -294,8 +402,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +LL | LL | type _T40 = dyn _10 + ObjA; - | ^^^^ additional non-auto trait + | --- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:106:24 @@ -304,14 +421,15 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here + | -- referenced here (additional use) LL | trait _10 = Unpin + _9; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T41 = dyn ObjA + _10; - | ---- ^^^ + | ---- ^^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:109:23 @@ -319,13 +437,20 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +... LL | type _T42 = dyn _10 + _1; - | ^^ + | --- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:112:37 @@ -333,8 +458,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +... LL | type _T43 = dyn Send + _10 + Sync + ObjA; - | ^^^^ additional non-auto trait + | --- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:115:24 @@ -343,14 +477,15 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here + | -- referenced here (additional use) LL | trait _10 = Unpin + _9; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T44 = dyn ObjA + _10 + Send + Sync; - | ---- ^^^ + | ---- ^^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:118:37 @@ -358,13 +493,20 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +... LL | type _T45 = dyn Sync + Send + _10 + _1; - | ^^ + | --- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error: aborting due to 28 previous errors diff --git a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs index f7c410c6362f..fb26b7e2df7c 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs @@ -1,6 +1,6 @@ // run-pass -// This test hecks that trait objects involving trait aliases are well-formed. +// This test checks that trait objects involving trait aliases are well-formed. #![feature(trait_alias)] diff --git a/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr index 52e90c00c374..d4f77200fd5a 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr @@ -1,13 +1,13 @@ error[E0224]: at least one non-builtin trait is required for an object type - --> $DIR/trait-alias-maybe-bound.rs:12:12 + --> $DIR/trait-alias-only-maybe-bound.rs:13:12 | LL | type _T0 = dyn _1; | ^^^^^^ error[E0224]: at least one non-builtin trait is required for an object type - --> $DIR/trait-alias-maybe-bound.rs:24:12 + --> $DIR/trait-alias-only-maybe-bound.rs:19:12 | -LL | type _T3 = dyn _2; +LL | type _T1 = dyn _2; | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/wf-trait-object-no-duplicates.stderr b/src/test/ui/traits/wf-trait-object-no-duplicates.stderr index 75dacb2e1565..269d92fe43db 100644 --- a/src/test/ui/traits/wf-trait-object-no-duplicates.stderr +++ b/src/test/ui/traits/wf-trait-object-no-duplicates.stderr @@ -2,41 +2,56 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/wf-trait-object-no-duplicates.rs:8:21 | LL | type _0 = dyn Obj + Obj; - | --- ^^^ additional non-auto trait - | | + | --- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/wf-trait-object-no-duplicates.rs:13:28 | LL | type _1 = dyn Send + Obj + Obj; - | --- ^^^ additional non-auto trait - | | + | --- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/wf-trait-object-no-duplicates.rs:16:28 | LL | type _2 = dyn Obj + Send + Obj; - | --- ^^^ additional non-auto trait - | | + | --- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/wf-trait-object-no-duplicates.rs:26:34 | LL | type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>; - | ---------------- ^^^^^^^^^^^^^^^^ additional non-auto trait - | | + | ---------------- ^^^^^^^^^^^^^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/wf-trait-object-no-duplicates.rs:30:42 | LL | type _5 = dyn ObjT fn(&'a u8)> + ObjT fn(&'b u8)>; - | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ additional non-auto trait - | | + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error: aborting due to 5 previous errors diff --git a/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr index ba24b8342118..7a5080bbd0c0 100644 --- a/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr +++ b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr @@ -1,5 +1,5 @@ error[E0224]: at least one non-builtin trait is required for an object type - --> $DIR/wf-trait-object-maybe-bound.rs:4:11 + --> $DIR/wf-trait-object-only-maybe-bound.rs:3:11 | LL | type _0 = dyn ?Sized; | ^^^^^^^^^^ From a0a61904f4b38c76fe32c7cda57626be94b9c65a Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Mon, 13 May 2019 19:51:33 +0100 Subject: [PATCH 10/12] 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 d950746f6e6d..a4b9ed0a206b 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 77588d713dfc..5ba23a9c45a4 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 7d4243c4842e..ce5963e3ce5c 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() { From ce75a23c0d56764cef7c633139f01b80f040cd25 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Sun, 19 May 2019 22:26:42 +0100 Subject: [PATCH 11/12] Reinstated shallow disallowing of maybe bounds in trait objects. --- src/librustc_passes/ast_validation.rs | 1 + src/test/ui/maybe-bounds.rs | 5 ++- src/test/ui/maybe-bounds.stderr | 14 +++++++- .../ui/parser/trait-object-trait-parens.rs | 2 ++ .../parser/trait-object-trait-parens.stderr | 16 ++++++++-- .../ui/traits/wf-trait-object-maybe-bound.rs | 7 +++- .../traits/wf-trait-object-maybe-bound.stderr | 32 +++++++++++++++++++ .../wf-trait-object-only-maybe-bound.rs | 1 + .../wf-trait-object-only-maybe-bound.stderr | 8 ++++- 9 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/traits/wf-trait-object-maybe-bound.stderr diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index d70c81854955..2bea1db841ae 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -504,6 +504,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { any_lifetime_bounds = true; } } + self.no_questions_in_bounds(bounds, "trait object types", false); } TyKind::ImplTrait(_, ref bounds) => { if self.is_impl_trait_banned { diff --git a/src/test/ui/maybe-bounds.rs b/src/test/ui/maybe-bounds.rs index 95d14f6d1da3..02ed45c656f1 100644 --- a/src/test/ui/maybe-bounds.rs +++ b/src/test/ui/maybe-bounds.rs @@ -1,6 +1,9 @@ -trait Tr: ?Sized {} //~ ERROR `?Trait` is not permitted in supertraits +trait Tr: ?Sized {} +//~^ ERROR `?Trait` is not permitted in supertraits type A1 = dyn Tr + (?Sized); +//~^ ERROR `?Trait` is not permitted in trait object types type A2 = dyn for<'a> Tr + (?Sized); +//~^ ERROR `?Trait` is not permitted in trait object types fn main() {} diff --git a/src/test/ui/maybe-bounds.stderr b/src/test/ui/maybe-bounds.stderr index d8c2adfc61c5..1d823b6acb28 100644 --- a/src/test/ui/maybe-bounds.stderr +++ b/src/test/ui/maybe-bounds.stderr @@ -6,5 +6,17 @@ LL | trait Tr: ?Sized {} | = note: traits are `?Sized` by default -error: aborting due to previous error +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bounds.rs:4:20 + | +LL | type A1 = dyn Tr + (?Sized); + | ^^^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bounds.rs:6:28 + | +LL | type A2 = dyn for<'a> Tr + (?Sized); + | ^^^^^^^^ + +error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/trait-object-trait-parens.rs b/src/test/ui/parser/trait-object-trait-parens.rs index 49373564f673..9ac10cd13279 100644 --- a/src/test/ui/parser/trait-object-trait-parens.rs +++ b/src/test/ui/parser/trait-object-trait-parens.rs @@ -4,7 +4,9 @@ fn f Trait<'a>)>() {} fn main() { let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>; + //~^ ERROR `?Trait` is not permitted in trait object types let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>; let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; //~^ ERROR use of undeclared lifetime name `'a` + //~| ERROR `?Trait` is not permitted in trait object types } diff --git a/src/test/ui/parser/trait-object-trait-parens.stderr b/src/test/ui/parser/trait-object-trait-parens.stderr index 1cf40b30406c..36494b765394 100644 --- a/src/test/ui/parser/trait-object-trait-parens.stderr +++ b/src/test/ui/parser/trait-object-trait-parens.stderr @@ -1,9 +1,21 @@ +error: `?Trait` is not permitted in trait object types + --> $DIR/trait-object-trait-parens.rs:6:25 + | +LL | let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>; + | ^^^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/trait-object-trait-parens.rs:9:47 + | +LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; + | ^^^^^^^^ + error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/trait-object-trait-parens.rs:8:31 + --> $DIR/trait-object-trait-parens.rs:9:31 | LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; | ^^ undeclared lifetime -error: aborting due to previous error +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/traits/wf-trait-object-maybe-bound.rs b/src/test/ui/traits/wf-trait-object-maybe-bound.rs index 405104fe0814..f24c1301c53a 100644 --- a/src/test/ui/traits/wf-trait-object-maybe-bound.rs +++ b/src/test/ui/traits/wf-trait-object-maybe-bound.rs @@ -1,15 +1,20 @@ -// compile-pass +// compile-fail // Test that `dyn ... + ?Sized + ...` is okay (though `?Sized` has no effect in trait objects). trait Foo {} type _0 = dyn ?Sized + Foo; +//~^ ERROR `?Trait` is not permitted in trait object types type _1 = dyn Foo + ?Sized; +//~^ ERROR `?Trait` is not permitted in trait object types type _2 = dyn Foo + ?Sized + ?Sized; +//~^ ERROR `?Trait` is not permitted in trait object types +//~| ERROR `?Trait` is not permitted in trait object types type _3 = dyn ?Sized + Foo; +//~^ ERROR `?Trait` is not permitted in trait object types fn main() {} diff --git a/src/test/ui/traits/wf-trait-object-maybe-bound.stderr b/src/test/ui/traits/wf-trait-object-maybe-bound.stderr new file mode 100644 index 000000000000..11187342d59f --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-maybe-bound.stderr @@ -0,0 +1,32 @@ +error: `?Trait` is not permitted in trait object types + --> $DIR/wf-trait-object-maybe-bound.rs:7:15 + | +LL | type _0 = dyn ?Sized + Foo; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/wf-trait-object-maybe-bound.rs:10:21 + | +LL | type _1 = dyn Foo + ?Sized; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/wf-trait-object-maybe-bound.rs:13:21 + | +LL | type _2 = dyn Foo + ?Sized + ?Sized; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/wf-trait-object-maybe-bound.rs:13:30 + | +LL | type _2 = dyn Foo + ?Sized + ?Sized; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/wf-trait-object-maybe-bound.rs:17:15 + | +LL | type _3 = dyn ?Sized + Foo; + | ^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs b/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs index c8e6ac38b5a3..1b83d2487f4c 100644 --- a/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs +++ b/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs @@ -2,5 +2,6 @@ type _0 = dyn ?Sized; //~^ ERROR at least one non-builtin trait is required for an object type [E0224] +//~| ERROR ?Trait` is not permitted in trait object types fn main() {} diff --git a/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr index 7a5080bbd0c0..0cfb389fd899 100644 --- a/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr +++ b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr @@ -1,8 +1,14 @@ +error: `?Trait` is not permitted in trait object types + --> $DIR/wf-trait-object-only-maybe-bound.rs:3:15 + | +LL | type _0 = dyn ?Sized; + | ^^^^^^ + error[E0224]: at least one non-builtin trait is required for an object type --> $DIR/wf-trait-object-only-maybe-bound.rs:3:11 | LL | type _0 = dyn ?Sized; | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors From ce2ee305f9165c037ecddddb5792588a15ff6c37 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Mon, 20 May 2019 16:19:34 +0100 Subject: [PATCH 12/12] Fixed nits raised in review. --- src/librustc/hir/mod.rs | 2 +- src/librustc/infer/outlives/verify.rs | 4 ++-- src/librustc/query/mod.rs | 8 ++++---- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/librustc_typeck/astconv.rs | 6 +++--- src/librustc_typeck/collect.rs | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index fafe1cf85a3e..fd7a83427efe 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2143,7 +2143,7 @@ pub enum UseKind { ListStem, } -/// `TraitRef` are references to traits in impls. +/// 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 diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs index 5b8d89c865a5..e1ad5aeea19f 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: Vec<_> = ty.walk_shallow() + let mut bounds = 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/query/mod.rs b/src/librustc/query/mod.rs index d043a32f06bd..8825c94cdb81 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -248,12 +248,12 @@ rustc_queries! { desc { "computing the variances for items in this crate" } } - /// Maps from def-ID of a type or region parameter to its (inferred) variance. + /// Maps from the `DefId` of a type or region parameter to its (inferred) variance. query variances_of(_: DefId) -> &'tcx [ty::Variance] {} } TypeChecking { - /// Maps from def-ID of a type to its (inferred) outlives. + /// Maps from thee `DefId` of a type to its (inferred) outlives. query inferred_outlives_crate(_: CrateNum) -> Lrc> { desc { "computing the inferred outlives predicates for items in this crate" } @@ -261,7 +261,7 @@ rustc_queries! { } Other { - /// Maps from an impl/trait def-ID to a list of the def-ids of its items. + /// Maps from an impl/trait `DefId to a list of the `DefId`s of its items. query associated_item_def_ids(_: DefId) -> Lrc> {} /// Maps from a trait item to the trait item "descriptor". @@ -274,7 +274,7 @@ rustc_queries! { } TypeChecking { - /// Maps a def-ID of a type to a list of its inherent impls. + /// Maps a `DefId` of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. query inherent_impls(_: DefId) -> Lrc> { diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 5f184bf4a7d4..1fdfcc84926f 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -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 `DefId` 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 ce5963e3ce5c..4110a5584019 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -702,7 +702,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } /// Instantiates the path for the given trait reference, assuming that it's - /// bound to a valid trait type. Returns the def-ID for the defining trait. + /// bound to a valid trait type. Returns the `DefId` of the defining trait. /// The type _cannot_ be a type other than a trait type. /// /// If the `projections` argument is `None`, then assoc type bindings like `Foo` @@ -994,7 +994,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { // Expand trait aliases recursively and check that only one regular (non-auto) trait // is used and no 'maybe' bounds are used. - let expanded_traits = traits::expand_trait_aliases(tcx, bound_trait_refs.clone()); + let expanded_traits = traits::expand_trait_aliases(tcx, bound_trait_refs.iter().cloned()); let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); if regular_traits.len() > 1 { @@ -1240,7 +1240,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } // Search for a bound on a type parameter which includes the associated item - // given by `assoc_name`. `ty_param_def_id` is the `DefId` for the type parameter + // given by `assoc_name`. `ty_param_def_id` is the `DefId` of the type parameter // This function will fail if there are no suitable bounds or there is // any ambiguity. fn find_bound_for_assoc_item(&self, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 104c8e25d138..7adf86a99bd4 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -713,9 +713,9 @@ fn super_predicates_of<'a, 'tcx>( let superbounds1 = superbounds1.predicates(tcx, self_param_ty); - // Convert any explicit superbounds in the wheree-clause, + // Convert any explicit superbounds in the where-clause, // e.g., `trait Foo where Self: Bar`. - // In the case of trait aliases, however, we include all bounds in the where clause, + // In the case of trait aliases, however, we include all bounds in the where-clause, // so e.g., `trait Foo = where u32: PartialEq` would include `u32: PartialEq` // as one of its "superpredicates". let is_trait_alias = tcx.is_trait_alias(trait_def_id);