diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 6eac848740106..8768f1ff081c1 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 4b94f772554e7..23f4d20857135 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 22312e7459be1..fd7a83427efe8 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. +/// 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/query/mod.rs b/src/librustc/query/mod.rs index 2fff4c3f109b1..8825c94cdb81c 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 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" } @@ -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 `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" + /// 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 `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> { @@ -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/mod.rs b/src/librustc/traits/mod.rs index 846924fb591e6..a4b9ed0a206b9 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -60,8 +60,10 @@ 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::{ + supertraits, supertrait_def_ids, transitive_bounds, Supertraits, SupertraitDefIds, +}; +pub use self::util::{expand_trait_aliases, TraitAliasExpander}; pub use self::chalk_fulfill::{ CanonicalGoal as ChalkCanonicalGoal, @@ -1043,7 +1045,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 c4be85050dbc2..ec5e127a5ec4b 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 be29ea5701b2f..5ba23a9c45a4f 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -1,3 +1,7 @@ +use errors::DiagnosticBuilder; +use smallvec::SmallVec; +use syntax_pos::Span; + use crate::hir; use crate::hir::def_id::DefId; use crate::traits::specialize::specialization_graph::NodeItem; @@ -41,15 +45,14 @@ 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>, } 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 new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self { + Self { tcx: tcx, set: Default::default() } } fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool { @@ -67,18 +70,25 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { } } +impl<'a, 'gcx, 'tcx, T: AsRef>> Extend for PredicateSet<'a, 'gcx, 'tcx> { + fn extend>(&mut self, iter: I) { + for pred in iter { + self.insert(pred.as_ref()); + } + } +} + /////////////////////////////////////////////////////////////////////////// // `Elaboration` iterator /////////////////////////////////////////////////////////////////////////// /// "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 +106,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) } @@ -108,7 +117,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> { @@ -116,28 +125,25 @@ 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) => { - // 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 - .iter() - .map(|(p, _)| p.subst_supertrait(tcx, &data.to_poly_trait_ref())) - .collect(); - + let predicates = predicates.predicates + .iter() + .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(|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 { }`. + let visited = &mut self.visited; + let predicates = predicates.filter(|pred| visited.insert(pred)); self.stack.extend(predicates); } @@ -150,8 +156,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. @@ -163,11 +169,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 @@ -194,34 +198,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)) + ); } } } @@ -236,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 + } } } @@ -256,20 +258,161 @@ 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() } /////////////////////////////////////////////////////////////////////////// -// Iterator over def-ids of supertraits +// `TraitAliasExpander` iterator +/////////////////////////////////////////////////////////////////////////// + +/// "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`. +/// 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>, +} + +/// 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 path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, +} + +impl<'tcx> TraitAliasExpansionInfo<'tcx> { + fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { + Self { + path: smallvec![(trait_ref, span)] + } + } + + /// 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> { + &self.top().0 + } + + pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { + self.path.last().unwrap() + } + + pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { + self.path.first().unwrap() + } + + 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 + } + } +} + +pub fn expand_trait_aliases<'cx, 'gcx, 'tcx>( + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + trait_refs: impl IntoIterator, Span)> +) -> TraitAliasExpander<'cx, 'gcx, 'tcx> { + let items: Vec<_> = trait_refs + .into_iter() + .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)) + .collect(); + TraitAliasExpander { tcx, stack: items } +} + +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, 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 be yielded to the user. + 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 if this bound is not a trait alias. + let is_alias = tcx.is_trait_alias(trait_ref.def_id()); + if !is_alias { + return true; + } + + // 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()); + + 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)) + }); + debug!("expand_trait_aliases: items={:?}", items.clone()); + + self.stack.extend(items); + + false + } +} + +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> { + while let Some(item) = self.stack.pop() { + if self.expand(&item) { + return Some(item); + } + } + None + } +} + +/////////////////////////////////////////////////////////////////////////// +// Iterator over def-IDs of supertraits +/////////////////////////////////////////////////////////////////////////// pub struct SupertraitDefIds<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, @@ -298,8 +441,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) } @@ -325,17 +468,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/ty/mod.rs b/src/librustc/ty/mod.rs index e1c432d5b6da1..6020a737853e4 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<...>` @@ -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/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 18d575f73645c..be52b7e645198 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 1a1000f0bb41d..32d182edfdcde 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_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 1e65f868ebac0..1fdfcc84926f6 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 `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 4b052aec5fc2f..4110a55840196 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 { @@ -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` @@ -973,60 +973,81 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { { let tcx = self.tcx(); - if trait_bounds.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 mut potential_assoc_types = 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); - - 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![]); + // 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() + .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 and no 'maybe' bounds are used. + 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 { + let first_trait = ®ular_traits[0]; + let additional_trait = ®ular_traits[1]; + 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" + ); + 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(); } - 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(); + 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; } // 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()) - .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 @@ -1035,7 +1056,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 +1065,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)) } } @@ -1081,20 +1102,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( @@ -1130,9 +1149,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| { @@ -1145,19 +1171,14 @@ 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`. - auto_traits.sort(); - auto_traits.dedup(); - - // 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()) - }; + // Calling `skip_binder` is okay because the predicates are re-bound. + 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::>(); @@ -1175,14 +1196,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); @@ -1220,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, @@ -2097,33 +2117,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)] @@ -2138,7 +2131,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/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 251400e65f383..590ae9d46e8db 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 b009c8ea6dce1..7e7a8d5926673 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/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 711d79f95f53a..7adf86a99bd43 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,15 +707,15 @@ 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`. - // In the case of trait aliases, however, we include all bounds in the where 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, // 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); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d12240655e628..e299518af0be0 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, 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 ad0b6515490b9..85724cb7c6e85 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 321f97541587c..6307af5d725d1 100644 --- a/src/test/ui/bad/bad-sized.stderr +++ b/src/test/ui/bad/bad-sized.stderr @@ -2,7 +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(); - | ^^^^^ non-auto additional 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.rs b/src/test/ui/error-codes/E0225.rs index 1789be1559d82..b50f68e64516f 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; + 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 85a04708cb255..c7a66c327f1c1 100644 --- a/src/test/ui/error-codes/E0225.stderr +++ b/src/test/ui/error-codes/E0225.stderr @@ -1,9 +1,28 @@ error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/E0225.rs:2:32 + --> $DIR/E0225.rs:6:36 | -LL | let _: Box; - | ^^^^^^^^^^^^^^ non-auto additional 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: aborting due to previous error +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $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; + | ^^^ + | | + | 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 For more information about this error, try `rustc --explain E0225`. diff --git a/src/test/ui/issues/issue-22560.stderr b/src/test/ui/issues/issue-22560.stderr index 5a056dff590fe..322136d35cad1 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,32 @@ 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 + | trait alias used in trait object type (first use) +... LL | Sub; - | ^^^ non-auto additional trait + | ^^^ + | | + | additional non-auto trait + | trait alias used in trait object type (additional use) -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 70fda313170df..cde4123dc3f40 100644 --- a/src/test/ui/issues/issue-32963.stderr +++ b/src/test/ui/issues/issue-32963.stderr @@ -2,7 +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::(); - | ^^^^ non-auto additional 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/maybe-bounds.rs b/src/test/ui/maybe-bounds.rs index 3e07026fb7d71..02ed45c656f1c 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 = 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 = 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 20446c257df09..1d823b6acb283 100644 --- a/src/test/ui/maybe-bounds.stderr +++ b/src/test/ui/maybe-bounds.stderr @@ -7,16 +7,16 @@ 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 + --> $DIR/maybe-bounds.rs:4:20 | -LL | type A1 = Tr + (?Sized); - | ^^^^^^^^ +LL | type A1 = dyn Tr + (?Sized); + | ^^^^^^^^ error: `?Trait` is not permitted in trait object types - --> $DIR/maybe-bounds.rs:4:24 + --> $DIR/maybe-bounds.rs:6:28 | -LL | type A2 = for<'a> Tr + (?Sized); - | ^^^^^^^^ +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 2bbc5800015bd..9ac10cd13279b 100644 --- a/src/test/ui/parser/trait-object-trait-parens.rs +++ b/src/test/ui/parser/trait-object-trait-parens.rs @@ -7,6 +7,6 @@ fn main() { //~^ 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` + //~| ERROR `?Trait` is not permitted in trait object types } 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 379637401179b..0000000000000 --- 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 d3dd5cee0c33b..428ce5102bad8 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 0000000000000..3dfcf03ce79da --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs @@ -0,0 +1,29 @@ +// 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: +trait _0 = S; +trait _1 = _0; + +// Straight list expansion: +type _T0 = dyn _1 + Foo; + +// In second position: +type _T1 = dyn Foo + _1; + +// ... and with an auto trait: +type _T2 = dyn Foo + Send + _1; + +// Twice: +trait _2 = _1 + _1; + +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 new file mode 100644 index 0000000000000..afd8400e23050 --- /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 arbitrary 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 0000000000000..eb667c9522ce1 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr @@ -0,0 +1,458 @@ +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; + | -- ^^ 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 + | +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 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- + | | + | 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 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- 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 + | | 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 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _2 = _0 + _1; + | -- -- 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 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +... +LL | trait _2 = _0 + _1; + | -- 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 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +... +LL | trait _2 = _0 + _1; + | -- 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 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _2 = _0 + _1; + | -- -- 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 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- 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 (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 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- 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 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | 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 + | +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 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T22 = dyn _5 + Obj; + | -- ^^^ + | | | + | | 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 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T23 = dyn _5 + Send + Sync + Obj; + | -- ^^^ + | | | + | | 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 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- -- 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 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- -- 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 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- -- 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 + | +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 + | | 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 + | +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here (additional use) +LL | trait _8 = Unpin + _7; + | -- 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 + | +LL | trait _3 = Obj; + | --- additional non-auto trait +LL | trait _4 = _3; + | -- 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 (additional use) +LL | trait _8 = Unpin + _7; + | -- 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 (additional use) +LL | trait _8 = Unpin + _7; + | -- 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 + | +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; + | -- ^^^ 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 + | +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; + | --- ^^^ 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 + +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 0000000000000..4dad8c0f87349 --- /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 arbitrary 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 0000000000000..15685a228833d --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr @@ -0,0 +1,513 @@ +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 + | | 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 + | +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 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- 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 + | | 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 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- 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 + | +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 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- referenced here (additional use) +LL | trait _4 = _3; + | -- 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 + | +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 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- 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 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T22 = dyn _5 + ObjA; + | -- ^^^^ + | | | + | | 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 + | +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 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- 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 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T26 = dyn Sync + Send + _5 + ObjA; + | -- ^^^^ + | | | + | | 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 + | +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 (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 (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 (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 (additional use) + | | + | referenced here (first use) +LL | trait _7 = _6; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +LL | trait _8 = _7; + | -- + | | + | 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 (additional use) + | | + | referenced here (first use) +LL | trait _7 = _6; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +LL | trait _8 = _7; + | -- + | | + | 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 (additional use) + | | + | referenced here (first use) +LL | trait _7 = _6; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +LL | trait _8 = _7; + | -- + | | + | 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 + | +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 + | | 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 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (additional use) +LL | trait _10 = Unpin + _9; + | -- 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 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- 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 + | +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 + | | 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 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (additional use) +LL | trait _10 = Unpin + _9; + | -- 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 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- 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 + +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 0000000000000..d62fd7e59c920 --- /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 353aea311e90a..9a9b917703085 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 0000000000000..fb26b7e2df7cb --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs @@ -0,0 +1,85 @@ +// 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; + +fn _f0() { + let _: Box; + let _: Box; + let _: Box; +} + +// Include object safe traits: + +fn _f1() { + let _: Box; + let _: Box; + let _: Box; +} + +// And when the object safe trait is in a trait alias: + +trait _2 = Obj; + +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; + +fn _f3() { + let _: Box; + let _: Box; + let _: Box; +} + +// Nest the trait deeply: + +trait _4 = _3; +trait _5 = _4 + Sync + _0 + Send; +trait _6 = _5 + Send + _1 + Sync; + +fn _f4() { + let _: Box; + let _: Box; + let _: Box; +} + +// Just nest the trait alone: + +trait _7 = _2; +trait _8 = _7; +trait _9 = _8; + +fn _f5() { + let _: Box; +} + +// First bound is auto trait: + +trait _10 = Send + Obj; +trait _11 = Obj + Send; +trait _12 = Sync + _11; +trait _13 = Send + _12; + +fn f6() { + let _: Box; + let _: Box; +} + +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 1cf9e34edf307..12177cd827fdf 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/trait-alias-only-maybe-bound.rs b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.rs new file mode 100644 index 0000000000000..d6c611d2a4d91 --- /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-only-maybe-bound.stderr b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr new file mode 100644 index 0000000000000..d4f77200fd5a0 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr @@ -0,0 +1,14 @@ +error[E0224]: at least one non-builtin trait is required for an object type + --> $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-only-maybe-bound.rs:19:12 + | +LL | type _T1 = dyn _2; + | ^^^^^^ + +error: aborting due to 2 previous errors + 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 f99cc45d8ae94..f456a2d778c25 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 7cdd9184d3f5c..17557a51aa723 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 9be5664869e05..d8168f2990c46 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 0000000000000..f24c1301c53ab --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-maybe-bound.rs @@ -0,0 +1,20 @@ +// 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 0000000000000..11187342d59f2 --- /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-no-duplicates.rs b/src/test/ui/traits/wf-trait-object-no-duplicates.rs new file mode 100644 index 0000000000000..678ede58296a4 --- /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 arbitrary 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 0000000000000..269d92fe43db8 --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-no-duplicates.stderr @@ -0,0 +1,58 @@ +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 + | | 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 + | | 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 + | | 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 + | | 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 + | | 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 + +For more information about this error, try `rustc --explain E0225`. 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 0000000000000..1b83d2487f4c6 --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs @@ -0,0 +1,7 @@ +// 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] +//~| 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 new file mode 100644 index 0000000000000..0cfb389fd899e --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr @@ -0,0 +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 2 previous errors + 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 0000000000000..4f676cbe33846 --- /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 arbitrary object-safe trait: +trait 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() {}