diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index c97f80cf09ba1..4676ad5c31fca 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -432,17 +432,25 @@ impl<'hir> LoweringContext<'_, 'hir> { self.with_catch_scope(body.id, |this| { let mut block = this.lower_block_noalloc(body, true); - let try_span = this.mark_span_with_reason( - DesugaringKind::TryBlock, - body.span, - this.allow_try_trait.clone(), - ); - // Final expression of the block (if present) or `()` with span at the end of block - let tail_expr = block - .expr - .take() - .unwrap_or_else(|| this.expr_unit(this.sess.source_map().end_point(try_span))); + let (try_span, tail_expr) = if let Some(expr) = block.expr.take() { + ( + this.mark_span_with_reason( + DesugaringKind::TryBlock, + expr.span, + this.allow_try_trait.clone(), + ), + expr, + ) + } else { + let try_span = this.mark_span_with_reason( + DesugaringKind::TryBlock, + this.sess.source_map().end_point(body.span), + this.allow_try_trait.clone(), + ); + + (try_span, this.expr_unit(try_span)) + }; let ok_wrapped_span = this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None); @@ -1553,7 +1561,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::LangItem::TryFromError, unstable_span, from_expr, - try_span, + unstable_span, ); let thin_attrs = ThinVec::from(attrs); let catch_scope = self.catch_scopes.last().copied(); diff --git a/compiler/rustc_error_codes/src/error_codes/E0284.md b/compiler/rustc_error_codes/src/error_codes/E0284.md index a1ffa2bda0050..82598aeec0215 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0284.md +++ b/compiler/rustc_error_codes/src/error_codes/E0284.md @@ -5,37 +5,29 @@ as the `collect` method for `Iterator`s. For example: ```compile_fail,E0284 -fn foo() -> Result { - let results = [Ok(true), Ok(false), Err(())].iter().cloned(); - let v: Vec = results.collect()?; - // Do things with v... - Ok(true) +fn main() { + let n: u32 = 1; + let mut d: u64 = 2; + d = d + n.into(); } ``` -Here we have an iterator `results` over `Result`. -Hence, `results.collect()` can return any type implementing -`FromIterator>`. On the other hand, the -`?` operator can accept any type implementing `Try`. +Here we have an addition of `d` and `n.into()`. Hence, `n.into()` can return +any type `T` where `u64: Add`. On the other hand, the `into` method can +return any type where `u32: Into`. -The author of this code probably wants `collect()` to return a -`Result, ()>`, but the compiler can't be sure -that there isn't another type `T` implementing both `Try` and -`FromIterator>` in scope such that -`T::Ok == Vec`. Hence, this code is ambiguous and an error -is returned. +The author of this code probably wants `into()` to return a `u64`, but the +compiler can't be sure that there isn't another type `T` where both +`u32: Into` and `u64: Add`. To resolve this error, use a concrete type for the intermediate expression: ``` -fn foo() -> Result { - let results = [Ok(true), Ok(false), Err(())].iter().cloned(); - let v = { - let temp: Result, ()> = results.collect(); - temp? - }; - // Do things with v... - Ok(true) +fn main() { + let n: u32 = 1; + let mut d: u64 = 2; + let m: u64 = n.into(); + d = d + m; } ``` diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index ea19dff7db125..e3365e8590b5e 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -2,7 +2,7 @@ //! the end of the file for details. use super::combine::CombineFields; -use super::{HigherRankedType, InferCtxt, PlaceholderMap}; +use super::{HigherRankedType, InferCtxt}; use crate::infer::CombinedSnapshot; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; @@ -33,7 +33,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { self.infcx.commit_if_ok(|_| { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. - let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(&b); + let b_prime = self.infcx.replace_bound_vars_with_placeholders(&b); // Next, we instantiate each bound region in the subtype // with a fresh region variable. These region variables -- @@ -66,10 +66,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// the [rustc dev guide]. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html - pub fn replace_bound_vars_with_placeholders( - &self, - binder: &ty::Binder, - ) -> (T, PlaceholderMap<'tcx>) + pub fn replace_bound_vars_with_placeholders(&self, binder: &ty::Binder) -> T where T: TypeFoldable<'tcx>, { @@ -122,7 +119,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { next_universe, binder, result, map, ); - (result, map) + result } /// See `infer::region_constraints::RegionConstraintCollector::leak_check`. diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 07a55c7f859c3..9742f5e234651 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -351,11 +351,6 @@ pub struct InferCtxt<'a, 'tcx> { universe: Cell, } -/// A map returned by `replace_bound_vars_with_placeholders()` -/// indicating the placeholder region that each late-bound region was -/// replaced with. -pub type PlaceholderMap<'tcx> = BTreeMap>; - /// See the `error_reporting` module for more details. #[derive(Clone, Debug, PartialEq, Eq, TypeFoldable)] pub enum ValuePairs<'tcx> { @@ -992,7 +987,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } Some(self.commit_if_ok(|_snapshot| { - let (ty::SubtypePredicate { a_is_expected, a, b }, _) = + let ty::SubtypePredicate { a_is_expected, a, b } = self.replace_bound_vars_with_placeholders(&predicate); let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; @@ -1007,7 +1002,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { predicate: ty::PolyRegionOutlivesPredicate<'tcx>, ) -> UnitResult<'tcx> { self.commit_if_ok(|_snapshot| { - let (ty::OutlivesPredicate(r_a, r_b), _) = + let ty::OutlivesPredicate(r_a, r_b) = self.replace_bound_vars_with_placeholders(&predicate); let origin = SubregionOrigin::from_obligation_cause(cause, || { RelateRegionParamBound(cause.span) diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 07924298c241b..2b827f4f4eddc 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -328,8 +328,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { assoc_item_def_id: DefId, ) -> impl Iterator> { let tcx = self.tcx; - let predicates = tcx.projection_predicates(assoc_item_def_id); - predicates + let bounds = tcx.item_bounds(assoc_item_def_id); + bounds .into_iter() .filter_map(|p| p.to_opt_type_outlives()) .filter_map(|p| p.no_bound_vars()) diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 9c0d934a03529..1b7269706a758 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -4,7 +4,6 @@ use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::ty::outlives::Component; use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness}; -use rustc_span::Span; pub fn anonymize_predicate<'tcx>( tcx: TyCtxt<'tcx>, @@ -94,7 +93,11 @@ pub fn elaborate_predicates<'tcx>( tcx: TyCtxt<'tcx>, predicates: impl Iterator>, ) -> Elaborator<'tcx> { - let obligations = predicates.map(|predicate| predicate_obligation(predicate, None)).collect(); + let obligations = predicates + .map(|predicate| { + predicate_obligation(predicate, ty::ParamEnv::empty(), ObligationCause::dummy()) + }) + .collect(); elaborate_obligations(tcx, obligations) } @@ -109,15 +112,10 @@ pub fn elaborate_obligations<'tcx>( fn predicate_obligation<'tcx>( predicate: ty::Predicate<'tcx>, - span: Option, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, ) -> PredicateObligation<'tcx> { - let cause = if let Some(span) = span { - ObligationCause::dummy_with_span(span) - } else { - ObligationCause::dummy() - }; - - Obligation { cause, param_env: ty::ParamEnv::empty(), recursion_depth: 0, predicate } + Obligation { cause, param_env, recursion_depth: 0, predicate } } impl Elaborator<'tcx> { @@ -133,10 +131,11 @@ impl Elaborator<'tcx> { // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); - let obligations = predicates.predicates.iter().map(|&(pred, span)| { + let obligations = predicates.predicates.iter().map(|&(pred, _)| { predicate_obligation( pred.subst_supertrait(tcx, &ty::Binder::bind(data.trait_ref)), - Some(span), + obligation.param_env, + obligation.cause.clone(), ) }); debug!("super_predicates: data={:?}", data); @@ -233,7 +232,13 @@ impl Elaborator<'tcx> { }) .map(|predicate_kind| predicate_kind.to_predicate(tcx)) .filter(|&predicate| visited.insert(predicate)) - .map(|predicate| predicate_obligation(predicate, None)), + .map(|predicate| { + predicate_obligation( + predicate, + obligation.param_env, + obligation.cause.clone(), + ) + }), ); } ty::PredicateAtom::TypeWellFormedFromEnv(..) => { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 1e8c30071e762..3abd9a6325d6e 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -200,7 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ty::Adt(def, _) => check_must_use_def(cx, def.did, span, descr_pre, descr_post), ty::Opaque(def, _) => { let mut has_emitted = false; - for (predicate, _) in cx.tcx.predicates_of(def).predicates { + for &(predicate, _) in cx.tcx.explicit_item_bounds(def) { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateAtom::Trait(ref poly_trait_predicate, _) = predicate.skip_binders() diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 8b11d2c913ac2..2662f6b6ed65c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -937,7 +937,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .inferred_outlives .get(self, item_id) - .map(|predicates| predicates.decode((self, tcx))) + .map(|predicates| tcx.arena.alloc_from_iter(predicates.decode((self, tcx)))) .unwrap_or_default() } @@ -949,6 +949,19 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.super_predicates.get(self, item_id).unwrap().decode((self, tcx)) } + fn get_explicit_item_bounds( + &self, + item_id: DefIndex, + tcx: TyCtxt<'tcx>, + ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + self.root + .tables + .explicit_item_bounds + .get(self, item_id) + .map(|bounds| tcx.arena.alloc_from_iter(bounds.decode((self, tcx)))) + .unwrap_or_default() + } + fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics { self.root.tables.generics.get(self, item_id).unwrap().decode((self, sess)) } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 578ce382912f0..60705f68681a1 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -89,6 +89,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, explicit_predicates_of => { cdata.get_explicit_predicates(def_id.index, tcx) } inferred_outlives_of => { cdata.get_inferred_outlives(def_id.index, tcx) } super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) } + explicit_item_bounds => { cdata.get_explicit_item_bounds(def_id.index, tcx) } trait_def => { cdata.get_trait_def(def_id.index, tcx.sess) } adt_def => { cdata.get_adt_def(def_id.index, tcx) } adt_destructor => { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 4350ac5c27a88..f0911928e81c9 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -965,6 +965,14 @@ impl EncodeContext<'a, 'tcx> { record!(self.tables.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id)); } + fn encode_explicit_item_bounds(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id); + let bounds = self.tcx.explicit_item_bounds(def_id); + if !bounds.is_empty() { + record!(self.tables.explicit_item_bounds[def_id] <- bounds); + } + } + fn encode_info_for_trait_item(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; @@ -1017,7 +1025,10 @@ impl EncodeContext<'a, 'tcx> { has_self: trait_item.fn_has_self_parameter, })) } - ty::AssocKind::Type => EntryKind::AssocType(container), + ty::AssocKind::Type => { + self.encode_explicit_item_bounds(def_id); + EntryKind::AssocType(container) + } }); record!(self.tables.visibility[def_id] <- trait_item.vis); record!(self.tables.span[def_id] <- ast_item.span); @@ -1255,7 +1266,10 @@ impl EncodeContext<'a, 'tcx> { hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod, hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, hir::ItemKind::TyAlias(..) => EntryKind::Type, - hir::ItemKind::OpaqueTy(..) => EntryKind::OpaqueTy, + hir::ItemKind::OpaqueTy(..) => { + self.encode_explicit_item_bounds(def_id); + EntryKind::OpaqueTy + } hir::ItemKind::Enum(..) => EntryKind::Enum(self.tcx.adt_def(def_id).repr), hir::ItemKind::Struct(ref struct_def, _) => { let adt_def = self.tcx.adt_def(def_id); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 9e26d02e4e16d..2bd2019d3cdb5 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -295,13 +295,11 @@ define_tables! { generics: Table>, explicit_predicates: Table)>, expn_that_defined: Table>, - // FIXME(eddyb) this would ideally be `Lazy<[...]>` but `ty::Predicate` - // doesn't handle shorthands in its own (de)serialization impls, - // as it's an `enum` for which we want to derive (de)serialization, - // so the `ty::codec` APIs handle the whole `&'tcx [...]` at once. - // Also, as an optimization, a missing entry indicates an empty `&[]`. - inferred_outlives: Table, Span)])>, + // As an optimization, a missing entry indicates an empty `&[]`. + inferred_outlives: Table, Span)])>, super_predicates: Table)>, + // As an optimization, a missing entry indicates an empty `&[]`. + explicit_item_bounds: Table, Span)])>, mir: Table)>, promoted_mir: Table>)>, mir_abstract_consts: Table])>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index fe115bbb9c334..fc4c343372a42 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -156,12 +156,11 @@ rustc_queries! { cache_on_disk_if { key.is_local() } } - /// Returns the list of predicates that can be used for - /// `SelectionCandidate::ProjectionCandidate` and + /// Returns the list of bounds that can be used for + /// `SelectionCandidate::ProjectionCandidate(_)` and /// `ProjectionTyCandidate::TraitDef`. - /// Specifically this is the bounds (equivalent to) those - /// written on the trait's type definition, or those - /// after the `impl` keyword + /// Specifically this is the bounds written on the trait's type + /// definition, or those after the `impl` keyword /// /// type X: Bound + 'lt /// ^^^^^^^^^^^ @@ -169,8 +168,30 @@ rustc_queries! { /// ^^^^^^^^^^^^^^^ /// /// `key` is the `DefId` of the associated type or opaque type. - query projection_predicates(key: DefId) -> &'tcx ty::List> { - desc { |tcx| "finding projection predicates for `{}`", tcx.def_path_str(key) } + /// + /// Bounds from the parent (e.g. with nested impl trait) are not included. + query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } + } + + /// Elaborated version of the predicates from `explicit_item_bounds`. + /// + /// Example for + /// + /// trait MyTrait { + /// type MyAType: Eq + ?Sized` + /// } + /// + /// `explicit_item_bounds` returns `[::MyAType: Eq]`, + /// and `item_bounds` returns + /// [ + /// ::MyAType: Eq, + /// ::MyAType: PartialEq<::MyAType> + /// ] + /// + /// Bounds from the parent (e.g. with nested impl trait) are not included. + query item_bounds(key: DefId) -> &'tcx ty::List> { + desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } query projection_ty_from_predicates(key: (DefId, DefId)) -> Option> { @@ -370,6 +391,24 @@ rustc_queries! { desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) } } + /// Returns everything that looks like a predicate written explicitly + /// by the user on a trait item. + /// + /// Traits are unusual, because predicates on associated types are + /// converted into bounds on that type for backwards compatibility: + /// + /// trait X where Self::U: Copy { type U; } + /// + /// becomes + /// + /// trait X { type U: Copy; } + /// + /// `explicit_predicates_of` and `explicit_item_bounds` will then take + /// the appropriate subsets of the predicates here. + query trait_explicit_predicates_and_bounds(key: LocalDefId) -> ty::GenericPredicates<'tcx> { + desc { |tcx| "computing explicit predicates of trait `{}`", tcx.def_path_str(key.to_def_id()) } + } + /// Returns the predicates written explicitly by the user. query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) } diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 6ad514c6be21b..358ead507b4d0 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -105,9 +105,10 @@ pub enum SelectionCandidate<'tcx> { ImplCandidate(DefId), AutoImplCandidate(DefId), - /// This is a trait matching with a projected type as `Self`, and - /// we found an applicable bound in the trait definition. - ProjectionCandidate, + /// This is a trait matching with a projected type as `Self`, and we found + /// an applicable bound in the trait definition. The `usize` is an index + /// into the list returned by `tcx.item_bounds`. + ProjectionCandidate(usize), /// Implementation of a `Fn`-family trait by one of the anonymous types /// generated for a `||` expression. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 238bce94cf505..e1f02d0f70418 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -607,12 +607,13 @@ pub trait PrettyPrinter<'tcx>: } // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. - let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs); + let bounds = self.tcx().explicit_item_bounds(def_id); let mut first = true; let mut is_sized = false; p!("impl"); - for predicate in bounds.predicates { + for (predicate, _) in bounds { + let predicate = predicate.subst(self.tcx(), substs); // Note: We can't use `to_opt_poly_trait_ref` here as `predicate` // may contain unbound variables. We therefore do this manually. // diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 5cba451ea6e3c..1af56972ad083 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1513,6 +1513,9 @@ impl<'tcx> ExistentialProjection<'tcx> { /// then this function would return a `exists T. T: Iterator` existential trait /// reference. pub fn trait_ref(&self, tcx: TyCtxt<'_>) -> ty::ExistentialTraitRef<'tcx> { + // FIXME(generic_associated_types): substs is the substs of the + // associated type, which should be truncated to get the correct substs + // for the trait. let def_id = tcx.associated_item(self.item_def_id).container.id(); ty::ExistentialTraitRef { def_id, substs: self.substs } } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs index b145e1d5fa333..e22dab0151703 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs @@ -6,6 +6,7 @@ use rustc_infer::infer::{ error_reporting::unexpected_hidden_region_diagnostic, NLLRegionVariableOrigin, }; use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; +use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; @@ -585,14 +586,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // // eg. check for `impl Trait + 'static` instead of `impl Trait`. let has_static_predicate = { - let predicates_of = self.infcx.tcx.predicates_of(did); - let bounds = predicates_of.instantiate(self.infcx.tcx, substs); + let bounds = self.infcx.tcx.explicit_item_bounds(did); let mut found = false; - for predicate in bounds.predicates { + for (bound, _) in bounds { if let ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(_, r)) = - predicate.skip_binders() + bound.skip_binders() { + let r = r.subst(self.infcx.tcx, substs); if let ty::RegionKind::ReStatic = r { found = true; break; diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 8d1b826ea3595..8f93bce6e9923 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -194,11 +194,14 @@ where // The intent is to treat `impl Trait1 + Trait2` identically to // `dyn Trait1 + Trait2`. Therefore we ignore def-id of the opaque type itself // (it either has no visibility, or its visibility is insignificant, like - // visibilities of type aliases) and recurse into predicates instead to go + // visibilities of type aliases) and recurse into bounds instead to go // through the trait list (default type visitor doesn't visit those traits). // All traits in the list are considered the "primary" part of the type // and are visited by shallow visitors. - if self.visit_predicates(tcx.predicates_of(def_id)) { + if self.visit_predicates(ty::GenericPredicates { + parent: None, + predicates: tcx.explicit_item_bounds(def_id), + }) { return true; } } @@ -1800,6 +1803,14 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { self } + fn bounds(&mut self) -> &mut Self { + self.visit_predicates(ty::GenericPredicates { + parent: None, + predicates: self.tcx.explicit_item_bounds(self.item_def_id), + }); + self + } + fn ty(&mut self) -> &mut Self { self.visit(self.tcx.type_of(self.item_def_id)); self @@ -1975,7 +1986,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> hir::ItemKind::OpaqueTy(..) => { // `ty()` for opaque types is the underlying type, // it's not a part of interface, so we skip it. - self.check(item.hir_id, item_visibility).generics().predicates(); + self.check(item.hir_id, item_visibility).generics().bounds(); } hir::ItemKind::Trait(.., trait_item_refs) => { self.check(item.hir_id, item_visibility).generics().predicates(); @@ -1987,6 +1998,10 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> trait_item_ref.defaultness, item_visibility, ); + + if let AssocItemKind::Type = trait_item_ref.kind { + self.check(trait_item_ref.id.hir_id, item_visibility).bounds(); + } } } hir::ItemKind::TraitAlias(..) => { diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 618f3e045e712..610c6fd7e35f8 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -10,7 +10,7 @@ use rustc_infer::infer::free_regions::FreeRegionRelations; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{self, InferCtxt, InferOk}; use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef}; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::config::nightly_options; use rustc_span::Span; @@ -428,14 +428,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // If there are required region bounds, we can use them. if opaque_defn.has_required_region_bounds { - let predicates_of = tcx.predicates_of(def_id); - debug!("constrain_opaque_type: predicates: {:#?}", predicates_of,); - let bounds = predicates_of.instantiate(tcx, opaque_defn.substs); + let bounds = tcx.explicit_item_bounds(def_id); + debug!("constrain_opaque_type: predicates: {:#?}", bounds); + let bounds: Vec<_> = + bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_defn.substs)).collect(); debug!("constrain_opaque_type: bounds={:#?}", bounds); let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs); let required_region_bounds = - required_region_bounds(tcx, opaque_type, bounds.predicates.into_iter()); + required_region_bounds(tcx, opaque_type, bounds.into_iter()); debug_assert!(!required_region_bounds.is_empty()); for required_region in required_region_bounds { @@ -1112,9 +1113,10 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { let ty_var = infcx .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }); - let predicates_of = tcx.predicates_of(def_id); - debug!("instantiate_opaque_types: predicates={:#?}", predicates_of,); - let bounds = predicates_of.instantiate(tcx, substs); + let item_bounds = tcx.explicit_item_bounds(def_id); + debug!("instantiate_opaque_types: bounds={:#?}", item_bounds); + let bounds: Vec<_> = + item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect(); let param_env = tcx.param_env(def_id); let InferOk { value: bounds, obligations } = @@ -1123,8 +1125,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { debug!("instantiate_opaque_types: bounds={:?}", bounds); - let required_region_bounds = - required_region_bounds(tcx, ty, bounds.predicates.iter().cloned()); + let required_region_bounds = required_region_bounds(tcx, ty, bounds.iter().copied()); debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds); // Make sure that we are in fact defining the *entire* type @@ -1153,7 +1154,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { ); debug!("instantiate_opaque_types: ty_var={:?}", ty_var); - for predicate in &bounds.predicates { + for predicate in &bounds { if let ty::PredicateAtom::Projection(projection) = predicate.skip_binders() { if projection.ty.references_error() { // No point on adding these obligations since there's a type error involved. @@ -1162,14 +1163,14 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { } } - self.obligations.reserve(bounds.predicates.len()); - for predicate in bounds.predicates { + self.obligations.reserve(bounds.len()); + for predicate in bounds { // Change the predicate to refer to the type variable, // which will be the concrete type instead of the opaque type. // This also instantiates nested instances of `impl Trait`. let predicate = self.instantiate_opaque_types_in_map(&predicate); - let cause = traits::ObligationCause::new(span, self.body_id, traits::SizedReturnType); + let cause = traits::ObligationCause::new(span, self.body_id, traits::MiscObligation); // Require that the predicate holds for the concrete type. debug!("instantiate_opaque_types: predicate={:?}", predicate); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 8586a550230f9..27751eb554d3c 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -376,7 +376,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { | ty::PredicateAtom::Subtype(_) | ty::PredicateAtom::ConstEvaluatable(..) | ty::PredicateAtom::ConstEquate(..) => { - let (pred, _) = infcx.replace_bound_vars_with_placeholders(binder); + let pred = infcx.replace_bound_vars_with_placeholders(binder); ProcessResult::Changed(mk_pending(vec![ obligation.with(pred.to_predicate(self.selcx.tcx())), ])) @@ -449,6 +449,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { self.selcx.infcx(), obligation.param_env, obligation.cause.body_id, + obligation.recursion_depth + 1, arg, obligation.cause.span, ) { @@ -672,7 +673,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { Ok(Ok(None)) => { *stalled_on = trait_ref_infer_vars( self.selcx, - project_obligation.predicate.to_poly_trait_ref(self.selcx.tcx()), + project_obligation.predicate.to_poly_trait_ref(tcx), ); ProcessResult::Unchanged } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 8fc14cb29971d..0e43f1655ddb2 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -160,6 +160,10 @@ fn object_safety_violations_for_trait( if !spans.is_empty() { violations.push(ObjectSafetyViolation::SupertraitSelf(spans)); } + let spans = bounds_reference_self(tcx, trait_def_id); + if !spans.is_empty() { + violations.push(ObjectSafetyViolation::SupertraitSelf(spans)); + } violations.extend( tcx.associated_items(trait_def_id) @@ -239,51 +243,70 @@ fn predicates_reference_self( } else { tcx.predicates_of(trait_def_id) }; - let self_ty = tcx.types.self_param; - let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into()); predicates .predicates .iter() - .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp)) - .filter_map(|(predicate, &sp)| { - match predicate.skip_binders() { - ty::PredicateAtom::Trait(ref data, _) => { - // In the case of a trait predicate, we can skip the "self" type. - if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None } - } - ty::PredicateAtom::Projection(ref data) => { - // And similarly for projections. This should be redundant with - // the previous check because any projection should have a - // matching `Trait` predicate with the same inputs, but we do - // the check to be safe. - // - // Note that we *do* allow projection *outputs* to contain - // `self` (i.e., `trait Foo: Bar { type Result; }`), - // we just require the user to specify *both* outputs - // in the object type (i.e., `dyn Foo`). - // - // This is ALT2 in issue #56288, see that for discussion of the - // possible alternatives. - if data.projection_ty.trait_ref(tcx).substs[1..].iter().any(has_self_ty) { - Some(sp) - } else { - None - } - } - ty::PredicateAtom::WellFormed(..) - | ty::PredicateAtom::ObjectSafe(..) - | ty::PredicateAtom::TypeOutlives(..) - | ty::PredicateAtom::RegionOutlives(..) - | ty::PredicateAtom::ClosureKind(..) - | ty::PredicateAtom::Subtype(..) - | ty::PredicateAtom::ConstEvaluatable(..) - | ty::PredicateAtom::ConstEquate(..) - | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None, - } - }) + .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), *sp)) + .filter_map(|predicate| predicate_references_self(tcx, predicate)) + .collect() +} + +fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> { + let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id)); + tcx.associated_items(trait_def_id) + .in_definition_order() + .filter(|item| item.kind == ty::AssocKind::Type) + .flat_map(|item| tcx.explicit_item_bounds(item.def_id)) + .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), *sp)) + .filter_map(|predicate| predicate_references_self(tcx, predicate)) .collect() } +fn predicate_references_self( + tcx: TyCtxt<'tcx>, + (predicate, sp): (ty::Predicate<'tcx>, Span), +) -> Option { + let self_ty = tcx.types.self_param; + let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into()); + match predicate.skip_binders() { + ty::PredicateAtom::Trait(ref data, _) => { + // In the case of a trait predicate, we can skip the "self" type. + if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None } + } + ty::PredicateAtom::Projection(ref data) => { + // And similarly for projections. This should be redundant with + // the previous check because any projection should have a + // matching `Trait` predicate with the same inputs, but we do + // the check to be safe. + // + // It's also won't be redundant if we allow type-generic associated + // types for trait objects. + // + // Note that we *do* allow projection *outputs* to contain + // `self` (i.e., `trait Foo: Bar { type Result; }`), + // we just require the user to specify *both* outputs + // in the object type (i.e., `dyn Foo`). + // + // This is ALT2 in issue #56288, see that for discussion of the + // possible alternatives. + if data.projection_ty.trait_ref(tcx).substs[1..].iter().any(has_self_ty) { + Some(sp) + } else { + None + } + } + ty::PredicateAtom::WellFormed(..) + | ty::PredicateAtom::ObjectSafe(..) + | ty::PredicateAtom::TypeOutlives(..) + | ty::PredicateAtom::RegionOutlives(..) + | ty::PredicateAtom::ClosureKind(..) + | ty::PredicateAtom::Subtype(..) + | ty::PredicateAtom::ConstEvaluatable(..) + | ty::PredicateAtom::ConstEquate(..) + | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None, + } +} + fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { generics_require_sized_self(tcx, trait_def_id) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index ef8f7b69b5d60..de42aa0e6b764 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1,6 +1,5 @@ //! Code for projecting associated types out of trait references. -use super::elaborate_predicates; use super::specialization_graph; use super::translate_substs; use super::util; @@ -29,7 +28,6 @@ use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_span::symbol::sym; -use rustc_span::DUMMY_SP; pub use rustc_middle::traits::Reveal; @@ -53,13 +51,16 @@ pub enum ProjectionTyError<'tcx> { #[derive(PartialEq, Eq, Debug)] enum ProjectionTyCandidate<'tcx> { - // from a where-clause in the env or object type + /// From a where-clause in the env or object type ParamEnv(ty::PolyProjectionPredicate<'tcx>), - // from the definition of `Trait` when you have something like <::B as Trait2>::C + /// From the definition of `Trait` when you have something like <::B as Trait2>::C TraitDef(ty::PolyProjectionPredicate<'tcx>), - // from a "impl" (or a "pseudo-impl" returned by select) + /// Bounds specified on an object type + Object(ty::PolyProjectionPredicate<'tcx>), + + /// From a "impl" (or a "pseudo-impl" returned by select) Select(Selection<'tcx>), } @@ -167,7 +168,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( let infcx = selcx.infcx(); infcx.commit_if_ok(|_snapshot| { - let (placeholder_predicate, _) = + let placeholder_predicate = infcx.replace_bound_vars_with_placeholders(&obligation.predicate); let placeholder_obligation = obligation.with(placeholder_predicate); @@ -561,14 +562,6 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( } else { obligations.extend(ty.obligations); } - - obligations.push(get_paranoid_cache_value_obligation( - infcx, - param_env, - projection_ty, - cause, - depth, - )); return Ok(Some(ty.value)); } Err(ProjectionCacheEntry::Error) => { @@ -703,45 +696,6 @@ fn prune_cache_value_obligations<'a, 'tcx>( NormalizedTy { value: result.value, obligations } } -/// Whenever we give back a cache result for a projection like `::Item ==> X`, we *always* include the obligation to prove -/// that `T: Trait` (we may also include some other obligations). This -/// may or may not be necessary -- in principle, all the obligations -/// that must be proven to show that `T: Trait` were also returned -/// when the cache was first populated. But there are some vague concerns, -/// and so we take the precautionary measure of including `T: Trait` in -/// the result: -/// -/// Concern #1. The current setup is fragile. Perhaps someone could -/// have failed to prove the concerns from when the cache was -/// populated, but also not have used a snapshot, in which case the -/// cache could remain populated even though `T: Trait` has not been -/// shown. In this case, the "other code" is at fault -- when you -/// project something, you are supposed to either have a snapshot or -/// else prove all the resulting obligations -- but it's still easy to -/// get wrong. -/// -/// Concern #2. Even within the snapshot, if those original -/// obligations are not yet proven, then we are able to do projections -/// that may yet turn out to be wrong. This *may* lead to some sort -/// of trouble, though we don't have a concrete example of how that -/// can occur yet. But it seems risky at best. -fn get_paranoid_cache_value_obligation<'a, 'tcx>( - infcx: &'a InferCtxt<'a, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - projection_ty: ty::ProjectionTy<'tcx>, - cause: ObligationCause<'tcx>, - depth: usize, -) -> PredicateObligation<'tcx> { - let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref(); - Obligation { - cause, - recursion_depth: depth, - param_env, - predicate: trait_ref.without_const().to_predicate(infcx.tcx), - } -} - /// If we are projecting `::Item`, but `T: Trait` does not /// hold. In various error cases, we cannot generate a valid /// normalized projection. Therefore, we create an inference variable @@ -848,12 +802,21 @@ fn project_type<'cx, 'tcx>( assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates); - assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates); + assemble_candidates_from_object_ty(selcx, obligation, &obligation_trait_ref, &mut candidates); + + if let ProjectionTyCandidateSet::Single(ProjectionTyCandidate::Object(_)) = candidates { + // Avoid normalization cycle from selection (see + // `assemble_candidates_from_object_ty`). + // FIXME(lazy_normalization): Lazy normalization should save us from + // having to do special case this. + } else { + assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates); + }; match candidates { - ProjectionTyCandidateSet::Single(candidate) => Ok(ProjectedTy::Progress( - confirm_candidate(selcx, obligation, &obligation_trait_ref, candidate), - )), + ProjectionTyCandidateSet::Single(candidate) => { + Ok(ProjectedTy::Progress(confirm_candidate(selcx, obligation, candidate))) + } ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress( selcx .tcx() @@ -884,6 +847,7 @@ fn assemble_candidates_from_param_env<'cx, 'tcx>( candidate_set, ProjectionTyCandidate::ParamEnv, obligation.param_env.caller_bounds().iter(), + false, ); } @@ -909,10 +873,8 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( // Check whether the self-type is itself a projection. // If so, extract what we know from the trait and try to come up with a good answer. let bounds = match *obligation_trait_ref.self_ty().kind() { - ty::Projection(ref data) => { - tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs) - } - ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs), + ty::Projection(ref data) => tcx.item_bounds(data.item_def_id).subst(tcx, data.substs), + ty::Opaque(def_id, substs) => tcx.item_bounds(def_id).subst(tcx, substs), ty::Infer(ty::TyVar(_)) => { // If the self-type is an inference variable, then it MAY wind up // being a projected type, so induce an ambiguity. @@ -929,9 +891,57 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( candidate_set, ProjectionTyCandidate::TraitDef, bounds.iter(), + true, ) } +/// In the case of a trait object like +/// ` as Iterator>::Item` we can use the existential +/// predicate in the trait object. +/// +/// We don't go through the select candidate for these bounds to avoid cycles: +/// In the above case, `dyn Iterator: Iterator` would create a +/// nested obligation of ` as Iterator>::Item: Sized`, +/// this then has to be normalized without having to prove +/// `dyn Iterator: Iterator` again. +fn assemble_candidates_from_object_ty<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &ty::TraitRef<'tcx>, + candidate_set: &mut ProjectionTyCandidateSet<'tcx>, +) { + debug!("assemble_candidates_from_object_ty(..)"); + + let tcx = selcx.tcx(); + + let self_ty = obligation_trait_ref.self_ty(); + let object_ty = selcx.infcx().shallow_resolve(self_ty); + let data = match object_ty.kind() { + ty::Dynamic(data, ..) => data, + ty::Infer(ty::TyVar(_)) => { + // If the self-type is an inference variable, then it MAY wind up + // being an object type, so induce an ambiguity. + candidate_set.mark_ambiguous(); + return; + } + _ => return, + }; + let env_predicates = data + .projection_bounds() + .filter(|bound| bound.item_def_id() == obligation.predicate.item_def_id) + .map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx)); + + assemble_candidates_from_predicates( + selcx, + obligation, + obligation_trait_ref, + candidate_set, + ProjectionTyCandidate::Object, + env_predicates, + false, + ); +} + fn assemble_candidates_from_predicates<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, @@ -939,6 +949,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( candidate_set: &mut ProjectionTyCandidateSet<'tcx>, ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>, env_predicates: impl Iterator>, + potentially_unnormalized_candidates: bool, ) { debug!("assemble_candidates_from_predicates(obligation={:?})", obligation); let infcx = selcx.infcx(); @@ -950,16 +961,12 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( let is_match = same_def_id && infcx.probe(|_| { - let data_poly_trait_ref = data.to_poly_trait_ref(infcx.tcx); - let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); - infcx - .at(&obligation.cause, obligation.param_env) - .sup(obligation_poly_trait_ref, data_poly_trait_ref) - .map(|InferOk { obligations: _, value: () }| { - // FIXME(#32730) -- do we need to take obligations - // into account in any way? At the moment, no. - }) - .is_ok() + selcx.match_projection_projections( + obligation, + obligation_trait_ref, + &data, + potentially_unnormalized_candidates, + ) }); debug!( @@ -970,6 +977,15 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( if is_match { candidate_set.push_candidate(ctor(data)); + + if potentially_unnormalized_candidates + && !obligation.predicate.has_infer_types_or_consts() + { + // HACK: Pick the first trait def candidate for a fully + // inferred predicate. This is to allow duplicates that + // differ only in normalization. + return; + } } } } @@ -1003,7 +1019,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( super::ImplSource::Closure(_) | super::ImplSource::Generator(_) | super::ImplSource::FnPointer(_) - | super::ImplSource::Object(_) | super::ImplSource::TraitAlias(_) => { debug!("assemble_candidates_from_impls: impl_source={:?}", impl_source); true @@ -1128,6 +1143,12 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // in `assemble_candidates_from_param_env`. false } + super::ImplSource::Object(_) => { + // Handled by the `Object` projection candidate. See + // `assemble_candidates_from_object_ty` for an explanation of + // why we special case object types. + false + } super::ImplSource::AutoImpl(..) | super::ImplSource::Builtin(..) => { // These traits have no associated types. selcx.tcx().sess.delay_span_bug( @@ -1153,19 +1174,22 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( fn confirm_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - obligation_trait_ref: &ty::TraitRef<'tcx>, candidate: ProjectionTyCandidate<'tcx>, ) -> Progress<'tcx> { debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation); let mut progress = match candidate { ProjectionTyCandidate::ParamEnv(poly_projection) - | ProjectionTyCandidate::TraitDef(poly_projection) => { - confirm_param_env_candidate(selcx, obligation, poly_projection) + | ProjectionTyCandidate::Object(poly_projection) => { + confirm_param_env_candidate(selcx, obligation, poly_projection, false) + } + + ProjectionTyCandidate::TraitDef(poly_projection) => { + confirm_param_env_candidate(selcx, obligation, poly_projection, true) } ProjectionTyCandidate::Select(impl_source) => { - confirm_select_candidate(selcx, obligation, obligation_trait_ref, impl_source) + confirm_select_candidate(selcx, obligation, impl_source) } }; // When checking for cycle during evaluation, we compare predicates with @@ -1182,7 +1206,6 @@ fn confirm_candidate<'cx, 'tcx>( fn confirm_select_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - obligation_trait_ref: &ty::TraitRef<'tcx>, impl_source: Selection<'tcx>, ) -> Progress<'tcx> { match impl_source { @@ -1193,10 +1216,8 @@ fn confirm_select_candidate<'cx, 'tcx>( super::ImplSource::DiscriminantKind(data) => { confirm_discriminant_kind_candidate(selcx, obligation, data) } - super::ImplSource::Object(_) => { - confirm_object_candidate(selcx, obligation, obligation_trait_ref) - } - super::ImplSource::AutoImpl(..) + super::ImplSource::Object(_) + | super::ImplSource::AutoImpl(..) | super::ImplSource::Param(..) | super::ImplSource::Builtin(..) | super::ImplSource::TraitAlias(..) => @@ -1211,72 +1232,6 @@ fn confirm_select_candidate<'cx, 'tcx>( } } -fn confirm_object_candidate<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - obligation_trait_ref: &ty::TraitRef<'tcx>, -) -> Progress<'tcx> { - let self_ty = obligation_trait_ref.self_ty(); - let object_ty = selcx.infcx().shallow_resolve(self_ty); - debug!("confirm_object_candidate(object_ty={:?})", object_ty); - let data = match object_ty.kind() { - ty::Dynamic(data, ..) => data, - _ => span_bug!( - obligation.cause.span, - "confirm_object_candidate called with non-object: {:?}", - object_ty - ), - }; - let env_predicates = data - .projection_bounds() - .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate(selcx.tcx())); - let env_predicate = { - let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates); - - // select only those projections that are actually projecting an - // item with the correct name - - let env_predicates = env_predicates.filter_map(|o| match o.predicate.skip_binders() { - ty::PredicateAtom::Projection(data) - if data.projection_ty.item_def_id == obligation.predicate.item_def_id => - { - Some(ty::Binder::bind(data)) - } - _ => None, - }); - - // select those with a relevant trait-ref - let mut env_predicates = env_predicates.filter(|data| { - let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx()); - let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); - selcx.infcx().probe(|_| { - selcx - .infcx() - .at(&obligation.cause, obligation.param_env) - .sup(obligation_poly_trait_ref, data_poly_trait_ref) - .is_ok() - }) - }); - - // select the first matching one; there really ought to be one or - // else the object type is not WF, since an object type should - // include all of its projections explicitly - match env_predicates.next() { - Some(env_predicate) => env_predicate, - None => { - debug!( - "confirm_object_candidate: no env-predicate \ - found in object type `{:?}`; ill-formed", - object_ty - ); - return Progress::error(selcx.tcx()); - } - } - }; - - confirm_param_env_candidate(selcx, obligation, env_predicate) -} - fn confirm_generator_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, @@ -1325,7 +1280,7 @@ fn confirm_generator_candidate<'cx, 'tcx>( } }); - confirm_param_env_candidate(selcx, obligation, predicate) + confirm_param_env_candidate(selcx, obligation, predicate, false) .with_addl_obligations(impl_source.nested) .with_addl_obligations(obligations) } @@ -1347,7 +1302,7 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>( ty: self_ty.discriminant_ty(tcx), }; - confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate)) + confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate), false) } fn confirm_fn_pointer_candidate<'cx, 'tcx>( @@ -1422,13 +1377,14 @@ fn confirm_callable_candidate<'cx, 'tcx>( ty: ret_type, }); - confirm_param_env_candidate(selcx, obligation, predicate) + confirm_param_env_candidate(selcx, obligation, predicate, false) } fn confirm_param_env_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, poly_cache_entry: ty::PolyProjectionPredicate<'tcx>, + potentially_unnormalized_candidate: bool, ) -> Progress<'tcx> { let infcx = selcx.infcx(); let cause = &obligation.cause; @@ -1442,8 +1398,28 @@ fn confirm_param_env_candidate<'cx, 'tcx>( let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx); let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx); + let mut nested_obligations = Vec::new(); + let cache_trait_ref = if potentially_unnormalized_candidate { + ensure_sufficient_stack(|| { + normalize_with_depth_to( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &cache_trait_ref, + &mut nested_obligations, + ) + }) + } else { + cache_trait_ref + }; + match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) { - Ok(InferOk { value: _, obligations }) => Progress { ty: cache_entry.ty, obligations }, + Ok(InferOk { value: _, obligations }) => { + nested_obligations.extend(obligations); + assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations); + Progress { ty: cache_entry.ty, obligations: nested_obligations } + } Err(e) => { let msg = format!( "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}", @@ -1463,7 +1439,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( ) -> Progress<'tcx> { let tcx = selcx.tcx(); - let ImplSourceUserDefinedData { impl_def_id, substs, nested } = impl_impl_source; + let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source; let assoc_item_id = obligation.predicate.item_def_id; let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); @@ -1496,15 +1472,48 @@ fn confirm_impl_candidate<'cx, 'tcx>( let ty = tcx.type_of(assoc_ty.item.def_id); if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() { let err = tcx.ty_error_with_message( - DUMMY_SP, + obligation.cause.span, "impl item and trait item have different parameter counts", ); Progress { ty: err, obligations: nested } } else { + assoc_ty_own_obligations(selcx, obligation, &mut nested); Progress { ty: ty.subst(tcx, substs), obligations: nested } } } +// Get obligations corresponding to the predicates from the where-clause of the +// associated type itself. +// Note: `feature(generic_associated_types)` is required to write such +// predicates, even for non-generic associcated types. +fn assoc_ty_own_obligations<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + nested: &mut Vec>, +) { + let tcx = selcx.tcx(); + for predicate in tcx + .predicates_of(obligation.predicate.item_def_id) + .instantiate_own(tcx, obligation.predicate.substs) + .predicates + { + let normalized = normalize_with_depth_to( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &predicate, + nested, + ); + nested.push(Obligation::with_depth( + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + normalized, + )); + } +} + /// Locate the definition of an associated type in the specialization hierarchy, /// starting from the given impl. /// diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 9cb5c232646f8..038ba431c47d3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -165,7 +165,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("winnowed to {} candidates for {:?}: {:?}", candidates.len(), stack, candidates); - let needs_infer = stack.obligation.predicate.needs_infer(); + let needs_infer = stack.obligation.predicate.has_infer_types_or_consts(); // If there are STILL multiple candidates, we can further // reduce the list by dropping duplicates -- including @@ -327,8 +327,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .infcx .probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); - if result { - candidates.vec.push(ProjectionCandidate); + for predicate_index in result { + candidates.vec.push(ProjectionCandidate(predicate_index)); } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 88b656ce68082..96f0bedf6f1a7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -10,12 +10,13 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; +use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{ToPolyTraitRef, ToPredicate, WithConstness}; use rustc_span::def_id::DefId; -use crate::traits::project::{self, normalize_with_depth}; +use crate::traits::project::{normalize_with_depth, normalize_with_depth_to}; use crate::traits::select::TraitObligationExt; use crate::traits::util; use crate::traits::util::{closure_trait_ref_and_return_type, predicate_for_trait_def}; @@ -68,9 +69,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(ImplSource::AutoImpl(data)) } - ProjectionCandidate => { - self.confirm_projection_candidate(obligation); - Ok(ImplSource::Param(Vec::new())) + ProjectionCandidate(idx) => { + let obligations = self.confirm_projection_candidate(obligation, idx); + Ok(ImplSource::Param(obligations)) } ClosureCandidate => { @@ -116,10 +117,72 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { + fn confirm_projection_candidate( + &mut self, + obligation: &TraitObligation<'tcx>, + idx: usize, + ) -> Vec> { self.infcx.commit_unconditionally(|_| { - let result = self.match_projection_obligation_against_definition_bounds(obligation); - assert!(result); + let tcx = self.tcx(); + + let trait_predicate = self.infcx.shallow_resolve(obligation.predicate); + let placeholder_trait_predicate = + self.infcx().replace_bound_vars_with_placeholders(&trait_predicate); + let placeholder_self_ty = placeholder_trait_predicate.self_ty(); + let (def_id, substs) = match *placeholder_self_ty.kind() { + ty::Projection(proj) => (proj.item_def_id, proj.substs), + ty::Opaque(def_id, substs) => (def_id, substs), + _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty), + }; + + let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs); + let candidate = candidate_predicate + .to_opt_poly_trait_ref() + .expect("projection candidate is not a trait predicate"); + let mut obligations = Vec::new(); + let candidate = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &candidate, + &mut obligations, + ); + + obligations.extend( + self.infcx + .at(&obligation.cause, obligation.param_env) + .sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate) + .map(|InferOk { obligations, .. }| obligations) + .unwrap_or_else(|_| { + bug!( + "Projection bound `{:?}` was applicable to `{:?}` but now is not", + candidate, + obligation + ); + }), + ); + + if let ty::Projection(..) = placeholder_self_ty.kind() { + for predicate in tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates { + let normalized = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &predicate, + &mut obligations, + ); + obligations.push(Obligation::with_depth( + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + normalized, + )); + } + } + + obligations }) } @@ -229,7 +292,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let trait_obligations: Vec> = self.infcx.commit_unconditionally(|_| { let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); - let (trait_ref, _) = + let trait_ref = self.infcx.replace_bound_vars_with_placeholders(&poly_trait_ref); let cause = obligation.derived_cause(ImplDerivedObligation); self.impl_or_trait_obligations( @@ -307,55 +370,70 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // relying on projections in the impl-trait-ref. // // e.g., `impl> Foo<::T> for V` - impl_obligations.append(&mut substs.obligations); + substs.obligations.append(&mut impl_obligations); - ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: impl_obligations } + ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: substs.obligations } } fn confirm_object_candidate( &mut self, obligation: &TraitObligation<'tcx>, ) -> ImplSourceObjectData<'tcx, PredicateObligation<'tcx>> { + let tcx = self.tcx(); debug!("confirm_object_candidate({:?})", obligation); - // FIXME(nmatsakis) skipping binder here seems wrong -- we should - // probably flatten the binder from the obligation and the binder - // from the object. Have to try to make a broken test case that - // results. - let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); - let poly_trait_ref = match self_ty.kind() { - ty::Dynamic(data, ..) => data - .principal() - .unwrap_or_else(|| { - span_bug!(obligation.cause.span, "object candidate with no principal") - }) - .with_self_ty(self.tcx(), self_ty), + let trait_predicate = + self.infcx.replace_bound_vars_with_placeholders(&obligation.predicate); + let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty()); + let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref); + let data = match self_ty.kind() { + ty::Dynamic(data, ..) => { + self.infcx + .replace_bound_vars_with_fresh_vars( + obligation.cause.span, + HigherRankedType, + data, + ) + .0 + } _ => span_bug!(obligation.cause.span, "object candidate with non-object"), }; + let object_trait_ref = data + .principal() + .unwrap_or_else(|| { + span_bug!(obligation.cause.span, "object candidate with no principal") + }) + .with_self_ty(self.tcx(), self_ty); + let mut upcast_trait_ref = None; let mut nested = vec![]; let vtable_base; { - let tcx = self.tcx(); - // We want to find the first supertrait in the list of // supertraits that we can unify with, and do that // unification. We know that there is exactly one in the list // where we can unify, because otherwise select would have // reported an ambiguity. (When we do find a match, also // record it for later.) - let nonmatching = util::supertraits(tcx, poly_trait_ref).take_while(|&t| { - match self.infcx.commit_if_ok(|_| self.match_poly_trait_ref(obligation, t)) { - Ok(obligations) => { - upcast_trait_ref = Some(t); - nested.extend(obligations); - false + let nonmatching = util::supertraits(tcx, ty::Binder::dummy(object_trait_ref)) + .take_while(|&t| { + match self.infcx.commit_if_ok(|_| { + self.infcx + .at(&obligation.cause, obligation.param_env) + .sup(obligation_trait_ref, t) + .map(|InferOk { obligations, .. }| obligations) + .map_err(|_| ()) + }) { + Ok(obligations) => { + upcast_trait_ref = Some(t); + nested.extend(obligations); + false + } + Err(_) => true, } - Err(_) => true, - } - }); + }); // Additionally, for each of the non-matching predicates that // we pass over, we sum up the set of number of vtable @@ -364,7 +442,73 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { vtable_base = nonmatching.map(|t| super::util::count_own_vtable_entries(tcx, t)).sum(); } - ImplSourceObjectData { upcast_trait_ref: upcast_trait_ref.unwrap(), vtable_base, nested } + let upcast_trait_ref = upcast_trait_ref.unwrap(); + + // Check supertraits hold. This is so that their associated type bounds + // will be checked in the code below. + for super_trait in tcx + .super_predicates_of(trait_predicate.def_id()) + .instantiate(tcx, trait_predicate.trait_ref.substs) + .predicates + .into_iter() + { + if let ty::PredicateAtom::Trait(..) = super_trait.skip_binders() { + let normalized_super_trait = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &super_trait, + &mut nested, + ); + nested.push(Obligation::new( + obligation.cause.clone(), + obligation.param_env.clone(), + normalized_super_trait, + )); + } + } + + let assoc_types: Vec<_> = tcx + .associated_items(trait_predicate.def_id()) + .in_definition_order() + .filter_map( + |item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None }, + ) + .collect(); + + for assoc_type in assoc_types { + if !tcx.generics_of(assoc_type).params.is_empty() { + // FIXME(generic_associated_types) generate placeholders to + // extend the trait substs. + tcx.sess.span_fatal( + obligation.cause.span, + "generic associated types in trait objects are not supported yet", + ); + } + // This maybe belongs in wf, but that can't (doesn't) handle + // higher-ranked things. + // Prevent, e.g., `dyn Iterator`. + for bound in self.tcx().item_bounds(assoc_type) { + let subst_bound = bound.subst(tcx, trait_predicate.trait_ref.substs); + let normalized_bound = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &subst_bound, + &mut nested, + ); + nested.push(Obligation::new( + obligation.cause.clone(), + obligation.param_env.clone(), + normalized_bound, + )); + } + } + + debug!("confirm_object_candidate: nested: {:?}", nested); + ImplSourceObjectData { upcast_trait_ref, vtable_base, nested } } fn confirm_fn_pointer_candidate( @@ -386,8 +530,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) .map_bound(|(trait_ref, _)| trait_ref); - let Normalized { value: trait_ref, obligations } = ensure_sufficient_stack(|| { - project::normalize_with_depth( + let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| { + normalize_with_depth( self, obligation.param_env, obligation.cause.clone(), @@ -396,12 +540,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) }); - self.confirm_poly_trait_refs( + obligations.extend(self.confirm_poly_trait_refs( obligation.cause.clone(), obligation.param_env, obligation.predicate.to_poly_trait_ref(), trait_ref, - )?; + )?); Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested: obligations }) } @@ -413,7 +557,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("confirm_trait_alias_candidate({:?}, {:?})", obligation, alias_def_id); self.infcx.commit_unconditionally(|_| { - let (predicate, _) = + let predicate = self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate); let trait_ref = predicate.trait_ref; let trait_def_id = trait_ref.def_id; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 114dc79c44f50..a142ba58a6904 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -9,6 +9,7 @@ use super::coherence::{self, Conflict}; use super::const_evaluatable; use super::project; use super::project::normalize_with_depth_to; +use super::project::ProjectionTyObligation; use super::util; use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def}; use super::wf; @@ -36,9 +37,8 @@ use rustc_middle::ty::fast_reject; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef}; -use rustc_middle::ty::{ - self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, -}; +use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; +use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_span::symbol::sym; use std::cell::{Cell, RefCell}; @@ -343,7 +343,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Err(SelectionError::Overflow) } Err(e) => Err(e), - Ok(candidate) => Ok(Some(candidate)), + Ok(candidate) => { + debug!("select: candidate = {:?}", candidate); + Ok(Some(candidate)) + } } } @@ -413,9 +416,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { predicates: I, ) -> Result where - I: IntoIterator>, + I: IntoIterator> + std::fmt::Debug, { let mut result = EvaluatedToOk; + debug!("evaluate_predicates_recursively({:?})", predicates); for obligation in predicates { let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?; debug!("evaluate_predicate_recursively({:?}) = {:?}", obligation, eval); @@ -436,9 +440,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: PredicateObligation<'tcx>, ) -> Result { debug!( - "evaluate_predicate_recursively(previous_stack={:?}, obligation={:?})", - previous_stack.head(), - obligation + "evaluate_predicate_recursively(obligation={:?}, previous_stack={:?})", + obligation, + previous_stack.head() ); // `previous_stack` stores a `TraitObligation`, while `obligation` is @@ -479,15 +483,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx, obligation.param_env, obligation.cause.body_id, + obligation.recursion_depth + 1, arg, obligation.cause.span, ) { Some(mut obligations) => { self.add_depth(obligations.iter_mut(), obligation.recursion_depth); - self.evaluate_predicates_recursively( - previous_stack, - obligations.into_iter(), - ) + self.evaluate_predicates_recursively(previous_stack, obligations) } None => Ok(EvaluatedToAmbig), }, @@ -511,10 +513,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match project::poly_project_and_unify_type(self, &project_obligation) { Ok(Ok(Some(mut subobligations))) => { self.add_depth(subobligations.iter_mut(), obligation.recursion_depth); - let result = self.evaluate_predicates_recursively( - previous_stack, - subobligations.into_iter(), - ); + let result = self + .evaluate_predicates_recursively(previous_stack, subobligations); if let Some(key) = ProjectionCacheKey::from_poly_projection_predicate(self, data) { @@ -879,10 +879,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let result = self.evaluation_probe(|this| { let candidate = (*candidate).clone(); match this.confirm_candidate(stack.obligation, candidate) { - Ok(selection) => this.evaluate_predicates_recursively( - stack.list(), - selection.nested_obligations().into_iter(), - ), + Ok(selection) => { + debug!("evaluate_candidate: selection = {:?}", selection); + this.evaluate_predicates_recursively( + stack.list(), + selection.nested_obligations().into_iter(), + ) + } Err(..) => Ok(EvaluatedToErr), } })?; @@ -943,10 +946,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// to have a *lower* recursion_depth than the obligation used to create it. /// Projection sub-obligations may be returned from the projection cache, /// which results in obligations with an 'old' `recursion_depth`. - /// Additionally, methods like `wf::obligations` and - /// `InferCtxt.subtype_predicate` produce subobligations without - /// taking in a 'parent' depth, causing the generated subobligations - /// to have a `recursion_depth` of `0`. + /// Additionally, methods like `InferCtxt.subtype_predicate` produce + /// subobligations without taking in a 'parent' depth, causing the + /// generated subobligations to have a `recursion_depth` of `0`. /// /// To ensure that obligation_depth never decreasees, we force all subobligations /// to have at least the depth of the original obligation. @@ -1156,12 +1158,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate); } + /// Matches a predicate against the bounds of its self type. + /// + /// Given an obligation like `::Bar: Baz` where the self type is + /// a projection, look at the bounds of `T::Bar`, see if we can find a + /// `Baz` bound. We return indexes into the list returned by + /// `tcx.item_bounds` for any applicable bounds. fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, - ) -> bool { + ) -> smallvec::SmallVec<[usize; 2]> { let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate); - let (placeholder_trait_predicate, _) = + let placeholder_trait_predicate = self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate); debug!( "match_projection_obligation_against_definition_bounds: \ @@ -1170,11 +1178,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); let tcx = self.infcx.tcx; - let predicates = match *placeholder_trait_predicate.trait_ref.self_ty().kind() { - ty::Projection(ref data) => { - tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs) - } - ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs), + let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() { + ty::Projection(ref data) => (data.item_def_id, data.substs), + ty::Opaque(def_id, substs) => (def_id, substs), _ => { span_bug!( obligation.cause.span, @@ -1184,48 +1190,86 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); } }; + let bounds = tcx.item_bounds(def_id).subst(tcx, substs); + + // The bounds returned by `item_bounds` may contain duplicates after + // normalization, so try to deduplicate when possible to avoid + // unnecessary ambiguity. + let mut distinct_normalized_bounds = FxHashSet::default(); - let matching_bound = predicates.iter().find_map(|bound| { - if let ty::PredicateAtom::Trait(pred, _) = bound.skip_binders() { - let bound = ty::Binder::bind(pred.trait_ref); - if self.infcx.probe(|_| { - self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref) - }) { - return Some(bound); + let matching_bounds = bounds + .iter() + .enumerate() + .filter_map(|(idx, bound)| { + if let ty::PredicateAtom::Trait(pred, _) = bound.skip_binders() { + let bound = ty::Binder::bind(pred.trait_ref); + if self.infcx.probe(|_| { + match self.match_projection( + obligation, + bound, + placeholder_trait_predicate.trait_ref, + ) { + Ok(None) => true, + Ok(Some(normalized_trait)) + if distinct_normalized_bounds.insert(normalized_trait) => + { + true + } + _ => false, + } + }) { + return Some(idx); + } } - } - None - }); + None + }) + .collect(); debug!( "match_projection_obligation_against_definition_bounds: \ - matching_bound={:?}", - matching_bound + matching_bounds={:?}", + matching_bounds ); - match matching_bound { - None => false, - Some(bound) => { - // Repeat the successful match, if any, this time outside of a probe. - let result = - self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref); - - assert!(result); - true - } - } + matching_bounds } + /// Equates the trait in `obligation` with trait bound. If the two traits + /// can be equated and the normalized trait bound doesn't contain inference + /// variables or placeholders, the normalized bound is returned. fn match_projection( &mut self, obligation: &TraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, placeholder_trait_ref: ty::TraitRef<'tcx>, - ) -> bool { + ) -> Result>, ()> { debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars()); + if placeholder_trait_ref.def_id != trait_bound.def_id() { + // Avoid unnecessary normalization + return Err(()); + } + + let Normalized { value: trait_bound, obligations: _ } = ensure_sufficient_stack(|| { + project::normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &trait_bound, + ) + }); self.infcx .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) - .is_ok() + .map(|InferOk { obligations: _, value: () }| { + // This method is called within a probe, so we can't have + // inference variables and placeholders escape. + if !trait_bound.needs_infer() && !trait_bound.has_placeholders() { + Some(trait_bound) + } else { + None + } + }) + .map_err(|_| ()) } fn evaluate_where_clause<'o>( @@ -1235,14 +1279,50 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result { self.evaluation_probe(|this| { match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { - Ok(obligations) => { - this.evaluate_predicates_recursively(stack.list(), obligations.into_iter()) - } + Ok(obligations) => this.evaluate_predicates_recursively(stack.list(), obligations), Err(()) => Ok(EvaluatedToErr), } }) } + pub(super) fn match_projection_projections( + &mut self, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &ty::TraitRef<'tcx>, + data: &PolyProjectionPredicate<'tcx>, + potentially_unnormalized_candidates: bool, + ) -> bool { + let mut nested_obligations = Vec::new(); + let projection_ty = if potentially_unnormalized_candidates { + ensure_sufficient_stack(|| { + project::normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &data.map_bound_ref(|data| data.projection_ty), + &mut nested_obligations, + ) + }) + } else { + data.map_bound_ref(|data| data.projection_ty) + }; + + // FIXME(generic_associated_types): Compare the whole projections + let data_poly_trait_ref = projection_ty.map_bound(|proj| proj.trait_ref(self.tcx())); + let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); + self.infcx + .at(&obligation.cause, obligation.param_env) + .sup(obligation_poly_trait_ref, data_poly_trait_ref) + .map_or(false, |InferOk { obligations, value: () }| { + self.evaluate_predicates_recursively( + TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()), + nested_obligations.into_iter().chain(obligations), + ) + .map_or(false, |res| res.may_apply()) + }) + } + /////////////////////////////////////////////////////////////////////////// // WINNOW // @@ -1277,18 +1357,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // // This is a fix for #53123 and prevents winnowing from accidentally extending the // lifetime of a variable. - match other.candidate { + match (&other.candidate, &victim.candidate) { + (_, AutoImplCandidate(..)) | (AutoImplCandidate(..), _) => { + bug!( + "default implementations shouldn't be recorded \ + when there are other valid candidates" + ); + } + // (*) - BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate => true, - ParamCandidate(ref cand) => match victim.candidate { - AutoImplCandidate(..) => { - bug!( - "default implementations shouldn't be recorded \ - when there are other valid candidates" - ); - } - // (*) - BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate => false, + (BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate, _) => true, + (_, BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate) => false, + + (ParamCandidate(..), ParamCandidate(..)) => false, + + // Global bounds from the where clause should be ignored + // here (see issue #50825). Otherwise, we have a where + // clause so don't go around looking for impls. + // Arbitrarily give param candidates priority + // over projection and object candidates. + ( + ParamCandidate(ref cand), ImplCandidate(..) | ClosureCandidate | GeneratorCandidate @@ -1296,28 +1385,45 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | BuiltinObjectCandidate | BuiltinUnsizeCandidate | BuiltinCandidate { .. } - | TraitAliasCandidate(..) => { - // Global bounds from the where clause should be ignored - // here (see issue #50825). Otherwise, we have a where - // clause so don't go around looking for impls. - !is_global(cand) - } - ObjectCandidate | ProjectionCandidate => { - // Arbitrarily give param candidates priority - // over projection and object candidates. - !is_global(cand) - } - ParamCandidate(..) => false, - }, - ObjectCandidate | ProjectionCandidate => match victim.candidate { - AutoImplCandidate(..) => { - bug!( - "default implementations shouldn't be recorded \ - when there are other valid candidates" - ); - } - // (*) - BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate => false, + | TraitAliasCandidate(..) + | ObjectCandidate + | ProjectionCandidate(_), + ) => !is_global(cand), + (ObjectCandidate | ProjectionCandidate(_), ParamCandidate(ref cand)) => { + // Prefer these to a global where-clause bound + // (see issue #50825). + is_global(cand) + } + ( + ImplCandidate(_) + | ClosureCandidate + | GeneratorCandidate + | FnPointerCandidate + | BuiltinObjectCandidate + | BuiltinUnsizeCandidate + | BuiltinCandidate { has_nested: true } + | TraitAliasCandidate(..), + ParamCandidate(ref cand), + ) => { + // Prefer these to a global where-clause bound + // (see issue #50825). + is_global(cand) && other.evaluation.must_apply_modulo_regions() + } + + (ProjectionCandidate(i), ProjectionCandidate(j)) => { + // Arbitrarily pick the first candidate for backwards + // compatibility reasons. Don't let this affect inference. + i > j && !needs_infer + } + (ObjectCandidate, ObjectCandidate) => bug!("Duplicate object candidate"), + (ObjectCandidate, ProjectionCandidate(_)) + | (ProjectionCandidate(_), ObjectCandidate) => { + bug!("Have both object and projection candidate") + } + + // Arbitrarily give projection and object candidates priority. + ( + ObjectCandidate | ProjectionCandidate(_), ImplCandidate(..) | ClosureCandidate | GeneratorCandidate @@ -1325,98 +1431,100 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | BuiltinObjectCandidate | BuiltinUnsizeCandidate | BuiltinCandidate { .. } - | TraitAliasCandidate(..) => true, - ObjectCandidate | ProjectionCandidate => { - // Arbitrarily give param candidates priority - // over projection and object candidates. - true - } - ParamCandidate(ref cand) => is_global(cand), - }, - ImplCandidate(other_def) => { + | TraitAliasCandidate(..), + ) => true, + + ( + ImplCandidate(..) + | ClosureCandidate + | GeneratorCandidate + | FnPointerCandidate + | BuiltinObjectCandidate + | BuiltinUnsizeCandidate + | BuiltinCandidate { .. } + | TraitAliasCandidate(..), + ObjectCandidate | ProjectionCandidate(_), + ) => false, + + (&ImplCandidate(other_def), &ImplCandidate(victim_def)) => { // See if we can toss out `victim` based on specialization. // This requires us to know *for sure* that the `other` impl applies // i.e., `EvaluatedToOk`. if other.evaluation.must_apply_modulo_regions() { - match victim.candidate { - ImplCandidate(victim_def) => { - let tcx = self.tcx(); - if tcx.specializes((other_def, victim_def)) { - return true; - } - return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) { - Some(ty::ImplOverlapKind::Permitted { marker: true }) => { - // Subtle: If the predicate we are evaluating has inference - // variables, do *not* allow discarding candidates due to - // marker trait impls. - // - // Without this restriction, we could end up accidentally - // constrainting inference variables based on an arbitrarily - // chosen trait impl. - // - // Imagine we have the following code: - // - // ```rust - // #[marker] trait MyTrait {} - // impl MyTrait for u8 {} - // impl MyTrait for bool {} - // ``` - // - // And we are evaluating the predicate `<_#0t as MyTrait>`. - // - // During selection, we will end up with one candidate for each - // impl of `MyTrait`. If we were to discard one impl in favor - // of the other, we would be left with one candidate, causing - // us to "successfully" select the predicate, unifying - // _#0t with (for example) `u8`. - // - // However, we have no reason to believe that this unification - // is correct - we've essentially just picked an arbitrary - // *possibility* for _#0t, and required that this be the *only* - // possibility. - // - // Eventually, we will either: - // 1) Unify all inference variables in the predicate through - // some other means (e.g. type-checking of a function). We will - // then be in a position to drop marker trait candidates - // without constraining inference variables (since there are - // none left to constrin) - // 2) Be left with some unconstrained inference variables. We - // will then correctly report an inference error, since the - // existence of multiple marker trait impls tells us nothing - // about which one should actually apply. - !needs_infer - } - Some(_) => true, - None => false, - }; - } - ParamCandidate(ref cand) => { - // Prefer the impl to a global where clause candidate. - return is_global(cand); - } - _ => (), + let tcx = self.tcx(); + if tcx.specializes((other_def, victim_def)) { + return true; } - } - - false - } - ClosureCandidate - | GeneratorCandidate - | FnPointerCandidate - | BuiltinObjectCandidate - | BuiltinUnsizeCandidate - | BuiltinCandidate { has_nested: true } => { - match victim.candidate { - ParamCandidate(ref cand) => { - // Prefer these to a global where-clause bound - // (see issue #50825). - is_global(cand) && other.evaluation.must_apply_modulo_regions() - } - _ => false, + return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) { + Some(ty::ImplOverlapKind::Permitted { marker: true }) => { + // Subtle: If the predicate we are evaluating has inference + // variables, do *not* allow discarding candidates due to + // marker trait impls. + // + // Without this restriction, we could end up accidentally + // constrainting inference variables based on an arbitrarily + // chosen trait impl. + // + // Imagine we have the following code: + // + // ```rust + // #[marker] trait MyTrait {} + // impl MyTrait for u8 {} + // impl MyTrait for bool {} + // ``` + // + // And we are evaluating the predicate `<_#0t as MyTrait>`. + // + // During selection, we will end up with one candidate for each + // impl of `MyTrait`. If we were to discard one impl in favor + // of the other, we would be left with one candidate, causing + // us to "successfully" select the predicate, unifying + // _#0t with (for example) `u8`. + // + // However, we have no reason to believe that this unification + // is correct - we've essentially just picked an arbitrary + // *possibility* for _#0t, and required that this be the *only* + // possibility. + // + // Eventually, we will either: + // 1) Unify all inference variables in the predicate through + // some other means (e.g. type-checking of a function). We will + // then be in a position to drop marker trait candidates + // without constraining inference variables (since there are + // none left to constrin) + // 2) Be left with some unconstrained inference variables. We + // will then correctly report an inference error, since the + // existence of multiple marker trait impls tells us nothing + // about which one should actually apply. + !needs_infer + } + Some(_) => true, + None => false, + }; + } else { + false } } - _ => false, + + // Everything else is ambiguous + ( + ImplCandidate(_) + | ClosureCandidate + | GeneratorCandidate + | FnPointerCandidate + | BuiltinObjectCandidate + | BuiltinUnsizeCandidate + | BuiltinCandidate { has_nested: true } + | TraitAliasCandidate(..), + ImplCandidate(_) + | ClosureCandidate + | GeneratorCandidate + | FnPointerCandidate + | BuiltinObjectCandidate + | BuiltinUnsizeCandidate + | BuiltinCandidate { has_nested: true } + | TraitAliasCandidate(..), + ) => false, } } @@ -1649,7 +1757,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let ty: ty::Binder> = ty::Binder::bind(ty); // <----/ self.infcx.commit_unconditionally(|_| { - let (placeholder_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty); + let placeholder_ty = self.infcx.replace_bound_vars_with_placeholders(&ty); let Normalized { value: normalized_ty, mut obligations } = ensure_sufficient_stack(|| { project::normalize_with_depth( @@ -1717,7 +1825,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(()); } - let (placeholder_obligation, _) = + let placeholder_obligation = self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate); let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 909cd2aa1551e..d66bfd482069d 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -20,6 +20,7 @@ pub fn obligations<'a, 'tcx>( infcx: &InferCtxt<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, + recursion_depth: usize, arg: GenericArg<'tcx>, span: Span, ) -> Option>> { @@ -59,7 +60,8 @@ pub fn obligations<'a, 'tcx>( GenericArgKind::Lifetime(..) => return Some(Vec::new()), }; - let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None }; + let mut wf = + WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth, item: None }; wf.compute(arg); debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out); @@ -80,7 +82,8 @@ pub fn trait_obligations<'a, 'tcx>( span: Span, item: Option<&'tcx hir::Item<'tcx>>, ) -> Vec> { - let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item }; + let mut wf = + WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth: 0, item }; wf.compute_trait_ref(trait_ref, Elaborate::All); wf.normalize() } @@ -92,7 +95,15 @@ pub fn predicate_obligations<'a, 'tcx>( predicate: ty::Predicate<'tcx>, span: Span, ) -> Vec> { - let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None }; + let mut wf = WfPredicates { + infcx, + param_env, + body_id, + span, + out: vec![], + recursion_depth: 0, + item: None, + }; // It's ok to skip the binder here because wf code is prepared for it match predicate.skip_binders() { @@ -142,6 +153,7 @@ struct WfPredicates<'a, 'tcx> { body_id: hir::HirId, span: Span, out: Vec>, + recursion_depth: usize, item: Option<&'tcx hir::Item<'tcx>>, } @@ -241,18 +253,27 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { traits::ObligationCause::new(self.span, self.body_id, code) } - fn normalize(&mut self) -> Vec> { + fn normalize(mut self) -> Vec> { let cause = self.cause(traits::MiscObligation); let infcx = &mut self.infcx; let param_env = self.param_env; let mut obligations = Vec::with_capacity(self.out.len()); - for pred in &self.out { - assert!(!pred.has_escaping_bound_vars()); + for mut obligation in self.out { + assert!(!obligation.has_escaping_bound_vars()); let mut selcx = traits::SelectionContext::new(infcx); - let i = obligations.len(); - let value = - traits::normalize_to(&mut selcx, param_env, cause.clone(), pred, &mut obligations); - obligations.insert(i, value); + // Don't normalize the whole obligation, the param env is either + // already normalized, or we're currently normalizing the + // param_env. Either way we should only normalize the predicate. + let normalized_predicate = traits::project::normalize_with_depth_to( + &mut selcx, + param_env, + cause.clone(), + self.recursion_depth, + &obligation.predicate, + &mut obligations, + ); + obligation.predicate = normalized_predicate; + obligations.push(obligation); } obligations } @@ -265,6 +286,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { debug!("compute_trait_ref obligations {:?}", obligations); let cause = self.cause(traits::MiscObligation); let param_env = self.param_env; + let depth = self.recursion_depth; let item = self.item; @@ -286,7 +308,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { &obligation.predicate, tcx.associated_items(trait_ref.def_id).in_definition_order(), ); - traits::Obligation::new(cause, param_env, obligation.predicate) + traits::Obligation::with_depth(cause, depth, param_env, obligation.predicate) }; if let Elaborate::All = elaborate { @@ -315,8 +337,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { new_cause.make_mut().span = self_ty.span; } } - traits::Obligation::new( + traits::Obligation::with_depth( new_cause, + depth, param_env, ty::PredicateAtom::WellFormed(arg).to_predicate(tcx), ) @@ -327,17 +350,51 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { /// Pushes the obligations required for `trait_ref::Item` to be WF /// into `self.out`. fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) { - // A projection is well-formed if (a) the trait ref itself is - // WF and (b) the trait-ref holds. (It may also be - // normalizable and be WF that way.) - let trait_ref = data.trait_ref(self.infcx.tcx); - self.compute_trait_ref(&trait_ref, Elaborate::None); - - if !data.has_escaping_bound_vars() { - let predicate = trait_ref.without_const().to_predicate(self.infcx.tcx); - let cause = self.cause(traits::ProjectionWf(data)); - self.out.push(traits::Obligation::new(cause, self.param_env, predicate)); - } + // A projection is well-formed if + // + // (a) its predicates hold (*) + // (b) its substs are wf + // + // (*) The predicates of an associated type include the predicates of + // the trait that it's contained in. For example, given + // + // trait A: Clone { + // type X where T: Copy; + // } + // + // The predicates of `<() as A>::X` are: + // [ + // `(): Sized` + // `(): Clone` + // `(): A` + // `i32: Sized` + // `i32: Clone` + // `i32: Copy` + // ] + let obligations = self.nominal_obligations(data.item_def_id, data.substs); + self.out.extend(obligations); + + let tcx = self.tcx(); + let cause = self.cause(traits::MiscObligation); + let param_env = self.param_env; + let depth = self.recursion_depth; + + self.out.extend( + data.substs + .iter() + .filter(|arg| { + matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) + }) + .filter(|arg| !arg.has_escaping_bound_vars()) + .map(|arg| { + traits::Obligation::with_depth( + cause.clone(), + depth, + param_env, + ty::PredicateAtom::WellFormed(arg).to_predicate(tcx), + ) + }), + ); } fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) { @@ -347,8 +404,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { def_id: self.infcx.tcx.require_lang_item(LangItem::Sized, None), substs: self.infcx.tcx.mk_substs_trait(subty, &[]), }; - self.out.push(traits::Obligation::new( + self.out.push(traits::Obligation::with_depth( cause, + self.recursion_depth, self.param_env, trait_ref.without_const().to_predicate(self.infcx.tcx), )); @@ -359,6 +417,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { fn compute(&mut self, arg: GenericArg<'tcx>) { let mut walker = arg.walk(); let param_env = self.param_env; + let depth = self.recursion_depth; while let Some(arg) = walker.next() { let ty = match arg.unpack() { GenericArgKind::Type(ty) => ty, @@ -378,8 +437,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let predicate = ty::PredicateAtom::ConstEvaluatable(def, substs) .to_predicate(self.tcx()); let cause = self.cause(traits::MiscObligation); - self.out.push(traits::Obligation::new( + self.out.push(traits::Obligation::with_depth( cause, + self.recursion_depth, self.param_env, predicate, )); @@ -394,8 +454,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { val: ty::ConstKind::Infer(resolved), ..*constant }); - self.out.push(traits::Obligation::new( + self.out.push(traits::Obligation::with_depth( cause, + self.recursion_depth, self.param_env, ty::PredicateAtom::WellFormed(resolved_constant.into()) .to_predicate(self.tcx()), @@ -480,8 +541,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // WfReference if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() { let cause = self.cause(traits::ReferenceOutlivesReferent(ty)); - self.out.push(traits::Obligation::new( + self.out.push(traits::Obligation::with_depth( cause, + depth, param_env, ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(rty, r)) .to_predicate(self.tcx()), @@ -571,8 +633,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let component_traits = data.auto_traits().chain(data.principal_def_id()); let tcx = self.tcx(); self.out.extend(component_traits.map(|did| { - traits::Obligation::new( + traits::Obligation::with_depth( cause.clone(), + depth, param_env, ty::PredicateAtom::ObjectSafe(did).to_predicate(tcx), ) @@ -597,8 +660,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { if let ty::Infer(ty::TyVar(_)) = ty.kind() { // Not yet resolved, but we've made progress. let cause = self.cause(traits::MiscObligation); - self.out.push(traits::Obligation::new( + self.out.push(traits::Obligation::with_depth( cause, + self.recursion_depth, param_env, ty::PredicateAtom::WellFormed(ty.into()).to_predicate(self.tcx()), )); @@ -635,7 +699,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { .zip(origins.into_iter().rev()) .map(|((pred, span), origin_def_id)| { let cause = self.cause(traits::BindingObligation(origin_def_id, span)); - traits::Obligation::new(cause, self.param_env, pred) + traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred) }) .filter(|pred| !pred.has_escaping_bound_vars()) .collect() @@ -688,8 +752,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound)); let outlives = ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound)); - self.out.push(traits::Obligation::new( + self.out.push(traits::Obligation::with_depth( cause, + self.recursion_depth, self.param_env, outlives.to_predicate(self.infcx.tcx), )); diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 828ee6dea6256..223635e9aecd9 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -50,6 +50,19 @@ impl<'tcx> RustIrDatabase<'tcx> { .map(|wc| wc.fold_with(&mut regions_substitutor)) .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect() } + + fn bounds_for(&self, def_id: DefId, bound_vars: SubstsRef<'tcx>) -> Vec + where + ty::Predicate<'tcx>: LowerInto<'tcx, std::option::Option>, + { + self.interner + .tcx + .explicit_item_bounds(def_id) + .iter() + .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars)) + .filter_map(|bound| LowerInto::>::lower_into(bound, &self.interner)) + .collect() + } } impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'tcx> { @@ -73,10 +86,9 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t } let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); let binders = binders_for(&self.interner, bound_vars); - // FIXME(chalk): this really isn't right I don't think. The functions - // for GATs are a bit hard to figure out. Are these supposed to be where - // clauses or bounds? + let where_clauses = self.where_clauses_for(def_id, bound_vars); + let bounds = self.bounds_for(def_id, bound_vars); Arc::new(chalk_solve::rust_ir::AssociatedTyDatum { trait_id: chalk_ir::TraitId(trait_def_id), @@ -84,7 +96,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t name: (), binders: chalk_ir::Binders::new( binders, - chalk_solve::rust_ir::AssociatedTyDatumBound { bounds: vec![], where_clauses }, + chalk_solve::rust_ir::AssociatedTyDatumBound { bounds, where_clauses }, ), }) } @@ -442,11 +454,13 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let bound_vars = bound_vars_for_item(self.interner.tcx, opaque_ty_id.0); let binders = binders_for(&self.interner, bound_vars); let where_clauses = self.where_clauses_for(opaque_ty_id.0, bound_vars); + let bounds = self.bounds_for(opaque_ty_id.0, bound_vars); let value = chalk_solve::rust_ir::OpaqueTyDatumBound { - bounds: chalk_ir::Binders::new(binders.clone(), vec![]), + bounds: chalk_ir::Binders::new(binders.clone(), bounds), where_clauses: chalk_ir::Binders::new(binders, where_clauses), }; + Arc::new(chalk_solve::rust_ir::OpaqueTyDatum { opaque_ty_id, bound: chalk_ir::Binders::empty(&self.interner, value), diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 1e1841a57f818..bdb2513cc4602 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -728,6 +728,87 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::FnSig>> for ty::Binder LowerInto<'tcx, Option>>> + for ty::Predicate<'tcx> +{ + fn lower_into( + self, + interner: &RustInterner<'tcx>, + ) -> Option>> { + match self.bound_atom(interner.tcx).skip_binder() { + ty::PredicateAtom::Trait(predicate, _) => { + let (predicate, binders, _named_regions) = + collect_bound_vars(interner, interner.tcx, &ty::Binder::bind(predicate)); + + Some(chalk_ir::Binders::new( + binders, + chalk_solve::rust_ir::InlineBound::TraitBound( + predicate.trait_ref.lower_into(interner), + ), + )) + } + ty::PredicateAtom::Projection(predicate) => { + let (predicate, binders, _named_regions) = + collect_bound_vars(interner, interner.tcx, &ty::Binder::bind(predicate)); + + Some(chalk_ir::Binders::new( + binders, + chalk_solve::rust_ir::InlineBound::AliasEqBound(predicate.lower_into(interner)), + )) + } + ty::PredicateAtom::TypeOutlives(_predicate) => None, + ty::PredicateAtom::WellFormed(_ty) => None, + + ty::PredicateAtom::RegionOutlives(..) + | ty::PredicateAtom::ObjectSafe(..) + | ty::PredicateAtom::ClosureKind(..) + | ty::PredicateAtom::Subtype(..) + | ty::PredicateAtom::ConstEvaluatable(..) + | ty::PredicateAtom::ConstEquate(..) + | ty::PredicateAtom::TypeWellFormedFromEnv(..) => { + bug!("unexpected predicate {}", &self) + } + } + } +} + +impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::TraitBound>> + for ty::TraitRef<'tcx> +{ + fn lower_into( + self, + interner: &RustInterner<'tcx>, + ) -> chalk_solve::rust_ir::TraitBound> { + chalk_solve::rust_ir::TraitBound { + trait_id: chalk_ir::TraitId(self.def_id), + args_no_self: self.substs[1..].iter().map(|arg| arg.lower_into(interner)).collect(), + } + } +} + +impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound>> + for ty::ProjectionPredicate<'tcx> +{ + fn lower_into( + self, + interner: &RustInterner<'tcx>, + ) -> chalk_solve::rust_ir::AliasEqBound> { + let trait_ref = self.projection_ty.trait_ref(interner.tcx); + chalk_solve::rust_ir::AliasEqBound { + trait_bound: trait_ref.lower_into(interner), + associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id), + parameters: self.projection_ty.substs[trait_ref.substs.len()..] + .iter() + .map(|arg| arg.lower_into(interner)) + .collect(), + value: self.ty.lower_into(interner), + } + } +} + /// To collect bound vars, we have to do two passes. In the first pass, we /// collect all `BoundRegion`s and `ty::Bound`s. In the second pass, we then /// replace `BrNamed` into `BrAnon`. The two separate passes are important, diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 79308b032eccd..bc5c07fce045c 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -61,8 +61,8 @@ fn compute_implied_outlives_bounds<'tcx>( // than the ultimate set. (Note: normally there won't be // unresolved inference variables here anyway, but there might be // during typeck under some circumstances.) - let obligations = - wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, arg, DUMMY_SP).unwrap_or(vec![]); + let obligations = wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP) + .unwrap_or(vec![]); // N.B., all of these predicates *ought* to be easily proven // true. In fact, their correctness is (mostly) implied by diff --git a/compiler/rustc_ty/src/ty.rs b/compiler/rustc_ty/src/ty.rs index c4b6b64339a03..1f21d9488a454 100644 --- a/compiler/rustc_ty/src/ty.rs +++ b/compiler/rustc_ty/src/ty.rs @@ -1,11 +1,9 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::svh::Svh; use rustc_hir as hir; -use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; -use rustc_infer::traits::util; use rustc_middle::hir::map as hir_map; -use rustc_middle::ty::subst::{InternalSubsts, Subst}; +use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{ self, Binder, Predicate, PredicateAtom, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness, }; @@ -492,133 +490,6 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { fn_like.asyncness() } -/// For associated types we allow bounds written on the associated type -/// (`type X: Trait`) to be used as candidates. We also allow the same bounds -/// when desugared as bounds on the trait `where Self::X: Trait`. -/// -/// Note that this filtering is done with the items identity substs to -/// simplify checking that these bounds are met in impls. This means that -/// a bound such as `for<'b> >::U: Clone` can't be used, as in -/// `hr-associated-type-bound-1.rs`. -fn associated_type_projection_predicates( - tcx: TyCtxt<'_>, - assoc_item_def_id: DefId, -) -> &'_ ty::List> { - let generic_trait_bounds = tcx.predicates_of(assoc_item_def_id); - // We include predicates from the trait as well to handle - // `where Self::X: Trait`. - let item_bounds = generic_trait_bounds.instantiate_identity(tcx); - let item_predicates = util::elaborate_predicates(tcx, item_bounds.predicates.into_iter()); - - let assoc_item_ty = ty::ProjectionTy { - item_def_id: assoc_item_def_id, - substs: InternalSubsts::identity_for_item(tcx, assoc_item_def_id), - }; - - let predicates = item_predicates.filter_map(|obligation| { - let pred = obligation.predicate; - match pred.skip_binders() { - ty::PredicateAtom::Trait(tr, _) => { - if let ty::Projection(p) = *tr.self_ty().kind() { - if p == assoc_item_ty { - return Some(pred); - } - } - } - ty::PredicateAtom::Projection(proj) => { - if let ty::Projection(p) = *proj.projection_ty.self_ty().kind() { - if p == assoc_item_ty { - return Some(pred); - } - } - } - ty::PredicateAtom::TypeOutlives(outlives) => { - if let ty::Projection(p) = *outlives.0.kind() { - if p == assoc_item_ty { - return Some(pred); - } - } - } - _ => {} - } - None - }); - - let result = tcx.mk_predicates(predicates); - debug!( - "associated_type_projection_predicates({}) = {:?}", - tcx.def_path_str(assoc_item_def_id), - result - ); - result -} - -/// Opaque types don't have the same issues as associated types: the only -/// predicates on an opaque type (excluding those it inherits from its parent -/// item) should be of the form we're expecting. -fn opaque_type_projection_predicates( - tcx: TyCtxt<'_>, - def_id: DefId, -) -> &'_ ty::List> { - let substs = InternalSubsts::identity_for_item(tcx, def_id); - - let bounds = tcx.predicates_of(def_id); - let predicates = - util::elaborate_predicates(tcx, bounds.predicates.iter().map(|&(pred, _)| pred)); - - let filtered_predicates = predicates.filter_map(|obligation| { - let pred = obligation.predicate; - match pred.skip_binders() { - ty::PredicateAtom::Trait(tr, _) => { - if let ty::Opaque(opaque_def_id, opaque_substs) = *tr.self_ty().kind() { - if opaque_def_id == def_id && opaque_substs == substs { - return Some(pred); - } - } - } - ty::PredicateAtom::Projection(proj) => { - if let ty::Opaque(opaque_def_id, opaque_substs) = - *proj.projection_ty.self_ty().kind() - { - if opaque_def_id == def_id && opaque_substs == substs { - return Some(pred); - } - } - } - ty::PredicateAtom::TypeOutlives(outlives) => { - if let ty::Opaque(opaque_def_id, opaque_substs) = *outlives.0.kind() { - if opaque_def_id == def_id && opaque_substs == substs { - return Some(pred); - } - } else { - // These can come from elaborating other predicates - return None; - } - } - // These can come from elaborating other predicates - ty::PredicateAtom::RegionOutlives(_) => return None, - _ => {} - } - tcx.sess.delay_span_bug( - obligation.cause.span(tcx), - &format!("unexpected predicate {:?} on opaque type", pred), - ); - None - }); - - let result = tcx.mk_predicates(filtered_predicates); - debug!("opaque_type_projection_predicates({}) = {:?}", tcx.def_path_str(def_id), result); - result -} - -fn projection_predicates(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List> { - match tcx.def_kind(def_id) { - DefKind::AssocTy => associated_type_projection_predicates(tcx, def_id), - DefKind::OpaqueTy => opaque_type_projection_predicates(tcx, def_id), - k => bug!("projection_predicates called on {}", k.descr(def_id)), - } -} - pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { asyncness, @@ -636,7 +507,6 @@ pub fn provide(providers: &mut ty::query::Providers) { instance_def_size_estimate, issue33140_self_ty, impl_defaultness, - projection_predicates, ..*providers }; } diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_typeck/src/bounds.rs index 63295f5faacc9..80f39051c587f 100644 --- a/compiler/rustc_typeck/src/bounds.rs +++ b/compiler/rustc_typeck/src/bounds.rs @@ -71,12 +71,8 @@ impl<'tcx> Bounds<'tcx> { self.region_bounds .iter() .map(|&(region_bound, span)| { - // Account for the binder being introduced below; no need to shift `param_ty` - // because, at present at least, it either only refers to early-bound regions, - // or it's a generic associated type that deliberately has escaping bound vars. - let region_bound = ty::fold::shift_region(tcx, region_bound, 1); let outlives = ty::OutlivesPredicate(param_ty, region_bound); - (ty::Binder::bind(outlives).to_predicate(tcx), span) + (ty::Binder::dummy(outlives).to_predicate(tcx), span) }) .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| { let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx); diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 0647be2dfde0b..d319ac2cba654 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -1,15 +1,16 @@ use super::coercion::CoerceMany; +use super::compare_method::check_type_bounds; use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl}; use super::*; use rustc_attr as attr; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, ErrorReported}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ItemKind, Node}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::RegionVariableOrigin; +use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt, Representability}; @@ -18,6 +19,8 @@ use rustc_session::config::EntryFnType; use rustc_span::symbol::sym; use rustc_span::{self, MultiSpan, Span}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::opaque_types::InferCtxtExt as _; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::{self, ObligationCauseCode}; pub fn check_wf_new(tcx: TyCtxt<'_>) { @@ -385,8 +388,13 @@ pub(super) fn check_opaque<'tcx>( origin: &hir::OpaqueTyOrigin, ) { check_opaque_for_inheriting_lifetimes(tcx, def_id, span); - tcx.ensure().type_of(def_id); - check_opaque_for_cycles(tcx, def_id, substs, span, origin); + if tcx.type_of(def_id).references_error() { + return; + } + if check_opaque_for_cycles(tcx, def_id, substs, span, origin).is_err() { + return; + } + check_opaque_meets_bounds(tcx, def_id, substs, span, origin); } /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result @@ -453,8 +461,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( ty: None, }; let prohibit_opaque = tcx - .predicates_of(def_id) - .predicates + .explicit_item_bounds(def_id) .iter() .any(|(predicate, _)| predicate.visit_with(&mut visitor)); debug!( @@ -476,7 +483,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( span, E0760, "`{}` return type cannot contain a projection or `Self` that references lifetimes from \ - a parent scope", + a parent scope", if is_async { "async fn" } else { "impl Trait" }, ); @@ -504,7 +511,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>( substs: SubstsRef<'tcx>, span: Span, origin: &hir::OpaqueTyOrigin, -) { +) -> Result<(), ErrorReported> { if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs) { match origin { @@ -514,9 +521,82 @@ pub(super) fn check_opaque_for_cycles<'tcx>( } _ => opaque_type_cycle_error(tcx, def_id, span), } + Err(ErrorReported) + } else { + Ok(()) } } +/// Check that the concrete type behind `impl Trait` actually implements `Trait`. +/// +/// This is mostly checked at the places that specify the opaque type, but we +/// check those cases in the `param_env` of that function, which may have +/// bounds not on this opaque type: +/// +/// type X = impl Clone +/// fn f(t: T) -> X { +/// t +/// } +/// +/// Without this check the above code is incorrectly accepted: we would ICE if +/// some tried, for example, to clone an `Option>`. +fn check_opaque_meets_bounds<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + substs: SubstsRef<'tcx>, + span: Span, + origin: &hir::OpaqueTyOrigin, +) { + match origin { + // Checked when type checking the function containing them. + hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return, + // Can have different predicates to their defining use + hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc => {} + } + + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let param_env = tcx.param_env(def_id); + + tcx.infer_ctxt().enter(move |infcx| { + let inh = Inherited::new(infcx, def_id); + let infcx = &inh.infcx; + let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs); + + let misc_cause = traits::ObligationCause::misc(span, hir_id); + + let (_, opaque_type_map) = inh.register_infer_ok_obligations( + infcx.instantiate_opaque_types(def_id, hir_id, param_env, &opaque_ty, span), + ); + + for (def_id, opaque_defn) in opaque_type_map { + match infcx + .at(&misc_cause, param_env) + .eq(opaque_defn.concrete_ty, tcx.type_of(def_id).subst(tcx, opaque_defn.substs)) + { + Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok), + Err(ty_err) => tcx.sess.delay_span_bug( + opaque_defn.definition_span, + &format!( + "could not unify `{}` with revealed type:\n{}", + opaque_defn.concrete_ty, ty_err, + ), + ), + } + } + + // Check that all obligations are satisfied by the implementation's + // version. + if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { + infcx.report_fulfillment_errors(errors, None, false); + } + + // Finally, resolve all regions. This catches wily misuses of + // lifetime parameters. + let fcx = FnCtxt::new(&inh, param_env, hir_id); + fcx.regionck_item(hir_id, span, &[]); + }); +} + pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { debug!( "check_item_type(it.hir_id={}, it.name={})", @@ -553,9 +633,25 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { for item in items.iter() { let item = tcx.hir().trait_item(item.id); - if let hir::TraitItemKind::Fn(sig, _) = &item.kind { - let abi = sig.header.abi; - fn_maybe_err(tcx, item.ident.span, abi); + match item.kind { + hir::TraitItemKind::Fn(ref sig, _) => { + let abi = sig.header.abi; + fn_maybe_err(tcx, item.ident.span, abi); + } + hir::TraitItemKind::Type(.., Some(_default)) => { + let item_def_id = tcx.hir().local_def_id(item.hir_id).to_def_id(); + let assoc_item = tcx.associated_item(item_def_id); + let trait_substs = + InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let _: Result<_, rustc_errors::ErrorReported> = check_type_bounds( + tcx, + assoc_item, + assoc_item, + item.span, + ty::TraitRef { def_id: def_id.to_def_id(), substs: trait_substs }, + ); + } + _ => {} } } } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 7aa54e0ebcc6b..4acc7451a2131 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -5,6 +5,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; +use rustc_infer::traits::util; use rustc_middle::ty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; @@ -327,7 +328,7 @@ fn compare_predicate_entailment<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id); - fcx.regionck_item(impl_m_hir_id, impl_m_span, &[]); + fcx.regionck_item(impl_m_hir_id, impl_m_span, trait_sig.inputs_and_output); Ok(()) }) @@ -1052,7 +1053,7 @@ crate fn compare_ty_impl<'tcx>( compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?; - compare_projection_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref) + check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref) })(); } @@ -1170,20 +1171,13 @@ fn compare_type_predicate_entailment<'tcx>( /// For default associated types the normalization is not possible (the value /// from the impl could be overridden). We also can't normalize generic /// associated types (yet) because they contain bound parameters. -fn compare_projection_bounds<'tcx>( +pub fn check_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, trait_ty: &ty::AssocItem, impl_ty: &ty::AssocItem, impl_ty_span: Span, impl_trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorReported> { - let have_gats = tcx.features().generic_associated_types; - if impl_ty.defaultness.is_final() && !have_gats { - // For "final", non-generic associate type implementations, we - // don't need this as described above. - return Ok(()); - } - // Given // // impl Foo for (A, B) { @@ -1211,16 +1205,27 @@ fn compare_projection_bounds<'tcx>( // ParamEnv for normalization specifically. let normalize_param_env = { let mut predicates = param_env.caller_bounds().iter().collect::>(); - predicates.push( - ty::Binder::dummy(ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { - item_def_id: trait_ty.def_id, - substs: rebased_substs, - }, - ty: impl_ty_value, - }) - .to_predicate(tcx), - ); + match impl_ty_value.kind() { + ty::Projection(proj) + if proj.item_def_id == trait_ty.def_id && proj.substs == rebased_substs => + { + // Don't include this predicate if the projected type is + // exactly the same as the projection. This can occur in + // (somewhat dubious) code like this: + // + // impl X for T where T: X { type Y = ::Y; } + } + _ => predicates.push( + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + item_def_id: trait_ty.def_id, + substs: rebased_substs, + }, + ty: impl_ty_value, + }) + .to_predicate(tcx), + ), + }; ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing) }; @@ -1231,33 +1236,38 @@ fn compare_projection_bounds<'tcx>( let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local()); let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id); - let cause = ObligationCause::new( - impl_ty_span, - impl_ty_hir_id, - ObligationCauseCode::ItemObligation(trait_ty.def_id), - ); + let mk_cause = |span| { + ObligationCause::new( + impl_ty_span, + impl_ty_hir_id, + ObligationCauseCode::BindingObligation(trait_ty.def_id, span), + ) + }; - let predicates = tcx.projection_predicates(trait_ty.def_id); - debug!("compare_projection_bounds: projection_predicates={:?}", predicates); + let obligations = tcx + .explicit_item_bounds(trait_ty.def_id) + .iter() + .map(|&(bound, span)| { + let concrete_ty_bound = bound.subst(tcx, rebased_substs); + debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound); - for predicate in predicates { - let concrete_ty_predicate = predicate.subst(tcx, rebased_substs); - debug!("compare_projection_bounds: concrete predicate = {:?}", concrete_ty_predicate); + traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound) + }) + .collect(); + debug!("check_type_bounds: item_bounds={:?}", obligations); + for mut obligation in util::elaborate_obligations(tcx, obligations) { let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize( &mut selcx, normalize_param_env, normalize_cause.clone(), - &concrete_ty_predicate, + &obligation.predicate, ); debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate); + obligation.predicate = normalized_predicate; inh.register_predicates(obligations); - inh.register_predicate(traits::Obligation::new( - cause.clone(), - param_env, - normalized_predicate, - )); + inh.register_predicate(obligation); } // Check that all obligations are satisfied by the implementation's @@ -1270,7 +1280,11 @@ fn compare_projection_bounds<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id); - fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]); + let implied_bounds = match impl_ty.container { + ty::TraitContainer(_) => vec![], + ty::ImplContainer(def_id) => fcx.impl_implied_bounds(def_id, impl_ty_span), + }; + fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &implied_bounds); Ok(()) }) diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 5203f3fa8f1d5..b4e950ab6e9e5 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -420,6 +420,9 @@ fn check_associated_item( check_method_receiver(fcx, hir_sig, &item, self_ty); } ty::AssocKind::Type => { + if let ty::AssocItemContainer::TraitContainer(_) = item.container { + check_associated_type_bounds(fcx, item, span) + } if item.defaultness.has_value() { let ty = fcx.tcx.type_of(item.def_id); let ty = fcx.normalize_associated_types_in(span, &ty); @@ -571,7 +574,6 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { for_item(tcx, item).with_fcx(|fcx, _| { check_where_clauses(tcx, fcx, item.span, trait_def_id.to_def_id(), None); - check_associated_type_defaults(fcx, trait_def_id.to_def_id()); vec![] }); @@ -581,96 +583,26 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { /// /// Assuming the defaults are used, check that all predicates (bounds on the /// assoc type and where clauses on the trait) hold. -fn check_associated_type_defaults(fcx: &FnCtxt<'_, '_>, trait_def_id: DefId) { +fn check_associated_type_bounds(fcx: &FnCtxt<'_, '_>, item: &ty::AssocItem, span: Span) { let tcx = fcx.tcx; - let substs = InternalSubsts::identity_for_item(tcx, trait_def_id); - - // For all assoc. types with defaults, build a map from - // `>::Assoc` to the default type. - let map = tcx - .associated_items(trait_def_id) - .in_definition_order() - .filter_map(|item| { - if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { - // `>::Assoc` - let proj = ty::ProjectionTy { substs, item_def_id: item.def_id }; - let default_ty = tcx.type_of(item.def_id); - debug!("assoc. type default mapping: {} -> {}", proj, default_ty); - Some((proj, default_ty)) - } else { - None - } - }) - .collect::>(); - - /// Replaces projections of associated types with their default types. - /// - /// This does a "shallow substitution", meaning that defaults that refer to - /// other defaulted assoc. types will still refer to the projection - /// afterwards, not to the other default. For example: - /// - /// ```compile_fail - /// trait Tr { - /// type A: Clone = Vec; - /// type B = u8; - /// } - /// ``` - /// - /// This will end up replacing the bound `Self::A: Clone` with - /// `Vec: Clone`, not with `Vec: Clone`. If we did a deep - /// substitution and ended up with the latter, the trait would be accepted. - /// If an `impl` then replaced `B` with something that isn't `Clone`, - /// suddenly the default for `A` is no longer valid. The shallow - /// substitution forces the trait to add a `B: Clone` bound to be accepted, - /// which means that an `impl` can replace any default without breaking - /// others. - /// - /// Note that this isn't needed for soundness: The defaults would still be - /// checked in any impl that doesn't override them. - struct DefaultNormalizer<'tcx> { - tcx: TyCtxt<'tcx>, - map: FxHashMap, Ty<'tcx>>, - } - impl<'tcx> ty::fold::TypeFolder<'tcx> for DefaultNormalizer<'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { - self.tcx - } + let bounds = tcx.explicit_item_bounds(item.def_id); - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.kind() { - ty::Projection(proj_ty) => { - if let Some(default) = self.map.get(&proj_ty) { - default - } else { - t.super_fold_with(self) - } - } - _ => t.super_fold_with(self), - } - } - } - - // Now take all predicates defined on the trait, replace any mention of - // the assoc. types with their default, and prove them. - // We only consider predicates that directly mention the assoc. type. - let mut norm = DefaultNormalizer { tcx, map }; - let predicates = fcx.tcx.predicates_of(trait_def_id); - for &(orig_pred, span) in predicates.predicates.iter() { - let pred = orig_pred.fold_with(&mut norm); - if pred != orig_pred { - // Mentions one of the defaulted assoc. types - debug!("default suitability check: proving predicate: {} -> {}", orig_pred, pred); - let pred = fcx.normalize_associated_types_in(span, &pred); - let cause = traits::ObligationCause::new( - span, - fcx.body_id, - traits::ItemObligation(trait_def_id), - ); - let obligation = traits::Obligation::new(cause, fcx.param_env, pred); + debug!("check_associated_type_bounds: bounds={:?}", bounds); + let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| { + let normalized_bound = fcx.normalize_associated_types_in(span, &bound); + traits::wf::predicate_obligations( + fcx, + fcx.param_env, + fcx.body_id, + normalized_bound, + bound_span, + ) + }); - fcx.register_predicate(obligation); - } + for obligation in wf_obligations { + debug!("next obligation cause: {:?}", obligation.cause); + fcx.register_predicate(obligation); } } @@ -1493,7 +1425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect() } - fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec> { + pub(super) fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec> { match self.tcx.impl_trait_ref(impl_def_id) { Some(ref trait_ref) => { // Trait impl: take implied bounds from all types that diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 1f4f40fca9be3..092dae18192e5 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -50,6 +50,7 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; +mod item_bounds; mod type_of; struct OnlySelfBounds(bool); @@ -68,12 +69,15 @@ pub fn provide(providers: &mut Providers) { *providers = Providers { opt_const_param_of: type_of::opt_const_param_of, type_of: type_of::type_of, + item_bounds: item_bounds::item_bounds, + explicit_item_bounds: item_bounds::explicit_item_bounds, generics_of, predicates_of, predicates_defined_on, projection_ty_from_predicates, explicit_predicates_of, super_predicates_of, + trait_explicit_predicates_and_bounds, type_param_predicates, trait_def, adt_def, @@ -700,6 +704,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) { hir::ItemKind::OpaqueTy(..) => { tcx.ensure().generics_of(def_id); tcx.ensure().predicates_of(def_id); + tcx.ensure().explicit_item_bounds(def_id); } hir::ItemKind::TyAlias(..) | hir::ItemKind::Static(..) @@ -708,8 +713,10 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) { tcx.ensure().generics_of(def_id); tcx.ensure().type_of(def_id); tcx.ensure().predicates_of(def_id); - if let hir::ItemKind::Fn(..) = it.kind { - tcx.ensure().fn_sig(def_id); + match it.kind { + hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id), + hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id), + _ => (), } } } @@ -730,15 +737,25 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) { tcx.ensure().type_of(def_id); } - hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(_, Some(_)) => { + hir::TraitItemKind::Const(..) => { tcx.ensure().type_of(def_id); - // Account for `const C: _;` and `type T = _;`. + // Account for `const C: _;`. + let mut visitor = PlaceholderHirTyCollector::default(); + visitor.visit_trait_item(trait_item); + placeholder_type_error(tcx, None, &[], visitor.0, false); + } + + hir::TraitItemKind::Type(_, Some(_)) => { + tcx.ensure().item_bounds(def_id); + tcx.ensure().type_of(def_id); + // Account for `type T = _;`. let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_trait_item(trait_item); placeholder_type_error(tcx, None, &[], visitor.0, false); } hir::TraitItemKind::Type(_, None) => { + tcx.ensure().item_bounds(def_id); // #74612: Visit and try to find bad placeholders // even if there is no concrete type. let mut visitor = PlaceholderHirTyCollector::default(); @@ -1716,7 +1733,7 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { /// Returns a list of user-specified type predicates for the definition with ID `def_id`. /// N.B., this does not include any implied/inferred constraints. -fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { +fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { use rustc_hir::*; debug!("explicit_predicates_of(def_id={:?})", def_id); @@ -1726,7 +1743,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat let mut is_trait = None; let mut is_default_impl_trait = None; - let mut is_trait_associated_type = None; let icx = ItemCtxt::new(tcx, def_id); let constness = icx.default_constness_for_trait_bounds(); @@ -1739,12 +1755,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default(); let ast_generics = match node { - Node::TraitItem(item) => { - if let hir::TraitItemKind::Type(bounds, _) = item.kind { - is_trait_associated_type = Some((bounds, item.span)); - } - &item.generics - } + Node::TraitItem(item) => &item.generics, Node::ImplItem(item) => &item.generics, @@ -1762,44 +1773,38 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) => generics, - ItemKind::Trait(_, _, ref generics, .., items) => { - is_trait = Some((ty::TraitRef::identity(tcx, def_id), items)); + ItemKind::Trait(_, _, ref generics, ..) => { + is_trait = Some(ty::TraitRef::identity(tcx, def_id)); generics } ItemKind::TraitAlias(ref generics, _) => { - is_trait = Some((ty::TraitRef::identity(tcx, def_id), &[])); + is_trait = Some(ty::TraitRef::identity(tcx, def_id)); generics } ItemKind::OpaqueTy(OpaqueTy { - ref bounds, + bounds: _, impl_trait_fn, ref generics, origin: _, }) => { - let bounds_predicates = ty::print::with_no_queries(|| { - let substs = InternalSubsts::identity_for_item(tcx, def_id); - let opaque_ty = tcx.mk_opaque(def_id, substs); - - // Collect the bounds, i.e., the `A + B + 'c` in `impl A + B + 'c`. - let bounds = AstConv::compute_bounds( - &icx, - opaque_ty, - bounds, - SizedByDefault::Yes, - tcx.def_span(def_id), - ); - - bounds.predicates(tcx, opaque_ty) - }); if impl_trait_fn.is_some() { - // opaque types - return ty::GenericPredicates { - parent: None, - predicates: tcx.arena.alloc_from_iter(bounds_predicates), - }; + // return-position impl trait + // + // We don't inherit predicates from the parent here: + // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` + // then the return type is `f::<'static, T>::{{opaque}}`. + // + // If we inherited the predicates of `f` then we would + // require that `T: 'static` to show that the return + // type is well-formed. + // + // The only way to have something with this opaque type + // is from the return type of the containing function, + // which will ensure that the function's predicates + // hold. + return ty::GenericPredicates { parent: None, predicates: &[] }; } else { - // named opaque types - predicates.extend(bounds_predicates); + // type-alias impl trait generics } } @@ -1825,7 +1830,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat // and the explicit where-clauses, but to get the full set of predicates // on a trait we need to add in the supertrait bounds and bounds found on // associated types. - if let Some((_trait_ref, _)) = is_trait { + if let Some(_trait_ref) = is_trait { predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned()); } @@ -1992,24 +1997,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat } } - // Add predicates from associated type bounds (`type X: Bound`) - if tcx.features().generic_associated_types { - // New behavior: bounds declared on associate type are predicates of that - // associated type. Not the default because it needs more testing. - if let Some((bounds, span)) = is_trait_associated_type { - let projection_ty = - tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id)); - - predicates.extend(associated_item_bounds(tcx, def_id, bounds, projection_ty, span)) - } - } else if let Some((self_trait_ref, trait_items)) = is_trait { - // Current behavior: bounds declared on associate type are predicates - // of its parent trait. - predicates.extend(trait_items.iter().flat_map(|trait_item_ref| { - trait_associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref) - })) - } - if tcx.features().const_evaluatable_checked { predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local())); } @@ -2131,6 +2118,69 @@ fn const_evaluatable_predicates_of<'tcx>( collector.preds } +fn trait_explicit_predicates_and_bounds( + tcx: TyCtxt<'_>, + def_id: LocalDefId, +) -> ty::GenericPredicates<'_> { + assert_eq!(tcx.def_kind(def_id), DefKind::Trait); + gather_explicit_predicates_of(tcx, def_id.to_def_id()) +} + +fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { + if let DefKind::Trait = tcx.def_kind(def_id) { + // Remove bounds on associated types from the predicates, they will be + // returned by `explicit_item_bounds`. + let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local()); + let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id); + + let is_assoc_item_ty = |ty: Ty<'_>| { + // For a predicate from a where clause to become a bound on an + // associated type: + // * It must use the identity substs of the item. + // * Since any generic parameters on the item are not in scope, + // this means that the item is not a GAT, and its identity + // substs are the same as the trait's. + // * It must be an associated type for this trait (*not* a + // supertrait). + if let ty::Projection(projection) = ty.kind() { + if projection.substs == trait_identity_substs + && tcx.associated_item(projection.item_def_id).container.id() == def_id + { + true + } else { + false + } + } else { + false + } + }; + + let predicates: Vec<_> = predicates_and_bounds + .predicates + .iter() + .copied() + .filter(|(pred, _)| match pred.skip_binders() { + ty::PredicateAtom::Trait(tr, _) => !is_assoc_item_ty(tr.self_ty()), + ty::PredicateAtom::Projection(proj) => { + !is_assoc_item_ty(proj.projection_ty.self_ty()) + } + ty::PredicateAtom::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0), + _ => true, + }) + .collect(); + if predicates.len() == predicates_and_bounds.predicates.len() { + predicates_and_bounds + } else { + ty::GenericPredicates { + parent: predicates_and_bounds.parent, + predicates: tcx.arena.alloc_slice(&predicates), + } + } + } else { + gather_explicit_predicates_of(tcx, def_id) + } +} + fn projection_ty_from_predicates( tcx: TyCtxt<'tcx>, key: ( @@ -2153,55 +2203,6 @@ fn projection_ty_from_predicates( projection_ty } -fn trait_associated_item_predicates( - tcx: TyCtxt<'tcx>, - def_id: DefId, - self_trait_ref: ty::TraitRef<'tcx>, - trait_item_ref: &hir::TraitItemRef, -) -> Vec<(ty::Predicate<'tcx>, Span)> { - let trait_item = tcx.hir().trait_item(trait_item_ref.id); - let item_def_id = tcx.hir().local_def_id(trait_item_ref.id.hir_id); - let bounds = match trait_item.kind { - hir::TraitItemKind::Type(ref bounds, _) => bounds, - _ => return Vec::new(), - }; - - if !tcx.generics_of(item_def_id).params.is_empty() { - // For GATs the substs provided to the mk_projection call below are - // wrong. We should emit a feature gate error if we get here so skip - // this type. - tcx.sess.delay_span_bug(trait_item.span, "gats used without feature gate"); - return Vec::new(); - } - - let assoc_ty = tcx.mk_projection( - tcx.hir().local_def_id(trait_item.hir_id).to_def_id(), - self_trait_ref.substs, - ); - - associated_item_bounds(tcx, def_id, bounds, assoc_ty, trait_item.span) -} - -fn associated_item_bounds( - tcx: TyCtxt<'tcx>, - def_id: DefId, - bounds: &'tcx [hir::GenericBound<'tcx>], - projection_ty: Ty<'tcx>, - span: Span, -) -> Vec<(ty::Predicate<'tcx>, Span)> { - let bounds = AstConv::compute_bounds( - &ItemCtxt::new(tcx, def_id), - projection_ty, - bounds, - SizedByDefault::Yes, - span, - ); - - let predicates = bounds.predicates(tcx, projection_ty); - - predicates -} - /// Converts a specific `GenericBound` from the AST into a set of /// predicates that apply to the self type. A vector is returned /// because this can be anywhere from zero predicates (`T: ?Sized` adds no diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs new file mode 100644 index 0000000000000..9c29ceeb593df --- /dev/null +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -0,0 +1,111 @@ +use super::ItemCtxt; +use crate::astconv::{AstConv, SizedByDefault}; +use rustc_hir as hir; +use rustc_infer::traits::util; +use rustc_middle::ty::subst::InternalSubsts; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_span::def_id::DefId; +use rustc_span::Span; + +/// For associated types we include both bounds written on the type +/// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`. +/// +/// Note that this filtering is done with the items identity substs to +/// simplify checking that these bounds are met in impls. This means that +/// a bound such as `for<'b> >::U: Clone` can't be used, as in +/// `hr-associated-type-bound-1.rs`. +fn associated_type_bounds<'tcx>( + tcx: TyCtxt<'tcx>, + assoc_item_def_id: DefId, + bounds: &'tcx [hir::GenericBound<'tcx>], + span: Span, +) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + let item_ty = tcx.mk_projection( + assoc_item_def_id, + InternalSubsts::identity_for_item(tcx, assoc_item_def_id), + ); + + let bounds = AstConv::compute_bounds( + &ItemCtxt::new(tcx, assoc_item_def_id), + item_ty, + bounds, + SizedByDefault::Yes, + span, + ); + + let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id(); + let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local()); + + let bounds_from_parent = + trait_predicates.predicates.iter().copied().filter(|(pred, _)| match pred.skip_binders() { + ty::PredicateAtom::Trait(tr, _) => tr.self_ty() == item_ty, + ty::PredicateAtom::Projection(proj) => proj.projection_ty.self_ty() == item_ty, + ty::PredicateAtom::TypeOutlives(outlives) => outlives.0 == item_ty, + _ => false, + }); + + let all_bounds = tcx + .arena + .alloc_from_iter(bounds.predicates(tcx, item_ty).into_iter().chain(bounds_from_parent)); + debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds); + all_bounds +} + +/// Opaque types don't inherit bounds from their parent: for return position +/// impl trait it isn't possible to write a suitable predicate on the +/// containing function and for type-alias impl trait we don't have a backwards +/// compatibility issue. +fn opaque_type_bounds<'tcx>( + tcx: TyCtxt<'tcx>, + opaque_def_id: DefId, + bounds: &'tcx [hir::GenericBound<'tcx>], + span: Span, +) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + let item_ty = + tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id)); + + let bounds = ty::print::with_no_queries(|| { + AstConv::compute_bounds( + &ItemCtxt::new(tcx, opaque_def_id), + item_ty, + bounds, + SizedByDefault::Yes, + span, + ) + }); + + let bounds = bounds.predicates(tcx, item_ty); + debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds); + + tcx.arena.alloc_slice(&bounds) +} + +pub(super) fn explicit_item_bounds( + tcx: TyCtxt<'_>, + def_id: DefId, +) -> &'_ [(ty::Predicate<'_>, Span)] { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + match tcx.hir().get(hir_id) { + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Type(bounds, _), + span, + .. + }) => associated_type_bounds(tcx, def_id, bounds, *span), + hir::Node::Item(hir::Item { + kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }), + span, + .. + }) => opaque_type_bounds(tcx, def_id, bounds, *span), + _ => bug!("item_bounds called on {:?}", def_id), + } +} + +pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List> { + tcx.mk_predicates( + util::elaborate_predicates( + tcx, + tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound), + ) + .map(|obligation| obligation.predicate), + ) +} diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index 60b9467fca8b3..4cf3efcf5136d 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -337,6 +337,7 @@ fn check_predicates<'tcx>( infcx, tcx.param_env(impl1_def_id), tcx.hir().local_def_id_to_hir_id(impl1_def_id), + 0, arg, span, ) { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 788bb5e787b82..ac1e2b467045c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -21,7 +21,7 @@ use rustc_middle::bug; use rustc_middle::middle::resolve_lifetime as rl; use rustc_middle::middle::stability; use rustc_middle::ty::fold::TypeFolder; -use rustc_middle::ty::subst::InternalSubsts; +use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{self, AdtKind, Lift, Ty, TyCtxt}; use rustc_mir::const_eval::{is_const_fn, is_min_const_fn, is_unstable_const_fn}; use rustc_span::hygiene::MacroKind; @@ -1268,13 +1268,10 @@ impl Clean for ty::AssocItem { ty::AssocKind::Type => { let my_name = self.ident.name.clean(cx); - if let ty::TraitContainer(did) = self.container { - // When loading a cross-crate associated type, the bounds for this type - // are actually located on the trait/impl itself, so we need to load - // all of the generics from there and then look for bounds that are - // applied to this associated type in question. - let predicates = cx.tcx.explicit_predicates_of(did); - let generics = (cx.tcx.generics_of(did), predicates).clean(cx); + if let ty::TraitContainer(_) = self.container { + let bounds = cx.tcx.explicit_item_bounds(self.def_id); + let predicates = ty::GenericPredicates { parent: None, predicates: bounds }; + let generics = (cx.tcx.generics_of(self.def_id), predicates).clean(cx); let mut bounds = generics .where_predicates .iter() @@ -1678,19 +1675,22 @@ impl<'tcx> Clean for Ty<'tcx> { ty::Opaque(def_id, substs) => { // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, - // by looking up the projections associated with the def_id. - let predicates_of = cx.tcx.explicit_predicates_of(def_id); + // by looking up the bounds associated with the def_id. let substs = cx.tcx.lift(&substs).expect("Opaque lift failed"); - let bounds = predicates_of.instantiate(cx.tcx, substs); + let bounds = cx + .tcx + .explicit_item_bounds(def_id) + .iter() + .map(|(bound, _)| bound.subst(cx.tcx, substs)) + .collect::>(); let mut regions = vec![]; let mut has_sized = false; let mut bounds = bounds - .predicates .iter() - .filter_map(|predicate| { + .filter_map(|bound| { // Note: The substs of opaque types can contain unbound variables, // meaning that we have to use `ignore_quantifiers_with_unbound_vars` here. - let trait_ref = match predicate.bound_atom(cx.tcx).skip_binder() { + let trait_ref = match bound.bound_atom(cx.tcx).skip_binder() { ty::PredicateAtom::Trait(tr, _constness) => { ty::Binder::bind(tr.trait_ref) } @@ -1711,11 +1711,10 @@ impl<'tcx> Clean for Ty<'tcx> { } let bounds: Vec<_> = bounds - .predicates .iter() - .filter_map(|pred| { + .filter_map(|bound| { if let ty::PredicateAtom::Projection(proj) = - pred.bound_atom(cx.tcx).skip_binder() + bound.bound_atom(cx.tcx).skip_binder() { if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() @@ -2067,13 +2066,10 @@ impl Clean for doctree::OpaqueTy<'_> { visibility: self.vis.clean(cx), stability: cx.stability(self.id).clean(cx), deprecation: cx.deprecation(self.id).clean(cx), - inner: OpaqueTyItem( - OpaqueTy { - bounds: self.opaque_ty.bounds.clean(cx), - generics: self.opaque_ty.generics.clean(cx), - }, - false, - ), + inner: OpaqueTyItem(OpaqueTy { + bounds: self.opaque_ty.bounds.clean(cx), + generics: self.opaque_ty.generics.clean(cx), + }), } } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d70446d257498..bb6f449e3550d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -252,7 +252,7 @@ pub enum ItemEnum { FunctionItem(Function), ModuleItem(Module), TypedefItem(Typedef, bool /* is associated type */), - OpaqueTyItem(OpaqueTy, bool /* is associated type */), + OpaqueTyItem(OpaqueTy), StaticItem(Static), ConstantItem(Constant), TraitItem(Trait), diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 8b5ba7a239c5f..afd1dc596427f 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1709,7 +1709,7 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer, cache: &Cache) clean::ConstantItem(ref c) => item_constant(buf, cx, item, c), clean::ForeignTypeItem => item_foreign_type(buf, cx, item, cache), clean::KeywordItem(_) => item_keyword(buf, cx, item), - clean::OpaqueTyItem(ref e, _) => item_opaque_ty(buf, cx, item, e, cache), + clean::OpaqueTyItem(ref e) => item_opaque_ty(buf, cx, item, e, cache), clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta, cache), _ => { // We don't generate pages for any other type. diff --git a/src/test/incremental/issue-54242.rs b/src/test/incremental/issue-54242.rs index 25dc7cdf129d5..9e449de0cf5ac 100644 --- a/src/test/incremental/issue-54242.rs +++ b/src/test/incremental/issue-54242.rs @@ -1,6 +1,9 @@ // revisions: rpass cfail -trait Tr { +trait Tr +where + (Self::Arr,): Sized, +{ type Arr; const C: usize = 0; diff --git a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir index 62bf97a772ead..c1421f20a0ba2 100644 --- a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir +++ b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir @@ -69,7 +69,7 @@ fn test() -> Option> { bb5: { StorageDead(_9); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 - _0 = > as Try>::from_error(move _8) -> [return: bb6, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 + _0 = > as Try>::from_error(move _8) -> [return: bb6, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20 // mir::Constant // + span: $DIR/issue-62289.rs:9:15: 9:20 // + literal: Const { ty: fn(> as std::ops::Try>::Error) -> std::option::Option> {> as std::ops::Try>::from_error}, val: Value(Scalar()) } diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff index 33245b65e8c42..a811a2c178f17 100644 --- a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff @@ -29,7 +29,7 @@ scope 8 { - debug v => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL + debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:14: 24:15 + let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 } } } diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff index eb2521c8ba08e..b0cc3e88f35ac 100644 --- a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff +++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff @@ -25,7 +25,7 @@ } scope 8 { debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:14: 24:15 + let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 } } } diff --git a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff index 2af387a73b762..12a6617cc5a27 100644 --- a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff +++ b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff @@ -25,7 +25,7 @@ } scope 8 { debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:14: 8:15 + let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 } } } diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff index 6fa14f1e0d840..534836eff7b2d 100644 --- a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff @@ -29,7 +29,7 @@ scope 8 { - debug v => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL + debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:14: 8:15 + let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 } } } diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir index ceb5bfb19a133..d2e37bf4e12eb 100644 --- a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir +++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir @@ -24,7 +24,7 @@ fn try_identity(_1: std::result::Result) -> std::result::Result ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:14: 8:15 + let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 } } } diff --git a/src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs b/src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs new file mode 100644 index 0000000000000..49f11140741c2 --- /dev/null +++ b/src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs @@ -0,0 +1,16 @@ +// Check that `where Self::Output: Copy` is turned into a bound on `Op::Output`. + +//check-pass + +trait Op +where + Self::Output: Copy, +{ + type Output; +} + +fn duplicate(x: T::Output) -> (T::Output, T::Output) { + (x, x) +} + +fn main() {} diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs index 498a555c441b8..73b23da5bcb66 100644 --- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs @@ -12,7 +12,9 @@ fn main() {} -trait Bar { type Assoc; } +trait Bar { + type Assoc; +} trait Thing { type Out; @@ -20,11 +22,14 @@ trait Thing { } struct AssocNoCopy; -impl Bar for AssocNoCopy { type Assoc = String; } +impl Bar for AssocNoCopy { + type Assoc = String; +} impl Thing for AssocNoCopy { type Out = Box>; //~^ ERROR the trait bound `String: Copy` is not satisfied + //~| ERROR the trait bound `String: Copy` is not satisfied fn func() -> Self::Out { Box::new(AssocNoCopy) diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr index 5236f0efa869e..414d74d4786d9 100644 --- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -1,11 +1,15 @@ error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:26:28 + --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28 | LL | type Out = Box>; | ^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28 | - = note: the return type of a function must have a statically known size +LL | type Out = Box>; + | ^^^^^^^^^^^ the trait `Copy` is not implemented for `String` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs index 556d8900d1a2e..d180de9be3bf3 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs @@ -6,40 +6,49 @@ use std::fmt::Debug; use std::iter::Once; -trait Lam { type App; } +trait Lam { + type App; +} #[derive(Clone)] struct L1; -impl<'a> Lam<&'a u8> for L1 { type App = u8; } +impl<'a> Lam<&'a u8> for L1 { + type App = u8; +} #[derive(Clone)] struct L2; -impl<'a, 'b> Lam<&'a &'b u8> for L2 { type App = u8; } +impl<'a, 'b> Lam<&'a &'b u8> for L2 { + type App = u8; +} trait Case1 { - type C: Clone + Iterator Lam<&'a u8, App: - Debug - > - > + Sync>; + type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; + //~^ ERROR `<::C as Iterator>::Item` is not an iterator + //~| ERROR `<::C as Iterator>::Item` cannot be sent between threads safely + //~| ERROR `<::C as Iterator>::Item` cannot be shared between threads safely } pub struct S1; impl Case1 for S1 { -//~^ ERROR `>::App` doesn't implement `Debug` [E0277] type C = Once>; } fn assume_case1() { -//~^ ERROR `<_ as Lam<&'a u8>>::App` doesn't implement `Debug` [E0277] -//~| ERROR `<::C as Iterator>::Item` is not an iterator [E0277] -//~| ERROR `<::C as Iterator>::Item` cannot be sent between threads safely [E0277] -//~| ERROR `<::C as Iterator>::Item` cannot be shared between threads safely [E0277] - fn assert_a<_0, A>() where A: Iterator, _0: Debug {} + fn assert_a<_0, A>() + where + A: Iterator, + _0: Debug, + { + } assert_a::<_, T::A>(); - fn assert_b<_0, B>() where B: Iterator, _0: 'static {} + fn assert_b<_0, B>() + where + B: Iterator, + _0: 'static, + { + } assert_b::<_, T::B>(); fn assert_c<_0, _1, _2, C>() @@ -48,7 +57,8 @@ fn assume_case1() { _2: Send + Iterator, _1: for<'a> Lam<&'a u8, App = _0>, _0: Debug, - {} + { + } assert_c::<_, _, _, T::C>(); } diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr index 49b5e7fbb89a9..e68b5b342a40c 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr @@ -1,79 +1,49 @@ -error[E0277]: `>::App` doesn't implement `Debug` - --> $DIR/bad-bounds-on-assoc-in-trait.rs:29:6 +error[E0277]: `<::C as Iterator>::Item` is not an iterator + --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:5 | -LL | trait Case1 { - | ----- required by a bound in this -... -LL | Debug - | ----- required by this bound in `Case1` -... -LL | impl Case1 for S1 { - | ^^^^^ `>::App` cannot be formatted using `{:?}` because it doesn't implement `Debug` +LL | type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<::C as Iterator>::Item` is not an iterator | - = help: the trait `for<'a> Debug` is not implemented for `>::App` - -error[E0277]: `<::C as Iterator>::Item` is not an iterator - --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20 - | -LL | fn assume_case1() { - | ^^^^^ `<::C as Iterator>::Item` is not an iterator - | - = help: the trait `Iterator` is not implemented for `<::C as Iterator>::Item` + = help: the trait `Iterator` is not implemented for `<::C as Iterator>::Item` help: consider further restricting the associated type | -LL | fn assume_case1() where <::C as Iterator>::Item: Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait Case1 where <::C as Iterator>::Item: Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: `<::C as Iterator>::Item` cannot be sent between threads safely - --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20 +error[E0277]: `<::C as Iterator>::Item` cannot be sent between threads safely + --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:36 + | +LL | type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; + | ^^^^ `<::C as Iterator>::Item` cannot be sent between threads safely + | + ::: $SRC_DIR/core/src/marker.rs:LL:COL | -LL | trait Case1 { - | ----- required by a bound in this -LL | type C: Clone + Iterator() { - | ^^^^^ `<::C as Iterator>::Item` cannot be sent between threads safely +LL | pub unsafe auto trait Send { + | -------------------------- required by this bound in `Send` | - = help: the trait `Send` is not implemented for `<::C as Iterator>::Item` + = help: the trait `Send` is not implemented for `<::C as Iterator>::Item` help: consider further restricting the associated type | -LL | fn assume_case1() where <::C as Iterator>::Item: Send { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait Case1 where <::C as Iterator>::Item: Send { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: `<::C as Iterator>::Item` cannot be shared between threads safely - --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20 +error[E0277]: `<::C as Iterator>::Item` cannot be shared between threads safely + --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:93 | -LL | trait Case1 { - | ----- required by a bound in this -... -LL | > + Sync>; - | ---- required by this bound in `Case1` -... -LL | fn assume_case1() { - | ^^^^^ `<::C as Iterator>::Item` cannot be shared between threads safely +LL | type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; + | ^^^^ `<::C as Iterator>::Item` cannot be shared between threads safely + | + ::: $SRC_DIR/core/src/marker.rs:LL:COL | - = help: the trait `Sync` is not implemented for `<::C as Iterator>::Item` -help: consider further restricting the associated type - | -LL | fn assume_case1() where <::C as Iterator>::Item: Sync { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: `<_ as Lam<&'a u8>>::App` doesn't implement `Debug` - --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20 +LL | pub unsafe auto trait Sync { + | -------------------------- required by this bound in `Sync` | -LL | trait Case1 { - | ----- required by a bound in this -... -LL | Debug - | ----- required by this bound in `Case1` -... -LL | fn assume_case1() { - | ^^^^^ `<_ as Lam<&'a u8>>::App` cannot be formatted using `{:?}` because it doesn't implement `Debug` + = help: the trait `Sync` is not implemented for `<::C as Iterator>::Item` +help: consider further restricting the associated type | - = help: the trait `for<'a> Debug` is not implemented for `<_ as Lam<&'a u8>>::App` +LL | trait Case1 where <::C as Iterator>::Item: Sync { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs index ceca54b7cd75f..23be735010bf3 100644 --- a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs +++ b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs @@ -1,5 +1,3 @@ -// check-pass - #![feature(associated_type_bounds)] use std::fmt::Debug; @@ -18,6 +16,7 @@ impl<'a, 'b> Lam<&'a &'b u8> for L2 { type App = u8; } trait Case1 { type A: Iterator; + //~^ ERROR `<::A as Iterator>::Item` doesn't implement `Debug` type B: Iterator; } @@ -30,7 +29,11 @@ impl Case1 for S1 { // Ensure we don't have opaque `impl Trait` desugaring: +// What is this supposed to mean? Rustc currently lowers `: Default` in the +// bounds of `Out`, but trait selection can't find the bound since it applies +// to a type other than `Self::Out`. pub trait Foo { type Out: Baz; } +//~^ ERROR trait bound `<::Out as Baz>::Assoc: Default` is not satisfied pub trait Baz { type Assoc; } #[derive(Default)] diff --git a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr new file mode 100644 index 0000000000000..919b18632e61c --- /dev/null +++ b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr @@ -0,0 +1,36 @@ +error[E0277]: `<::A as Iterator>::Item` doesn't implement `Debug` + --> $DIR/bounds-on-assoc-in-trait.rs:18:28 + | +LL | type A: Iterator; + | ^^^^^ `<::A as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL + | +LL | pub trait Debug { + | --------------- required by this bound in `Debug` + | + = help: the trait `Debug` is not implemented for `<::A as Iterator>::Item` +help: consider further restricting the associated type + | +LL | trait Case1 where <::A as Iterator>::Item: Debug { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `<::Out as Baz>::Assoc: Default` is not satisfied + --> $DIR/bounds-on-assoc-in-trait.rs:35:38 + | +LL | pub trait Foo { type Out: Baz; } + | ^^^^^^^ the trait `Default` is not implemented for `<::Out as Baz>::Assoc` + | + ::: $SRC_DIR/core/src/default.rs:LL:COL + | +LL | pub trait Default: Sized { + | ------------------------ required by this bound in `Default` + | +help: consider further restricting the associated type + | +LL | pub trait Foo where <::Out as Baz>::Assoc: Default { type Out: Baz; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr index 77cd88e524f5f..de2876d6b60b8 100644 --- a/src/test/ui/associated-type-bounds/duplicate.stderr +++ b/src/test/ui/associated-type-bounds/duplicate.stderr @@ -511,30 +511,6 @@ LL | trait TRSW3 where Self: Iterator {} | | | `Item` bound here first -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:145:43 - | -LL | trait TRA1 { type A: Iterator; } - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:147:43 - | -LL | trait TRA2 { type A: Iterator; } - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:149:46 - | -LL | trait TRA3 { type A: Iterator; } - | ------------- ^^^^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified --> $DIR/duplicate.rs:152:40 | @@ -559,6 +535,30 @@ LL | type TADyn3 = dyn Iterator; | | | `Item` bound here first +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:145:43 + | +LL | trait TRA1 { type A: Iterator; } + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:147:43 + | +LL | trait TRA2 { type A: Iterator; } + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:149:46 + | +LL | trait TRA3 { type A: Iterator; } + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + error: aborting due to 69 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0719`. diff --git a/src/test/ui/associated-types/associate-type-bound-normalization.rs b/src/test/ui/associated-types/associate-type-bound-normalization.rs new file mode 100644 index 0000000000000..db092970f79b8 --- /dev/null +++ b/src/test/ui/associated-types/associate-type-bound-normalization.rs @@ -0,0 +1,25 @@ +// Make sure that we normalize bounds on associated types before checking them +// as candidates. + +// check-pass + +trait Mul { + type Output; +} + +trait Matrix: Mul<::Row, Output = ()> { + type Row; + + type Transpose: Matrix; +} + +fn is_mul>() {} + +fn f() { + // The unnormalized bound on `T::Transpose` is + // `Mul<::Row` which has to be normalized to be + // equal to `T::Row`. + is_mul::(); +} + +fn main() {} diff --git a/src/test/ui/associated-types/associated-types-bound-ambiguity.rs b/src/test/ui/associated-types/associated-types-bound-ambiguity.rs new file mode 100644 index 0000000000000..9f179b6454e52 --- /dev/null +++ b/src/test/ui/associated-types/associated-types-bound-ambiguity.rs @@ -0,0 +1,23 @@ +// Make sure that if there are multiple applicable bounds on a projection, we +// consider them ambiguous. In this test we are initially trying to solve +// `Self::Repr: From<_>`, which is ambiguous until we later infer `_` to +// `{integer}`. + +// check-pass + +trait PrimeField: Sized { + type Repr: From + From; + type Repr2: From + From; + + fn method() { + Self::Repr::from(10); + Self::Repr2::from(10); + } +} + +fn function() { + T::Repr::from(10); + T::Repr2::from(10); +} + +fn main() {} diff --git a/src/test/ui/associated-types/associated-types-projection-bound-ambiguity.rs b/src/test/ui/associated-types/associated-types-projection-bound-ambiguity.rs new file mode 100644 index 0000000000000..353f82e7c6e63 --- /dev/null +++ b/src/test/ui/associated-types/associated-types-projection-bound-ambiguity.rs @@ -0,0 +1,16 @@ +// Check that if we have multiple applicable projection bounds we pick one (for +// backwards compatibility reasons). + +// check-pass +use std::ops::Mul; + +trait A { + type V; + type U: Mul + Mul<(), Output = ()>; +} + +fn g>() { + let y: >::Output = (); +} + +fn main() {} diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr index 2914a7f868b2b..9d084203e3a86 100644 --- a/src/test/ui/associated-types/associated-types-unconstrained.stderr +++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr @@ -1,11 +1,14 @@ -error[E0284]: type annotations needed +error[E0283]: type annotations needed --> $DIR/associated-types-unconstrained.rs:14:20 | +LL | fn bar() -> isize; + | ------------------ required by `Foo::bar` +... LL | let x: isize = Foo::bar(); | ^^^^^^^^ cannot infer type | - = note: cannot satisfy `<_ as Foo>::A == _` + = note: cannot satisfy `_: Foo` error: aborting due to previous error -For more information about this error, try `rustc --explain E0284`. +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.rs b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs index fa75f6bc15228..afb2b3df716eb 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-1.rs +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs @@ -6,11 +6,8 @@ trait Tr { type B = Self::A; } -// ...but is an error in any impl that doesn't override at least one of the defaults impl Tr for () {} -//~^ ERROR overflow evaluating the requirement -// As soon as at least one is redefined, it works: impl Tr for u8 { type A = u8; } @@ -24,16 +21,14 @@ impl Tr for u32 { type B = u8; } -// ...but only if this actually breaks the cycle +// ...but not in an impl that redefines one of the types. impl Tr for bool { - //~^ ERROR type mismatch resolving `::B == _` type A = Box; //~^ ERROR type mismatch resolving `::B == _` } // (the error is shown twice for some reason) impl Tr for usize { - //~^ ERROR type mismatch resolving `::B == _` type B = &'static Self::A; //~^ ERROR type mismatch resolving `::A == _` } diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr index 0aea30b11126b..ae7150d47ca99 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr @@ -1,34 +1,15 @@ -error[E0275]: overflow evaluating the requirement `<() as Tr>::B == _` - --> $DIR/defaults-cyclic-fail-1.rs:10:6 - | -LL | impl Tr for () {} - | ^^ - -error[E0271]: type mismatch resolving `::B == _` - --> $DIR/defaults-cyclic-fail-1.rs:28:6 - | -LL | impl Tr for bool { - | ^^ cyclic type of infinite size - -error[E0271]: type mismatch resolving `::B == _` - --> $DIR/defaults-cyclic-fail-1.rs:35:6 - | -LL | impl Tr for usize { - | ^^ cyclic type of infinite size - error[E0271]: type mismatch resolving `::B == _` - --> $DIR/defaults-cyclic-fail-1.rs:30:5 + --> $DIR/defaults-cyclic-fail-1.rs:26:5 | LL | type A = Box; | ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size error[E0271]: type mismatch resolving `::A == _` - --> $DIR/defaults-cyclic-fail-1.rs:37:5 + --> $DIR/defaults-cyclic-fail-1.rs:32:5 | LL | type B = &'static Self::A; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0271, E0275. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs index edcd310908aa4..ba4bb0d5a296b 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs @@ -8,11 +8,8 @@ trait Tr { type B = Box; } -// ...but is an error in any impl that doesn't override at least one of the defaults impl Tr for () {} -//~^ ERROR type mismatch resolving `<() as Tr>::B == _` -// As soon as at least one is redefined, it works: impl Tr for u8 { type A = u8; } @@ -26,16 +23,13 @@ impl Tr for u32 { type B = u8; } -// ...but only if this actually breaks the cycle impl Tr for bool { - //~^ ERROR type mismatch resolving `::B == _` type A = Box; //~^ ERROR type mismatch resolving `::B == _` } // (the error is shown twice for some reason) impl Tr for usize { - //~^ ERROR type mismatch resolving `::B == _` type B = &'static Self::A; //~^ ERROR type mismatch resolving `::A == _` } diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr index f39021c30edc1..0dfbac2dec5d5 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr @@ -1,33 +1,15 @@ -error[E0271]: type mismatch resolving `<() as Tr>::B == _` - --> $DIR/defaults-cyclic-fail-2.rs:12:6 - | -LL | impl Tr for () {} - | ^^ cyclic type of infinite size - -error[E0271]: type mismatch resolving `::B == _` - --> $DIR/defaults-cyclic-fail-2.rs:30:6 - | -LL | impl Tr for bool { - | ^^ cyclic type of infinite size - -error[E0271]: type mismatch resolving `::B == _` - --> $DIR/defaults-cyclic-fail-2.rs:37:6 - | -LL | impl Tr for usize { - | ^^ cyclic type of infinite size - error[E0271]: type mismatch resolving `::B == _` - --> $DIR/defaults-cyclic-fail-2.rs:32:5 + --> $DIR/defaults-cyclic-fail-2.rs:27:5 | LL | type A = Box; | ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size error[E0271]: type mismatch resolving `::A == _` - --> $DIR/defaults-cyclic-fail-2.rs:39:5 + --> $DIR/defaults-cyclic-fail-2.rs:33:5 | LL | type B = &'static Self::A; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/defaults-suitability.rs b/src/test/ui/associated-types/defaults-suitability.rs index 30c2555df8bb9..504c957d98753 100644 --- a/src/test/ui/associated-types/defaults-suitability.rs +++ b/src/test/ui/associated-types/defaults-suitability.rs @@ -1,10 +1,8 @@ //! Checks that associated type defaults are properly validated. //! //! This means: -//! * Default types are wfchecked //! * Default types are checked against where clauses on the assoc. type -//! (eg. `type Assoc: Clone = NotClone`), and also against where clauses on -//! the trait itself when possible +//! (eg. `type Assoc: Clone = NotClone`) #![feature(associated_type_defaults)] @@ -17,15 +15,12 @@ trait Tr { } // Where-clauses defined on the trait must also be considered -trait Tr2 where Self::Ty: Clone { - //~^ ERROR the trait bound `NotClone: Clone` is not satisfied +trait Tr2 +where + Self::Ty: Clone, +{ type Ty = NotClone; -} - -// Independent of where-clauses (there are none here), default types must always be wf -trait Tr3 { - type Ty = Vec<[u8]>; - //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + //~^ ERROR the trait bound `NotClone: Clone` is not satisfied } // Involved type parameters must fulfill all bounds required by defaults that mention them @@ -43,7 +38,7 @@ trait Bar: Sized { trait IsU8 {} impl IsU8 for T {} -// Test that mentioning the assoc. type inside where clauses works +// Test that mentioning the assoc. type inside where clauses is not allowed trait C where Vec: Clone, Self::Assoc: IsU8, @@ -55,13 +50,11 @@ trait C where // Test that we get all expected errors if that default is unsuitable trait D where Vec: Clone, - //~^ ERROR the trait bound `NotClone: Clone` is not satisfied Self::Assoc: IsU8, - //~^ ERROR the trait bound `NotClone: IsU8` is not satisfied bool: IsU8, - //~^ ERROR the trait bound `bool: IsU8` is not satisfied { type Assoc = NotClone; + //~^ ERROR the trait bound `NotClone: IsU8` is not satisfied } // Test behavior of the check when defaults refer to other defaults: @@ -85,18 +78,20 @@ trait Foo25 { // Adding the `Baz: Clone` bound isn't enough since the default is type // parameter `T`, which also might not be `Clone`. -trait Foo3 where +trait Foo3 +where Self::Bar: Clone, Self::Baz: Clone, - //~^ ERROR the trait bound `T: Clone` is not satisfied { type Bar = Vec; type Baz = T; + //~^ ERROR the trait bound `T: Clone` is not satisfied } // This one finally works, with `Clone` bounds on all assoc. types and the type // parameter. -trait Foo4 where +trait Foo4 +where T: Clone, { type Bar: Clone = Vec; diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index c2ad4c5824ea9..274d09fd09c86 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -1,27 +1,32 @@ error[E0277]: the trait bound `NotClone: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:15:14 + --> $DIR/defaults-suitability.rs:13:5 | -LL | trait Tr { - | -------- required by `Tr` LL | type Ty: Clone = NotClone; - | ^^^^^ the trait `Clone` is not implemented for `NotClone` + | ^^^^^^^^^-----^^^^^^^^^^^^ + | | | + | | required by this bound in `Tr::Ty` + | the trait `Clone` is not implemented for `NotClone` error[E0277]: the trait bound `NotClone: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:20:27 - | -LL | trait Tr2 where Self::Ty: Clone { - | --------------------------^^^^^ - | | | - | | the trait `Clone` is not implemented for `NotClone` - | required by `Tr2` + --> $DIR/defaults-suitability.rs:22:5 + | +LL | Self::Ty: Clone, + | ----- required by this bound in `Tr2::Ty` +LL | { +LL | type Ty = NotClone; + | ^^^^^--^^^^^^^^^^^^ + | | | + | | required by a bound in this + | the trait `Clone` is not implemented for `NotClone` error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:33:15 + --> $DIR/defaults-suitability.rs:28:5 | -LL | trait Foo { - | ------------ required by `Foo` LL | type Bar: Clone = Vec; - | ^^^^^ the trait `Clone` is not implemented for `T` + | ^^^^^^^^^^-----^^^^^^^^^^ + | | | + | | required by this bound in `Foo::Bar` + | the trait `Clone` is not implemented for `T` | = note: required because of the requirements on the impl of `Clone` for `Vec` help: consider restricting type parameter `T` @@ -30,64 +35,34 @@ LL | trait Foo { | ^^^^^^^ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/defaults-suitability.rs:39:17 + --> $DIR/defaults-suitability.rs:34:5 | -LL | trait Bar: Sized { - | ---------------- required by `Bar` -LL | // `(): Foo` might hold for some possible impls but not all. LL | type Assoc: Foo = (); - | ^^^^^^^^^ the trait `Foo` is not implemented for `()` + | ^^^^^^^^^^^^---------^^^^^^ + | | | + | | required by this bound in `Bar::Assoc` + | the trait `Foo` is not implemented for `()` error[E0277]: the trait bound `NotClone: IsU8` is not satisfied - --> $DIR/defaults-suitability.rs:59:18 - | -LL | / trait D where -LL | | Vec: Clone, -LL | | -LL | | Self::Assoc: IsU8, - | | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `NotClone` -... | -LL | | type Assoc = NotClone; -LL | | } - | |_- required by `D` - -error[E0277]: the trait bound `bool: IsU8` is not satisfied - --> $DIR/defaults-suitability.rs:61:11 - | -LL | / trait D where -LL | | Vec: Clone, -LL | | -LL | | Self::Assoc: IsU8, -LL | | -LL | | bool: IsU8, - | | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `bool` -... | -LL | | type Assoc = NotClone; -LL | | } - | |_- required by `D` - -error[E0277]: the trait bound `NotClone: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:57:23 - | -LL | / trait D where -LL | | Vec: Clone, - | | ^^^^^ the trait `Clone` is not implemented for `NotClone` -LL | | -LL | | Self::Assoc: IsU8, -... | -LL | | type Assoc = NotClone; -LL | | } - | |_- required by `D` - | - = note: required because of the requirements on the impl of `Clone` for `Vec` + --> $DIR/defaults-suitability.rs:56:5 + | +LL | Self::Assoc: IsU8, + | ----------------- required by this bound in `D::Assoc` +... +LL | type Assoc = NotClone; + | ^^^^^-----^^^^^^^^^^^^ + | | | + | | required by a bound in this + | the trait `IsU8` is not implemented for `NotClone` error[E0277]: the trait bound `>::Baz: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:72:15 + --> $DIR/defaults-suitability.rs:65:5 | -LL | trait Foo2 { - | ------------- required by `Foo2` LL | type Bar: Clone = Vec; - | ^^^^^ the trait `Clone` is not implemented for `>::Baz` + | ^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `Foo2::Bar` + | the trait `Clone` is not implemented for `>::Baz` | = note: required because of the requirements on the impl of `Clone` for `Vec<>::Baz>` help: consider further restricting the associated type @@ -96,12 +71,13 @@ LL | trait Foo2 where >::Baz: Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `>::Baz: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:81:15 + --> $DIR/defaults-suitability.rs:74:5 | -LL | trait Foo25 { - | --------------------- required by `Foo25` LL | type Bar: Clone = Vec; - | ^^^^^ the trait `Clone` is not implemented for `>::Baz` + | ^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `Foo25::Bar` + | the trait `Clone` is not implemented for `>::Baz` | = note: required because of the requirements on the impl of `Clone` for `Vec<>::Baz>` help: consider further restricting the associated type @@ -110,36 +86,22 @@ LL | trait Foo25 where >::Baz: Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:90:16 - | -LL | / trait Foo3 where -LL | | Self::Bar: Clone, -LL | | Self::Baz: Clone, - | | ^^^^^ the trait `Clone` is not implemented for `T` -LL | | -... | -LL | | type Baz = T; -LL | | } - | |_- required by `Foo3` + --> $DIR/defaults-suitability.rs:87:5 + | +LL | Self::Baz: Clone, + | ----- required by this bound in `Foo3::Baz` +... +LL | type Baz = T; + | ^^^^^---^^^^^ + | | | + | | required by a bound in this + | the trait `Clone` is not implemented for `T` | help: consider further restricting type parameter `T` | LL | Self::Baz: Clone, T: Clone | ^^^^^^^^^^ -error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/defaults-suitability.rs:27:5 - | -LL | type Ty = Vec<[u8]>; - | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - ::: $SRC_DIR/alloc/src/vec.rs:LL:COL - | -LL | pub struct Vec { - | - required by this bound in `Vec` - | - = help: the trait `Sized` is not implemented for `[u8]` - -error: aborting due to 11 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.rs b/src/test/ui/associated-types/defaults-unsound-62211-1.rs index f283d22b3c7eb..fa6a208b4f1ba 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.rs @@ -11,22 +11,17 @@ use std::{ fmt::Display, - ops::{AddAssign, Deref} + ops::{AddAssign, Deref}, }; - trait UncheckedCopy: Sized { // This Output is said to be Copy. Yet we default to Self // and it's accepted, not knowing if Self ineed is Copy - type Output: Copy + type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; //~^ ERROR the trait bound `Self: Copy` is not satisfied - + Deref - //~^ ERROR the trait bound `Self: Deref` is not satisfied - + AddAssign<&'static str> - //~^ ERROR cannot add-assign `&'static str` to `Self` - + From - + Display = Self; - //~^ ERROR `Self` doesn't implement `std::fmt::Display` + //~| ERROR the trait bound `Self: Deref` is not satisfied + //~| ERROR cannot add-assign `&'static str` to `Self` + //~| ERROR `Self` doesn't implement `std::fmt::Display` // We said the Output type was Copy, so we can Copy it freely! fn unchecked_copy(other: &Self::Output) -> Self::Output { @@ -39,10 +34,6 @@ trait UncheckedCopy: Sized { } impl UncheckedCopy for T {} -//~^ ERROR `T` doesn't implement `std::fmt::Display` -//~| ERROR the trait bound `T: Deref` is not satisfied -//~| ERROR cannot add-assign `&'static str` to `T` -//~| ERROR the trait bound `T: Copy` is not satisfied fn bug(origin: T) { let origin = T::make_origin(origin); diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr index 29a7c2eab41d5..8e446cf051f47 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -1,129 +1,60 @@ -error[E0277]: the trait bound `Self: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:21:18 - | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | type Output: Copy - | ^^^^ the trait `Copy` is not implemented for `Self` - | -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + Copy { - | ^^^^^^ - -error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-1.rs:25:7 +error[E0277]: `Self` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-1.rs:20:5 | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | + AddAssign<&'static str> - | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | `Self` cannot be formatted with the default formatter | + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead help: consider further restricting `Self` | -LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait UncheckedCopy: Sized + std::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:23:7 + --> $DIR/defaults-unsound-62211-1.rs:20:5 | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | + Deref - | ^^^^^^^^^^^^^^^^^^^ the trait `Deref` is not implemented for `Self` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^-------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | the trait `Deref` is not implemented for `Self` | help: consider further restricting `Self` | LL | trait UncheckedCopy: Sized + Deref { | ^^^^^^^ -error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:28:7 +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-1.rs:20:5 | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | + Display = Self; - | ^^^^^^^ `Self` cannot be formatted with the default formatter +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | no implementation for `Self += &'static str` | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead help: consider further restricting `Self` | -LL | trait UncheckedCopy: Sized + std::fmt::Display { - | ^^^^^^^^^^^^^^^^^^^ - -error[E0277]: `T` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | + Display = Self; - | ------- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter - | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead -help: consider restricting type parameter `T` - | -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `T: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | + Deref - | ------------------- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `Deref` is not implemented for `T` - | -help: consider restricting type parameter `T` - | -LL | impl UncheckedCopy for T {} - | ^^^^^^^ - -error[E0277]: cannot add-assign `&'static str` to `T` - --> $DIR/defaults-unsound-62211-1.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | + AddAssign<&'static str> - | ----------------------- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ no implementation for `T += &'static str` - | -help: consider restricting type parameter `T` - | -LL | impl> UncheckedCopy for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:41:9 +error[E0277]: the trait bound `Self: Copy` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:20:5 | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | type Output: Copy - | ---- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | the trait `Copy` is not implemented for `Self` | -help: consider restricting type parameter `T` +help: consider further restricting `Self` | -LL | impl UncheckedCopy for T {} - | ^^^^^^ +LL | trait UncheckedCopy: Sized + Copy { + | ^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.rs b/src/test/ui/associated-types/defaults-unsound-62211-2.rs index 5518cda37087c..c13ec776afe2b 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.rs @@ -11,22 +11,17 @@ use std::{ fmt::Display, - ops::{AddAssign, Deref} + ops::{AddAssign, Deref}, }; - trait UncheckedCopy: Sized { // This Output is said to be Copy. Yet we default to Self // and it's accepted, not knowing if Self ineed is Copy - type Output: Copy + type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; //~^ ERROR the trait bound `Self: Copy` is not satisfied - + Deref - //~^ ERROR the trait bound `Self: Deref` is not satisfied - + AddAssign<&'static str> - //~^ ERROR cannot add-assign `&'static str` to `Self` - + From - + Display = Self; - //~^ ERROR `Self` doesn't implement `std::fmt::Display` + //~| ERROR the trait bound `Self: Deref` is not satisfied + //~| ERROR cannot add-assign `&'static str` to `Self` + //~| ERROR `Self` doesn't implement `std::fmt::Display` // We said the Output type was Copy, so we can Copy it freely! fn unchecked_copy(other: &Self::Output) -> Self::Output { @@ -39,10 +34,6 @@ trait UncheckedCopy: Sized { } impl UncheckedCopy for T {} -//~^ ERROR `T` doesn't implement `std::fmt::Display` -//~| ERROR the trait bound `T: Deref` is not satisfied -//~| ERROR cannot add-assign `&'static str` to `T` -//~| ERROR the trait bound `T: Copy` is not satisfied fn bug(origin: T) { let origin = T::make_origin(origin); diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr index 49c66093bf039..93f4f497b38a2 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -1,129 +1,60 @@ -error[E0277]: the trait bound `Self: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:21:18 - | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | type Output: Copy - | ^^^^ the trait `Copy` is not implemented for `Self` - | -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + Copy { - | ^^^^^^ - -error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-2.rs:25:7 +error[E0277]: `Self` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-2.rs:20:5 | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | + AddAssign<&'static str> - | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | `Self` cannot be formatted with the default formatter | + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead help: consider further restricting `Self` | -LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait UncheckedCopy: Sized + std::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:23:7 + --> $DIR/defaults-unsound-62211-2.rs:20:5 | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | + Deref - | ^^^^^^^^^^^^^^^^^^^ the trait `Deref` is not implemented for `Self` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^-------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | the trait `Deref` is not implemented for `Self` | help: consider further restricting `Self` | LL | trait UncheckedCopy: Sized + Deref { | ^^^^^^^ -error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:28:7 +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-2.rs:20:5 | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | + Display = Self; - | ^^^^^^^ `Self` cannot be formatted with the default formatter +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | no implementation for `Self += &'static str` | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead help: consider further restricting `Self` | -LL | trait UncheckedCopy: Sized + std::fmt::Display { - | ^^^^^^^^^^^^^^^^^^^ - -error[E0277]: `T` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | + Display = Self; - | ------- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter - | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead -help: consider restricting type parameter `T` - | -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `T: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | + Deref - | ------------------- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `Deref` is not implemented for `T` - | -help: consider restricting type parameter `T` - | -LL | impl UncheckedCopy for T {} - | ^^^^^^^ - -error[E0277]: cannot add-assign `&'static str` to `T` - --> $DIR/defaults-unsound-62211-2.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | + AddAssign<&'static str> - | ----------------------- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ no implementation for `T += &'static str` - | -help: consider restricting type parameter `T` - | -LL | impl> UncheckedCopy for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:41:9 +error[E0277]: the trait bound `Self: Copy` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:20:5 | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | type Output: Copy - | ---- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | the trait `Copy` is not implemented for `Self` | -help: consider restricting type parameter `T` +help: consider further restricting `Self` | -LL | impl UncheckedCopy for T {} - | ^^^^^^ +LL | trait UncheckedCopy: Sized + Copy { + | ^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/defaults-wf.rs b/src/test/ui/associated-types/defaults-wf.rs new file mode 100644 index 0000000000000..99b5125033465 --- /dev/null +++ b/src/test/ui/associated-types/defaults-wf.rs @@ -0,0 +1,11 @@ +// Check that associated type defaults are wf checked. + +#![feature(associated_type_defaults)] + +// Default types must always be wf +trait Tr3 { + type Ty = Vec<[u8]>; + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +} + +fn main() {} diff --git a/src/test/ui/associated-types/defaults-wf.stderr b/src/test/ui/associated-types/defaults-wf.stderr new file mode 100644 index 0000000000000..f9044c2ea1b66 --- /dev/null +++ b/src/test/ui/associated-types/defaults-wf.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/defaults-wf.rs:7:5 + | +LL | type Ty = Vec<[u8]>; + | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/alloc/src/vec.rs:LL:COL + | +LL | pub struct Vec { + | - required by this bound in `Vec` + | + = help: the trait `Sized` is not implemented for `[u8]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr index 566e390a31e48..b0e9e33a6c38e 100644 --- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr @@ -9,7 +9,6 @@ LL | fn baz() -> impl Bar { | = note: expected associated type `::Item` found type `i32` - = note: the return type of a function must have a statically known size help: consider constraining the associated type `::Item` to `i32` | LL | fn bar() -> impl Bar { diff --git a/src/test/ui/associated-types/issue-43924.rs b/src/test/ui/associated-types/issue-43924.rs index 26f1183c6bd76..6a63b3e093674 100644 --- a/src/test/ui/associated-types/issue-43924.rs +++ b/src/test/ui/associated-types/issue-43924.rs @@ -4,12 +4,13 @@ // type-checked. trait Foo { - type Out: Default + ToString + ?Sized = dyn ToString; //~ error: not satisfied + type Out: Default + ToString + ?Sized = dyn ToString; //~ ERROR not satisfied } -impl Foo for () {} //~ error: not satisfied -impl Foo for () {} //~ error: not satisfied +impl Foo for () {} +impl Foo for () {} fn main() { assert_eq!(<() as Foo>::Out::default().to_string(), "false"); + //~^ ERROR no function or associated item named `default` found for trait object } diff --git a/src/test/ui/associated-types/issue-43924.stderr b/src/test/ui/associated-types/issue-43924.stderr index 661730bcd757a..8d4ecac750268 100644 --- a/src/test/ui/associated-types/issue-43924.stderr +++ b/src/test/ui/associated-types/issue-43924.stderr @@ -1,33 +1,19 @@ error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied - --> $DIR/issue-43924.rs:7:15 + --> $DIR/issue-43924.rs:7:5 | -LL | trait Foo { - | -------------------------------- required by `Foo` LL | type Out: Default + ToString + ?Sized = dyn ToString; - | ^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)` + | ^^^^^^^^^^-------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `Foo::Out` + | the trait `Default` is not implemented for `(dyn ToString + 'static)` -error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied - --> $DIR/issue-43924.rs:10:6 - | -LL | trait Foo { - | --- required by a bound in this -LL | type Out: Default + ToString + ?Sized = dyn ToString; - | ------- required by this bound in `Foo` -... -LL | impl Foo for () {} - | ^^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)` - -error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied - --> $DIR/issue-43924.rs:11:6 +error[E0599]: no function or associated item named `default` found for trait object `(dyn ToString + 'static)` in the current scope + --> $DIR/issue-43924.rs:14:39 | -LL | trait Foo { - | --- required by a bound in this -LL | type Out: Default + ToString + ?Sized = dyn ToString; - | ------- required by this bound in `Foo` -... -LL | impl Foo for () {} - | ^^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)` +LL | assert_eq!(<() as Foo>::Out::default().to_string(), "false"); + | ^^^^^^^ function or associated item not found in `(dyn ToString + 'static)` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/issue-63593.stderr b/src/test/ui/associated-types/issue-63593.stderr index ddc0bf436f6d5..16ae07687e2c7 100644 --- a/src/test/ui/associated-types/issue-63593.stderr +++ b/src/test/ui/associated-types/issue-63593.stderr @@ -1,10 +1,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/issue-63593.rs:9:5 | -LL | trait MyTrait { - | ------------- required by `MyTrait` LL | type This = Self; - | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by this bound in `MyTrait::This` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/issue-65774-1.rs b/src/test/ui/associated-types/issue-65774-1.rs index 0ffd6cc2cf230..9345140558b07 100644 --- a/src/test/ui/associated-types/issue-65774-1.rs +++ b/src/test/ui/associated-types/issue-65774-1.rs @@ -14,7 +14,6 @@ trait MPU { struct S; impl MPU for S { } -//~^ ERROR the trait bound `T: MyDisplay` is not satisfied trait MyWrite { fn my_write(&self, _: &dyn MyDisplay) { } @@ -43,6 +42,7 @@ impl ProcessType for Process { // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), // depth=1),Unimplemented) let closure = |config: &mut ::MpuConfig| writer.my_write(&config); + //~^ ERROR the trait bound `T: MyDisplay` is not satisfied closure(valref); } } diff --git a/src/test/ui/associated-types/issue-65774-1.stderr b/src/test/ui/associated-types/issue-65774-1.stderr index 72f47df5d80e7..f644eb5a1f478 100644 --- a/src/test/ui/associated-types/issue-65774-1.stderr +++ b/src/test/ui/associated-types/issue-65774-1.stderr @@ -1,21 +1,20 @@ error[E0277]: the trait bound `T: MyDisplay` is not satisfied - --> $DIR/issue-65774-1.rs:10:21 + --> $DIR/issue-65774-1.rs:10:5 | -LL | trait MPU { - | --------- required by `MPU` LL | type MpuConfig: MyDisplay = T; - | ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T` + | ^^^^^^^^^^^^^^^^---------^^^^^ + | | | + | | required by this bound in `MPU::MpuConfig` + | the trait `MyDisplay` is not implemented for `T` error[E0277]: the trait bound `T: MyDisplay` is not satisfied - --> $DIR/issue-65774-1.rs:16:6 + --> $DIR/issue-65774-1.rs:44:76 | -LL | trait MPU { - | --- required by a bound in this -LL | type MpuConfig: MyDisplay = T; - | --------- required by this bound in `MPU` -... -LL | impl MPU for S { } - | ^^^ the trait `MyDisplay` is not implemented for `T` +LL | let closure = |config: &mut ::MpuConfig| writer.my_write(&config); + | ^^^^^^^ the trait `MyDisplay` is not implemented for `T` + | + = note: required because of the requirements on the impl of `MyDisplay` for `&mut T` + = note: required for the cast to the object type `dyn MyDisplay` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/issue-65774-2.rs b/src/test/ui/associated-types/issue-65774-2.rs index 31e203a81d397..171e0893b4719 100644 --- a/src/test/ui/associated-types/issue-65774-2.rs +++ b/src/test/ui/associated-types/issue-65774-2.rs @@ -14,7 +14,6 @@ trait MPU { struct S; impl MPU for S { } -//~^ ERROR the trait bound `T: MyDisplay` is not satisfied trait MyWrite { fn my_write(&self, _: &dyn MyDisplay) { } @@ -38,6 +37,7 @@ impl ProcessType for Process { // // `Unimplemented` selecting `Binder()` during codegen // writer.my_write(valref) + //~^ ERROR the trait bound `T: MyDisplay` is not satisfied // This one causes the ICE: // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), diff --git a/src/test/ui/associated-types/issue-65774-2.stderr b/src/test/ui/associated-types/issue-65774-2.stderr index aef70885af369..572a9cf190952 100644 --- a/src/test/ui/associated-types/issue-65774-2.stderr +++ b/src/test/ui/associated-types/issue-65774-2.stderr @@ -1,21 +1,19 @@ error[E0277]: the trait bound `T: MyDisplay` is not satisfied - --> $DIR/issue-65774-2.rs:10:21 + --> $DIR/issue-65774-2.rs:10:5 | -LL | trait MPU { - | --------- required by `MPU` LL | type MpuConfig: MyDisplay = T; - | ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T` + | ^^^^^^^^^^^^^^^^---------^^^^^ + | | | + | | required by this bound in `MPU::MpuConfig` + | the trait `MyDisplay` is not implemented for `T` error[E0277]: the trait bound `T: MyDisplay` is not satisfied - --> $DIR/issue-65774-2.rs:16:6 + --> $DIR/issue-65774-2.rs:39:25 | -LL | trait MPU { - | --- required by a bound in this -LL | type MpuConfig: MyDisplay = T; - | --------- required by this bound in `MPU` -... -LL | impl MPU for S { } - | ^^^ the trait `MyDisplay` is not implemented for `T` +LL | writer.my_write(valref) + | ^^^^^^ the trait `MyDisplay` is not implemented for `T` + | + = note: required for the cast to the object type `dyn MyDisplay` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/issue-72806.rs b/src/test/ui/associated-types/issue-72806.rs index ae63781d568a1..94758250346d1 100644 --- a/src/test/ui/associated-types/issue-72806.rs +++ b/src/test/ui/associated-types/issue-72806.rs @@ -9,9 +9,10 @@ trait Bar2 { struct Foo; struct Foo2; -impl Bar for Foo { //~ ERROR type mismatch resolving `::Ok == char` +impl Bar for Foo { type Ok = (); type Sibling = Foo2; + //~^ ERROR type mismatch resolving `::Ok == char` } impl Bar2 for Foo2 { type Ok = u32; diff --git a/src/test/ui/associated-types/issue-72806.stderr b/src/test/ui/associated-types/issue-72806.stderr index 03a6565848dc3..23fabbee1c5d4 100644 --- a/src/test/ui/associated-types/issue-72806.stderr +++ b/src/test/ui/associated-types/issue-72806.stderr @@ -1,8 +1,11 @@ error[E0271]: type mismatch resolving `::Ok == char` - --> $DIR/issue-72806.rs:12:6 + --> $DIR/issue-72806.rs:14:5 | -LL | impl Bar for Foo { - | ^^^ expected `u32`, found `char` +LL | type Sibling: Bar2; + | ------- required by this bound in `Bar::Sibling` +... +LL | type Sibling = Foo2; + | ^^^^^^^^^^^^^^^^^^^^ expected `char`, found `u32` error: aborting due to previous error diff --git a/src/test/ui/associated-types/object-normalization.rs b/src/test/ui/associated-types/object-normalization.rs new file mode 100644 index 0000000000000..1f93248e10ec4 --- /dev/null +++ b/src/test/ui/associated-types/object-normalization.rs @@ -0,0 +1,26 @@ +// ignore-tidy-linelength + +// Check that we normalize super predicates for object candidates. + +// check-pass + +use std::ops::Index; + +fn next<'a, T>(s: &'a mut dyn SVec) { + // To prove + // `dyn SVec: SVec` + // we need to show + // `dyn SVec as Index>::Output == as SVec>::Item` + // which, with the current normalization strategy, has to be eagerly + // normalized to: + // `dyn SVec as Index>::Output == T`. + let _ = s.len(); +} + +trait SVec: Index::Item> { + type Item; + + fn len(&self) -> usize; +} + +fn main() {} diff --git a/src/test/ui/associated-types/param-env-normalize-cycle.rs b/src/test/ui/associated-types/param-env-normalize-cycle.rs new file mode 100644 index 0000000000000..12db595ed2572 --- /dev/null +++ b/src/test/ui/associated-types/param-env-normalize-cycle.rs @@ -0,0 +1,39 @@ +// Minimized case from typenum that didn't compile because: +// - We tried to normalize the ParamEnv of the second impl +// - This requires trying to normalize `GrEq>>` +// - This requires proving `Square>: Sized` so that the first impl +// applies +// - This requires Providing `Square>` is well-formed, so that we +// can use the `Sized` bound on `Mul::Output` +// - This requires proving `Square: Mul` +// - But first we tried normalizing the whole obligation, including the +// ParamEnv, which leads to a cycle error. + +// check-pass + +trait PrivateSquareRoot {} + +pub trait Mul { + type Output; +} + +pub trait IsGreaterOrEqual { + type Output; +} + +pub type Square = ::Output; +pub type GrEq = >::Output; + +impl IsGreaterOrEqual for A { + type Output = (); +} + +impl PrivateSquareRoot for U +where + U: Mul, + Square: Mul, + GrEq>>: Sized, +{ +} + +fn main() {} diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs index 67b7c78071c37..4b3d6e9d6067f 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs @@ -8,7 +8,10 @@ impl Foo for () { type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied } -trait Baz where Self::Assoc: Bar { +trait Baz +where + Self::Assoc: Bar, +{ type Assoc; } @@ -16,7 +19,10 @@ impl Baz for () { type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied } -trait Bat where ::Assoc: Bar { +trait Bat +where + ::Assoc: Bar, +{ type Assoc; } diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr index 3118a9c5352c3..b23030d7cb52b 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr @@ -1,31 +1,35 @@ error[E0277]: the trait bound `bool: Bar` is not satisfied - --> $DIR/point-at-type-on-obligation-failure-2.rs:8:18 + --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5 | -LL | trait Foo { - | --- required by a bound in this LL | type Assoc: Bar; - | --- required by this bound in `Foo` + | --- required by this bound in `Foo::Assoc` ... LL | type Assoc = bool; - | ^^^^ the trait `Bar` is not implemented for `bool` + | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` error[E0277]: the trait bound `bool: Bar` is not satisfied - --> $DIR/point-at-type-on-obligation-failure-2.rs:16:18 + --> $DIR/point-at-type-on-obligation-failure-2.rs:19:5 | -LL | trait Baz where Self::Assoc: Bar { - | --- required by this bound in `Baz` +LL | Self::Assoc: Bar, + | --- required by this bound in `Baz::Assoc` +LL | { +LL | type Assoc; + | ----- required by a bound in this ... LL | type Assoc = bool; - | ^^^^ the trait `Bar` is not implemented for `bool` + | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` error[E0277]: the trait bound `bool: Bar` is not satisfied - --> $DIR/point-at-type-on-obligation-failure-2.rs:24:18 + --> $DIR/point-at-type-on-obligation-failure-2.rs:30:5 | -LL | trait Bat where ::Assoc: Bar { - | --- required by this bound in `Bat` +LL | ::Assoc: Bar, + | --- required by this bound in `Bat::Assoc` +LL | { +LL | type Assoc; + | ----- required by a bound in this ... LL | type Assoc = bool; - | ^^^^ the trait `Bar` is not implemented for `bool` + | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` error: aborting due to 3 previous errors diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs index dc43dbaf54b99..66666006887e6 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs @@ -10,8 +10,9 @@ struct Foo; struct Foo2; impl Bar for Foo { - type Ok = (); //~ ERROR type mismatch resolving `::Ok == ()` + type Ok = (); type Sibling = Foo2; + //~^ ERROR type mismatch resolving `::Ok == ()` } impl Bar2 for Foo2 { type Ok = u32; diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr index 818702b7afe2a..7417a5aa3d43a 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr @@ -1,8 +1,11 @@ error[E0271]: type mismatch resolving `::Ok == ()` - --> $DIR/point-at-type-on-obligation-failure.rs:13:15 + --> $DIR/point-at-type-on-obligation-failure.rs:14:5 | -LL | type Ok = (); - | ^^ expected `u32`, found `()` +LL | type Sibling: Bar2; + | ----------- required by this bound in `Bar::Sibling` +... +LL | type Sibling = Foo2; + | ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `u32` error: aborting due to previous error diff --git a/src/test/ui/associated-types/wf-cycle-2.rs b/src/test/ui/associated-types/wf-cycle-2.rs new file mode 100644 index 0000000000000..d7467ac22371f --- /dev/null +++ b/src/test/ui/associated-types/wf-cycle-2.rs @@ -0,0 +1,18 @@ +// check-pass + +trait IntoIt { + type Item; +} + +impl IntoIt for I { + type Item = (); +} + +trait BaseGraph +where + ::Item: Sized, +{ + type VertexIter: IntoIt; +} + +fn main() {} diff --git a/src/test/ui/associated-types/wf-cycle.rs b/src/test/ui/associated-types/wf-cycle.rs new file mode 100644 index 0000000000000..cf6508551a558 --- /dev/null +++ b/src/test/ui/associated-types/wf-cycle.rs @@ -0,0 +1,13 @@ +// check-pass + +trait A { + type U: Copy; +} + +trait B where + ::U: Copy, +{ + type V: A; +} + +fn main() {} diff --git a/src/test/ui/async-await/async-error-span.stderr b/src/test/ui/async-await/async-error-span.stderr index d808a5939bbe7..994bfd33ba42e 100644 --- a/src/test/ui/async-await/async-error-span.stderr +++ b/src/test/ui/async-await/async-error-span.stderr @@ -3,12 +3,8 @@ error[E0277]: `()` is not a future | LL | fn get_future() -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future -LL | -LL | panic!() - | -------- this returned value is of type `!` | = help: the trait `Future` is not implemented for `()` - = note: the return type of a function must have a statically known size error[E0698]: type inside `async fn` body must be known in this context --> $DIR/async-error-span.rs:13:9 diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr index f1f1b2d4439ec..88ea7251eaf1f 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -27,33 +27,18 @@ error[E0609]: no field `0` on type `impl Future` | LL | let _: i32 = tuple().0; | ^ - | -help: consider awaiting before field access - | -LL | let _: i32 = tuple().await.0; - | ^^^^^^ error[E0609]: no field `a` on type `impl Future` --> $DIR/issue-61076.rs:60:28 | LL | let _: i32 = struct_().a; | ^ - | -help: consider awaiting before field access - | -LL | let _: i32 = struct_().await.a; - | ^^^^^^ error[E0599]: no method named `method` found for opaque type `impl Future` in the current scope --> $DIR/issue-61076.rs:62:15 | LL | struct_().method(); | ^^^^^^ method not found in `impl Future` - | -help: consider awaiting before this method call - | -LL | struct_().await.method(); - | ^^^^^^ error[E0308]: mismatched types --> $DIR/issue-61076.rs:69:9 @@ -66,10 +51,6 @@ LL | Tuple(_) => {} | = note: expected opaque type `impl Future` found struct `Tuple` -help: consider awaiting on the future - | -LL | match tuple().await { - | ^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index 440ea0a38e6b9..2d46dfb7269d1 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -1,17 +1,8 @@ error: future cannot be sent between threads safely --> $DIR/issue-64130-4-async-move.rs:15:17 | -LL | pub fn foo() -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` -... -LL | / async move { -LL | | match client.status() { -LL | | 200 => { -LL | | let _x = get().await; -... | -LL | | } -LL | | } - | |_____- this returned value is of type `impl Future` +LL | pub fn foo() -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)` note: future is not `Send` as this value is used across an await @@ -30,7 +21,6 @@ help: consider moving this into a `let` binding to create a shorter lived borrow | LL | match client.status() { | ^^^^^^^^^^^^^^^ - = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-67765-async-diagnostic.stderr b/src/test/ui/async-await/issue-67765-async-diagnostic.stderr index 78253042bee1c..832b736ad8642 100644 --- a/src/test/ui/async-await/issue-67765-async-diagnostic.stderr +++ b/src/test/ui/async-await/issue-67765-async-diagnostic.stderr @@ -1,11 +1,11 @@ error[E0515]: cannot return value referencing local variable `s` - --> $DIR/issue-67765-async-diagnostic.rs:13:11 + --> $DIR/issue-67765-async-diagnostic.rs:13:5 | LL | let b = &s[..]; | - `s` is borrowed here LL | LL | Err(b)?; - | ^ returns a value referencing data owned by the current function + | ^^^^^^^ returns a value referencing data owned by the current function error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-70818.stderr b/src/test/ui/async-await/issue-70818.stderr index 364194bea100e..11fca2dd8ef4c 100644 --- a/src/test/ui/async-await/issue-70818.stderr +++ b/src/test/ui/async-await/issue-70818.stderr @@ -3,16 +3,12 @@ error: future cannot be sent between threads safely | LL | fn foo(ty: T, ty1: U) -> impl Future + Send { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` -LL | -LL | async { (ty, ty1) } - | ------------------- this returned value is of type `impl Future` | note: captured value is not `Send` --> $DIR/issue-70818.rs:6:18 | LL | async { (ty, ty1) } | ^^^ has type `U` which is not `Send` - = note: the return type of a function must have a statically known size help: consider restricting type parameter `U` | LL | fn foo(ty: T, ty1: U) -> impl Future + Send { diff --git a/src/test/ui/chalkify/impl_wf.rs b/src/test/ui/chalkify/impl_wf.rs index 465eb10241ea2..66f57c2d11009 100644 --- a/src/test/ui/chalkify/impl_wf.rs +++ b/src/test/ui/chalkify/impl_wf.rs @@ -15,19 +15,6 @@ impl Foo for str { } // Implicit `T: Sized` bound. impl Foo for Option { } -impl Bar for () { - type Item = i32; -} - -impl Bar for Option { - type Item = Option; -} - -impl Bar for f32 { - type Item = f32; - //~^ ERROR the trait bound `f32: Foo` is not satisfied -} - trait Baz where U: Foo { } impl Baz for i32 { } diff --git a/src/test/ui/chalkify/impl_wf.stderr b/src/test/ui/chalkify/impl_wf.stderr index 4ca5ae472f207..24c7f0d82bdc8 100644 --- a/src/test/ui/chalkify/impl_wf.stderr +++ b/src/test/ui/chalkify/impl_wf.stderr @@ -10,18 +10,7 @@ LL | impl Foo for str { } = help: the trait `Sized` is not implemented for `str` error[E0277]: the trait bound `f32: Foo` is not satisfied - --> $DIR/impl_wf.rs:27:17 - | -LL | trait Bar { - | --- required by a bound in this -LL | type Item: Foo; - | --- required by this bound in `Bar` -... -LL | type Item = f32; - | ^^^ the trait `Foo` is not implemented for `f32` - -error[E0277]: the trait bound `f32: Foo` is not satisfied - --> $DIR/impl_wf.rs:35:6 + --> $DIR/impl_wf.rs:22:6 | LL | trait Baz where U: Foo { } | --- required by this bound in `Baz` @@ -29,6 +18,6 @@ LL | trait Baz where U: Foo { } LL | impl Baz for f32 { } | ^^^^^^^^ the trait `Foo` is not implemented for `f32` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/chalkify/impl_wf_2.rs b/src/test/ui/chalkify/impl_wf_2.rs new file mode 100644 index 0000000000000..758a7185e3912 --- /dev/null +++ b/src/test/ui/chalkify/impl_wf_2.rs @@ -0,0 +1,33 @@ +// Split out of impl_wf.rs to work around rust aborting compilation early + +// compile-flags: -Z chalk + +trait Foo: Sized { } + +trait Bar { + type Item: Foo; +} + +impl Foo for i32 { } + +// Implicit `T: Sized` bound. +impl Foo for Option { } + +impl Bar for () { + type Item = i32; +} + +impl Bar for Option { + type Item = Option; +} + +impl Bar for f32 { + type Item = f32; + //~^ ERROR the trait bound `f32: Foo` is not satisfied +} + +trait Baz where U: Foo { } + +impl Baz for i32 { } + +fn main() {} diff --git a/src/test/ui/chalkify/impl_wf_2.stderr b/src/test/ui/chalkify/impl_wf_2.stderr new file mode 100644 index 0000000000000..1da2144c0a5d4 --- /dev/null +++ b/src/test/ui/chalkify/impl_wf_2.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `f32: Foo` is not satisfied + --> $DIR/impl_wf_2.rs:25:5 + | +LL | type Item: Foo; + | --- required by this bound in `Bar::Item` +... +LL | type Item = f32; + | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `f32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/closures/issue-41366.rs b/src/test/ui/closures/issue-41366.rs index af1e37ba867de..909c33f642d31 100644 --- a/src/test/ui/closures/issue-41366.rs +++ b/src/test/ui/closures/issue-41366.rs @@ -9,4 +9,5 @@ impl<'g> T<'g> for u32 { fn main() { (&|_| ()) as &dyn for<'x> Fn(>::V); //~^ ERROR: type mismatch in closure arguments + //~| ERROR: size for values of type `>::V` cannot be known at compilation time } diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr index df0495cdc4643..200d411b51194 100644 --- a/src/test/ui/closures/issue-41366.stderr +++ b/src/test/ui/closures/issue-41366.stderr @@ -9,6 +9,24 @@ LL | (&|_| ()) as &dyn for<'x> Fn(>::V); | = note: required for the cast to the object type `dyn for<'x> Fn(>::V)` -error: aborting due to previous error +error[E0277]: the size for values of type `>::V` cannot be known at compilation time + --> $DIR/issue-41366.rs:10:8 + | +LL | (&|_| ()) as &dyn for<'x> Fn(>::V); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `>::V` + = help: unsized locals are gated as an unstable feature +help: consider further restricting the associated type + | +LL | fn main() where >::V: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | (&|&_| ()) as &dyn for<'x> Fn(>::V); + | ^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0631`. +Some errors have detailed explanations: E0277, E0631. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/conservative_impl_trait.stderr b/src/test/ui/conservative_impl_trait.stderr index 87058c3c29cf4..63a4df242f85f 100644 --- a/src/test/ui/conservative_impl_trait.stderr +++ b/src/test/ui/conservative_impl_trait.stderr @@ -5,7 +5,6 @@ LL | fn will_ice(something: &u32) -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` - = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs index 9bce274027ee0..38be85ff8201e 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -14,6 +14,7 @@ impl Tr1 for S1 { type As1 = S2; } trait _Tr3 { type A: Iterator; //~^ ERROR associated type bounds are unstable + //~| ERROR the trait bound `<::A as Iterator>::Item: Copy` is not satisfied type B: Iterator; //~^ ERROR associated type bounds are unstable diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr index 7f2704e1bc371..be5d35139b65c 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -8,7 +8,7 @@ LL | type A: Iterator; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:18:22 + --> $DIR/feature-gate-associated_type_bounds.rs:19:22 | LL | type B: Iterator; | ^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | type B: Iterator; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:22:20 + --> $DIR/feature-gate-associated_type_bounds.rs:23:20 | LL | struct _St1> { | ^^^^^^^^ @@ -26,7 +26,7 @@ LL | struct _St1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:29:18 + --> $DIR/feature-gate-associated_type_bounds.rs:30:18 | LL | enum _En1> { | ^^^^^^^^ @@ -35,7 +35,7 @@ LL | enum _En1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:36:19 + --> $DIR/feature-gate-associated_type_bounds.rs:37:19 | LL | union _Un1> { | ^^^^^^^^ @@ -44,7 +44,7 @@ LL | union _Un1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:43:37 + --> $DIR/feature-gate-associated_type_bounds.rs:44:37 | LL | type _TaWhere1 where T: Iterator = T; | ^^^^^^^^^^ @@ -53,7 +53,7 @@ LL | type _TaWhere1 where T: Iterator = T; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:46:22 + --> $DIR/feature-gate-associated_type_bounds.rs:47:22 | LL | fn _apit(_: impl Tr1) {} | ^^^^^^^^^ @@ -62,7 +62,7 @@ LL | fn _apit(_: impl Tr1) {} = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:48:26 + --> $DIR/feature-gate-associated_type_bounds.rs:49:26 | LL | fn _apit_dyn(_: &dyn Tr1) {} | ^^^^^^^^^ @@ -71,7 +71,7 @@ LL | fn _apit_dyn(_: &dyn Tr1) {} = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:51:24 + --> $DIR/feature-gate-associated_type_bounds.rs:52:24 | LL | fn _rpit() -> impl Tr1 { S1 } | ^^^^^^^^^ @@ -80,7 +80,7 @@ LL | fn _rpit() -> impl Tr1 { S1 } = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:54:31 + --> $DIR/feature-gate-associated_type_bounds.rs:55:31 | LL | fn _rpit_dyn() -> Box> { Box::new(S1) } | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | fn _rpit_dyn() -> Box> { Box::new(S1) } = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:57:23 + --> $DIR/feature-gate-associated_type_bounds.rs:58:23 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -98,7 +98,7 @@ LL | const _cdef: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:63:24 + --> $DIR/feature-gate-associated_type_bounds.rs:64:24 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -107,7 +107,7 @@ LL | static _sdef: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:70:21 + --> $DIR/feature-gate-associated_type_bounds.rs:71:21 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^ @@ -116,7 +116,7 @@ LL | let _: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:57:14 + --> $DIR/feature-gate-associated_type_bounds.rs:58:14 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -124,7 +124,7 @@ LL | const _cdef: impl Tr1 = S1; = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:63:15 + --> $DIR/feature-gate-associated_type_bounds.rs:64:15 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -132,14 +132,30 @@ LL | static _sdef: impl Tr1 = S1; = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:70:12 + --> $DIR/feature-gate-associated_type_bounds.rs:71:12 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable -error: aborting due to 16 previous errors +error[E0277]: the trait bound `<::A as Iterator>::Item: Copy` is not satisfied + --> $DIR/feature-gate-associated_type_bounds.rs:15:28 + | +LL | type A: Iterator; + | ^^^^ the trait `Copy` is not implemented for `<::A as Iterator>::Item` + | + ::: $SRC_DIR/core/src/marker.rs:LL:COL + | +LL | pub trait Copy: Clone { + | --------------------- required by this bound in `Copy` + | +help: consider further restricting the associated type + | +LL | trait _Tr3 where <::A as Iterator>::Item: Copy { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 17 previous errors -Some errors have detailed explanations: E0562, E0658. -For more information about an error, try `rustc --explain E0562`. +Some errors have detailed explanations: E0277, E0562, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs index 17548d7b9e88c..1d2be3657ffb2 100644 --- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs +++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs @@ -15,6 +15,7 @@ impl PointerFamily for Foo { //~^ ERROR generic associated types are unstable type Pointer2 = Box; //~^ ERROR generic associated types are unstable + //~| ERROR the trait bound `U32: Clone` is not satisfied } trait Bar { diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr index 8499b1ab70f5d..266008cc0def4 100644 --- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr +++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr @@ -44,7 +44,7 @@ LL | type Pointer2 = Box; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: where clauses on associated types are unstable - --> $DIR/feature-gate-generic_associated_types.rs:21:5 + --> $DIR/feature-gate-generic_associated_types.rs:22:5 | LL | type Assoc where Self: Sized; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -53,7 +53,7 @@ LL | type Assoc where Self: Sized; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: where clauses on associated types are unstable - --> $DIR/feature-gate-generic_associated_types.rs:26:5 + --> $DIR/feature-gate-generic_associated_types.rs:27:5 | LL | type Assoc where Self: Sized = Foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,6 +61,18 @@ LL | type Assoc where Self: Sized = Foo; = note: see issue #44265 for more information = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable -error: aborting due to 7 previous errors +error[E0277]: the trait bound `U32: Clone` is not satisfied + --> $DIR/feature-gate-generic_associated_types.rs:16:5 + | +LL | type Pointer2 = Box; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `U32` + | +help: consider restricting type parameter `U32` + | +LL | type Pointer2 = Box; + | ^^^^^^^ + +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/for/for-c-in-str.rs b/src/test/ui/for/for-c-in-str.rs index df66127c6041a..97a4ea53af583 100644 --- a/src/test/ui/for/for-c-in-str.rs +++ b/src/test/ui/for/for-c-in-str.rs @@ -1,14 +1,16 @@ -// E0277 should point exclusively at line 14, not the entire for loop span +// E0277 should point exclusively at line 6, not the entire for loop span fn main() { for c in "asdf" { - //~^ ERROR `&str` is not an iterator - //~| NOTE `&str` is not an iterator - //~| HELP the trait `Iterator` is not implemented for `&str` - //~| NOTE required by `into_iter` - //~| NOTE in this expansion of desugaring of `for` loop - //~| NOTE in this expansion of desugaring of `for` loop - //~| NOTE in this expansion of desugaring of `for` loop + //~^ ERROR `&str` is not an iterator + //~| NOTE `&str` is not an iterator + //~| HELP the trait `Iterator` is not implemented for `&str` + //~| NOTE required because of the requirements on the impl of `IntoIterator` for `&str` + //~| NOTE required by `into_iter` + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop println!(); } } diff --git a/src/test/ui/for/for-c-in-str.stderr b/src/test/ui/for/for-c-in-str.stderr index b0f959ba0273c..18e46e1d7ded7 100644 --- a/src/test/ui/for/for-c-in-str.stderr +++ b/src/test/ui/for/for-c-in-str.stderr @@ -5,6 +5,7 @@ LL | for c in "asdf" { | ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` | = help: the trait `Iterator` is not implemented for `&str` + = note: required because of the requirements on the impl of `IntoIterator` for `&str` = note: required by `into_iter` error: aborting due to previous error diff --git a/src/test/ui/for/for-loop-bogosity.stderr b/src/test/ui/for/for-loop-bogosity.stderr index ccacd655a147d..0d9409626897f 100644 --- a/src/test/ui/for/for-loop-bogosity.stderr +++ b/src/test/ui/for/for-loop-bogosity.stderr @@ -5,6 +5,7 @@ LL | for x in bogus { | ^^^^^ `MyStruct` is not an iterator | = help: the trait `Iterator` is not implemented for `MyStruct` + = note: required because of the requirements on the impl of `IntoIterator` for `MyStruct` = note: required by `into_iter` error: aborting due to previous error diff --git a/src/test/ui/generator/sized-yield.stderr b/src/test/ui/generator/sized-yield.stderr index 2bcf66dbeae27..8e3c2f67ed165 100644 --- a/src/test/ui/generator/sized-yield.stderr +++ b/src/test/ui/generator/sized-yield.stderr @@ -16,6 +16,11 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t | LL | Pin::new(&mut gen).resume(()); | ^^^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/core/src/ops/generator.rs:LL:COL + | +LL | pub enum GeneratorState { + | - required by this bound in `GeneratorState` | = help: the trait `Sized` is not implemented for `str` diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index 260fbb2ec7e6a..8f6f87f78de70 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -15,7 +15,6 @@ LL | fn foo() -> impl Generator { | = note: expected enum `std::result::Result<{integer}, _>` found type `i32` - = note: the return type of a function must have a statically known size error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/auxiliary/foo_defn.rs b/src/test/ui/generic-associated-types/auxiliary/foo_defn.rs new file mode 100644 index 0000000000000..0e8e14852d9db --- /dev/null +++ b/src/test/ui/generic-associated-types/auxiliary/foo_defn.rs @@ -0,0 +1,8 @@ +#![feature(generic_associated_types)] + +use std::{future::Future, pin::Pin}; + +pub trait Foo { + type Bar: AsRef<()>; + fn foo(&self) -> Pin + '_>>; +} diff --git a/src/test/ui/generic-associated-types/cross-crate-bounds.rs b/src/test/ui/generic-associated-types/cross-crate-bounds.rs new file mode 100644 index 0000000000000..8934a07fd4e39 --- /dev/null +++ b/src/test/ui/generic-associated-types/cross-crate-bounds.rs @@ -0,0 +1,32 @@ +// regression test for #73816 +// We handled bounds differently when `feature(generic_associated_types)` was enabled + +// edition:2018 +// aux-build:foo_defn.rs + +extern crate foo_defn; + +use foo_defn::Foo; +use std::{future::Future, pin::Pin}; + +pub struct FooImpl; + +impl Foo for FooImpl { + type Bar = (); + //~^ ERROR the trait bound `(): AsRef<()>` is not satisfied + fn foo(&self) -> Pin + '_>> { + panic!() + } +} + +async fn foo() { + bar(&FooImpl).await; +} + +async fn bar(foo: &F) { + foo.foo().await.as_ref(); +} + +fn main() { + // futures::executor::block_on(foo()); +} diff --git a/src/test/ui/generic-associated-types/cross-crate-bounds.stderr b/src/test/ui/generic-associated-types/cross-crate-bounds.stderr new file mode 100644 index 0000000000000..d96c5f4540ef5 --- /dev/null +++ b/src/test/ui/generic-associated-types/cross-crate-bounds.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `(): AsRef<()>` is not satisfied + --> $DIR/cross-crate-bounds.rs:15:5 + | +LL | type Bar = (); + | ^^^^^^^^^^^^^^ the trait `AsRef<()>` is not implemented for `()` + | + ::: $DIR/auxiliary/foo_defn.rs:6:15 + | +LL | type Bar: AsRef<()>; + | --------- required by this bound in `foo_defn::Foo::Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.rs b/src/test/ui/generic-associated-types/generic-associated-types-where.rs index 1a94796535c14..27970b15a411d 100644 --- a/src/test/ui/generic-associated-types/generic-associated-types-where.rs +++ b/src/test/ui/generic-associated-types/generic-associated-types-where.rs @@ -19,8 +19,9 @@ struct Bar; impl Foo for Bar { type Assoc = usize; type Assoc2 = Vec; + //~^ ERROR `T` doesn't implement `std::fmt::Display` type Assoc3 where T: Iterator = Vec; - //~^ impl has stricter requirements than trait + //~^ ERROR impl has stricter requirements than trait type WithDefault<'a, T: Debug + 'a> = &'a dyn Iterator; type NoGenerics = ::std::cell::Cell; } diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr index c95765d906c22..da8b625ea7f75 100644 --- a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr +++ b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr @@ -1,5 +1,17 @@ +error[E0277]: `T` doesn't implement `std::fmt::Display` + --> $DIR/generic-associated-types-where.rs:21:5 + | +LL | type Assoc2 = Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +help: consider restricting type parameter `T` + | +LL | type Assoc2 = Vec; + | ^^^^^^^^^^^^^^^^^^^ + error[E0276]: impl has stricter requirements than trait - --> $DIR/generic-associated-types-where.rs:22:5 + --> $DIR/generic-associated-types-where.rs:23:5 | LL | type Assoc3; | --------------- definition of `Assoc3` from trait @@ -7,6 +19,7 @@ LL | type Assoc3; LL | type Assoc3 where T: Iterator = Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0276`. +Some errors have detailed explanations: E0276, E0277. +For more information about an error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs index 77bebc9854aa0..089a214667ea2 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.rs +++ b/src/test/ui/generic-associated-types/impl_bounds.rs @@ -16,6 +16,7 @@ impl Foo for Fooy { //~^ ERROR the parameter type `T` may not live long enough type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); //~^ ERROR lifetime bound not satisfied + //~| ERROR lifetime bound not satisfied type C where Self: Copy = String; //~^ ERROR the trait bound `T: Copy` is not satisfied } diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index 0546e38a33da7..645d292714562 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -24,8 +24,25 @@ note: but lifetime parameter must outlive the lifetime `'a` as defined on the as LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); | ^^ +error[E0478]: lifetime bound not satisfied + --> $DIR/impl_bounds.rs:17:5 + | +LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 17:12 + --> $DIR/impl_bounds.rs:17:12 + | +LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); + | ^^ +note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 17:16 + --> $DIR/impl_bounds.rs:17:16 + | +LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); + | ^^ + error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/impl_bounds.rs:19:5 + --> $DIR/impl_bounds.rs:20:5 | LL | type C where Self: Copy = String; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` @@ -37,7 +54,7 @@ help: consider restricting type parameter `T` LL | impl Foo for Fooy { | ^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0310, E0478. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/impl_bounds_ok.rs b/src/test/ui/generic-associated-types/impl_bounds_ok.rs index 2387b89175524..98aa82aba8305 100644 --- a/src/test/ui/generic-associated-types/impl_bounds_ok.rs +++ b/src/test/ui/generic-associated-types/impl_bounds_ok.rs @@ -10,11 +10,12 @@ trait Foo { type C where Self: Clone; } +#[derive(Clone)] struct Fooy; impl Foo for Fooy { type A<'a> = (&'a ()); - type B<'a, 'b> = (&'a(), &'b ()); + type B<'a: 'b, 'b> = (&'a(), &'b ()); type C = String; } @@ -24,7 +25,7 @@ struct Fooer(T); impl Foo for Fooer { type A<'x> where T: 'x = (&'x ()); type B<'u, 'v> where 'u: 'v = (&'v &'u ()); - type C where Self: ToOwned = String; + type C where Self: Clone + ToOwned = String; } fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr index 6ba79dd5437be..b380f0da2ea40 100644 --- a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr +++ b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr @@ -11,7 +11,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/issue-68641-check-gat-bounds.rs:15:5 | LL | type Item<'a>: Copy; - | -------------------- required by `UnsafeCopy::Item` + | ---- required by this bound in `UnsafeCopy::Item` ... LL | type Item<'a> = T; | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` diff --git a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr index 15a66e25b191b..61950478c32a8 100644 --- a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr +++ b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr @@ -11,7 +11,7 @@ error[E0277]: expected a `Fn<()>` closure, found `T` --> $DIR/issue-68642-broken-llvm-ir.rs:15:5 | LL | type F<'a>: Fn() -> u32; - | ------------------------ required by `Fun::F` + | ----------- required by this bound in `Fun::F` ... LL | type F<'a> = Self; | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` diff --git a/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr index 9b2ddb23267ad..13980618987be 100644 --- a/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr +++ b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr @@ -11,7 +11,7 @@ error[E0277]: expected a `Fn<()>` closure, found `T` --> $DIR/issue-68643-broken-mir.rs:15:5 | LL | type F<'a>: Fn() -> u32; - | ------------------------ required by `Fun::F` + | ----------- required by this bound in `Fun::F` ... LL | type F<'a> = Self; | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` diff --git a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr index f7bfab35052e1..8112425146959 100644 --- a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr +++ b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr @@ -11,7 +11,7 @@ error[E0277]: expected a `Fn<()>` closure, found `T` --> $DIR/issue-68644-codegen-selection.rs:15:5 | LL | type F<'a>: Fn() -> u32; - | ------------------------ required by `Fun::F` + | ----------- required by this bound in `Fun::F` ... LL | type F<'a> = Self; | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` diff --git a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr index 6c2d330a19a82..22f50b3949828 100644 --- a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr +++ b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr @@ -11,7 +11,7 @@ error[E0277]: expected a `Fn<()>` closure, found `T` --> $DIR/issue-68645-codegen-fulfillment.rs:15:5 | LL | type F<'a>: Fn() -> u32; - | ------------------------ required by `Fun::F` + | ----------- required by this bound in `Fun::F` ... LL | type F<'a> = Self; | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` diff --git a/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr index a9336151b6afe..c4ee2c4e61872 100644 --- a/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr +++ b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr @@ -11,7 +11,7 @@ error[E0271]: type mismatch resolving `::Target == T` --> $DIR/issue-68656-unsized-values.rs:16:5 | LL | type Item<'a>: std::ops::Deref; - | ------------------------------------------- required by `UnsafeCopy::Item` + | ---------- required by this bound in `UnsafeCopy::Item` ... LL | impl UnsafeCopy for T { | - this type parameter diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs new file mode 100644 index 0000000000000..0cd676a9b37f3 --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs @@ -0,0 +1,62 @@ +// Like `projection-bound-cycle.rs` but this avoids using +// `feature(trivial_bounds)`. + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete + +trait Print { + fn print(); +} + +trait Foo { + type Item: Sized where ::Item: Sized; +} + +struct Number { t: T } + +impl Foo for Number { + // Well-formedness checks require that the following + // goal is true: + // ``` + // if ([T]: Sized) { # if the where clauses hold + // [T]: Sized # then the bound on the associated type hold + // } + // ``` + // which it is :) + type Item where [T]: Sized = [T]; +} + +struct OnlySized where T: Sized { f: T } +impl Print for OnlySized { + fn print() { + println!("{}", std::mem::size_of::()); + } +} + +trait Bar { + type Assoc: Print; +} + +impl Bar for T where T: Foo { + // This is not ok, we need to prove `wf(::Item)`, which requires + // knowing that `::Item: Sized` to satisfy the where clause. We + // can use the bound on `Foo::Item` for this, but that requires + // `wf(::Item)`, which is an invalid cycle. + type Assoc = OnlySized<::Item>; + //~^ ERROR overflow evaluating the requirement `::Item: Sized` +} + +fn foo() { + T::print() // oops, in fact `T = OnlySized` which is ill-formed +} + +fn bar() { + // we have `FromEnv(T: Bar)` hence + // `::Assoc` is well-formed and + // `Implemented(::Assoc: Print)` hold + foo::<::Assoc>() +} + +fn main() { + bar::>() +} diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr new file mode 100644 index 0000000000000..d27e46f6836df --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr @@ -0,0 +1,21 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/projection-bound-cycle-generic.rs:4:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0275]: overflow evaluating the requirement `::Item: Sized` + --> $DIR/projection-bound-cycle-generic.rs:45:5 + | +LL | struct OnlySized where T: Sized { f: T } + | - required by this bound in `OnlySized` +... +LL | type Assoc = OnlySized<::Item>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.rs b/src/test/ui/generic-associated-types/projection-bound-cycle.rs new file mode 100644 index 0000000000000..5043fe5c08f51 --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.rs @@ -0,0 +1,64 @@ +// Test case from Chalk. +// Make sure that we make sure that we don't allow arbitrary bounds to be +// proven when a bound and a where clause of an associated type are the same. + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete +#![feature(trivial_bounds)] + +trait Print { + fn print(); +} + +trait Foo { + type Item: Sized where ::Item: Sized; +} + +struct Number { } + +impl Foo for Number { + // Well-formedness checks require that the following + // goal is true: + // ``` + // if (str: Sized) { # if the where clauses hold + // str: Sized # then the bound on the associated type hold + // } + // ``` + // which it is :) + type Item where str: Sized = str; +} + +struct OnlySized where T: Sized { f: T } +impl Print for OnlySized { + fn print() { + println!("{}", std::mem::size_of::()); + } +} + +trait Bar { + type Assoc: Print; +} + +impl Bar for T where T: Foo { + // This is not ok, we need to prove `wf(::Item)`, which requires + // knowing that `::Item: Sized` to satisfy the where clause. We + // can use the bound on `Foo::Item` for this, but that requires + // `wf(::Item)`, which is an invalid cycle. + type Assoc = OnlySized<::Item>; + //~^ ERROR overflow evaluating the requirement `::Item: Sized` +} + +fn foo() { + T::print() // oops, in fact `T = OnlySized` which is ill-formed +} + +fn bar() { + // we have `FromEnv(T: Bar)` hence + // `::Assoc` is well-formed and + // `Implemented(::Assoc: Print)` hold + foo::<::Assoc>() +} + +fn main() { + bar::() +} diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr new file mode 100644 index 0000000000000..400b664f97ca9 --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr @@ -0,0 +1,21 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/projection-bound-cycle.rs:5:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0275]: overflow evaluating the requirement `::Item: Sized` + --> $DIR/projection-bound-cycle.rs:47:5 + | +LL | struct OnlySized where T: Sized { f: T } + | - required by this bound in `OnlySized` +... +LL | type Assoc = OnlySized<::Item>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs index 7510c58d57489..99d5bcf2bace9 100644 --- a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs @@ -7,7 +7,7 @@ trait ATy { impl<'b> ATy for &'b () { type Item<'a> = &'b (); - //~^ ERROR does not fulfill the required lifetime + //~^ ERROR the type `&'b ()` does not fulfill the required lifetime } trait StaticTy { @@ -16,7 +16,7 @@ trait StaticTy { impl StaticTy for () { type Item<'a> = &'a (); - //~^ ERROR does not fulfill the required lifetime + //~^ ERROR the type `&'a ()` does not fulfill the required lifetime } fn main() {} diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index 03aba10cc79b4..a7d06c71663de 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -15,7 +15,6 @@ LL | fn foo_fail() -> impl FooLike { | = note: expected type `()` found associated type `::Assoc` - = note: the return type of a function must have a statically known size help: consider constraining the associated type `::Assoc` to `()` | LL | fn foo_fail>() -> impl FooLike { @@ -35,7 +34,6 @@ LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | = note: expected type `()` found associated type `>::Assoc` - = note: the return type of a function must have a statically known size help: consider constraining the associated type `>::Assoc` to `()` | LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { diff --git a/src/test/ui/impl-trait/issue-55872-1.stderr b/src/test/ui/impl-trait/issue-55872-1.stderr index db49d988bb8eb..64c536cf1fe30 100644 --- a/src/test/ui/impl-trait/issue-55872-1.stderr +++ b/src/test/ui/impl-trait/issue-55872-1.stderr @@ -14,7 +14,6 @@ LL | type E = impl Copy; | ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S` | = note: required because it appears within the type `(S, T)` - = note: the return type of a function must have a statically known size help: consider further restricting this bound | LL | impl Bar for S { @@ -27,7 +26,6 @@ LL | type E = impl Copy; | ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T` | = note: required because it appears within the type `(S, T)` - = note: the return type of a function must have a statically known size help: consider further restricting this bound | LL | fn foo() -> Self::E { diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr index 6da3704184abb..58c5ee45051af 100644 --- a/src/test/ui/impl-trait/issue-55872-2.stderr +++ b/src/test/ui/impl-trait/issue-55872-2.stderr @@ -3,8 +3,6 @@ error[E0277]: the trait bound `impl Future: Copy` is not satisfied | LL | type E = impl std::marker::Copy; | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` - | - = note: the return type of a function must have a statically known size error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias --> $DIR/issue-55872-2.rs:15:28 diff --git a/src/test/ui/impl-trait/wf-eval-order.rs b/src/test/ui/impl-trait/wf-eval-order.rs new file mode 100644 index 0000000000000..c7d6bb870962a --- /dev/null +++ b/src/test/ui/impl-trait/wf-eval-order.rs @@ -0,0 +1,39 @@ +// Check that we handle evaluating `wf` predicates correctly. + +// check-pass + +struct X(T) +where + T::V: Clone; + +fn hide(t: T) -> impl Sized { + t +} + +trait A { + type U; +} + +impl A for T { + type U = T; +} + +trait B { + type V; +} + +impl, T> B for S { + type V = T; +} + +fn main() { + // Evaluating `typeof(x): Sized` requires + // + // - `wf(typeof(x))` because we use a projection candidate. + // - `::V: Clone` because that's a bound on the trait. + // - `::V` normalizes to `_#1` where `::U == _#1` + // + // This all works if we evaluate `::U == _#1` before + // `::V`, but we previously had the opposite order. + let x = hide(X(0)); +} diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr index b6e3bb190ea7f..2f630c2c9ad71 100644 --- a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr @@ -8,12 +8,12 @@ LL | #![feature(impl_trait_in_bindings)] = note: see issue #63065 for more information error[E0282]: type annotations needed for `impl Future` - --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:9 + --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:20 | LL | let fut = async { | --- consider giving `fut` the explicit type `impl Future`, with the type parameters specified LL | make_unit()?; - | ^^^^^^^^^^^^ cannot infer type + | ^ cannot infer type error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/inference/cannot-infer-async.stderr b/src/test/ui/inference/cannot-infer-async.stderr index bf31fb85cf6db..92a9045f6db50 100644 --- a/src/test/ui/inference/cannot-infer-async.stderr +++ b/src/test/ui/inference/cannot-infer-async.stderr @@ -1,10 +1,10 @@ error[E0282]: type annotations needed - --> $DIR/cannot-infer-async.rs:11:9 + --> $DIR/cannot-infer-async.rs:11:20 | LL | let fut = async { | --- consider giving `fut` a type LL | make_unit()?; - | ^^^^^^^^^^^^ cannot infer type + | ^ cannot infer type error: aborting due to previous error diff --git a/src/test/ui/inference/cannot-infer-closure.stderr b/src/test/ui/inference/cannot-infer-closure.stderr index c26c24f1dc573..d5366e422dbff 100644 --- a/src/test/ui/inference/cannot-infer-closure.stderr +++ b/src/test/ui/inference/cannot-infer-closure.stderr @@ -1,8 +1,8 @@ error[E0282]: type annotations needed for the closure `fn((), ()) -> std::result::Result<(), _>` - --> $DIR/cannot-infer-closure.rs:3:9 + --> $DIR/cannot-infer-closure.rs:3:15 | LL | Err(a)?; - | ^^^^^^^ cannot infer type + | ^ cannot infer type | help: give this closure an explicit return type without `_` placeholders | diff --git a/src/test/ui/issues-71798.stderr b/src/test/ui/issues-71798.stderr index 867f8f0496c03..bbcdd3e37a96e 100644 --- a/src/test/ui/issues-71798.stderr +++ b/src/test/ui/issues-71798.stderr @@ -9,11 +9,8 @@ error[E0277]: `u32` is not a future | LL | fn test_ref(x: &u32) -> impl std::future::Future + '_ { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future -LL | *x - | -- this returned value is of type `u32` | = help: the trait `Future` is not implemented for `u32` - = note: the return type of a function must have a statically known size error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr index e8d16a55e926e..9940f43cc4440 100644 --- a/src/test/ui/issues/issue-20605.stderr +++ b/src/test/ui/issues/issue-20605.stderr @@ -5,6 +5,7 @@ LL | for item in *things { *item = 0 } | ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Iterator` + = note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator` = note: required by `into_iter` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20831-debruijn.rs b/src/test/ui/issues/issue-20831-debruijn.rs index d0e15cb393ae8..20d980763ea9c 100644 --- a/src/test/ui/issues/issue-20831-debruijn.rs +++ b/src/test/ui/issues/issue-20831-debruijn.rs @@ -28,9 +28,6 @@ impl<'a> Publisher<'a> for MyStruct<'a> { fn subscribe(&mut self, t : Box::Output> + 'a>) { // Not obvious, but there is an implicit lifetime here -------^ //~^^ ERROR cannot infer - //~| ERROR cannot infer - //~| ERROR mismatched types - //~| ERROR mismatched types // // The fact that `Publisher` is using an implicit lifetime is // what was causing the debruijn accounting to be off, so diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr index 1ab89e818e31e..bcfb6b70b2e5f 100644 --- a/src/test/ui/issues/issue-20831-debruijn.stderr +++ b/src/test/ui/issues/issue-20831-debruijn.stderr @@ -1,77 +1,3 @@ -error[E0308]: mismatched types - --> $DIR/issue-20831-debruijn.rs:28:5 - | -LL | / fn subscribe(&mut self, t : Box::Output> + 'a>) { -LL | | // Not obvious, but there is an implicit lifetime here -------^ -LL | | -LL | | -... | -LL | | self.sub = t; -LL | | } - | |_____^ lifetime mismatch - | - = note: expected type `'a` - found type `'_` -note: the anonymous lifetime #2 defined on the method body at 28:5... - --> $DIR/issue-20831-debruijn.rs:28:5 - | -LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 26:6 - --> $DIR/issue-20831-debruijn.rs:26:6 - | -LL | impl<'a> Publisher<'a> for MyStruct<'a> { - | ^^ - -error[E0308]: mismatched types - --> $DIR/issue-20831-debruijn.rs:28:5 - | -LL | / fn subscribe(&mut self, t : Box::Output> + 'a>) { -LL | | // Not obvious, but there is an implicit lifetime here -------^ -LL | | -LL | | -... | -LL | | self.sub = t; -LL | | } - | |_____^ lifetime mismatch - | - = note: expected type `'a` - found type `'_` -note: the lifetime `'a` as defined on the impl at 26:6... - --> $DIR/issue-20831-debruijn.rs:26:6 - | -LL | impl<'a> Publisher<'a> for MyStruct<'a> { - | ^^ -note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 28:5 - --> $DIR/issue-20831-debruijn.rs:28:5 - | -LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/issue-20831-debruijn.rs:28:33 - | -LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 28:5... - --> $DIR/issue-20831-debruijn.rs:28:5 - | -LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6... - --> $DIR/issue-20831-debruijn.rs:26:6 - | -LL | impl<'a> Publisher<'a> for MyStruct<'a> { - | ^^ -note: ...so that the types are compatible - --> $DIR/issue-20831-debruijn.rs:28:33 - | -LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected `Publisher<'_>` - found `Publisher<'_>` - error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements --> $DIR/issue-20831-debruijn.rs:28:33 | @@ -96,7 +22,6 @@ LL | fn subscribe(&mut self, t : Box` found `Publisher<'_>` -error: aborting due to 4 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0308, E0495. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-21946.rs b/src/test/ui/issues/issue-21946.rs index 0a9f8f50bdcbe..d0c052cb2fd39 100644 --- a/src/test/ui/issues/issue-21946.rs +++ b/src/test/ui/issues/issue-21946.rs @@ -5,7 +5,6 @@ trait Foo { struct FooStruct; impl Foo for FooStruct { - //~^ ERROR overflow evaluating the requirement `::A == _` type A = ::A; //~^ ERROR overflow evaluating the requirement `::A == _` } diff --git a/src/test/ui/issues/issue-21946.stderr b/src/test/ui/issues/issue-21946.stderr index 582ce393d7f54..0497bd20469a0 100644 --- a/src/test/ui/issues/issue-21946.stderr +++ b/src/test/ui/issues/issue-21946.stderr @@ -1,15 +1,9 @@ error[E0275]: overflow evaluating the requirement `::A == _` - --> $DIR/issue-21946.rs:7:6 - | -LL | impl Foo for FooStruct { - | ^^^ - -error[E0275]: overflow evaluating the requirement `::A == _` - --> $DIR/issue-21946.rs:9:5 + --> $DIR/issue-21946.rs:8:5 | LL | type A = ::A; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/issues/issue-23122-1.rs b/src/test/ui/issues/issue-23122-1.rs index d6f64650f36bb..0937e029ef45e 100644 --- a/src/test/ui/issues/issue-23122-1.rs +++ b/src/test/ui/issues/issue-23122-1.rs @@ -5,7 +5,6 @@ trait Next { struct GetNext { t: T } impl Next for GetNext { - //~^ ERROR overflow evaluating the requirement type Next = as Next>::Next; //~^ ERROR overflow evaluating the requirement } diff --git a/src/test/ui/issues/issue-23122-1.stderr b/src/test/ui/issues/issue-23122-1.stderr index 4e2e837c07c6b..1f78b0d152d1b 100644 --- a/src/test/ui/issues/issue-23122-1.stderr +++ b/src/test/ui/issues/issue-23122-1.stderr @@ -1,15 +1,9 @@ error[E0275]: overflow evaluating the requirement ` as Next>::Next == _` - --> $DIR/issue-23122-1.rs:7:15 - | -LL | impl Next for GetNext { - | ^^^^ - -error[E0275]: overflow evaluating the requirement ` as Next>::Next == _` - --> $DIR/issue-23122-1.rs:9:5 + --> $DIR/issue-23122-1.rs:8:5 | LL | type Next = as Next>::Next; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/issues/issue-23122-2.rs b/src/test/ui/issues/issue-23122-2.rs index 695712d2cc929..84abebf6b74a7 100644 --- a/src/test/ui/issues/issue-23122-2.rs +++ b/src/test/ui/issues/issue-23122-2.rs @@ -5,7 +5,6 @@ trait Next { struct GetNext { t: T } impl Next for GetNext { - //~^ ERROR overflow evaluating the requirement type Next = as Next>::Next; //~^ ERROR overflow evaluating the requirement } diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr index 60dbb15d0f9c3..7ed04519b69ca 100644 --- a/src/test/ui/issues/issue-23122-2.stderr +++ b/src/test/ui/issues/issue-23122-2.stderr @@ -1,14 +1,5 @@ -error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized` - --> $DIR/issue-23122-2.rs:7:15 - | -LL | impl Next for GetNext { - | ^^^^ - | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`) - = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` - error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized` - --> $DIR/issue-23122-2.rs:9:5 + --> $DIR/issue-23122-2.rs:8:5 | LL | type Next = as Next>::Next; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,6 +7,6 @@ LL | type Next = as Next>::Next; = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`) = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/issues/issue-24204.rs b/src/test/ui/issues/issue-24204.rs index 61671b32e9b15..5a7b3459589eb 100644 --- a/src/test/ui/issues/issue-24204.rs +++ b/src/test/ui/issues/issue-24204.rs @@ -1,3 +1,5 @@ +// check-pass + #![allow(dead_code)] trait MultiDispatch { @@ -8,10 +10,16 @@ trait Trait: Sized { type A: MultiDispatch; type B; - fn new(u: U) -> >::O where Self::A : MultiDispatch; + fn new(u: U) -> >::O + where + Self::A: MultiDispatch; } -fn test>(b: i32) -> T where T::A: MultiDispatch { T::new(b) } -//~^ ERROR type mismatch resolving +fn test>(b: i32) -> T +where + T::A: MultiDispatch, +{ + T::new(b) +} fn main() {} diff --git a/src/test/ui/issues/issue-24204.stderr b/src/test/ui/issues/issue-24204.stderr deleted file mode 100644 index d5cbcf786bf1a..0000000000000 --- a/src/test/ui/issues/issue-24204.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0271]: type mismatch resolving `<::A as MultiDispatch>::O == T` - --> $DIR/issue-24204.rs:14:12 - | -LL | trait Trait: Sized { - | ----- required by a bound in this -LL | type A: MultiDispatch; - | -------- required by this bound in `Trait` -... -LL | fn test>(b: i32) -> T where T::A: MultiDispatch { T::new(b) } - | - ^^^^^^^^^^^^ expected type parameter `T`, found associated type - | | - | this type parameter - | - = note: expected type parameter `T` - found associated type `<::A as MultiDispatch>::O` - = note: you might be missing a type parameter or trait bound - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/issues/issue-28098.stderr b/src/test/ui/issues/issue-28098.stderr index df552fc2d0e2b..4c927a0cb458f 100644 --- a/src/test/ui/issues/issue-28098.stderr +++ b/src/test/ui/issues/issue-28098.stderr @@ -14,6 +14,7 @@ LL | for _ in false {} | ^^^^^ `bool` is not an iterator | = help: the trait `Iterator` is not implemented for `bool` + = note: required because of the requirements on the impl of `IntoIterator` for `bool` = note: required by `into_iter` error[E0277]: `()` is not an iterator @@ -58,6 +59,7 @@ LL | for _ in false {} | ^^^^^ `bool` is not an iterator | = help: the trait `Iterator` is not implemented for `bool` + = note: required because of the requirements on the impl of `IntoIterator` for `bool` = note: required by `into_iter` error[E0277]: `()` is not an iterator diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index aeab923d2df16..e91dae08b3a33 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -16,6 +16,8 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: expected tuple `(&_, &_)` found reference `&_` = note: required because of the requirements on the impl of `Iterator` for `Cloned>` + = note: required because of the requirements on the impl of `IntoIterator` for `Cloned>` + = note: required by `into_iter` error[E0271]: type mismatch resolving ` as Iterator>::Item == &_` --> $DIR/issue-33941.rs:4:14 @@ -26,6 +28,7 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: expected tuple `(&_, &_)` found reference `&_` = note: required because of the requirements on the impl of `Iterator` for `Cloned>` + = note: required by `std::iter::Iterator::next` error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-41139.rs b/src/test/ui/issues/issue-41139.rs index 4814232607cf8..94c53216f50ac 100644 --- a/src/test/ui/issues/issue-41139.rs +++ b/src/test/ui/issues/issue-41139.rs @@ -1,8 +1,12 @@ trait Trait {} -fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { panic!("") } +fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { + panic!("") +} fn main() { - let t : &dyn Trait = &get_function()(); - //~^ ERROR cannot move a value of type dyn Trait + // This isn't great. The issue here is that `dyn Trait` is not sized, so + // `dyn Fn() -> dyn Trait` is not well-formed. + let t: &dyn Trait = &get_function()(); + //~^ ERROR expected function, found `&dyn Fn() -> (dyn Trait + 'static)` } diff --git a/src/test/ui/issues/issue-41139.stderr b/src/test/ui/issues/issue-41139.stderr index 829d0cfa72ca7..48b22bca20f06 100644 --- a/src/test/ui/issues/issue-41139.stderr +++ b/src/test/ui/issues/issue-41139.stderr @@ -1,9 +1,14 @@ -error[E0161]: cannot move a value of type dyn Trait: the size of dyn Trait cannot be statically determined - --> $DIR/issue-41139.rs:6:27 +error[E0618]: expected function, found `&dyn Fn() -> (dyn Trait + 'static)` + --> $DIR/issue-41139.rs:10:26 | -LL | let t : &dyn Trait = &get_function()(); - | ^^^^^^^^^^^^^^^^ +LL | fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { + | -------------------------------------------------- `get_function` defined here returns `&dyn Fn() -> (dyn Trait + 'static)` +... +LL | let t: &dyn Trait = &get_function()(); + | ^^^^^^^^^^^^^^-- + | | + | call expression requires function error: aborting due to previous error -For more information about this error, try `rustc --explain E0161`. +For more information about this error, try `rustc --explain E0618`. diff --git a/src/test/ui/issues/issue-43784-associated-type.stderr b/src/test/ui/issues/issue-43784-associated-type.stderr index 039852ad16596..d5105ae3b5815 100644 --- a/src/test/ui/issues/issue-43784-associated-type.stderr +++ b/src/test/ui/issues/issue-43784-associated-type.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/issue-43784-associated-type.rs:14:18 + --> $DIR/issue-43784-associated-type.rs:14:5 | +LL | type Assoc: Partial; + | ------------- required by this bound in `Complete::Assoc` +... LL | type Assoc = T; - | ^ the trait `Copy` is not implemented for `T` + | ^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/issues/issue-43784-supertrait.stderr b/src/test/ui/issues/issue-43784-supertrait.stderr index d92e4fa9e4a5d..c73536ba97332 100644 --- a/src/test/ui/issues/issue-43784-supertrait.stderr +++ b/src/test/ui/issues/issue-43784-supertrait.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/issue-43784-supertrait.rs:8:9 | +LL | pub trait Complete: Partial { + | ------- required by this bound in `Complete` +... LL | impl Complete for T {} | ^^^^^^^^ the trait `Copy` is not implemented for `T` | diff --git a/src/test/ui/issues/issue-58344.rs b/src/test/ui/issues/issue-58344.rs index 9b184e296aa6f..0cb04dcb22a54 100644 --- a/src/test/ui/issues/issue-58344.rs +++ b/src/test/ui/issues/issue-58344.rs @@ -1,3 +1,5 @@ +// check-pass + use std::ops::Add; trait Trait { @@ -18,7 +20,11 @@ enum Either { } impl Either { - fn converge(self) -> T where L: Trait, R: Trait { + fn converge(self) -> T + where + L: Trait, + R: Trait, + { match self { Either::Left(val) => val.get(), Either::Right(val) => val.get(), @@ -26,22 +32,16 @@ impl Either { } } -fn add_generic, B>(lhs: A, rhs: B) -> Either< - impl Trait<>::Output>, - impl Trait<>::Output> -> { - if true { - Either::Left(Holder(lhs + rhs)) - } else { - Either::Right(Holder(lhs + rhs)) - } +fn add_generic, B>( + lhs: A, + rhs: B, +) -> Either>::Output>, impl Trait<>::Output>> { + if true { Either::Left(Holder(lhs + rhs)) } else { Either::Right(Holder(lhs + rhs)) } } fn add_one( value: u32, ) -> Either>::Output>, impl Trait<>::Output>> { - //~^ ERROR: the trait bound `impl Trait<::Output>: Trait` - //~| ERROR: the trait bound `impl Trait<::Output>: Trait` add_generic(value, 1u32) } diff --git a/src/test/ui/issues/issue-58344.stderr b/src/test/ui/issues/issue-58344.stderr deleted file mode 100644 index ade85d8b0168c..0000000000000 --- a/src/test/ui/issues/issue-58344.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0277]: the trait bound `impl Trait<::Output>: Trait` is not satisfied - --> $DIR/issue-58344.rs:42:13 - | -LL | ) -> Either>::Output>, impl Trait<>::Output>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `impl Trait<::Output>` -... -LL | add_generic(value, 1u32) - | ------------------------ this returned value is of type `Either::Output>, impl Trait<::Output>>` - | - = note: the return type of a function must have a statically known size - -error[E0277]: the trait bound `impl Trait<::Output>: Trait` is not satisfied - --> $DIR/issue-58344.rs:42:52 - | -LL | ) -> Either>::Output>, impl Trait<>::Output>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `impl Trait<::Output>` -... -LL | add_generic(value, 1u32) - | ------------------------ this returned value is of type `Either::Output>, impl Trait<::Output>>` - | - = note: the return type of a function must have a statically known size - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-60283.rs b/src/test/ui/issues/issue-60283.rs index 9c2b2dc9f4dae..c63b1544a5379 100644 --- a/src/test/ui/issues/issue-60283.rs +++ b/src/test/ui/issues/issue-60283.rs @@ -16,4 +16,5 @@ where fn main() { foo((), drop) //~^ ERROR type mismatch in function arguments + //~| ERROR size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time } diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr index ad679bfa22063..650570b6471eb 100644 --- a/src/test/ui/issues/issue-60283.stderr +++ b/src/test/ui/issues/issue-60283.stderr @@ -13,6 +13,24 @@ LL | foo((), drop) | expected signature of `fn(<() as Trait<'a>>::Item) -> _` | found signature of `fn(()) -> _` -error: aborting due to previous error +error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time + --> $DIR/issue-60283.rs:17:13 + | +LL | foo((), drop) + | ^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub fn drop(_x: T) {} + | - required by this bound in `std::mem::drop` + | + = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item` +help: consider further restricting the associated type + | +LL | fn main() where <() as Trait<'_>>::Item: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0631`. +Some errors have detailed explanations: E0277, E0631. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-65673.stderr b/src/test/ui/issues/issue-65673.stderr index aa43ac9414f19..64cc0bab3f33c 100644 --- a/src/test/ui/issues/issue-65673.stderr +++ b/src/test/ui/issues/issue-65673.stderr @@ -1,13 +1,11 @@ error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/issue-65673.rs:9:16 + --> $DIR/issue-65673.rs:9:5 | -LL | trait WithType { - | -------- required by a bound in this LL | type Ctx; - | --------- required by this bound in `WithType` + | --------- required by this bound in `WithType::Ctx` ... LL | type Ctx = dyn Alias; - | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Trait + 'static)` diff --git a/src/test/ui/iterators/array-of-ranges.stderr b/src/test/ui/iterators/array-of-ranges.stderr index 6271d8107bc05..601983a6153fd 100644 --- a/src/test/ui/iterators/array-of-ranges.stderr +++ b/src/test/ui/iterators/array-of-ranges.stderr @@ -6,6 +6,7 @@ LL | for _ in [0..1] {} | = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]` = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end` + = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator @@ -16,6 +17,7 @@ LL | for _ in [0..=1] {} | = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[RangeFrom<{integer}>; 1]` is not an iterator @@ -26,6 +28,7 @@ LL | for _ in [0..] {} | = help: the trait `Iterator` is not implemented for `[RangeFrom<{integer}>; 1]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[RangeFrom<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[RangeTo<{integer}>; 1]` is not an iterator @@ -36,6 +39,7 @@ LL | for _ in [..1] {} | = help: the trait `Iterator` is not implemented for `[RangeTo<{integer}>; 1]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[RangeTo<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[RangeToInclusive<{integer}>; 1]` is not an iterator @@ -46,6 +50,7 @@ LL | for _ in [..=1] {} | = help: the trait `Iterator` is not implemented for `[RangeToInclusive<{integer}>; 1]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[RangeToInclusive<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator @@ -56,6 +61,7 @@ LL | for _ in [start..end] {} | = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]` = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end` + = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator @@ -66,6 +72,7 @@ LL | for _ in array_of_range {} | = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]` = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end` + = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[std::ops::Range<{integer}>; 2]` is not an iterator @@ -76,6 +83,7 @@ LL | for _ in [0..1, 2..3] {} | = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 2]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 2]` = note: required by `into_iter` error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator @@ -86,6 +94,7 @@ LL | for _ in [0..=1] {} | = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]` = note: required by `into_iter` error: aborting due to 9 previous errors diff --git a/src/test/ui/iterators/array.stderr b/src/test/ui/iterators/array.stderr index f86c82e4917e6..68c6de5493f13 100644 --- a/src/test/ui/iterators/array.stderr +++ b/src/test/ui/iterators/array.stderr @@ -6,6 +6,7 @@ LL | for _ in [1, 2] {} | = help: the trait `Iterator` is not implemented for `[{integer}; 2]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]` = note: required by `into_iter` error[E0277]: `[{integer}; 2]` is not an iterator @@ -16,6 +17,7 @@ LL | for _ in x {} | = help: the trait `Iterator` is not implemented for `[{integer}; 2]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]` = note: required by `into_iter` error[E0277]: `[{float}; 2]` is not an iterator @@ -26,6 +28,7 @@ LL | for _ in [1.0, 2.0] {} | = help: the trait `Iterator` is not implemented for `[{float}; 2]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[{float}; 2]` = note: required by `into_iter` error: aborting due to 3 previous errors diff --git a/src/test/ui/iterators/integral.stderr b/src/test/ui/iterators/integral.stderr index c4c464126111d..e31ee59785c8b 100644 --- a/src/test/ui/iterators/integral.stderr +++ b/src/test/ui/iterators/integral.stderr @@ -6,6 +6,7 @@ LL | for _ in 42 {} | = help: the trait `Iterator` is not implemented for `{integer}` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `{integer}` = note: required by `into_iter` error[E0277]: `u8` is not an iterator @@ -16,6 +17,7 @@ LL | for _ in 42 as u8 {} | = help: the trait `Iterator` is not implemented for `u8` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `u8` = note: required by `into_iter` error[E0277]: `i8` is not an iterator @@ -26,6 +28,7 @@ LL | for _ in 42 as i8 {} | = help: the trait `Iterator` is not implemented for `i8` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `i8` = note: required by `into_iter` error[E0277]: `u16` is not an iterator @@ -36,6 +39,7 @@ LL | for _ in 42 as u16 {} | = help: the trait `Iterator` is not implemented for `u16` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `u16` = note: required by `into_iter` error[E0277]: `i16` is not an iterator @@ -46,6 +50,7 @@ LL | for _ in 42 as i16 {} | = help: the trait `Iterator` is not implemented for `i16` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `i16` = note: required by `into_iter` error[E0277]: `u32` is not an iterator @@ -56,6 +61,7 @@ LL | for _ in 42 as u32 {} | = help: the trait `Iterator` is not implemented for `u32` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `u32` = note: required by `into_iter` error[E0277]: `i32` is not an iterator @@ -66,6 +72,7 @@ LL | for _ in 42 as i32 {} | = help: the trait `Iterator` is not implemented for `i32` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `i32` = note: required by `into_iter` error[E0277]: `u64` is not an iterator @@ -76,6 +83,7 @@ LL | for _ in 42 as u64 {} | = help: the trait `Iterator` is not implemented for `u64` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `u64` = note: required by `into_iter` error[E0277]: `i64` is not an iterator @@ -86,6 +94,7 @@ LL | for _ in 42 as i64 {} | = help: the trait `Iterator` is not implemented for `i64` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `i64` = note: required by `into_iter` error[E0277]: `usize` is not an iterator @@ -96,6 +105,7 @@ LL | for _ in 42 as usize {} | = help: the trait `Iterator` is not implemented for `usize` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `usize` = note: required by `into_iter` error[E0277]: `isize` is not an iterator @@ -106,6 +116,7 @@ LL | for _ in 42 as isize {} | = help: the trait `Iterator` is not implemented for `isize` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `isize` = note: required by `into_iter` error[E0277]: `{float}` is not an iterator @@ -115,6 +126,7 @@ LL | for _ in 42.0 {} | ^^^^ `{float}` is not an iterator | = help: the trait `Iterator` is not implemented for `{float}` + = note: required because of the requirements on the impl of `IntoIterator` for `{float}` = note: required by `into_iter` error: aborting due to 12 previous errors diff --git a/src/test/ui/iterators/ranges.stderr b/src/test/ui/iterators/ranges.stderr index 0324d5f1a92a1..4678bafd196b5 100644 --- a/src/test/ui/iterators/ranges.stderr +++ b/src/test/ui/iterators/ranges.stderr @@ -5,6 +5,7 @@ LL | for _ in ..10 {} | ^^^^ `RangeTo<{integer}>` is not an iterator | = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>` + = note: required because of the requirements on the impl of `IntoIterator` for `RangeTo<{integer}>` = note: required by `into_iter` error[E0277]: `RangeToInclusive<{integer}>` is not an iterator @@ -14,6 +15,7 @@ LL | for _ in ..=10 {} | ^^^^^ `RangeToInclusive<{integer}>` is not an iterator | = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>` + = note: required because of the requirements on the impl of `IntoIterator` for `RangeToInclusive<{integer}>` = note: required by `into_iter` error: aborting due to 2 previous errors diff --git a/src/test/ui/iterators/string.stderr b/src/test/ui/iterators/string.stderr index fecdbd1785f61..1653006682427 100644 --- a/src/test/ui/iterators/string.stderr +++ b/src/test/ui/iterators/string.stderr @@ -5,6 +5,7 @@ LL | for _ in "".to_owned() {} | ^^^^^^^^^^^^^ `String` is not an iterator | = help: the trait `Iterator` is not implemented for `String` + = note: required because of the requirements on the impl of `IntoIterator` for `String` = note: required by `into_iter` error[E0277]: `&str` is not an iterator @@ -14,6 +15,7 @@ LL | for _ in "" {} | ^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` | = help: the trait `Iterator` is not implemented for `&str` + = note: required because of the requirements on the impl of `IntoIterator` for `&str` = note: required by `into_iter` error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr index e43fb6d0edfb9..c3d597bec2e40 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -3,11 +3,6 @@ error[E0277]: the trait bound `std::result::Result<(), _>: Future` is not satisf | LL | fn foo() -> impl Future> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `std::result::Result<(), _>` -LL | -LL | Ok(()) - | ------ this returned value is of type `std::result::Result<(), _>` - | - = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr index c652faafad461..670f76867ce45 100644 --- a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr +++ b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr @@ -3,11 +3,6 @@ error[E0277]: the trait bound `(): T` is not satisfied | LL | fn should_ret_unit() -> impl T { | ^^^^^^ the trait `T` is not implemented for `()` -LL | -LL | panic!() - | -------- this returned value is of type `!` - | - = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/never_type/issue-51506.stderr b/src/test/ui/never_type/issue-51506.stderr index c54cbe9b4d173..16d93c18900a9 100644 --- a/src/test/ui/never_type/issue-51506.stderr +++ b/src/test/ui/never_type/issue-51506.stderr @@ -2,7 +2,7 @@ error[E0277]: `!` is not an iterator --> $DIR/issue-51506.rs:13:5 | LL | type Out: Iterator; - | ------------------------------- required by `Trait::Out` + | -------------------- required by this bound in `Trait::Out` ... LL | default type Out = !; | ^^^^^^^^^^^^^^^^^^^^^ `!` is not an iterator diff --git a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs index d3964a7f515de..44dcd191d1ba2 100644 --- a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs +++ b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs @@ -32,5 +32,4 @@ fn main() { let _x = ::make_f(); //~^ higher-ranked subtype error //~| higher-ranked subtype error - //~| higher-ranked subtype error } diff --git a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr index 70fb877d71689..190b520c6786c 100644 --- a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr +++ b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -10,11 +10,5 @@ error: higher-ranked subtype error LL | let _x = ::make_f(); | ^^^^^^^^^^^^^^^^^^^ -error: higher-ranked subtype error - --> $DIR/impl-fn-ignore-binder-via-bottom.rs:32:14 - | -LL | let _x = ::make_f(); - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/object-safety/object-safety-bounds.rs b/src/test/ui/object-safety/object-safety-bounds.rs new file mode 100644 index 0000000000000..44bd369324a4b --- /dev/null +++ b/src/test/ui/object-safety/object-safety-bounds.rs @@ -0,0 +1,12 @@ +// Traits with bounds mentioning `Self` are not object safe + +trait X { + type U: PartialEq; +} + +fn f() -> Box> { + //~^ ERROR the trait `X` cannot be made into an object + loop {} +} + +fn main() {} diff --git a/src/test/ui/object-safety/object-safety-bounds.stderr b/src/test/ui/object-safety/object-safety-bounds.stderr new file mode 100644 index 0000000000000..af4548308631e --- /dev/null +++ b/src/test/ui/object-safety/object-safety-bounds.stderr @@ -0,0 +1,14 @@ +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/object-safety-bounds.rs:7:11 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | type U: PartialEq; + | --------------- ...because it uses `Self` as a type parameter in this +... +LL | fn f() -> Box> { + | ^^^^^^^^^^^^^^^^^^^ the trait `X` cannot be made into an object + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/parser/struct-literal-in-for.stderr b/src/test/ui/parser/struct-literal-in-for.stderr index 42f5f1e7e736d..fe9c113710c3c 100644 --- a/src/test/ui/parser/struct-literal-in-for.stderr +++ b/src/test/ui/parser/struct-literal-in-for.stderr @@ -24,6 +24,7 @@ LL | | }.hi() { | |__________^ `bool` is not an iterator | = help: the trait `Iterator` is not implemented for `bool` + = note: required because of the requirements on the impl of `IntoIterator` for `bool` = note: required by `into_iter` error: aborting due to 2 previous errors diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs index 5238894a974f4..fba72c13170fe 100644 --- a/src/test/ui/privacy/private-in-public-assoc-ty.rs +++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs @@ -21,15 +21,15 @@ mod m { // "Private-in-public in associated types is hard error" in RFC 2145 // applies only to the aliased types, not bounds. pub trait PubTr { + type Alias1: PrivTr; //~^ WARN private trait `PrivTr` in public interface //~| WARN this was previously accepted - //~| WARN private type `Priv` in public interface - //~| WARN private type `Priv` in public interface - //~| WARN this was previously accepted - //~| WARN this was previously accepted - type Alias1: PrivTr; type Alias2: PubTrAux1 = u8; + //~^ WARN private type `Priv` in public interface + //~| WARN this was previously accepted type Alias3: PubTrAux2 = u8; + //~^ WARN private type `Priv` in public interface + //~| WARN this was previously accepted type Alias4 = Priv; //~^ ERROR private type `Priv` in public interface diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr index acc6e20cf33e8..430be143f9187 100644 --- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr +++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr @@ -8,47 +8,29 @@ LL | type A = Priv; | ^^^^^^^^^^^^^^ can't leak private type warning: private trait `PrivTr` in public interface (error E0445) - --> $DIR/private-in-public-assoc-ty.rs:23:5 + --> $DIR/private-in-public-assoc-ty.rs:24:9 | -LL | / pub trait PubTr { -LL | | -LL | | -LL | | -... | -LL | | fn infer_exist() -> Self::Exist; -LL | | } - | |_____^ +LL | type Alias1: PrivTr; + | ^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(private_in_public)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 warning: private type `Priv` in public interface (error E0446) - --> $DIR/private-in-public-assoc-ty.rs:23:5 + --> $DIR/private-in-public-assoc-ty.rs:27:9 | -LL | / pub trait PubTr { -LL | | -LL | | -LL | | -... | -LL | | fn infer_exist() -> Self::Exist; -LL | | } - | |_____^ +LL | type Alias2: PubTrAux1 = u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 warning: private type `Priv` in public interface (error E0446) - --> $DIR/private-in-public-assoc-ty.rs:23:5 + --> $DIR/private-in-public-assoc-ty.rs:30:9 | -LL | / pub trait PubTr { -LL | | -LL | | -LL | | -... | -LL | | fn infer_exist() -> Self::Exist; -LL | | } - | |_____^ +LL | type Alias3: PubTrAux2 = u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 diff --git a/src/test/ui/privacy/private-in-public-warn.rs b/src/test/ui/privacy/private-in-public-warn.rs index 3022b470b7d81..1c8706d8ad2e1 100644 --- a/src/test/ui/privacy/private-in-public-warn.rs +++ b/src/test/ui/privacy/private-in-public-warn.rs @@ -55,9 +55,9 @@ mod traits { pub trait Tr2 {} //~ ERROR private trait `traits::PrivTr` in public interface //~^ WARNING hard error pub trait Tr3 { + type Alias: PrivTr; //~^ ERROR private trait `traits::PrivTr` in public interface //~| WARNING hard error - type Alias: PrivTr; fn f(arg: T) {} //~ ERROR private trait `traits::PrivTr` in public interface //~^ WARNING hard error } diff --git a/src/test/ui/privacy/private-in-public-warn.stderr b/src/test/ui/privacy/private-in-public-warn.stderr index 36577a6010260..f50dc48f8add3 100644 --- a/src/test/ui/privacy/private-in-public-warn.stderr +++ b/src/test/ui/privacy/private-in-public-warn.stderr @@ -130,16 +130,10 @@ LL | pub trait Tr2 {} = note: for more information, see issue #34537 error: private trait `traits::PrivTr` in public interface (error E0445) - --> $DIR/private-in-public-warn.rs:57:5 - | -LL | / pub trait Tr3 { -LL | | -LL | | -LL | | type Alias: PrivTr; -LL | | fn f(arg: T) {} -LL | | -LL | | } - | |_____^ + --> $DIR/private-in-public-warn.rs:58:9 + | +LL | type Alias: PrivTr; + | ^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs index e485263affcf7..f926eee9d92b2 100644 --- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs +++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs @@ -1,5 +1,5 @@ - // aux-crate:priv:priv_dep=priv_dep.rs - // aux-build:pub_dep.rs +// aux-crate:priv:priv_dep=priv_dep.rs +// aux-build:pub_dep.rs #![deny(exported_private_dependencies)] // This crate is a private dependency @@ -7,20 +7,20 @@ extern crate priv_dep; // This crate is a public dependency extern crate pub_dep; -use priv_dep::{OtherType, OtherTrait}; +use priv_dep::{OtherTrait, OtherType}; use pub_dep::PubType; // Type from private dependency used in private // type - this is fine struct PrivateType { - field: OtherType + field: OtherType, } pub struct PublicType { pub field: OtherType, //~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface - priv_field: OtherType, // Private field - this is fine - pub other_field: PubType // Type from public dependency - this is fine + priv_field: OtherType, // Private field - this is fine + pub other_field: PubType, // Type from public dependency - this is fine } impl PublicType { @@ -33,13 +33,11 @@ impl PublicType { pub trait MyPubTrait { type Foo: OtherTrait; } -//~^^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface +//~^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface pub struct AllowedPrivType { #[allow(exported_private_dependencies)] - pub allowed: OtherType + pub allowed: OtherType, } - - fn main() {} diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr index 3b5b78234436e..e6b4d33f10316 100644 --- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr +++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr @@ -17,12 +17,10 @@ LL | pub fn pub_fn(param: OtherType) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:33:1 + --> $DIR/pub-priv1.rs:34:5 | -LL | / pub trait MyPubTrait { -LL | | type Foo: OtherTrait; -LL | | } - | |_^ +LL | type Foo: OtherTrait; + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr index f530534ec801f..381959b7ae4cd 100644 --- a/src/test/ui/question-mark-type-infer.stderr +++ b/src/test/ui/question-mark-type-infer.stderr @@ -1,10 +1,11 @@ -error[E0284]: type annotations needed +error[E0283]: type annotations needed --> $DIR/question-mark-type-infer.rs:12:21 | LL | l.iter().map(f).collect()? | ^^^^^^^ cannot infer type | - = note: cannot satisfy `<_ as Try>::Ok == _` + = note: cannot satisfy `_: Try` + = note: required by `into_result` help: consider specifying the type argument in the method call | LL | l.iter().map(f).collect::()? @@ -12,4 +13,4 @@ LL | l.iter().map(f).collect::()? error: aborting due to previous error -For more information about this error, try `rustc --explain E0284`. +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/range/range-1.stderr b/src/test/ui/range/range-1.stderr index a7557320faa4b..2cebffec990f6 100644 --- a/src/test/ui/range/range-1.stderr +++ b/src/test/ui/range/range-1.stderr @@ -11,6 +11,8 @@ LL | for i in false..true {} | ^^^^^^^^^^^ the trait `Step` is not implemented for `bool` | = note: required because of the requirements on the impl of `Iterator` for `std::ops::Range` + = note: required because of the requirements on the impl of `IntoIterator` for `std::ops::Range` + = note: required by `into_iter` error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time --> $DIR/range-1.rs:14:17 diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs index 26cb40bb5c2b1..575dfafe15efc 100644 --- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs +++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs @@ -3,7 +3,7 @@ trait Foo<'a> { type Value: 'a; - fn dummy(&'a self) { } + fn dummy(&'a self) {} } impl<'a> Foo<'a> for &'a i16 { @@ -12,13 +12,13 @@ impl<'a> Foo<'a> for &'a i16 { } impl<'a> Foo<'static> for &'a i32 { - //~^ ERROR cannot infer type Value = &'a i32; + //~^ ERROR the type `&'a i32` does not fulfill the required lifetime } -impl<'a,'b> Foo<'b> for &'a i64 { - //~^ ERROR cannot infer +impl<'a, 'b> Foo<'b> for &'a i64 { type Value = &'a i32; + //~^ ERROR the type `&'a i32` does not fulfill the required lifetime } -fn main() { } +fn main() {} diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr index c134b3b3ed554..03da33ae11ffe 100644 --- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr @@ -1,57 +1,23 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10 +error[E0477]: the type `&'a i32` does not fulfill the required lifetime + --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:15:5 | -LL | impl<'a> Foo<'static> for &'a i32 { - | ^^^^^^^^^^^^ +LL | type Value = &'a i32; + | ^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 14:6... - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:6 - | -LL | impl<'a> Foo<'static> for &'a i32 { - | ^^ -note: ...so that the types are compatible - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10 - | -LL | impl<'a> Foo<'static> for &'a i32 { - | ^^^^^^^^^^^^ - = note: expected `Foo<'static>` - found `Foo<'static>` - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the type `&i32` will meet its required lifetime bounds - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10 - | -LL | impl<'a> Foo<'static> for &'a i32 { - | ^^^^^^^^^^^^ + = note: type must satisfy the static lifetime -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13 - | -LL | impl<'a,'b> Foo<'b> for &'a i64 { - | ^^^^^^^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 19:6... - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:6 - | -LL | impl<'a,'b> Foo<'b> for &'a i64 { - | ^^ -note: ...so that the types are compatible - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13 +error[E0477]: the type `&'a i32` does not fulfill the required lifetime + --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:20:5 | -LL | impl<'a,'b> Foo<'b> for &'a i64 { - | ^^^^^^^ - = note: expected `Foo<'b>` - found `Foo<'_>` -note: but, the lifetime must be valid for the lifetime `'b` as defined on the impl at 19:9... - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:9 +LL | type Value = &'a i32; + | ^^^^^^^^^^^^^^^^^^^^^ | -LL | impl<'a,'b> Foo<'b> for &'a i64 { - | ^^ -note: ...so that the type `&i32` will meet its required lifetime bounds - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13 +note: type must outlive the lifetime `'b` as defined on the impl at 19:10 + --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:10 | -LL | impl<'a,'b> Foo<'b> for &'a i64 { - | ^^^^^^^ +LL | impl<'a, 'b> Foo<'b> for &'a i64 { + | ^^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs index 599cd0bb756ea..00100e0e9ea75 100644 --- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs +++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs @@ -3,12 +3,12 @@ trait Foo { type Value: 'static; - fn dummy(&self) { } + fn dummy(&self) {} } impl<'a> Foo for &'a i32 { - //~^ ERROR cannot infer type Value = &'a i32; + //~^ ERROR the type `&'a i32` does not fulfill the required lifetime } impl<'a> Foo for i32 { @@ -16,4 +16,4 @@ impl<'a> Foo for i32 { type Value = i32; } -fn main() { } +fn main() {} diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr index ac8c55ccc8fd4..d8efeac5b8a30 100644 --- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr @@ -1,28 +1,11 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10 +error[E0477]: the type `&'a i32` does not fulfill the required lifetime + --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:10:5 | -LL | impl<'a> Foo for &'a i32 { - | ^^^ +LL | type Value = &'a i32; + | ^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 9:6... - --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:6 - | -LL | impl<'a> Foo for &'a i32 { - | ^^ -note: ...so that the types are compatible - --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10 - | -LL | impl<'a> Foo for &'a i32 { - | ^^^ - = note: expected `Foo` - found `Foo` - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the type `&i32` will meet its required lifetime bounds - --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10 - | -LL | impl<'a> Foo for &'a i32 { - | ^^^ + = note: type must satisfy the static lifetime error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/regions/regions-enum-not-wf.rs b/src/test/ui/regions/regions-enum-not-wf.rs index 781cdb7286a0e..6de08f66d7536 100644 --- a/src/test/ui/regions/regions-enum-not-wf.rs +++ b/src/test/ui/regions/regions-enum-not-wf.rs @@ -5,17 +5,18 @@ #![allow(dead_code)] trait Dummy<'a> { - type Out; + type Out; } impl<'a, T> Dummy<'a> for T -where T: 'a +where + T: 'a, { - type Out = (); + type Out = (); } type RequireOutlives<'a, T> = >::Out; enum Ref1<'a, T> { - Ref1Variant1(RequireOutlives<'a, T>) //~ ERROR the parameter type `T` may not live long enough + Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough } enum Ref2<'a, T> { @@ -23,18 +24,18 @@ enum Ref2<'a, T> { Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough } -enum RefOk<'a, T:'a> { - RefOkVariant1(&'a T) +enum RefOk<'a, T: 'a> { + RefOkVariant1(&'a T), } // This is now well formed. RFC 2093 enum RefIndirect<'a, T> { - RefIndirectVariant1(isize, RefOk<'a,T>) + RefIndirectVariant1(isize, RefOk<'a, T>), } -enum RefDouble<'a, 'b, T> { //~ ERROR the parameter type `T` may not live long enough [E0309] - RefDoubleVariant1(&'a RequireOutlives<'b, T>) - //~^ the parameter type `T` may not live long enough [E0309] +enum RefDouble<'a, 'b, T> { + RefDoubleVariant1(&'a RequireOutlives<'b, T>), + //~^ the parameter type `T` may not live long enough [E0309] } -fn main() { } +fn main() {} diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr index e32a36f72cd14..36686eaf92f32 100644 --- a/src/test/ui/regions/regions-enum-not-wf.stderr +++ b/src/test/ui/regions/regions-enum-not-wf.stderr @@ -1,13 +1,13 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:18:18 + --> $DIR/regions-enum-not-wf.rs:19:18 | LL | enum Ref1<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` -LL | Ref1Variant1(RequireOutlives<'a, T>) +LL | Ref1Variant1(RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:23:25 + --> $DIR/regions-enum-not-wf.rs:24:25 | LL | enum Ref2<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` @@ -16,25 +16,13 @@ LL | Ref2Variant2(isize, RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:35:1 - | -LL | enum RefDouble<'a, 'b, T> { - | ^ - help: consider adding an explicit lifetime bound...: `T: 'b` - | _| - | | -LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) -LL | | -LL | | } - | |_^ ...so that the type `T` will meet its required lifetime bounds - -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:36:23 + --> $DIR/regions-enum-not-wf.rs:37:23 | LL | enum RefDouble<'a, 'b, T> { | - help: consider adding an explicit lifetime bound...: `T: 'b` -LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) +LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs index e912805d855d2..9912e88c2ec57 100644 --- a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs +++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs @@ -6,7 +6,8 @@ trait Project<'a, 'b> { } impl<'a, 'b> Project<'a, 'b> for () - where 'a: 'b +where + 'a: 'b, { type Item = (); } @@ -14,16 +15,18 @@ impl<'a, 'b> Project<'a, 'b> for () // No error here, we have 'a: 'b. We used to report an error here // though, see https://github.com/rust-lang/rust/issues/45937. fn foo<'a: 'b, 'b>() - where <() as Project<'a, 'b>>::Item : Eq +where + <() as Project<'a, 'b>>::Item: Eq, { } // Here we get an error: we need `'a: 'b`. -fn bar<'a, 'b>() //~ ERROR cannot infer - //~| ERROR cannot infer - //~| ERROR cannot infer - where <() as Project<'a, 'b>>::Item : Eq +fn bar<'a, 'b>() +//~^ ERROR cannot infer +//~| ERROR cannot infer +where + <() as Project<'a, 'b>>::Item: Eq, { } -fn main() { } +fn main() {} diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr index 10ecb8d526292..ddb2b31ce1095 100644 --- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr +++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr @@ -1,87 +1,59 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/regions-normalize-in-where-clause-list.rs:22:1 + --> $DIR/regions-normalize-in-where-clause-list.rs:24:1 | LL | / fn bar<'a, 'b>() LL | | LL | | -LL | | where <() as Project<'a, 'b>>::Item : Eq - | |____________________________________________^ +LL | | where +LL | | <() as Project<'a, 'b>>::Item: Eq, + | |______________________________________^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8... - --> $DIR/regions-normalize-in-where-clause-list.rs:22:8 +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:8... + --> $DIR/regions-normalize-in-where-clause-list.rs:24:8 | LL | fn bar<'a, 'b>() | ^^ -note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12... - --> $DIR/regions-normalize-in-where-clause-list.rs:22:12 +note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 24:12... + --> $DIR/regions-normalize-in-where-clause-list.rs:24:12 | LL | fn bar<'a, 'b>() | ^^ note: ...so that the types are compatible - --> $DIR/regions-normalize-in-where-clause-list.rs:22:1 + --> $DIR/regions-normalize-in-where-clause-list.rs:24:1 | LL | / fn bar<'a, 'b>() LL | | LL | | -LL | | where <() as Project<'a, 'b>>::Item : Eq - | |____________________________________________^ +LL | | where +LL | | <() as Project<'a, 'b>>::Item: Eq, + | |______________________________________^ = note: expected `Project<'a, 'b>` found `Project<'_, '_>` error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/regions-normalize-in-where-clause-list.rs:22:1 - | -LL | / fn bar<'a, 'b>() -LL | | -LL | | -LL | | where <() as Project<'a, 'b>>::Item : Eq - | |____________________________________________^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8... - --> $DIR/regions-normalize-in-where-clause-list.rs:22:8 - | -LL | fn bar<'a, 'b>() - | ^^ -note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12... - --> $DIR/regions-normalize-in-where-clause-list.rs:22:12 - | -LL | fn bar<'a, 'b>() - | ^^ -note: ...so that the types are compatible - --> $DIR/regions-normalize-in-where-clause-list.rs:22:1 - | -LL | / fn bar<'a, 'b>() -LL | | -LL | | -LL | | where <() as Project<'a, 'b>>::Item : Eq - | |____________________________________________^ - = note: expected `Project<'a, 'b>` - found `Project<'_, '_>` - -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/regions-normalize-in-where-clause-list.rs:22:4 + --> $DIR/regions-normalize-in-where-clause-list.rs:24:4 | LL | fn bar<'a, 'b>() | ^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8... - --> $DIR/regions-normalize-in-where-clause-list.rs:22:8 +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:8... + --> $DIR/regions-normalize-in-where-clause-list.rs:24:8 | LL | fn bar<'a, 'b>() | ^^ -note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12... - --> $DIR/regions-normalize-in-where-clause-list.rs:22:12 +note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 24:12... + --> $DIR/regions-normalize-in-where-clause-list.rs:24:12 | LL | fn bar<'a, 'b>() | ^^ note: ...so that the types are compatible - --> $DIR/regions-normalize-in-where-clause-list.rs:22:4 + --> $DIR/regions-normalize-in-where-clause-list.rs:24:4 | LL | fn bar<'a, 'b>() | ^^^ = note: expected `Project<'a, 'b>` found `Project<'_, '_>` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-trait-1.rs b/src/test/ui/regions/regions-trait-1.rs index 0da8ac53695e9..b6dab1c32e8b2 100644 --- a/src/test/ui/regions/regions-trait-1.rs +++ b/src/test/ui/regions/regions-trait-1.rs @@ -1,30 +1,33 @@ -#![feature(box_syntax)] +// check-pass -struct Ctxt { v: usize } +struct Ctxt { + v: usize, +} trait GetCtxt { // Here the `&` is bound in the method definition: fn get_ctxt(&self) -> &Ctxt; } -struct HasCtxt<'a> { c: &'a Ctxt } +struct HasCtxt<'a> { + c: &'a Ctxt, +} impl<'a> GetCtxt for HasCtxt<'a> { - - // Here an error occurs because we used `&self` but - // the definition used `&`: - fn get_ctxt(&self) -> &'a Ctxt { //~ ERROR method not compatible with trait + // Ok: Have implied bound of WF(&'b HasCtxt<'a>) + // so know 'a: 'b + // so know &'a Ctxt <: &'b Ctxt + fn get_ctxt<'b>(&'b self) -> &'a Ctxt { self.c } - } -fn get_v(gc: Box) -> usize { +fn get_v(gc: Box) -> usize { gc.get_ctxt().v } fn main() { let ctxt = Ctxt { v: 22 }; let hc = HasCtxt { c: &ctxt }; - assert_eq!(get_v(box hc as Box), 22); + assert_eq!(get_v(Box::new(hc) as Box), 22); } diff --git a/src/test/ui/regions/regions-trait-1.stderr b/src/test/ui/regions/regions-trait-1.stderr deleted file mode 100644 index 92d96a722d4e9..0000000000000 --- a/src/test/ui/regions/regions-trait-1.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0308]: method not compatible with trait - --> $DIR/regions-trait-1.rs:16:5 - | -LL | fn get_ctxt(&self) -> &'a Ctxt { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected fn pointer `fn(&HasCtxt<'a>) -> &Ctxt` - found fn pointer `fn(&HasCtxt<'a>) -> &'a Ctxt` -note: the lifetime `'a` as defined on the impl at 12:6... - --> $DIR/regions-trait-1.rs:12:6 - | -LL | impl<'a> GetCtxt for HasCtxt<'a> { - | ^^ -note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 16:5 - --> $DIR/regions-trait-1.rs:16:5 - | -LL | fn get_ctxt(&self) -> &'a Ctxt { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs index 781cdb7286a0e..6de08f66d7536 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs +++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs @@ -5,17 +5,18 @@ #![allow(dead_code)] trait Dummy<'a> { - type Out; + type Out; } impl<'a, T> Dummy<'a> for T -where T: 'a +where + T: 'a, { - type Out = (); + type Out = (); } type RequireOutlives<'a, T> = >::Out; enum Ref1<'a, T> { - Ref1Variant1(RequireOutlives<'a, T>) //~ ERROR the parameter type `T` may not live long enough + Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough } enum Ref2<'a, T> { @@ -23,18 +24,18 @@ enum Ref2<'a, T> { Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough } -enum RefOk<'a, T:'a> { - RefOkVariant1(&'a T) +enum RefOk<'a, T: 'a> { + RefOkVariant1(&'a T), } // This is now well formed. RFC 2093 enum RefIndirect<'a, T> { - RefIndirectVariant1(isize, RefOk<'a,T>) + RefIndirectVariant1(isize, RefOk<'a, T>), } -enum RefDouble<'a, 'b, T> { //~ ERROR the parameter type `T` may not live long enough [E0309] - RefDoubleVariant1(&'a RequireOutlives<'b, T>) - //~^ the parameter type `T` may not live long enough [E0309] +enum RefDouble<'a, 'b, T> { + RefDoubleVariant1(&'a RequireOutlives<'b, T>), + //~^ the parameter type `T` may not live long enough [E0309] } -fn main() { } +fn main() {} diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr index e32a36f72cd14..36686eaf92f32 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr @@ -1,13 +1,13 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:18:18 + --> $DIR/regions-enum-not-wf.rs:19:18 | LL | enum Ref1<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` -LL | Ref1Variant1(RequireOutlives<'a, T>) +LL | Ref1Variant1(RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:23:25 + --> $DIR/regions-enum-not-wf.rs:24:25 | LL | enum Ref2<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` @@ -16,25 +16,13 @@ LL | Ref2Variant2(isize, RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:35:1 - | -LL | enum RefDouble<'a, 'b, T> { - | ^ - help: consider adding an explicit lifetime bound...: `T: 'b` - | _| - | | -LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) -LL | | -LL | | } - | |_^ ...so that the type `T` will meet its required lifetime bounds - -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:36:23 + --> $DIR/regions-enum-not-wf.rs:37:23 | LL | enum RefDouble<'a, 'b, T> { | - help: consider adding an explicit lifetime bound...: `T: 'b` -LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) +LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/specialization/deafult-associated-type-bound-1.stderr b/src/test/ui/specialization/deafult-associated-type-bound-1.stderr index 612e22c204fa6..4c21f8db8fad8 100644 --- a/src/test/ui/specialization/deafult-associated-type-bound-1.stderr +++ b/src/test/ui/specialization/deafult-associated-type-bound-1.stderr @@ -11,7 +11,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/deafult-associated-type-bound-1.rs:18:5 | LL | type U: Clone; - | -------------- required by `X::U` + | ----- required by this bound in `X::U` ... LL | default type U = str; | ^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` diff --git a/src/test/ui/specialization/deafult-associated-type-bound-2.stderr b/src/test/ui/specialization/deafult-associated-type-bound-2.stderr index a14024c160f76..8c9da81d277ef 100644 --- a/src/test/ui/specialization/deafult-associated-type-bound-2.stderr +++ b/src/test/ui/specialization/deafult-associated-type-bound-2.stderr @@ -11,7 +11,7 @@ error[E0277]: can't compare `&'static B` with `B` --> $DIR/deafult-associated-type-bound-2.rs:16:5 | LL | type U: PartialEq; - | --------------------- required by `X::U` + | ------------ required by this bound in `X::U` ... LL | default type U = &'static B; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&'static B == B` diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.rs b/src/test/ui/specialization/deafult-generic-associated-type-bound.rs index 8a94ea658d2d0..f14588e6e023c 100644 --- a/src/test/ui/specialization/deafult-generic-associated-type-bound.rs +++ b/src/test/ui/specialization/deafult-generic-associated-type-bound.rs @@ -6,7 +6,7 @@ //~^^ WARNING the feature `generic_associated_types` is incomplete trait X { - type U<'a>: PartialEq<&'a Self>; + type U<'a>: PartialEq<&'a Self> where Self: 'a; fn unsafe_compare<'b>(x: Option>, y: Option<&'b Self>) { match (x, y) { (Some(a), Some(b)) => a == b, diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr index 556feda642b54..f145b90f216ab 100644 --- a/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr +++ b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr @@ -18,8 +18,8 @@ LL | #![feature(generic_associated_types)] error[E0277]: can't compare `T` with `T` --> $DIR/deafult-generic-associated-type-bound.rs:19:5 | -LL | type U<'a>: PartialEq<&'a Self>; - | -------------------------------- required by `X::U` +LL | type U<'a>: PartialEq<&'a Self> where Self: 'a; + | ------------------- required by this bound in `X::U` ... LL | default type U<'a> = &'a T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T == T` diff --git a/src/test/ui/specialization/issue-38091-2.rs b/src/test/ui/specialization/issue-38091-2.rs new file mode 100644 index 0000000000000..9ed0b240d0a0f --- /dev/null +++ b/src/test/ui/specialization/issue-38091-2.rs @@ -0,0 +1,28 @@ +// build-fail +//~^ ERROR overflow evaluating the requirement `i32: Check` + +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait Iterate<'a> { + type Ty: Valid; + fn iterate(self); +} +impl<'a, T> Iterate<'a> for T +where + T: Check, +{ + default type Ty = (); + default fn iterate(self) {} +} + +trait Check {} +impl<'a, T> Check for T where >::Ty: Valid {} + +trait Valid {} + +impl Valid for () {} + +fn main() { + Iterate::iterate(0); +} diff --git a/src/test/ui/specialization/issue-38091-2.stderr b/src/test/ui/specialization/issue-38091-2.stderr new file mode 100644 index 0000000000000..a314c26ad147d --- /dev/null +++ b/src/test/ui/specialization/issue-38091-2.stderr @@ -0,0 +1,16 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-38091-2.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +error[E0275]: overflow evaluating the requirement `i32: Check` + | + = note: required because of the requirements on the impl of `Iterate` for `i32` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/issues/issue-38091.rs b/src/test/ui/specialization/issue-38091.rs similarity index 88% rename from src/test/ui/issues/issue-38091.rs rename to src/test/ui/specialization/issue-38091.rs index a84391b94d1de..5b398368a6733 100644 --- a/src/test/ui/issues/issue-38091.rs +++ b/src/test/ui/specialization/issue-38091.rs @@ -5,7 +5,10 @@ trait Iterate<'a> { type Ty: Valid; fn iterate(self); } -impl<'a, T> Iterate<'a> for T where T: Check { +impl<'a, T> Iterate<'a> for T +where + T: Check, +{ default type Ty = (); //~^ ERROR the trait bound `(): Valid` is not satisfied default fn iterate(self) {} diff --git a/src/test/ui/issues/issue-38091.stderr b/src/test/ui/specialization/issue-38091.stderr similarity index 88% rename from src/test/ui/issues/issue-38091.stderr rename to src/test/ui/specialization/issue-38091.stderr index 81beec8026314..6be0f26849f90 100644 --- a/src/test/ui/issues/issue-38091.stderr +++ b/src/test/ui/specialization/issue-38091.stderr @@ -8,10 +8,10 @@ LL | #![feature(specialization)] = note: see issue #31844 for more information error[E0277]: the trait bound `(): Valid` is not satisfied - --> $DIR/issue-38091.rs:9:5 + --> $DIR/issue-38091.rs:12:5 | LL | type Ty: Valid; - | --------------- required by `Iterate::Ty` + | ----- required by this bound in `Iterate::Ty` ... LL | default type Ty = (); | ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()` diff --git a/src/test/ui/specialization/issue-44861.stderr b/src/test/ui/specialization/issue-44861.stderr index be7196a63ce1d..3935a4a5f9931 100644 --- a/src/test/ui/specialization/issue-44861.stderr +++ b/src/test/ui/specialization/issue-44861.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `(): CoerceUnsized<*const [u8]>` is not satisfied --> $DIR/issue-44861.rs:21:5 | LL | type Data2: CoerceUnsized<*const [u8]>; - | --------------------------------------- required by `Smartass::Data2` + | -------------------------- required by this bound in `Smartass::Data2` ... LL | default type Data2 = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CoerceUnsized<*const [u8]>` is not implemented for `()` diff --git a/src/test/ui/specialization/issue-59435.stderr b/src/test/ui/specialization/issue-59435.stderr index ee5c0615927a8..f3f8b022b01e1 100644 --- a/src/test/ui/specialization/issue-59435.stderr +++ b/src/test/ui/specialization/issue-59435.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `MyStruct: Default` is not satisfied --> $DIR/issue-59435.rs:11:5 | LL | type MyType: Default; - | --------------------- required by `MyTrait::MyType` + | ------- required by this bound in `MyTrait::MyType` ... LL | default type MyType = MyStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `MyStruct` diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr index cc3a2b9419caf..d826222a06ae5 100644 --- a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr +++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr @@ -5,8 +5,6 @@ LL | fn foo() -> impl Bar { | ^^^^^^^^ the trait `Bar` is not implemented for `()` LL | 5; | - consider removing this semicolon - | - = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs index 394512c579474..4954a8a6965be 100644 --- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs +++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs @@ -1,5 +1,4 @@ -// Running rustfix would cause the same suggestion to be applied multiple times, which results in -// invalid code. +// check-pass trait Parent { type Ty; @@ -15,11 +14,8 @@ impl Child for ChildWrapper where T: Child {} struct ParentWrapper(T); impl> Parent for ParentWrapper { - //~^ ERROR the trait bound `::Assoc: Child` is not satisfied type Ty = A; type Assoc = ChildWrapper; - //~^ ERROR the trait bound `::Assoc: Child` is not satisfied - //~| ERROR the trait bound `::Assoc: Child` is not satisfied } fn main() {} diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr deleted file mode 100644 index a8ea214796183..0000000000000 --- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr +++ /dev/null @@ -1,55 +0,0 @@ -error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:17:19 - | -LL | trait Parent { - | ------ required by a bound in this -LL | type Ty; -LL | type Assoc: Child; - | --------------- required by this bound in `Parent` -... -LL | impl> Parent for ParentWrapper { - | ^^^^^^ the trait `Child` is not implemented for `::Assoc` - | -help: consider further restricting the associated type - | -LL | impl> Parent for ParentWrapper where ::Assoc: Child { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:20:18 - | -LL | trait Parent { - | ------ required by a bound in this -LL | type Ty; -LL | type Assoc: Child; - | --------------- required by this bound in `Parent` -... -LL | type Assoc = ChildWrapper; - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Child` is not implemented for `::Assoc` - | - = note: required because of the requirements on the impl of `Child` for `ChildWrapper<::Assoc>` -help: consider further restricting the associated type - | -LL | impl> Parent for ParentWrapper where ::Assoc: Child { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:20:5 - | -LL | trait Parent { - | ------ required by a bound in this -LL | type Ty; -LL | type Assoc: Child; - | --------------- required by this bound in `Parent` -... -LL | type Assoc = ChildWrapper; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Child` is not implemented for `::Assoc` - | -help: consider further restricting the associated type - | -LL | impl> Parent for ParentWrapper where ::Assoc: Child { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.stderr b/src/test/ui/suggestions/suggest-remove-refs-1.stderr index 0dd1b2a59eb9a..4aa0ad219cf25 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-1.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-1.stderr @@ -8,6 +8,7 @@ LL | for (i, _) in &v.iter().enumerate() { | help: consider removing the leading `&`-reference | = help: the trait `Iterator` is not implemented for `&Enumerate>` + = note: required because of the requirements on the impl of `IntoIterator` for `&Enumerate>` = note: required by `into_iter` error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-remove-refs-2.stderr b/src/test/ui/suggestions/suggest-remove-refs-2.stderr index 5c2efdb197f8c..15c4b7fcb8b3b 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-2.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-2.stderr @@ -8,6 +8,7 @@ LL | for (i, _) in & & & & &v.iter().enumerate() { | help: consider removing 5 leading `&`-references | = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` + = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate>` = note: required by `into_iter` error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-remove-refs-3.stderr b/src/test/ui/suggestions/suggest-remove-refs-3.stderr index c7fbd3d9bd961..0bd6d956aff97 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-3.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-3.stderr @@ -12,6 +12,7 @@ LL | | .enumerate() { | |_____________________^ `&&&&&Enumerate>` is not an iterator | = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` + = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate>` = note: required by `into_iter` error: aborting due to previous error diff --git a/src/test/ui/traits/check-trait-object-bounds-1.rs b/src/test/ui/traits/check-trait-object-bounds-1.rs new file mode 100644 index 0000000000000..b1f124c7ea26a --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-1.rs @@ -0,0 +1,14 @@ +// Check that we validate associated type bounds for trait objects + +trait X { + type Y: Clone; +} + +fn f() { + None::.clone(); +} + +fn main() { + f::>(); + //~^ ERROR the trait bound `str: Clone` is not satisfied +} diff --git a/src/test/ui/traits/check-trait-object-bounds-1.stderr b/src/test/ui/traits/check-trait-object-bounds-1.stderr new file mode 100644 index 0000000000000..170ed6eacfd41 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-1.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/check-trait-object-bounds-1.rs:12:5 + | +LL | fn f() { + | - required by this bound in `f` +... +LL | f::>(); + | ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/check-trait-object-bounds-2-ok.rs b/src/test/ui/traits/check-trait-object-bounds-2-ok.rs new file mode 100644 index 0000000000000..1422dda276b9b --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-2-ok.rs @@ -0,0 +1,15 @@ +// Make sure that we're handling bound lifetimes correctly when validating trait +// bounds. +// run-pass + +trait X<'a> { + type F: FnOnce(&i32) -> &'a i32; +} + +fn f X<'r> + ?Sized>() { + None::.map(|f| f(&0)); +} + +fn main() { + f:: X<'x, F = fn(&i32) -> &'x i32>>(); +} diff --git a/src/test/ui/traits/check-trait-object-bounds-2.rs b/src/test/ui/traits/check-trait-object-bounds-2.rs new file mode 100644 index 0000000000000..eb2fb6e841bce --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-2.rs @@ -0,0 +1,15 @@ +// Check that we validate associated type bounds for trait objects when they +// have bound lifetimes + +trait X<'a> { + type F: FnOnce(&i32) -> &'a i32; +} + +fn f X<'r> + ?Sized>() { + None::.map(|f| f(&0)); +} + +fn main() { + f:: X<'x, F = i32>>(); + //~^ expected a `FnOnce<(&i32,)>` closure, found `i32` +} diff --git a/src/test/ui/traits/check-trait-object-bounds-2.stderr b/src/test/ui/traits/check-trait-object-bounds-2.stderr new file mode 100644 index 0000000000000..04e2348634ed8 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-2.stderr @@ -0,0 +1,14 @@ +error[E0277]: expected a `FnOnce<(&i32,)>` closure, found `i32` + --> $DIR/check-trait-object-bounds-2.rs:13:5 + | +LL | fn f X<'r> + ?Sized>() { + | ------------- required by this bound in `f` +... +LL | f:: X<'x, F = i32>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32` + | + = help: the trait `for<'r> FnOnce<(&'r i32,)>` is not implemented for `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/check-trait-object-bounds-3.rs b/src/test/ui/traits/check-trait-object-bounds-3.rs new file mode 100644 index 0000000000000..ba04fd93accec --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-3.rs @@ -0,0 +1,20 @@ +// Check that we validate associated type bounds for trait objects + +trait X<'a> { + type Y: Into<&'static str> + From<&'a str>; +} + +fn f<'a, T: X<'a> + ?Sized>(s: &'a str) -> &'static str { + T::Y::from(s).into() +} + +pub fn main() { + let z; + { + let s = String::from("abcdef"); + z = f::>(&s); + //~^ ERROR `s` does not live long enough + } + + println!("{}", z) +} diff --git a/src/test/ui/traits/check-trait-object-bounds-3.stderr b/src/test/ui/traits/check-trait-object-bounds-3.stderr new file mode 100644 index 0000000000000..ade552c4bab41 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-3.stderr @@ -0,0 +1,15 @@ +error[E0597]: `s` does not live long enough + --> $DIR/check-trait-object-bounds-3.rs:15:34 + | +LL | z = f::>(&s); + | ---------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `s` is borrowed for `'static` +LL | +LL | } + | - `s` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/traits/check-trait-object-bounds-4.rs b/src/test/ui/traits/check-trait-object-bounds-4.rs new file mode 100644 index 0000000000000..e9ca1563f3b67 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-4.rs @@ -0,0 +1,17 @@ +// Check that we validate associated type bounds on super traits for trait +// objects + +trait Super { + type Y: Clone; +} + +trait X: Super {} + +fn f() { + None::.clone(); +} + +fn main() { + f::>(); + //~^ ERROR the trait bound `str: Clone` is not satisfied +} diff --git a/src/test/ui/traits/check-trait-object-bounds-4.stderr b/src/test/ui/traits/check-trait-object-bounds-4.stderr new file mode 100644 index 0000000000000..fc9f31c5ebc7e --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-4.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/check-trait-object-bounds-4.rs:15:5 + | +LL | fn f() { + | - required by this bound in `f` +... +LL | f::>(); + | ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/check-trait-object-bounds-5.rs b/src/test/ui/traits/check-trait-object-bounds-5.rs new file mode 100644 index 0000000000000..7d733ad26b752 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-5.rs @@ -0,0 +1,27 @@ +// Check that we validate associated type bounds on super traits for trait +// objects + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Super { + type V; +} + +trait Obj: Super { + type U: Is; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) + //~^ type mismatch resolving `::T == i64` +} + +fn main() {} diff --git a/src/test/ui/traits/check-trait-object-bounds-5.stderr b/src/test/ui/traits/check-trait-object-bounds-5.stderr new file mode 100644 index 0000000000000..bd2b789cd9908 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-5.stderr @@ -0,0 +1,12 @@ +error[E0271]: type mismatch resolving `::T == i64` + --> $DIR/check-trait-object-bounds-5.rs:23:5 + | +LL | fn is_obj(_: &T) {} + | --- required by this bound in `is_obj` +... +LL | is_obj(x) + | ^^^^^^ expected `i64`, found `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/traits/check-trait-object-bounds-6.rs b/src/test/ui/traits/check-trait-object-bounds-6.rs new file mode 100644 index 0000000000000..cb196d67f673d --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-6.rs @@ -0,0 +1,24 @@ +// Check that we validate associated type bounds on super traits for trait +// objects + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj { + type U: Is; + type V; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) + //~^ ERROR type mismatch resolving `::T == i64` +} + +fn main() {} diff --git a/src/test/ui/traits/check-trait-object-bounds-6.stderr b/src/test/ui/traits/check-trait-object-bounds-6.stderr new file mode 100644 index 0000000000000..ea1fdaf46f6ae --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-6.stderr @@ -0,0 +1,12 @@ +error[E0271]: type mismatch resolving `::T == i64` + --> $DIR/check-trait-object-bounds-6.rs:20:5 + | +LL | fn is_obj(_: &T) {} + | --- required by this bound in `is_obj` +... +LL | is_obj(x) + | ^^^^^^ expected `i64`, found `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/traits/cycle-cache-err-60010.rs b/src/test/ui/traits/cycle-cache-err-60010.rs index cbddef082be67..98bfcb8d67b51 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.rs +++ b/src/test/ui/traits/cycle-cache-err-60010.rs @@ -24,11 +24,13 @@ struct Runtime { _storage: Box, } struct SalsaStorage { - _parse: >::Data, //~ ERROR overflow + _parse: >::Data, } impl Database for RootDatabase { - type Storage = SalsaStorage; //~ ERROR overflow + // This would also be an error if we didn't abort compilation on the error + // above. + type Storage = SalsaStorage; } impl HasQueryGroup for RootDatabase {} impl Query for ParseQuery @@ -65,6 +67,7 @@ pub(crate) fn goto_implementation(db: &RootDatabase) -> u32 { // we used to fail to report an error here because we got the // caching wrong. SourceDatabase::parse(db); + //~^ ERROR overflow 22 } diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr index 25b1f427f3a16..b2702d977f8b6 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.stderr +++ b/src/test/ui/traits/cycle-cache-err-60010.stderr @@ -1,27 +1,19 @@ -error[E0275]: overflow evaluating the requirement `RootDatabase: SourceDatabase` - --> $DIR/cycle-cache-err-60010.rs:27:13 +error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe` + --> $DIR/cycle-cache-err-60010.rs:69:5 | -LL | _parse: >::Data, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: required because of the requirements on the impl of `Query` for `ParseQuery` - -error[E0275]: overflow evaluating the requirement `Runtime: RefUnwindSafe` - --> $DIR/cycle-cache-err-60010.rs:31:20 - | -LL | trait Database { - | -------- required by a bound in this -LL | type Storage; - | ------------- required by this bound in `Database` +LL | fn parse(&self) { + | --------------- required by `SourceDatabase::parse` ... -LL | type Storage = SalsaStorage; - | ^^^^^^^^^^^^ +LL | SourceDatabase::parse(db); + | ^^^^^^^^^^^^^^^^^^^^^ | + = note: required because it appears within the type `*const SalsaStorage` + = note: required because it appears within the type `Unique` + = note: required because it appears within the type `Box` + = note: required because it appears within the type `Runtime` = note: required because it appears within the type `RootDatabase` = note: required because of the requirements on the impl of `SourceDatabase` for `RootDatabase` - = note: required because of the requirements on the impl of `Query` for `ParseQuery` - = note: required because it appears within the type `SalsaStorage` -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/traits/trait-object-bounds-cycle-1.rs b/src/test/ui/traits/trait-object-bounds-cycle-1.rs new file mode 100644 index 0000000000000..3146764927cd8 --- /dev/null +++ b/src/test/ui/traits/trait-object-bounds-cycle-1.rs @@ -0,0 +1,24 @@ +// Check that we don't have a cycle when we try to normalize `Self::U` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj { + type U: Is; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) +} + +fn main() {} diff --git a/src/test/ui/traits/trait-object-bounds-cycle-2.rs b/src/test/ui/traits/trait-object-bounds-cycle-2.rs new file mode 100644 index 0000000000000..4c1df38058dad --- /dev/null +++ b/src/test/ui/traits/trait-object-bounds-cycle-2.rs @@ -0,0 +1,28 @@ +// Check that we don't have a cycle when we try to normalize `Self::V` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Super { + type V; +} + +trait Obj: Super { + type U: Is; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) +} + +fn main() {} diff --git a/src/test/ui/traits/trait-object-bounds-cycle-3.rs b/src/test/ui/traits/trait-object-bounds-cycle-3.rs new file mode 100644 index 0000000000000..55726a5ae4557 --- /dev/null +++ b/src/test/ui/traits/trait-object-bounds-cycle-3.rs @@ -0,0 +1,25 @@ +// Check that we don't have a cycle when we try to normalize `Self::V` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj { + type U: Is; + type V; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) +} + +fn main() {} diff --git a/src/test/ui/traits/trait-object-bounds-cycle-4.rs b/src/test/ui/traits/trait-object-bounds-cycle-4.rs new file mode 100644 index 0000000000000..f83cb75c7f29b --- /dev/null +++ b/src/test/ui/traits/trait-object-bounds-cycle-4.rs @@ -0,0 +1,25 @@ +// Check that we don't have a cycle when we try to normalize `Self::U` in the +// bound below. Make sure that having a lifetime on the trait object doesn't break things + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj<'a> { + type U: Is; + type V; +} + +fn is_obj<'a, T: ?Sized + Obj<'a>>(_: &T) {} + +fn f<'a>(x: &dyn Obj<'a, U = i32, V = i32>) { + is_obj(x) +} + +fn main() {} diff --git a/src/test/ui/traits/trait-object-supertrait-lifetime-bound.rs b/src/test/ui/traits/trait-object-supertrait-lifetime-bound.rs new file mode 100644 index 0000000000000..9d834727a4a1b --- /dev/null +++ b/src/test/ui/traits/trait-object-supertrait-lifetime-bound.rs @@ -0,0 +1,16 @@ +// check-pass + +use std::any::Any; + +trait A: Any { + fn m(&self) {} +} + +impl A for T {} + +fn call_obj<'a>() { + let obj: &dyn A<&'a ()> = &(); + obj.m(); +} + +fn main() {} diff --git a/src/test/ui/traits/traits-inductive-overflow-two-traits.rs b/src/test/ui/traits/traits-inductive-overflow-two-traits.rs index 63dd141920025..463b55d8581f8 100644 --- a/src/test/ui/traits/traits-inductive-overflow-two-traits.rs +++ b/src/test/ui/traits/traits-inductive-overflow-two-traits.rs @@ -9,6 +9,7 @@ pub trait Magic { } impl Magic for T { type X = Self; + //~^ ERROR E0277 } fn check() {} diff --git a/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr index f66cfce55c903..996544ae5162d 100644 --- a/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr @@ -1,5 +1,19 @@ +error[E0277]: `T` cannot be shared between threads safely + --> $DIR/traits-inductive-overflow-two-traits.rs:11:5 + | +LL | type X: Trait; + | ----- required by this bound in `Magic::X` +... +LL | type X = Self; + | ^^^^^^^^^^^^^^ `T` cannot be shared between threads safely + | +help: consider further restricting this bound + | +LL | impl Magic for T { + | ^^^^^^ + error[E0275]: overflow evaluating the requirement `*mut (): Magic` - --> $DIR/traits-inductive-overflow-two-traits.rs:19:5 + --> $DIR/traits-inductive-overflow-two-traits.rs:20:5 | LL | fn wizard() { check::<::X>(); } | ----- required by this bound in `wizard` @@ -7,6 +21,7 @@ LL | fn wizard() { check::<::X>(); } LL | wizard::<*mut ()>(); | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0275`. +Some errors have detailed explanations: E0275, E0277. +For more information about an error, try `rustc --explain E0275`. diff --git a/src/test/ui/try-block/try-block-bad-type.rs b/src/test/ui/try-block/try-block-bad-type.rs index c338294913f6c..496ba145810fb 100644 --- a/src/test/ui/try-block/try-block-bad-type.rs +++ b/src/test/ui/try-block/try-block-bad-type.rs @@ -14,7 +14,9 @@ pub fn main() { let res: Result = try { }; //~ ERROR type mismatch - let res: () = try { }; //~ the trait bound `(): Try` is not satisfied + let res: () = try { }; + //~^ ERROR the trait bound `(): Try` is not satisfied + //~| ERROR the trait bound `(): Try` is not satisfied let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try` is not satisfied } diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr index 03d5d3661ddf7..cadf3a841c961 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -26,22 +26,28 @@ LL | let res: Result = try { }; | ^ expected `i32`, found `()` error[E0277]: the trait bound `(): Try` is not satisfied - --> $DIR/try-block-bad-type.rs:17:23 + --> $DIR/try-block-bad-type.rs:17:25 | LL | let res: () = try { }; - | ^^^ the trait `Try` is not implemented for `()` + | ^ the trait `Try` is not implemented for `()` | = note: required by `from_ok` +error[E0277]: the trait bound `(): Try` is not satisfied + --> $DIR/try-block-bad-type.rs:17:25 + | +LL | let res: () = try { }; + | ^ the trait `Try` is not implemented for `()` + error[E0277]: the trait bound `i32: Try` is not satisfied - --> $DIR/try-block-bad-type.rs:19:24 + --> $DIR/try-block-bad-type.rs:21:26 | LL | let res: i32 = try { 5 }; - | ^^^^^ the trait `Try` is not implemented for `i32` + | ^ the trait `Try` is not implemented for `i32` | = note: required by `from_ok` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0271, E0277. For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/try-block/try-block-in-while.stderr b/src/test/ui/try-block/try-block-in-while.stderr index bc0f5bb6505b2..75a4e8d065cab 100644 --- a/src/test/ui/try-block/try-block-in-while.stderr +++ b/src/test/ui/try-block/try-block-in-while.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `bool: Try` is not satisfied - --> $DIR/try-block-in-while.rs:6:15 + --> $DIR/try-block-in-while.rs:6:17 | LL | while try { false } {} - | ^^^^^^^^^ the trait `Try` is not implemented for `bool` + | ^^^^^ the trait `Try` is not implemented for `bool` | = note: required by `from_ok` diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs new file mode 100644 index 0000000000000..c0359159aebea --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs @@ -0,0 +1,19 @@ +// Make sure that we check that impl trait types implement the traits that they +// claim to. + +#![feature(type_alias_impl_trait)] + +type X = impl Clone; +//~^ ERROR the trait bound `T: Clone` is not satisfied + +fn f(t: T) -> X { + t +} + +fn g(o: Option>) -> Option> { + o.clone() +} + +fn main() { + g(None::>); +} diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr new file mode 100644 index 0000000000000..26a2f4135cb0a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/bounds-are-checked-2.rs:6:13 + | +LL | type X = impl Clone; + | ^^^^^^^^^^ the trait `Clone` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | type X = impl Clone; + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs new file mode 100644 index 0000000000000..759bf4f4f0dee --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs @@ -0,0 +1,25 @@ +// Make sure that we check that impl trait types implement the traits that they +// claim to. + +#![feature(type_alias_impl_trait)] + +type X<'a> = impl Into<&'static str> + From<&'a str>; +//~^ ERROR mismatched types + +fn f<'a: 'static>(t: &'a str) -> X<'a> { + //~^ WARNING unnecessary lifetime parameter + t +} + +fn extend_lt<'a>(o: &'a str) -> &'static str { + X::<'_>::from(o).into() +} + +fn main() { + let r = + { + let s = "abcdef".to_string(); + extend_lt(&s) + }; + println!("{}", r); +} diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr new file mode 100644 index 0000000000000..d5fafe05887b9 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr @@ -0,0 +1,26 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/bounds-are-checked.rs:9:6 + | +LL | fn f<'a: 'static>(t: &'a str) -> X<'a> { + | ^^^^^^^^^^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +error[E0308]: mismatched types + --> $DIR/bounds-are-checked.rs:6:14 + | +LL | type X<'a> = impl Into<&'static str> + From<&'a str>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected trait `From<&'a str>` + found trait `From<&'static str>` +note: the lifetime `'a` as defined on the item at 6:8... + --> $DIR/bounds-are-checked.rs:6:8 + | +LL | type X<'a> = impl Into<&'static str> + From<&'a str>; + | ^^ + = note: ...does not necessarily outlive the static lifetime + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs index 898dab1b0b960..c17d595dbb3ad 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs @@ -1,11 +1,11 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(type_alias_impl_trait)] use std::fmt::Debug; fn main() {} -type Two = impl Debug; +type Two = impl Debug; fn two(t: T, _: U) -> Two { (t, 4u32) diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs index ac8773104147e..dd2f202cf5dc0 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs @@ -6,12 +6,14 @@ fn main() {} // test that unused generic parameters are ok type Two = impl Debug; +//~^ ERROR `T` doesn't implement `Debug` +//~| ERROR `U` doesn't implement `Debug` fn two(t: T, u: U) -> Two { (t, u) } fn three(t: T, u: U) -> Two { -//~^ concrete type differs from previous + //~^ concrete type differs from previous (u, t) } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr index 1ddbc0c8d6a8e..b4aed4a6323bf 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr @@ -1,14 +1,39 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use5.rs:14:1 + --> $DIR/generic_duplicate_param_use5.rs:16:1 | LL | fn three(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, U)`, got `(U, T)` | note: previous use here - --> $DIR/generic_duplicate_param_use5.rs:10:1 + --> $DIR/generic_duplicate_param_use5.rs:12:1 | LL | fn two(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use5.rs:8:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required because of the requirements on the impl of `Debug` for `(T, U)` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | ^^^^^^^ + +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use5.rs:8:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required because of the requirements on the impl of `Debug` for `(T, U)` +help: consider restricting type parameter `U` + | +LL | type Two = impl Debug; + | ^^^^^^^ + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs index 6cbb3069ecd4b..d54d3cd62e020 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs @@ -6,12 +6,13 @@ fn main() {} // test that unused generic parameters are ok type Two = impl Debug; +//~^ ERROR `T` doesn't implement `Debug` fn two(t: T, u: U) -> Two { (t, t) } fn three(t: T, u: U) -> Two { - //~^ concrete type differs from previous + //~^ ERROR concrete type differs from previous (u, t) } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr index ebd07b7c300f1..22e4d00667492 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr @@ -1,14 +1,27 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use6.rs:14:1 + --> $DIR/generic_duplicate_param_use6.rs:15:1 | LL | fn three(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, T)`, got `(U, T)` | note: previous use here - --> $DIR/generic_duplicate_param_use6.rs:10:1 + --> $DIR/generic_duplicate_param_use6.rs:11:1 | LL | fn two(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use6.rs:8:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required because of the requirements on the impl of `Debug` for `(T, T)` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | ^^^^^^^ + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs index 712a6539f0153..feebf81eef2a7 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs @@ -1,11 +1,11 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(type_alias_impl_trait)] use std::fmt::Debug; fn main() {} -type Two = impl Debug; +type Two = impl Debug; fn two(t: T, u: U) -> Two { (t, t) diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs index 777ded52609b8..4a723b64cdc4f 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs @@ -5,12 +5,13 @@ use std::fmt::Debug; fn main() {} type Two = impl Debug; +//~^ ERROR `T` doesn't implement `Debug` fn two(t: T, _: U) -> Two { (t, 4u32) } fn three(_: T, u: U) -> Two { -//~^ concrete type differs from previous + //~^ concrete type differs from previous (u, 4u32) } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr index 4778ee5155cf0..82da704c9ee22 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr @@ -1,14 +1,27 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use8.rs:13:1 + --> $DIR/generic_duplicate_param_use8.rs:14:1 | LL | fn three(_: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, u32)`, got `(U, u32)` | note: previous use here - --> $DIR/generic_duplicate_param_use8.rs:9:1 + --> $DIR/generic_duplicate_param_use8.rs:10:1 | LL | fn two(t: T, _: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use8.rs:7:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required because of the requirements on the impl of `Debug` for `(T, u32)` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | ^^^^^^^ + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs index 491e6647f45d0..747081933172b 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs @@ -5,6 +5,9 @@ use std::fmt::Debug; fn main() {} type Two = impl Debug; +//~^ ERROR the trait bound `A: Foo` is not satisfied in `(A, B, ::Bar)` +//~| ERROR `A` doesn't implement `Debug` +//~| ERROR `B` doesn't implement `Debug` trait Foo { type Bar: Debug; diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr index 247b042f61e05..63aa0f8a81c9a 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr @@ -1,14 +1,51 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use9.rs:18:1 + --> $DIR/generic_duplicate_param_use9.rs:21:1 | LL | fn three(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(A, B, ::Bar)`, got `(A, B, i32)` | note: previous use here - --> $DIR/generic_duplicate_param_use9.rs:14:1 + --> $DIR/generic_duplicate_param_use9.rs:17:1 | LL | fn two(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0277]: the trait bound `A: Foo` is not satisfied in `(A, B, ::Bar)` + --> $DIR/generic_duplicate_param_use9.rs:7:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ within `(A, B, ::Bar)`, the trait `Foo` is not implemented for `A` + | + = note: required because it appears within the type `(A, B, ::Bar)` +help: consider restricting type parameter `A` + | +LL | type Two = impl Debug; + | ^^^^^ + +error[E0277]: `A` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use9.rs:7:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required because of the requirements on the impl of `Debug` for `(A, B, ::Bar)` +help: consider restricting type parameter `A` + | +LL | type Two = impl Debug; + | ^^^^^^^ + +error[E0277]: `B` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use9.rs:7:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required because of the requirements on the impl of `Debug` for `(A, B, ::Bar)` +help: consider restricting type parameter `B` + | +LL | type Two = impl Debug; + | ^^^^^^^ + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr index 76654d7a718b8..ffd6f34c4b00e 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr @@ -18,6 +18,24 @@ LL | type WrongGeneric = impl 'static; = note: expected type `i32` found opaque type `impl Sized` -error: aborting due to 2 previous errors +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/generic_type_does_not_live_long_enough.rs:14:30 + | +LL | fn wrong_generic(t: T) -> WrongGeneric { + | ^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: 'static`... + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/generic_type_does_not_live_long_enough.rs:9:24 + | +LL | type WrongGeneric = impl 'static; + | ^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: 'static`... + = note: ...so that the type `T` will meet its required lifetime bounds + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0310. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs index c0f939a50482f..f6d490960365a 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs @@ -8,7 +8,8 @@ fn main() { type WrongGeneric = impl 'static; //~^ ERROR the parameter type `T` may not live long enough -//~^^ ERROR: at least one trait must be specified +//~| ERROR the parameter type `T` may not live long enough +//~| ERROR: at least one trait must be specified fn wrong_generic(t: T) -> WrongGeneric { t diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr index 18d8daa05e63d..4924c447d7e40 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr @@ -27,7 +27,16 @@ LL | type WrongGeneric = impl 'static; LL | fn wrong_generic(t: T) -> WrongGeneric { | - help: consider adding an explicit lifetime bound...: `T: 'static` -error: aborting due to 3 previous errors +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/generic_type_does_not_live_long_enough.rs:9:24 + | +LL | type WrongGeneric = impl 'static; + | ^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: 'static`... + = note: ...so that the type `T` will meet its required lifetime bounds + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0308, E0310. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr index 8c9cb742fac91..790aea87510e6 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr @@ -1,14 +1,33 @@ error: higher-ranked subtype error - --> $DIR/issue-57611-trait-alias.rs:21:9 + --> $DIR/issue-57611-trait-alias.rs:25:9 | LL | |x| x | ^^^^^ error: higher-ranked subtype error - --> $DIR/issue-57611-trait-alias.rs:21:9 + --> $DIR/issue-57611-trait-alias.rs:25:9 | LL | |x| x | ^^^^^ -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r> Fn<(&'r X,)>` + found type `Fn<(&'static X,)>` + +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `FnOnce<(&X,)>` + found type `FnOnce<(&'static X,)>` + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 782eb0fb3df5e..3372b81404ecb 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -16,6 +16,10 @@ struct X; impl Foo for X { type Bar = impl Baz; //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types fn bar(&self) -> Self::Bar { |x| x diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index a8706aa9a241f..5e2a8db02867f 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -7,6 +7,42 @@ LL | type Bar = impl Baz; = note: expected type `FnOnce<(&X,)>` found type `FnOnce<(&X,)>` -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r> Fn<(&'r X,)>` + found type `Fn<(&' X,)>` + +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `FnOnce<(&X,)>` + found type `FnOnce<(&' X,)>` + +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r> Fn<(&'r X,)>` + found type `Fn<(&' X,)>` + +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `FnOnce<(&X,)>` + found type `FnOnce<(&' X,)>` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr index bf2d612fcdb41..905248fb33755 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr @@ -15,7 +15,6 @@ LL | type Item = impl Bug; | = help: the following implementations were found: <&() as Bug> - = note: the return type of a function must have a statically known size error: could not find defining uses --> $DIR/issue-60371.rs:8:17 diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.stderr index 9ad181b3684c6..8615b3f741bf5 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr @@ -6,7 +6,6 @@ LL | type Closure = impl FnOnce(); | = note: expected opaque type `impl FnOnce<()>` found unit type `()` - = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs index 209134acf01f9..80192d19af98b 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs @@ -70,14 +70,14 @@ fn my_other_iter(u: U) -> MyOtherIter { } trait Trait {} -type GenericBound<'a, T: Trait> = impl Sized + 'a; +type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a; fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> { t } mod pass_through { - pub type Passthrough = impl Sized + 'static; + pub type Passthrough = impl Sized + 'static; fn define_passthrough(t: T) -> Passthrough { t diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index 9e710c15fdbce..a2bf963044582 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -5,6 +5,7 @@ LL | >::add(1, 2); | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` | = help: the trait `Add` is not implemented for `i32` + = note: required by `add` error[E0308]: mismatched types --> $DIR/ufcs-qpath-self-mismatch.rs:6:28 diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index 2ab257ca88e3b..d2a322e1223c6 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -3,6 +3,7 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl, HirId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{Opaque, PredicateAtom::Trait}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{sym, Span}; @@ -62,9 +63,10 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { } let ret_ty = utils::return_ty(cx, hir_id); if let Opaque(id, subst) = *ret_ty.kind() { - let preds = cx.tcx.predicates_of(id).instantiate(cx.tcx, subst); + let preds = cx.tcx.explicit_item_bounds(id); let mut is_future = false; - for p in preds.predicates { + for &(p, _span) in preds { + let p = p.subst(cx.tcx, subst); if let Some(trait_ref) = p.to_opt_poly_trait_ref() { if Some(trait_ref.def_id()) == cx.tcx.lang_items().future_trait() { is_future = true; @@ -90,8 +92,13 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { |db| { cx.tcx.infer_ctxt().enter(|infcx| { for FulfillmentError { obligation, .. } in send_errors { - infcx.maybe_note_obligation_cause_for_async_await(db, &obligation); - if let Trait(trait_pred, _) = obligation.predicate.skip_binders() { + infcx.maybe_note_obligation_cause_for_async_await( + db, + &obligation, + ); + if let Trait(trait_pred, _) = + obligation.predicate.skip_binders() + { db.note(&format!( "`{}` doesn't implement `{}`", trait_pred.self_ty(), diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index dadd0f8ebb7c8..e0651f9ab5d6c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -1667,8 +1667,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods { // if return type is impl trait, check the associated types if let ty::Opaque(def_id, _) = *ret_ty.kind() { // one of the associated types must be Self - for &(predicate, _span) in cx.tcx.predicates_of(def_id).predicates { - if let ty::PredicateAtom::Projection(projection_predicate) = predicate.skip_binders() { + for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) { + if let ty::PredicateAtom::Projection(projection_predicate) = + predicate.skip_binders() + { // walk the associated type and check for Self if contains_ty(projection_predicate.ty, self_ty) { return; diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs index 96d9905027b62..247effde19b9c 100644 --- a/src/tools/clippy/clippy_lints/src/utils/mod.rs +++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs @@ -1285,9 +1285,10 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { }, ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)), ty::Opaque(ref def_id, _) => { - for (predicate, _) in cx.tcx.predicates_of(*def_id).predicates { + for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { if let ty::PredicateAtom::Trait(trait_predicate, _) = predicate.skip_binders() { - if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() { + if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() + { return true; } }