diff --git a/src/librustc_infer/infer/outlives/verify.rs b/src/librustc_infer/infer/outlives/verify.rs index 82d32b008088d..383979f864075 100644 --- a/src/librustc_infer/infer/outlives/verify.rs +++ b/src/librustc_infer/infer/outlives/verify.rs @@ -1,9 +1,8 @@ use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::{GenericKind, VerifyBound}; -use crate::traits; use rustc_data_structures::captures::Captures; use rustc_hir::def_id::DefId; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst}; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst}; use rustc_middle::ty::{self, Ty, TyCtxt}; /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a` @@ -311,18 +310,14 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { fn region_bounds_declared_on_associated_item( &self, assoc_item_def_id: DefId, - ) -> impl Iterator> + 'cx + Captures<'tcx> { + ) -> impl Iterator> { let tcx = self.tcx; - let assoc_item = tcx.associated_item(assoc_item_def_id); - let trait_def_id = assoc_item.container.assert_trait(); - let trait_predicates = tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p); - let identity_substs = InternalSubsts::identity_for_item(tcx, assoc_item_def_id); - let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs); - self.collect_outlives_from_predicate_list( - move |ty| ty == identity_proj, - traits::elaborate_predicates(tcx, trait_predicates).map(|o| o.predicate), - ) - .map(|b| b.1) + let predicates = tcx.projection_predicates(assoc_item_def_id); + predicates + .into_iter() + .filter_map(|p| p.to_opt_type_outlives()) + .filter_map(|p| p.no_bound_vars()) + .map(|b| b.1) } /// Searches through a predicate list for a predicate `T: 'a`. diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs index a15ac819be966..43b6d8da03a79 100644 --- a/src/librustc_infer/traits/mod.rs +++ b/src/librustc_infer/traits/mod.rs @@ -25,8 +25,6 @@ pub use self::project::{ Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey, ProjectionCacheStorage, Reveal, }; -crate use self::util::elaborate_predicates; - pub use rustc_middle::traits::*; /// An `Obligation` represents some trait reference (e.g., `int: Eq`) for diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs index 3b6d54a1bc1ee..5b03046ad9e82 100644 --- a/src/librustc_middle/query/mod.rs +++ b/src/librustc_middle/query/mod.rs @@ -133,6 +133,23 @@ rustc_queries! { cache_on_disk_if { key.is_local() } } + /// Returns the list of predicates 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 + /// + /// type X: Bound + 'lt + /// ^^^^^^^^^^^ + /// impl Debug + Display + /// ^^^^^^^^^^^^^^^ + /// + /// `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) } + } + query native_libraries(_: CrateNum) -> Lrc> { desc { "looking up the native libraries of a linked crate" } } diff --git a/src/librustc_middle/ty/flags.rs b/src/librustc_middle/ty/flags.rs index edcb69c5e8cbd..994e824398c74 100644 --- a/src/librustc_middle/ty/flags.rs +++ b/src/librustc_middle/ty/flags.rs @@ -93,7 +93,6 @@ impl FlagComputation { &ty::Bound(debruijn, _) => { self.add_binder(debruijn); - self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } &ty::Placeholder(..) => { @@ -216,7 +215,6 @@ impl FlagComputation { } ty::ConstKind::Bound(debruijn, _) => { self.add_binder(debruijn); - self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } ty::ConstKind::Param(_) => { self.add_flags(TypeFlags::HAS_CT_PARAM); diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index fad96aa86cc0a..1d8858a2708d9 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -1583,19 +1583,16 @@ impl RegionKind { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_INFER; - flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE; } ty::RePlaceholder(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; - flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE; } ty::ReEarlyBound(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PARAM; - flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE; } ty::ReFree { .. } => { flags = flags | TypeFlags::HAS_FREE_REGIONS; diff --git a/src/librustc_middle/ty/subst.rs b/src/librustc_middle/ty/subst.rs index 1529f1173b391..0cbbb95fd6fef 100644 --- a/src/librustc_middle/ty/subst.rs +++ b/src/librustc_middle/ty/subst.rs @@ -333,6 +333,17 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { /// in a different item, with `target_substs` as the base for /// the target impl/trait, with the source child-specific /// parameters (e.g., method parameters) on top of that base. + /// + /// For example given: + /// + /// trait X { fn f(); } + /// impl X for U { fn f() {} } + /// + /// * If `self` is `[Self, S, T]`: the identity substs of `f` in the trait. + /// * If `source_ancestor` is the def_id of the trait. + /// * If `target_substs` is `[U]`, the substs for the impl. + /// * Then we will return `[U, T]`, the subst for `f` in the impl that + /// are needed for it to match the trait. pub fn rebase_onto( &self, tcx: TyCtxt<'tcx>, diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 5bbf8703f0b60..903eee672cf1f 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -883,7 +883,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }) .collect(); if !lifetimes.is_empty() { - self.trait_ref_hack = true; let next_early_index = self.next_early_index(); let scope = Scope::Binder { lifetimes, @@ -895,9 +894,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let result = self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &bound_generic_params); this.visit_ty(&bounded_ty); + this.trait_ref_hack = true; walk_list!(this, visit_param_bound, bounds); + this.trait_ref_hack = false; }); - self.trait_ref_hack = false; result } else { self.visit_ty(&bounded_ty); @@ -932,13 +932,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref); let should_pop_missing_lt = self.is_trait_ref_fn_scope(trait_ref); - if !self.trait_ref_hack + + let trait_ref_hack = take(&mut self.trait_ref_hack); + if !trait_ref_hack || trait_ref.bound_generic_params.iter().any(|param| match param.kind { GenericParamKind::Lifetime { .. } => true, _ => false, }) { - if self.trait_ref_hack { + if trait_ref_hack { struct_span_err!( self.tcx.sess, trait_ref.span, @@ -968,10 +970,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); this.visit_trait_ref(&trait_ref.trait_ref); - }) + }); } else { self.visit_trait_ref(&trait_ref.trait_ref); } + self.trait_ref_hack = trait_ref_hack; if should_pop_missing_lt { self.missing_named_lifetime_spots.pop(); } diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 9492c3c340995..a8173a1597098 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -895,9 +895,12 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( let tcx = selcx.tcx(); // Check whether the self-type is itself a projection. - let (def_id, substs) = match obligation_trait_ref.self_ty().kind { - ty::Projection(ref data) => (data.trait_ref(tcx).def_id, data.substs), - ty::Opaque(def_id, substs) => (def_id, substs), + // 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::Infer(ty::TyVar(_)) => { // If the self-type is an inference variable, then it MAY wind up // being a projected type, so induce an ambiguity. @@ -907,17 +910,13 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( _ => return, }; - // If so, extract what we know from the trait and try to come up with a good answer. - let trait_predicates = tcx.predicates_of(def_id); - let bounds = trait_predicates.instantiate(tcx, substs); - let bounds = elaborate_predicates(tcx, bounds.predicates.into_iter()).map(|o| o.predicate); assemble_candidates_from_predicates( selcx, obligation, obligation_trait_ref, candidate_set, ProjectionTyCandidate::TraitDef, - bounds, + bounds.iter(), ) } @@ -1474,6 +1473,12 @@ fn confirm_impl_candidate<'cx, 'tcx>( ); return Progress { ty: tcx.types.err, obligations: nested }; } + // If we're trying to normalize ` as X>::A` using + //`impl X for Vec { type A = Box; }`, then: + // + // * `obligation.predicate.substs` is `[Vec, S]` + // * `substs` is `[u32]` + // * `substs` ends up as `[u32, S]` let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs); let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node); diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs index 7ebf30f61c095..87d8408429c8e 100644 --- a/src/librustc_trait_selection/traits/select/mod.rs +++ b/src/librustc_trait_selection/traits/select/mod.rs @@ -1273,9 +1273,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { placeholder_trait_predicate, ); - let (def_id, substs) = match placeholder_trait_predicate.trait_ref.self_ty().kind { - ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs), - ty::Opaque(def_id, substs) => (def_id, substs), + 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), _ => { span_bug!( obligation.cause.span, @@ -1285,32 +1288,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); } }; - debug!( - "match_projection_obligation_against_definition_bounds: \ - def_id={:?}, substs={:?}", - def_id, substs - ); - let predicates_of = self.tcx().predicates_of(def_id); - let bounds = predicates_of.instantiate(self.tcx(), substs); - debug!( - "match_projection_obligation_against_definition_bounds: \ - bounds={:?}", - bounds - ); - - let elaborated_predicates = - util::elaborate_predicates(self.tcx(), bounds.predicates.into_iter()); - let matching_bound = elaborated_predicates.filter_to_traits().find(|bound| { - self.infcx.probe(|_| { - self.match_projection( - obligation, - *bound, - placeholder_trait_predicate.trait_ref, - &placeholder_map, - snapshot, - ) - }) + let matching_bound = predicates.iter().find_map(|bound| { + if let ty::PredicateKind::Trait(bound, _) = bound.kind() { + let bound = bound.to_poly_trait_ref(); + if self.infcx.probe(|_| { + self.match_projection( + obligation, + bound, + placeholder_trait_predicate.trait_ref, + &placeholder_map, + snapshot, + ) + }) { + return Some(bound); + } + } + None }); debug!( diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index 99094246a6378..be5004d136f54 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -1,8 +1,10 @@ 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::Subst; +use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_session::CrateDisambiguator; use rustc_span::symbol::Symbol; @@ -365,6 +367,132 @@ 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.kind() { + ty::PredicateKind::Trait(tr, _) => { + if let ty::Projection(p) = tr.skip_binder().self_ty().kind { + if p == assoc_item_ty { + return Some(pred); + } + } + } + ty::PredicateKind::Projection(proj) => { + if let ty::Projection(p) = proj.skip_binder().projection_ty.self_ty().kind { + if p == assoc_item_ty { + return Some(pred); + } + } + } + ty::PredicateKind::TypeOutlives(outlives) => { + if let ty::Projection(p) = outlives.skip_binder().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, but we use a +/// similar filtering for consistency. +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.into_iter().map(|&(pred, _)| pred)); + + let filtered_predicates = predicates.filter_map(|obligation| { + let pred = obligation.predicate; + match pred.kind() { + ty::PredicateKind::Trait(tr, _) => { + if let ty::Opaque(opaque_def_id, opaque_substs) = tr.skip_binder().self_ty().kind { + if opaque_def_id == def_id && opaque_substs == substs { + return Some(pred); + } + } + } + ty::PredicateKind::Projection(proj) => { + if let ty::Opaque(opaque_def_id, opaque_substs) = + proj.skip_binder().projection_ty.self_ty().kind + { + if opaque_def_id == def_id && opaque_substs == substs { + return Some(pred); + } + } + } + ty::PredicateKind::TypeOutlives(outlives) => { + if let ty::Opaque(opaque_def_id, opaque_substs) = outlives.skip_binder().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::PredicateKind::RegionOutlives(_) => return None, + _ => {} + } + // Other predicates are currently only possible for type alias impl + // trait. After #72080 is merged this can be a (delayed?) bug. + 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 | DefKind::AssocOpaqueTy => { + 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, @@ -381,6 +509,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { instance_def_size_estimate, issue33140_self_ty, impl_defaultness, + projection_predicates, ..*providers }; } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index b39cfcb377595..1ee2d669154ee 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -4,15 +4,17 @@ 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_middle::ty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::subst::{InternalSubsts, Subst}; +use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::util::ExplicitSelf; -use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt}; +use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt, WithConstness}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use super::{potentially_plural_count, FnCtxt, Inherited}; +use std::iter; /// Checks that a method from an impl conforms to the signature of /// the same method as declared in the trait. @@ -1057,13 +1059,15 @@ crate fn compare_ty_impl<'tcx>( let _: Result<(), ErrorReported> = (|| { compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?; - compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref) + 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) })(); } /// The equivalent of [compare_predicate_entailment], but for associated types /// instead of associated functions. -fn compare_type_predicate_entailment( +fn compare_type_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, impl_ty: &ty::AssocItem, impl_ty_span: Span, @@ -1165,6 +1169,145 @@ fn compare_type_predicate_entailment( }) } +/// Validate that `ProjectionCandidate`s created for this associated type will +/// be valid. +/// +/// Usually given +/// +/// trait X { type Y: Copy } impl X for T { type Y = S; } +/// +/// We are able to normalize `::U` to `S`, and so when we check the +/// impl is well-formed we have to prove `S: Copy`. +/// +/// 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>( + 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(()); + } + + let param_env = tcx.param_env(impl_ty.def_id); + + // Given + // + // impl Foo for (A, B) { + // type Bar =... + // } + // + // - `impl_substs` would be `[A, B, C]` + // - `rebased_substs` would be `[(A, B), u32, C]`, combining the substs from + // the *trait* with the generic associated type parameters. + let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id); + let rebased_substs = + impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs); + let impl_ty_value = tcx.type_of(impl_ty.def_id); + + // Map the predicate from the trait to the corresponding one for the impl. + // For example: + // + // trait X { type Y<'a>: PartialEq } impl X for T { type Y<'a> = &'a S; } + // impl<'x> X<&'x u32> for () { type Y<'c> = &'c u32; } + // + // For the `for<'a> <>::Y<'a>: PartialEq` bound, this + // function would translate and partially normalize + // `[>::Y<'a>, A]` to `[&'a u32, &'x u32]`. + let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| { + tcx.mk_substs( + iter::once(impl_ty_value.into()) + .chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, rebased_substs))), + ) + }; + + tcx.infer_ctxt().enter(move |infcx| { + let inh = Inherited::new(infcx, impl_ty.def_id.expect_local()); + let infcx = &inh.infcx; + let mut selcx = traits::SelectionContext::new(&infcx); + + let impl_ty_hir_id = tcx.hir().as_local_hir_id(impl_ty.def_id.expect_local()); + let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id); + let cause = ObligationCause { + span: impl_ty_span, + body_id: impl_ty_hir_id, + code: ObligationCauseCode::ItemObligation(trait_ty.def_id), + }; + + let predicates = tcx.projection_predicates(trait_ty.def_id); + + debug!("compare_projection_bounds: projection_predicates={:?}", predicates); + + for predicate in predicates { + let concrete_ty_predicate = match predicate.kind() { + ty::PredicateKind::Trait(poly_tr, c) => poly_tr + .map_bound(|tr| { + let trait_substs = translate_predicate_substs(tr.trait_ref.substs); + ty::TraitRef { def_id: tr.def_id(), substs: trait_substs } + }) + .with_constness(*c) + .to_predicate(tcx), + ty::PredicateKind::Projection(poly_projection) => poly_projection + .map_bound(|projection| { + let projection_substs = + translate_predicate_substs(projection.projection_ty.substs); + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + substs: projection_substs, + item_def_id: projection.projection_ty.item_def_id, + }, + ty: projection.ty.subst(tcx, rebased_substs), + } + }) + .to_predicate(tcx), + ty::PredicateKind::TypeOutlives(poly_outlives) => poly_outlives + .map_bound(|outlives| { + ty::OutlivesPredicate(impl_ty_value, outlives.1.subst(tcx, rebased_substs)) + }) + .to_predicate(tcx), + _ => bug!("unexepected projection predicate kind: `{:?}`", predicate), + }; + + let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize( + &mut selcx, + param_env, + normalize_cause.clone(), + &concrete_ty_predicate, + ); + + debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate); + + inh.register_predicates(obligations); + inh.register_predicate(traits::Obligation::new( + cause.clone(), + param_env, + normalized_predicate, + )); + } + + // 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); + return Err(ErrorReported); + } + + // 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, &[]); + + Ok(()) + }) +} + fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str { match impl_item.kind { ty::AssocKind::Const => "const", diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c26acd7a47703..a48dc58aac6e5 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2123,7 +2123,7 @@ fn check_impl_items_against_trait<'tcx>( &ty_trait_item, impl_trait_ref, opt_trait_span, - ) + ); } else { let mut err = struct_span_err!( tcx.sess, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1d59d749634ee..7061396bae98f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -35,7 +35,7 @@ use rustc_middle::hir::map::Map; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::mono::Linkage; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::subst::{InternalSubsts, Subst}; +use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::Discr; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt}; @@ -1693,6 +1693,7 @@ 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(); @@ -1702,7 +1703,12 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat let mut predicates = UniquePredicates::new(); let ast_generics = match node { - Node::TraitItem(item) => &item.generics, + Node::TraitItem(item) => { + if let hir::TraitItemKind::Type(bounds, _) = item.kind { + is_trait_associated_type = Some((bounds, item.span)); + } + &item.generics + } Node::ImplItem(item) => &item.generics, @@ -1926,10 +1932,21 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat } } - // Add predicates from associated type bounds. - if let Some((self_trait_ref, trait_items)) = is_trait { + // 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_predicates(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| { - associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref) + trait_associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref) })) } @@ -1959,7 +1976,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat result } -fn associated_item_predicates( +fn trait_associated_item_predicates( tcx: TyCtxt<'tcx>, def_id: DefId, self_trait_ref: ty::TraitRef<'tcx>, @@ -1972,93 +1989,40 @@ fn associated_item_predicates( _ => return Vec::new(), }; - let is_gat = !tcx.generics_of(item_def_id).params.is_empty(); - - let mut had_error = false; - - let mut unimplemented_error = |arg_kind: &str| { - if !had_error { - tcx.sess - .struct_span_err( - trait_item.span, - &format!("{}-generic associated types are not yet implemented", arg_kind), - ) - .note( - "for more information, see issue #44265 \ - for more information", - ) - .emit(); - had_error = true; - } - }; - - let mk_bound_param = |param: &ty::GenericParamDef, _: &_| { - match param.kind { - ty::GenericParamDefKind::Lifetime => tcx - .mk_region(ty::RegionKind::ReLateBound( - ty::INNERMOST, - ty::BoundRegion::BrNamed(param.def_id, param.name), - )) - .into(), - // FIXME(generic_associated_types): Use bound types and constants - // once they are handled by the trait system. - ty::GenericParamDefKind::Type { .. } => { - unimplemented_error("type"); - tcx.types.err.into() - } - ty::GenericParamDefKind::Const => { - unimplemented_error("const"); - tcx.mk_const(ty::Const { val: ty::ConstKind::Error, ty: tcx.type_of(param.def_id) }) - .into() - } - } - }; + 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 bound_substs = if is_gat { - // Given: - // - // trait X<'a, B, const C: usize> { - // type T<'d, E, const F: usize>: Default; - // } - // - // We need to create predicates on the trait: - // - // for<'d, E, const F: usize> - // >::T<'d, E, const F: usize>: Sized + Default - // - // We substitute escaping bound parameters for the generic - // arguments to the associated type which are then bound by - // the `Binder` around the the predicate. - // - // FIXME(generic_associated_types): Currently only lifetimes are handled. - self_trait_ref.substs.extend_to(tcx, item_def_id.to_def_id(), mk_bound_param) - } else { - self_trait_ref.substs - }; + let assoc_ty = tcx.mk_projection( + tcx.hir().local_def_id(trait_item.hir_id).to_def_id(), + self_trait_ref.substs, + ); - let assoc_ty = - tcx.mk_projection(tcx.hir().local_def_id(trait_item.hir_id).to_def_id(), bound_substs); + associated_item_predicates(tcx, def_id, bounds, assoc_ty, trait_item.span) +} +fn associated_item_predicates( + 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), - assoc_ty, + projection_ty, bounds, SizedByDefault::Yes, - trait_item.span, + span, ); - let predicates = bounds.predicates(tcx, assoc_ty); + let predicates = bounds.predicates(tcx, projection_ty); - if is_gat { - // We use shifts to get the regions that we're substituting to - // be bound by the binders in the `Predicate`s rather that - // escaping. - let shifted_in = ty::fold::shift_vars(tcx, &predicates, 1); - let substituted = shifted_in.subst(tcx, bound_substs); - ty::fold::shift_out_vars(tcx, &substituted, 1) - } else { - predicates - } + predicates } /// Converts a specific `GenericBound` from the AST into a set of diff --git a/src/test/ui/associated-types/hr-associated-type-bound-1.rs b/src/test/ui/associated-types/hr-associated-type-bound-1.rs new file mode 100644 index 0000000000000..497b86eeab88d --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-1.rs @@ -0,0 +1,18 @@ +trait X<'a> +where + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(&self, x: &Self::U) { + ::clone(x); + } +} + +impl X<'_> for i32 { + type U = str; + //~^ ERROR the trait bound `for<'b> >::U: std::clone::Clone` +} + +fn main() { + 1i32.f("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-1.stderr b/src/test/ui/associated-types/hr-associated-type-bound-1.stderr new file mode 100644 index 0000000000000..7ef2faef9c6e7 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-1.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `for<'b> >::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-1.rs:12:14 + | +LL | trait X<'a> + | - required by a bound in this +LL | where +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-2.rs b/src/test/ui/associated-types/hr-associated-type-bound-2.rs new file mode 100644 index 0000000000000..7ff0fede28cfe --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-2.rs @@ -0,0 +1,21 @@ +trait X<'a> +where + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(&self, x: &Self::U) { + ::clone(x); + } +} + +impl X<'_> for u32 +where + for<'b> >::U: Clone, +{ + type U = str; +} + +fn main() { + 1u32.f("abc"); + //~^ ERROR no method named `f` found for type `u32` in the current scope +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr new file mode 100644 index 0000000000000..2a364d349d77e --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr @@ -0,0 +1,13 @@ +error[E0599]: no method named `f` found for type `u32` in the current scope + --> $DIR/hr-associated-type-bound-2.rs:19:10 + | +LL | 1u32.f("abc"); + | ^ method not found in `u32` + | + = note: the method `f` exists but the following trait bounds were not satisfied: + `>::U: std::clone::Clone` + which is required by `u32: X` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-object.rs b/src/test/ui/associated-types/hr-associated-type-bound-object.rs new file mode 100644 index 0000000000000..7c64ae38caf60 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-object.rs @@ -0,0 +1,14 @@ +trait X<'a> +where + for<'b> >::U: Clone, +{ + type U: ?Sized; +} +fn f<'a, T: X<'a> + ?Sized>(x: &>::U) { + //~^ ERROR the trait bound `for<'b> >::U: std::clone::Clone` is not satisfied + <>::U>::clone(x); +} + +pub fn main() { + f::>("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-object.stderr b/src/test/ui/associated-types/hr-associated-type-bound-object.stderr new file mode 100644 index 0000000000000..db966875c708f --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-object.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `for<'b> >::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-object.rs:7:13 + | +LL | trait X<'a> + | - required by a bound in this +LL | where +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | fn f<'a, T: X<'a> + ?Sized>(x: &>::U) { + | ^^^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-1.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-1.rs new file mode 100644 index 0000000000000..a65f8a8c498b7 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-1.rs @@ -0,0 +1,20 @@ +trait Y<'a, T: ?Sized> +where + T: Y<'a, Self>, + for<'b> >::V: Clone, + for<'b> >::V: Clone, +{ + type V: ?Sized; + fn g(&self, x: &Self::V) { + ::clone(x); + } +} + +impl<'a> Y<'a, u8> for u8 { + type V = str; + //~^ ERROR the trait bound `for<'b> >::V: std::clone::Clone` is not satisfied +} + +fn main() { + 1u8.g("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr new file mode 100644 index 0000000000000..347a5818dce31 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `for<'b> >::V: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-1.rs:14:14 + | +LL | trait Y<'a, T: ?Sized> + | - required by a bound in this +... +LL | for<'b> >::V: Clone, + | ----- required by this bound in `Y` +... +LL | type V = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::V` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs new file mode 100644 index 0000000000000..9f849b0327669 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs @@ -0,0 +1,21 @@ +trait Z<'a, T: ?Sized> +where + T: Z<'a, u16>, + //~^ the trait bound `for<'b> >::W: std::clone::Clone` is not satisfied + //~| the trait bound `for<'b> >::W: std::clone::Clone` is not satisfied + for<'b> >::W: Clone, +{ + type W: ?Sized; + fn h(&self, x: &T::W) { + ::clone(x); + } +} + +impl<'a> Z<'a, u16> for u16 { + type W = str; + //~^ ERROR the trait bound `for<'b> >::W: std::clone::Clone +} + +fn main() { + 1u16.h("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr new file mode 100644 index 0000000000000..e06777e36a8c5 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr @@ -0,0 +1,51 @@ +error[E0277]: the trait bound `for<'b> >::W: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-2.rs:3:8 + | +LL | trait Z<'a, T: ?Sized> + | - required by a bound in this +LL | where +LL | T: Z<'a, u16>, + | ^^^^^^^^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::W` +... +LL | for<'b> >::W: Clone, + | ----- required by this bound in `Z` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error[E0277]: the trait bound `for<'b> >::W: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-2.rs:15:14 + | +LL | trait Z<'a, T: ?Sized> + | - required by a bound in this +... +LL | for<'b> >::W: Clone, + | ----- required by this bound in `Z` +... +LL | type W = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::W` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error[E0277]: the trait bound `for<'b> >::W: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-2.rs:3:8 + | +LL | trait Z<'a, T: ?Sized> + | - required by a bound in this +LL | where +LL | T: Z<'a, u16>, + | ^^^^^^^^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::W` +... +LL | for<'b> >::W: Clone, + | ----- required by this bound in `Z` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-3.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-3.rs new file mode 100644 index 0000000000000..9aca59f8ce6d7 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-3.rs @@ -0,0 +1,21 @@ +// ignore-tidy-linelength + +trait X<'a, T> +where + for<'b> T: X<'b, T>, + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(x: &>::U) { + <>::U>::clone(x); + } +} + +impl X<'_, (T,)> for (S,) { + type U = str; + //~^ ERROR the trait bound `for<'b> <(T,) as X<'b, (T,)>>::U: std::clone::Clone` is not satisfied +} + +pub fn main() { + <(i32,) as X<(i32,)>>::f("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr new file mode 100644 index 0000000000000..ff56f60e4c9e5 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `for<'b> <(T,) as X<'b, (T,)>>::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-3.rs:15:14 + | +LL | trait X<'a, T> + | - required by a bound in this +... +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<(T,) as X<'b, (T,)>>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-4.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-4.rs new file mode 100644 index 0000000000000..ffe43c674c3dc --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-4.rs @@ -0,0 +1,19 @@ +trait X<'a, T> +where + for<'b> (T,): X<'b, T>, + for<'b> <(T,) as X<'b, T>>::U: Clone, +{ + type U: ?Sized; + fn f(x: &<(T,) as X<'_, T>>::U) { + <<(T,) as X<'_, T>>::U>::clone(x); + } +} + +impl X<'_, T> for (S,) { + type U = str; + //~^ ERROR the trait bound `for<'b> <(T,) as X<'b, T>>::U: std::clone::Clone` is not satisfied +} + +pub fn main() { + <(i32,) as X>::f("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr new file mode 100644 index 0000000000000..c41efb8b6e1a2 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `for<'b> <(T,) as X<'b, T>>::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-4.rs:13:14 + | +LL | trait X<'a, T> + | - required by a bound in this +... +LL | for<'b> <(T,) as X<'b, T>>::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<(T,) as X<'b, T>>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs new file mode 100644 index 0000000000000..dcca0b3ce92aa --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs @@ -0,0 +1,41 @@ +// ignore-tidy-linelength + +trait Cycle: Sized { + type Next: Cycle; +} + +impl Cycle for Box { + type Next = Vec; +} + +impl Cycle for Vec { + type Next = Box; +} + +trait X<'a, T: Cycle + for<'b> X<'b, T>> +where + for<'b> >::U: Clone, + for<'b> T::Next: X<'b, T::Next>, + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(x: &>::U) { + <>::U>::clone(x); + } +} + +impl X<'_, Vec> for S { + type U = str; + //~^ ERROR the trait bound `for<'b> as X<'b, std::boxed::Box>>::U: std::clone::Clone` is not satisfied + //~| ERROR the trait bound `for<'b> as X<'b, std::vec::Vec>>::U: std::clone::Clone` is not satisfied +} + +impl X<'_, Box> for S { + type U = str; + //~^ ERROR the trait bound `for<'b> as X<'b, std::boxed::Box>>::U: std::clone::Clone` is not satisfied + //~| ERROR the trait bound `for<'b> as X<'b, std::vec::Vec>>::U: std::clone::Clone` is not satisfied +} + +pub fn main() { + >>::f("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr new file mode 100644 index 0000000000000..39c191e974777 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr @@ -0,0 +1,67 @@ +error[E0277]: the trait bound `for<'b> as X<'b, std::boxed::Box>>::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-5.rs:28:14 + | +LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> + | - required by a bound in this +... +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for ` as X<'b, std::boxed::Box>>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error[E0277]: the trait bound `for<'b> as X<'b, std::vec::Vec>>::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-5.rs:28:14 + | +LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> + | - required by a bound in this +LL | where +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for ` as X<'b, std::vec::Vec>>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error[E0277]: the trait bound `for<'b> as X<'b, std::vec::Vec>>::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-5.rs:34:14 + | +LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> + | - required by a bound in this +... +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for ` as X<'b, std::vec::Vec>>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error[E0277]: the trait bound `for<'b> as X<'b, std::boxed::Box>>::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-5.rs:34:14 + | +LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> + | - required by a bound in this +LL | where +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for ` as X<'b, std::boxed::Box>>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +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/hr-associated-type-bound-param-6.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-6.rs new file mode 100644 index 0000000000000..4b8018cb43024 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-6.rs @@ -0,0 +1,20 @@ +trait X<'a, T> +where + for<'b> T: X<'b, T>, + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(x: &>::U) { + <>::U>::clone(x); + } +} + +impl X<'_, T> for (S,) { + //~^ ERROR the trait bound `for<'b> T: X<'b, T>` is not satisfied + type U = str; + //~^ ERROR the trait bound `for<'b> >::U: std::clone::Clone` is not satisfied +} + +pub fn main() { + <(i32,) as X>::f("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-6.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-6.stderr new file mode 100644 index 0000000000000..83845d3a9410e --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-6.stderr @@ -0,0 +1,36 @@ +error[E0277]: the trait bound `for<'b> >::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-6.rs:14:14 + | +LL | trait X<'a, T> + | - required by a bound in this +... +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error[E0277]: the trait bound `for<'b> T: X<'b, T>` is not satisfied + --> $DIR/hr-associated-type-bound-param-6.rs:12:12 + | +LL | trait X<'a, T> + | - required by a bound in this +LL | where +LL | for<'b> T: X<'b, T>, + | -------- required by this bound in `X` +... +LL | impl X<'_, T> for (S,) { + | ^^^^^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | impl X<'b, T>> X<'_, T> for (S,) { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-projection-1.rs b/src/test/ui/associated-types/hr-associated-type-projection-1.rs new file mode 100644 index 0000000000000..0d4567a55fc99 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-projection-1.rs @@ -0,0 +1,21 @@ +trait UnsafeCopy<'a, T: Copy> +where + for<'b> >::Item: std::ops::Deref, +{ + type Item; + + fn bug(item: &Self::Item) -> () { + let x: T = **item; + &x as *const _; + } +} + +impl UnsafeCopy<'_, T> for T { + //~^ ERROR the trait bound `>::Item: std::ops::Deref` is not satisfied + type Item = T; + //~^ ERROR the trait bound `for<'b> >::Item: std::ops::Deref +} + +pub fn main() { + <&'static str>::bug(&""); +} diff --git a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr new file mode 100644 index 0000000000000..5ab57410c441b --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr @@ -0,0 +1,30 @@ +error[E0277]: the trait bound `for<'b> >::Item: std::ops::Deref` is not satisfied + --> $DIR/hr-associated-type-projection-1.rs:15:17 + | +LL | trait UnsafeCopy<'a, T: Copy> + | ---------- required by a bound in this +LL | where +LL | for<'b> >::Item: std::ops::Deref, + | --------------------------- required by this bound in `UnsafeCopy` +... +LL | type Item = T; + | ^ the trait `for<'b> std::ops::Deref` is not implemented for `>::Item` + | + = help: the following implementations were found: + <&T as std::ops::Deref> + <&mut T as std::ops::Deref> + +error[E0277]: the trait bound `>::Item: std::ops::Deref` is not satisfied + --> $DIR/hr-associated-type-projection-1.rs:13:33 + | +LL | impl UnsafeCopy<'_, T> for T { + | ^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `>::Item` + | +help: consider further restricting the associated type + | +LL | impl UnsafeCopy<'_, T> for T where >::Item: std::ops::Deref { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this 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 7ff348aca7cc1..17548d7b9e88c 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 @@ -3,11 +3,9 @@ use std::ops::Deref; trait PointerFamily { type Pointer: Deref; //~^ ERROR generic associated types are unstable - //~| ERROR type-generic associated types are not yet implemented type Pointer2: Deref where T: Clone, U: Clone; //~^ ERROR generic associated types are unstable //~| ERROR where clauses on associated types are unstable - //~| ERROR type-generic associated types are not yet implemented } struct Foo; 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 a0e06cb2b6795..8499b1ab70f5d 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 @@ -8,7 +8,7 @@ LL | type Pointer: Deref; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: generic associated types are unstable - --> $DIR/feature-gate-generic_associated_types.rs:7:5 + --> $DIR/feature-gate-generic_associated_types.rs:6:5 | LL | type Pointer2: Deref where T: Clone, U: Clone; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | type Pointer2: Deref where T: Clone, U: Clone; = 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:7:5 + --> $DIR/feature-gate-generic_associated_types.rs:6:5 | LL | type Pointer2: Deref where T: Clone, U: Clone; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | type Pointer2: Deref where T: Clone, U: Clone; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: generic associated types are unstable - --> $DIR/feature-gate-generic_associated_types.rs:16:5 + --> $DIR/feature-gate-generic_associated_types.rs:14:5 | LL | type Pointer = Box; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | type Pointer = Box; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: generic associated types are unstable - --> $DIR/feature-gate-generic_associated_types.rs:18:5 + --> $DIR/feature-gate-generic_associated_types.rs:16:5 | LL | type Pointer2 = Box; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -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:23:5 + --> $DIR/feature-gate-generic_associated_types.rs:21: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:28:5 + --> $DIR/feature-gate-generic_associated_types.rs:26:5 | LL | type Assoc where Self: Sized = Foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,22 +61,6 @@ 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: type-generic associated types are not yet implemented - --> $DIR/feature-gate-generic_associated_types.rs:4:5 - | -LL | type Pointer: Deref; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/feature-gate-generic_associated_types.rs:7:5 - | -LL | type Pointer2: Deref where T: Clone, U: Clone; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generic-associated-types/collections-project-default.rs b/src/test/ui/generic-associated-types/collections-project-default.rs new file mode 100644 index 0000000000000..5fbae02573c62 --- /dev/null +++ b/src/test/ui/generic-associated-types/collections-project-default.rs @@ -0,0 +1,72 @@ +#![allow(incomplete_features)] +#![feature(generic_associated_types)] +#![feature(associated_type_defaults)] + +// A Collection trait and collection families. Based on +// http://smallcultfollowing.com/babysteps/blog/2016/11/03/ +// associated-type-constructors-part-2-family-traits/ + +// check that we don't normalize with trait defaults. + +trait Collection { + type Iter<'iter>: Iterator where T: 'iter; + type Family: CollectionFamily; + // Test associated type defaults with parameters + type Sibling: Collection = + <>::Family as CollectionFamily>::Member; + + fn empty() -> Self; + + fn add(&mut self, value: T); + + fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; +} + +trait CollectionFamily { + type Member: Collection; +} + +struct VecFamily; + +impl CollectionFamily for VecFamily { + type Member = Vec; +} + +impl Collection for Vec { + type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>; + type Family = VecFamily; + + fn empty() -> Self { + Vec::new() + } + + fn add(&mut self, value: T) { + self.push(value) + } + + fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> { + self.iter() + } +} + +fn floatify_sibling(ints: &C) -> >::Sibling +where + C: Collection, +{ + let mut res = ::Member::::empty(); + for &v in ints.iterate() { + res.add(v as f32); + } + res + //~^ ERROR mismatched types +} + +fn use_floatify() { + let a = vec![1i32, 2, 3]; + let c = floatify_sibling(&a); + assert_eq!(Some(&1.0), c.iterate().next()); +} + +fn main() { + use_floatify(); +} diff --git a/src/test/ui/generic-associated-types/collections-project-default.stderr b/src/test/ui/generic-associated-types/collections-project-default.stderr new file mode 100644 index 0000000000000..ca02b2603ba64 --- /dev/null +++ b/src/test/ui/generic-associated-types/collections-project-default.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/collections-project-default.rs:60:5 + | +LL | fn floatify_sibling(ints: &C) -> >::Sibling + | ------------------------------------ expected `>::Sibling` because of return type +... +LL | res + | ^^^ expected Collection::Sibling, found CollectionFamily::Member + | + = note: expected associated type `>::Sibling` + found associated type `<>::Family as CollectionFamily>::Member` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generic-associated-types/collections.rs b/src/test/ui/generic-associated-types/collections.rs index 6f018f0401863..1b5b9c181fb61 100644 --- a/src/test/ui/generic-associated-types/collections.rs +++ b/src/test/ui/generic-associated-types/collections.rs @@ -6,13 +6,14 @@ // http://smallcultfollowing.com/babysteps/blog/2016/11/03/ // associated-type-constructors-part-2-family-traits/ +// run-pass + trait Collection { - type Iter<'iter>: Iterator; + type Iter<'iter>: Iterator where T: 'iter; type Family: CollectionFamily; // Test associated type defaults with parameters type Sibling: Collection = <>::Family as CollectionFamily>::Member; - //~^^ ERROR type-generic associated types are not yet implemented fn empty() -> Self; @@ -23,7 +24,6 @@ trait Collection { trait CollectionFamily { type Member: Collection; - //~^ ERROR type-generic associated types are not yet implemented } struct VecFamily; @@ -33,7 +33,7 @@ impl CollectionFamily for VecFamily { } impl Collection for Vec { - type Iter<'iter> = std::slice::Iter<'iter, T>; + type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>; type Family = VecFamily; fn empty() -> Self { @@ -53,18 +53,7 @@ fn floatify(ints: &C) -> <>::Family as CollectionFamily> where C: Collection, { - let mut res = C::Family::Member::::empty(); - for &v in ints.iterate() { - res.add(v as f32); - } - res -} - -fn floatify_sibling(ints: &C) -> >::Sibling -where - C: Collection, -{ - let mut res = C::Family::Member::::empty(); + let mut res = ::Member::::empty(); for &v in ints.iterate() { res.add(v as f32); } @@ -72,11 +61,11 @@ where } fn use_floatify() { - let a = vec![1i32, 2, 3]; - let b = floatify(a); - println!("{}", b.iterate().next()); - let c = floatify_sibling(a); - println!("{}", c.iterate().next()); + let a = vec![1, 2, 3]; + let b = floatify(&a); + assert_eq!(Some(&1.0), b.iterate().next()); } -fn main() {} +fn main() { + use_floatify(); +} diff --git a/src/test/ui/generic-associated-types/collections.stderr b/src/test/ui/generic-associated-types/collections.stderr deleted file mode 100644 index fb06d5e49a391..0000000000000 --- a/src/test/ui/generic-associated-types/collections.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: type-generic associated types are not yet implemented - --> $DIR/collections.rs:13:5 - | -LL | / type Sibling: Collection = -LL | | <>::Family as CollectionFamily>::Member; - | |_________________________________________________________________________^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/collections.rs:25:5 - | -LL | type Member: Collection; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/generic-associated-types/construct_with_other_type.rs b/src/test/ui/generic-associated-types/construct_with_other_type.rs index 2198b99db25c1..ff9d61658f4eb 100644 --- a/src/test/ui/generic-associated-types/construct_with_other_type.rs +++ b/src/test/ui/generic-associated-types/construct_with_other_type.rs @@ -1,7 +1,7 @@ #![allow(incomplete_features)] #![feature(generic_associated_types)] -// FIXME(#30472) normalize enough to handle this. +// check-pass use std::ops::Deref; @@ -17,7 +17,6 @@ trait Baz { } impl Baz for T where T: Foo { -//~^ ERROR type mismatch resolving type Quux<'a> where T: 'a = T; type Baa<'a> where T: 'a = &'a ::Bar<'a, 'static>; diff --git a/src/test/ui/generic-associated-types/construct_with_other_type.stderr b/src/test/ui/generic-associated-types/construct_with_other_type.stderr deleted file mode 100644 index b9468b3330b44..0000000000000 --- a/src/test/ui/generic-associated-types/construct_with_other_type.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0271]: type mismatch resolving `for<'a> <::Baa<'a> as std::ops::Deref>::Target == <::Quux<'a> as Foo>::Bar<'a, 'static>` - --> $DIR/construct_with_other_type.rs:19:9 - | -LL | impl Baz for T where T: Foo { - | - ^^^ expected type parameter `T`, found associated type - | | - | this type parameter - | - = note: expected associated type `::Bar<'_, 'static>` - found associated type `<::Quux<'_> as Foo>::Bar<'_, 'static>` -help: consider further restricting this bound - | -LL | impl Baz for T where T: Foo + Baz { - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs index f88df6a608aa3..c1d68812e9356 100644 --- a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs +++ b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs @@ -6,7 +6,6 @@ struct Foo; trait MyTrait { type Item; //~^ ERROR generic associated types are unstable [E0658] - //~| ERROR type-generic associated types are not yet implemented } impl MyTrait for Foo { diff --git a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr index f3da27775adcf..34f536dbe8f64 100644 --- a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr +++ b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr @@ -8,7 +8,7 @@ LL | type Item; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: generic associated types are unstable - --> $DIR/gat-dont-ice-on-absent-feature-2.rs:13:5 + --> $DIR/gat-dont-ice-on-absent-feature-2.rs:12:5 | LL | type Item = T; | ^^^^^^^^^^^^^^^^^ @@ -16,14 +16,6 @@ LL | type Item = T; = note: see issue #44265 for more information = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable -error: type-generic associated types are not yet implemented - --> $DIR/gat-dont-ice-on-absent-feature-2.rs:7:5 - | -LL | type Item; - | ^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. 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 589024e162166..1a94796535c14 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 @@ -9,11 +9,8 @@ use std::fmt::{Display, Debug}; trait Foo { type Assoc where Self: Sized; type Assoc2 where T: Display; - //~^ ERROR type-generic associated types are not yet implemented type Assoc3; - //~^ ERROR type-generic associated types are not yet implemented - type WithDefault<'a, T: Debug + 'a> = dyn Iterator; - //~^ ERROR type-generic associated types are not yet implemented + type WithDefault<'a, T: Debug + 'a>: ?Sized = dyn Iterator; type NoGenerics; } @@ -23,6 +20,7 @@ impl Foo for Bar { type Assoc = usize; type Assoc2 = Vec; type Assoc3 where T: Iterator = Vec; + //~^ 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 fb29b377a16e3..4d02f2c46a6d0 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,26 +1,12 @@ -error: type-generic associated types are not yet implemented - --> $DIR/generic-associated-types-where.rs:11:5 - | -LL | type Assoc2 where T: Display; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/generic-associated-types-where.rs:13:5 +error[E0276]: impl has stricter requirements than trait + --> $DIR/generic-associated-types-where.rs:22:5 | LL | type Assoc3; - | ^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/generic-associated-types-where.rs:15:5 - | -LL | type WithDefault<'a, T: Debug + 'a> = dyn Iterator; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information + | --------------- definition of `Assoc3` from trait +... +LL | type Assoc3 where T: Iterator = Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::iter::Iterator` -error: aborting due to 3 previous errors +error: aborting due to previous error +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/issue-47206-where-clause.rs b/src/test/ui/generic-associated-types/issue-47206-where-clause.rs index 53e350aacf88e..de2b978460f7f 100644 --- a/src/test/ui/generic-associated-types/issue-47206-where-clause.rs +++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.rs @@ -5,13 +5,13 @@ trait Foo { type Assoc3; - //~^ type-generic associated types are not yet implemented } struct Bar; impl Foo for Bar { type Assoc3 where T: Iterator = Vec; + //~^ ERROR impl has stricter requirements than trait } fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr index c9c1a4753b0dd..bc5c40ff029f9 100644 --- a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr +++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr @@ -1,10 +1,12 @@ -error: type-generic associated types are not yet implemented - --> $DIR/issue-47206-where-clause.rs:7:5 +error[E0276]: impl has stricter requirements than trait + --> $DIR/issue-47206-where-clause.rs:13:5 | LL | type Assoc3; - | ^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information + | --------------- definition of `Assoc3` from trait +... +LL | type Assoc3 where T: Iterator = Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::iter::Iterator` error: aborting due to previous error +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs index 1a79dbf2279a0..404be59a36d92 100644 --- a/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs +++ b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs @@ -1,11 +1,14 @@ #![allow(incomplete_features)] #![feature(generic_associated_types)] -// FIXME(generic-associated-types) Investigate why this doesn't compile. +// check-pass trait Iterator { type Item<'a>: 'a; - //~^ ERROR the requirement `for<'a> ::Item<'a>: 'a` is not satisfied +} + +impl Iterator for () { + type Item<'a> = &'a (); } fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.stderr b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.stderr deleted file mode 100644 index 4b06baa09ffbf..0000000000000 --- a/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error[E0280]: the requirement `for<'a> ::Item<'a>: 'a` is not satisfied - --> $DIR/issue-62326-parameter-out-of-range.rs:7:20 - | -LL | trait Iterator { - | -------- required by a bound in this -LL | type Item<'a>: 'a; - | ^^ required by this bound in `Iterator` - -error: aborting due to previous error - diff --git a/src/test/ui/generic-associated-types/issue-67424.rs b/src/test/ui/generic-associated-types/issue-67424.rs index 9b616b8abc2ee..fa35a3e8b04d1 100644 --- a/src/test/ui/generic-associated-types/issue-67424.rs +++ b/src/test/ui/generic-associated-types/issue-67424.rs @@ -7,7 +7,6 @@ trait Trait1 { trait Trait2 { type Type1: Trait1; //~^ ERROR: generic associated types are unstable - //~| ERROR: type-generic associated types are not yet implemented } fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-67424.stderr b/src/test/ui/generic-associated-types/issue-67424.stderr index 8b08c71759bb9..bbb7d56f5928e 100644 --- a/src/test/ui/generic-associated-types/issue-67424.stderr +++ b/src/test/ui/generic-associated-types/issue-67424.stderr @@ -7,14 +7,6 @@ LL | type Type1: Trait1; = note: see issue #44265 for more information = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable -error: type-generic associated types are not yet implemented - --> $DIR/issue-67424.rs:8:5 - | -LL | type Type1: Trait1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs new file mode 100644 index 0000000000000..71f9b2967dc58 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs @@ -0,0 +1,32 @@ +// Regression test for #68641 + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete and may not + +trait UnsafeCopy { + type Item<'a>: Copy; + + fn copy<'a>(item: &Self::Item<'a>) -> Self::Item<'a> { + *item + } +} + +impl UnsafeCopy for T { + type Item<'a> = T; + //~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied +} + +fn main() { + let mut s = String::from("Hello world!"); + + let copy = String::copy(&s); + + // Do we indeed point to the samme memory? + assert!(s.as_ptr() == copy.as_ptr()); + + // Any use of `copy` is certeinly UB after this + drop(s); + + // UB UB UB UB UB!! + println!("{}", copy); +} 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 new file mode 100644 index 0000000000000..834bc3b7878f2 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr @@ -0,0 +1,26 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68641-check-gat-bounds.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied + --> $DIR/issue-68641-check-gat-bounds.rs:15:5 + | +LL | type Item<'a>: Copy; + | -------------------- required by `UnsafeCopy::Item` +... +LL | type Item<'a> = T; + | ^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | impl UnsafeCopy for T { + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs new file mode 100644 index 0000000000000..c99073c13284d --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs @@ -0,0 +1,21 @@ +// Regression test for #68642 + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete and may not + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `std::ops::Fn<()>` closure, found `T` +} + +fn main() { + usize>::callme(|| 1); +} 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 new file mode 100644 index 0000000000000..89cc5dfd06018 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr @@ -0,0 +1,28 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68642-broken-llvm-ir.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0277]: expected a `std::ops::Fn<()>` closure, found `T` + --> $DIR/issue-68642-broken-llvm-ir.rs:15:5 + | +LL | type F<'a>: Fn() -> u32; + | ------------------------ required by `Fun::F` +... +LL | type F<'a> = Self; + | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` + | + = help: the trait `std::ops::Fn<()>` is not implemented for `T` + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ } +help: consider restricting type parameter `T` + | +LL | impl> Fun for T { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs b/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs new file mode 100644 index 0000000000000..24133e75cccee --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs @@ -0,0 +1,21 @@ +// Regression test for #68643 + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete and may not + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `std::ops::Fn<()>` closure, found `T` +} + +pub fn main() { + ::callme(|| {}); +} 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 new file mode 100644 index 0000000000000..efd3287853f03 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr @@ -0,0 +1,28 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68643-broken-mir.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0277]: expected a `std::ops::Fn<()>` closure, found `T` + --> $DIR/issue-68643-broken-mir.rs:15:5 + | +LL | type F<'a>: Fn() -> u32; + | ------------------------ required by `Fun::F` +... +LL | type F<'a> = Self; + | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` + | + = help: the trait `std::ops::Fn<()>` is not implemented for `T` + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ } +help: consider restricting type parameter `T` + | +LL | impl> Fun for T { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs new file mode 100644 index 0000000000000..22620c61b8390 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs @@ -0,0 +1,21 @@ +// Regression test for #68644 + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete and may not + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `std::ops::Fn<()>` closure, found `T` +} + +fn main() { + ::callme(0); +} 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 new file mode 100644 index 0000000000000..5da924a512f00 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr @@ -0,0 +1,28 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68644-codegen-selection.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0277]: expected a `std::ops::Fn<()>` closure, found `T` + --> $DIR/issue-68644-codegen-selection.rs:15:5 + | +LL | type F<'a>: Fn() -> u32; + | ------------------------ required by `Fun::F` +... +LL | type F<'a> = Self; + | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` + | + = help: the trait `std::ops::Fn<()>` is not implemented for `T` + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ } +help: consider restricting type parameter `T` + | +LL | impl> Fun for T { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs new file mode 100644 index 0000000000000..423b80e8476f4 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs @@ -0,0 +1,21 @@ +// Regression test for #68645 + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete and may not + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `std::ops::Fn<()>` closure, found `T` +} + +fn main() { + <&dyn Iterator>::callme(&std::iter::once(1)); +} 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 new file mode 100644 index 0000000000000..12d84ab6a369b --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr @@ -0,0 +1,28 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68645-codegen-fulfillment.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0277]: expected a `std::ops::Fn<()>` closure, found `T` + --> $DIR/issue-68645-codegen-fulfillment.rs:15:5 + | +LL | type F<'a>: Fn() -> u32; + | ------------------------ required by `Fun::F` +... +LL | type F<'a> = Self; + | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` + | + = help: the trait `std::ops::Fn<()>` is not implemented for `T` + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ } +help: consider restricting type parameter `T` + | +LL | impl> Fun for T { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs b/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs new file mode 100644 index 0000000000000..4ccd42ba6432d --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs @@ -0,0 +1,22 @@ +// Regression test for #68656 + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete and may not + +trait UnsafeCopy { + type Item<'a>: std::ops::Deref; + + fn bug<'a>(item: &Self::Item<'a>) -> () { + let x: T = **item; + &x as *const _; + } +} + +impl UnsafeCopy for T { + type Item<'a> = T; + //~^ ERROR type mismatch resolving `::Target == T` +} + +fn main() { + <&'static str>::bug(&""); +} 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 new file mode 100644 index 0000000000000..e1ceeac3196a8 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr @@ -0,0 +1,30 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68656-unsized-values.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +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` +... +LL | impl UnsafeCopy for T { + | - this type parameter +LL | type Item<'a> = T; + | ^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type + | + = note: expected type parameter `T` + found associated type `::Target` +help: consider further restricting this bound + | +LL | impl> UnsafeCopy for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/generic-associated-types/iterable.rs b/src/test/ui/generic-associated-types/iterable.rs index 105ab4a8adc38..600a69006c1ea 100644 --- a/src/test/ui/generic-associated-types/iterable.rs +++ b/src/test/ui/generic-associated-types/iterable.rs @@ -1,7 +1,7 @@ #![allow(incomplete_features)] #![feature(generic_associated_types)] -// FIXME(#30472) normalize enough to handle this. +// run-pass trait Iterable { type Item<'a> where Self: 'a; @@ -13,39 +13,35 @@ trait Iterable { // Impl for struct type impl Iterable for Vec { type Item<'a> where T: 'a = as Iterator>::Item; - //~^ ERROR type mismatch resolving type Iter<'a> where T: 'a = std::slice::Iter<'a, T>; fn iter<'a>(&'a self) -> Self::Iter<'a> { - //~^ ERROR type mismatch resolving - self.iter() + self[..].iter() } } // Impl for a primitive type impl Iterable for [T] { type Item<'a> where T: 'a = as Iterator>::Item; - //~^ ERROR type mismatch resolving type Iter<'a> where T: 'a = std::slice::Iter<'a, T>; fn iter<'a>(&'a self) -> Self::Iter<'a> { - //~^ ERROR type mismatch resolving self.iter() } } -fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> { +fn make_iter<'a, I: Iterable + ?Sized>(it: &'a I) -> I::Iter<'a> { it.iter() } -fn get_first<'a, I: Iterable>(it: &'a I) -> Option> { +fn get_first<'a, I: Iterable + ?Sized>(it: &'a I) -> Option> { it.iter().next() } fn main() { let v = vec![1, 2, 3]; - assert_eq!(v, make_iter(&v).copied().collect()); - assert_eq!(v, make_iter(&*v).copied().collect()); - assert_eq!(1, get_first(&v)); - assert_eq!(1, get_first(&*v)); + assert_eq!(v, make_iter(&v).copied().collect::>()); + assert_eq!(v, make_iter(&*v).copied().collect::>()); + assert_eq!(Some(&1), get_first(&v)); + assert_eq!(Some(&1), get_first(&*v)); } diff --git a/src/test/ui/generic-associated-types/iterable.stderr b/src/test/ui/generic-associated-types/iterable.stderr deleted file mode 100644 index 6e75462122513..0000000000000 --- a/src/test/ui/generic-associated-types/iterable.stderr +++ /dev/null @@ -1,59 +0,0 @@ -error[E0271]: type mismatch resolving `for<'a> < as Iterable>::Iter<'a> as std::iter::Iterator>::Item == as Iterable>::Item<'a>` - --> $DIR/iterable.rs:15:33 - | -LL | type Item<'a> where T: 'a = as Iterator>::Item; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type - | - = note: expected reference `&T` - found associated type ` as Iterable>::Item<'_>` - = help: consider constraining the associated type ` as Iterable>::Item<'_>` to `&_` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html - -error[E0271]: type mismatch resolving `for<'a> <<[T] as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <[T] as Iterable>::Item<'a>` - --> $DIR/iterable.rs:27:33 - | -LL | type Item<'a> where T: 'a = as Iterator>::Item; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type - | - = note: expected reference `&T` - found associated type `<[T] as Iterable>::Item<'_>` - = help: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html - -error[E0271]: type mismatch resolving `for<'a> < as Iterable>::Iter<'a> as std::iter::Iterator>::Item == as Iterable>::Item<'a>` - --> $DIR/iterable.rs:19:30 - | -LL | trait Iterable { - | -------- required by a bound in this -LL | type Item<'a> where Self: 'a; -LL | type Iter<'a>: Iterator> where Self: 'a; - | --------------------- required by this bound in `Iterable` -... -LL | fn iter<'a>(&'a self) -> Self::Iter<'a> { - | ^^^^^^^^^^^^^^ expected associated type, found reference - | - = note: expected associated type ` as Iterable>::Item<'_>` - found reference `&T` - = help: consider constraining the associated type ` as Iterable>::Item<'_>` to `&_` or calling a method that returns ` as Iterable>::Item<'_>` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html - -error[E0271]: type mismatch resolving `for<'a> <<[T] as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <[T] as Iterable>::Item<'a>` - --> $DIR/iterable.rs:31:30 - | -LL | trait Iterable { - | -------- required by a bound in this -LL | type Item<'a> where Self: 'a; -LL | type Iter<'a>: Iterator> where Self: 'a; - | --------------------- required by this bound in `Iterable` -... -LL | fn iter<'a>(&'a self) -> Self::Iter<'a> { - | ^^^^^^^^^^^^^^ expected associated type, found reference - | - = note: expected associated type `<[T] as Iterable>::Item<'_>` - found reference `&T` - = help: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_` or calling a method that returns `<[T] as Iterable>::Item<'_>` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/generic-associated-types/missing-bounds.fixed b/src/test/ui/generic-associated-types/missing-bounds.fixed index 364d2388741b0..3ba7d043d0759 100644 --- a/src/test/ui/generic-associated-types/missing-bounds.fixed +++ b/src/test/ui/generic-associated-types/missing-bounds.fixed @@ -34,12 +34,11 @@ impl> Add for D { struct E(B); -impl Add for E where B: Add, B: std::ops::Add { - //~^ ERROR equality constraints are not yet supported in `where` clauses +impl Add for E where B: Add { type Output = Self; fn add(self, rhs: Self) -> Self { - Self(self.0 + rhs.0) //~ ERROR mismatched types + Self(self.0 + rhs.0) } } diff --git a/src/test/ui/generic-associated-types/missing-bounds.rs b/src/test/ui/generic-associated-types/missing-bounds.rs index ffafff5e9f586..962d2db9476bd 100644 --- a/src/test/ui/generic-associated-types/missing-bounds.rs +++ b/src/test/ui/generic-associated-types/missing-bounds.rs @@ -34,12 +34,11 @@ impl Add for D { struct E(B); -impl Add for E where ::Output = B { - //~^ ERROR equality constraints are not yet supported in `where` clauses +impl Add for E where B: Add { type Output = Self; fn add(self, rhs: Self) -> Self { - Self(self.0 + rhs.0) //~ ERROR mismatched types + Self(self.0 + rhs.0) } } diff --git a/src/test/ui/generic-associated-types/missing-bounds.stderr b/src/test/ui/generic-associated-types/missing-bounds.stderr index 50536fdaca96e..630ceac093ef2 100644 --- a/src/test/ui/generic-associated-types/missing-bounds.stderr +++ b/src/test/ui/generic-associated-types/missing-bounds.stderr @@ -1,15 +1,3 @@ -error: equality constraints are not yet supported in `where` clauses - --> $DIR/missing-bounds.rs:37:33 - | -LL | impl Add for E where ::Output = B { - | ^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information -help: if `Output` is an associated type you're trying to set, use the associated type binding syntax - | -LL | impl Add for E where B: Add { - | ^^^^^^^^^^^^^^^^^^ - error[E0308]: mismatched types --> $DIR/missing-bounds.rs:11:11 | @@ -55,23 +43,7 @@ help: consider restricting type parameter `B` LL | impl> Add for D { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched types - --> $DIR/missing-bounds.rs:42:14 - | -LL | impl Add for E where ::Output = B { - | - this type parameter -... -LL | Self(self.0 + rhs.0) - | ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type - | - = note: expected type parameter `B` - found associated type `::Output` -help: consider further restricting type parameter `B` - | -LL | impl Add for E where ::Output = B, B: std::ops::Add { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0308, E0369. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind.rs b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs index 0edc5c48c01af..f4d09fc1539da 100644 --- a/src/test/ui/generic-associated-types/parameter_number_and_kind.rs +++ b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs @@ -7,18 +7,14 @@ trait Foo { type B<'a, 'b>; type C; type D; - //~^ ERROR type-generic associated types are not yet implemented type E<'a, T>; - //~^ ERROR type-generic associated types are not yet implemented // Test parameters in default values type FOk = Self::E<'static, T>; - //~^ ERROR type-generic associated types are not yet implemented type FErr1 = Self::E<'static, 'static>; //~^ ERROR wrong number of lifetime arguments: expected 1, found 2 //~| ERROR wrong number of type arguments: expected 1, found 0 type FErr2 = Self::E<'static, T, u32>; - //~^ ERROR type-generic associated types are not yet implemented - //~| ERROR wrong number of type arguments: expected 1, found 2 + //~^ ERROR wrong number of type arguments: expected 1, found 2 } fn main() {} diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr b/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr index 028ab72f48812..ed090e302cefa 100644 --- a/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr +++ b/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr @@ -1,53 +1,21 @@ -error: type-generic associated types are not yet implemented - --> $DIR/parameter_number_and_kind.rs:9:5 - | -LL | type D; - | ^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/parameter_number_and_kind.rs:11:5 - | -LL | type E<'a, T>; - | ^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/parameter_number_and_kind.rs:14:5 - | -LL | type FOk = Self::E<'static, T>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/parameter_number_and_kind.rs:19:5 - | -LL | type FErr2 = Self::E<'static, T, u32>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - error[E0107]: wrong number of lifetime arguments: expected 1, found 2 - --> $DIR/parameter_number_and_kind.rs:16:35 + --> $DIR/parameter_number_and_kind.rs:13:35 | LL | type FErr1 = Self::E<'static, 'static>; | ^^^^^^^ unexpected lifetime argument error[E0107]: wrong number of type arguments: expected 1, found 0 - --> $DIR/parameter_number_and_kind.rs:16:18 + --> $DIR/parameter_number_and_kind.rs:13:18 | LL | type FErr1 = Self::E<'static, 'static>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument error[E0107]: wrong number of type arguments: expected 1, found 2 - --> $DIR/parameter_number_and_kind.rs:19:41 + --> $DIR/parameter_number_and_kind.rs:16:41 | LL | type FErr2 = Self::E<'static, T, u32>; | ^^^ unexpected type argument -error: aborting due to 7 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/pointer_family.rs b/src/test/ui/generic-associated-types/pointer_family.rs index 1668759b4e39c..b322b752a1567 100644 --- a/src/test/ui/generic-associated-types/pointer_family.rs +++ b/src/test/ui/generic-associated-types/pointer_family.rs @@ -1,7 +1,7 @@ #![allow(incomplete_features)] #![feature(generic_associated_types)] -// FIXME(#44265): allow type-generic associated types. +// check-pass use std::rc::Rc; use std::sync::Arc; @@ -9,7 +9,6 @@ use std::ops::Deref; trait PointerFamily { type Pointer: Deref; - //~^ ERROR type-generic associated types are not yet implemented fn new(value: T) -> Self::Pointer; } diff --git a/src/test/ui/generic-associated-types/pointer_family.stderr b/src/test/ui/generic-associated-types/pointer_family.stderr deleted file mode 100644 index 83fe992fcb571..0000000000000 --- a/src/test/ui/generic-associated-types/pointer_family.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: type-generic associated types are not yet implemented - --> $DIR/pointer_family.rs:11:5 - | -LL | type Pointer: Deref; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: aborting due to previous error - diff --git a/src/test/ui/generic-associated-types/shadowing.rs b/src/test/ui/generic-associated-types/shadowing.rs index 5c308948bd3f8..44528ca1da36e 100644 --- a/src/test/ui/generic-associated-types/shadowing.rs +++ b/src/test/ui/generic-associated-types/shadowing.rs @@ -18,12 +18,10 @@ impl<'a> NoShadow<'a> for &'a u32 { trait ShadowT { type Bar; //~^ ERROR the name `T` is already used - //~| ERROR type-generic associated types are not yet implemented } trait NoShadowT { type Bar; // OK - //~^ ERROR type-generic associated types are not yet implemented } impl NoShadowT for Option { diff --git a/src/test/ui/generic-associated-types/shadowing.stderr b/src/test/ui/generic-associated-types/shadowing.stderr index 2d9a0d6fceb2d..d51c29080a0c9 100644 --- a/src/test/ui/generic-associated-types/shadowing.stderr +++ b/src/test/ui/generic-associated-types/shadowing.stderr @@ -7,7 +7,7 @@ LL | type Bar; | ^ already used error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters - --> $DIR/shadowing.rs:30:14 + --> $DIR/shadowing.rs:28:14 | LL | impl NoShadowT for Option { | - first use of `T` @@ -30,23 +30,7 @@ LL | impl<'a> NoShadow<'a> for &'a u32 { LL | type Bar<'a> = i32; | ^^ lifetime 'a already in scope -error: type-generic associated types are not yet implemented - --> $DIR/shadowing.rs:19:5 - | -LL | type Bar; - | ^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/shadowing.rs:25:5 - | -LL | type Bar; // OK - | ^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0403, E0496. For more information about an error, try `rustc --explain E0403`. diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs new file mode 100644 index 0000000000000..7510c58d57489 --- /dev/null +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs @@ -0,0 +1,22 @@ +#![allow(incomplete_features)] +#![feature(generic_associated_types)] + +trait ATy { + type Item<'a>: 'a; +} + +impl<'b> ATy for &'b () { + type Item<'a> = &'b (); + //~^ ERROR does not fulfill the required lifetime +} + +trait StaticTy { + type Item<'a>: 'static; +} + +impl StaticTy for () { + type Item<'a> = &'a (); + //~^ ERROR does not fulfill the required lifetime +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr new file mode 100644 index 0000000000000..5d612284a2187 --- /dev/null +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr @@ -0,0 +1,23 @@ +error[E0477]: the type `&'b ()` does not fulfill the required lifetime + --> $DIR/unsatisfied-outlives-bound.rs:9:5 + | +LL | type Item<'a> = &'b (); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type must outlive the lifetime `'a` as defined on the associated item at 9:15 + --> $DIR/unsatisfied-outlives-bound.rs:9:15 + | +LL | type Item<'a> = &'b (); + | ^^ + +error[E0477]: the type `&'a ()` does not fulfill the required lifetime + --> $DIR/unsatisfied-outlives-bound.rs:18:5 + | +LL | type Item<'a> = &'a (); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: type must satisfy the static lifetime + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/issues/issue-38091.rs b/src/test/ui/issues/issue-38091.rs index 00aa810f8308c..fcaf827ac63d4 100644 --- a/src/test/ui/issues/issue-38091.rs +++ b/src/test/ui/issues/issue-38091.rs @@ -1,4 +1,3 @@ -// run-pass #![feature(specialization)] trait Iterate<'a> { @@ -7,6 +6,7 @@ trait Iterate<'a> { } 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/issues/issue-38091.stderr new file mode 100644 index 0000000000000..fd5c31c311ccd --- /dev/null +++ b/src/test/ui/issues/issue-38091.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `(): Valid` is not satisfied + --> $DIR/issue-38091.rs:8:5 + | +LL | type Ty: Valid; + | --------------- required by `Iterate::Ty` +... +LL | default type Ty = (); + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/specialization/deafult-associated-type-bound-1.rs b/src/test/ui/specialization/deafult-associated-type-bound-1.rs new file mode 100644 index 0000000000000..5f7719c9e53e8 --- /dev/null +++ b/src/test/ui/specialization/deafult-associated-type-bound-1.rs @@ -0,0 +1,23 @@ +// Check that we check that default associated types satisfy the required +// bounds on them. + +#![feature(specialization)] + +trait X { + type U: Clone; + fn unsafe_clone(&self, x: Option<&Self::U>) { + x.cloned(); + } +} + +// We cannot normalize `::U` to `str` here, because the default could +// be overridden. The error here must therefore be found by a method other than +// normalization. +impl X for T { + default type U = str; + //~^ ERROR the trait bound `str: std::clone::Clone` is not satisfied +} + +pub fn main() { + 1.unsafe_clone(None); +} diff --git a/src/test/ui/specialization/deafult-associated-type-bound-1.stderr b/src/test/ui/specialization/deafult-associated-type-bound-1.stderr new file mode 100644 index 0000000000000..ae7a6bfe3a122 --- /dev/null +++ b/src/test/ui/specialization/deafult-associated-type-bound-1.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `str: std::clone::Clone` is not satisfied + --> $DIR/deafult-associated-type-bound-1.rs:17:5 + | +LL | type U: Clone; + | -------------- required by `X::U` +... +LL | default type U = str; + | ^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::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/specialization/deafult-associated-type-bound-2.rs b/src/test/ui/specialization/deafult-associated-type-bound-2.rs new file mode 100644 index 0000000000000..9ea31f34c5cba --- /dev/null +++ b/src/test/ui/specialization/deafult-associated-type-bound-2.rs @@ -0,0 +1,21 @@ +// Check that generic predicates are also checked for default associated types. +#![feature(specialization)] + +trait X { + type U: PartialEq; + fn unsafe_compare(x: Option, y: Option) { + match (x, y) { + (Some(a), Some(b)) => a == b, + _ => false, + }; + } +} + +impl X for T { + default type U = &'static B; + //~^ ERROR can't compare `&'static B` with `B` +} + +pub fn main() { + >::unsafe_compare(None, None); +} diff --git a/src/test/ui/specialization/deafult-associated-type-bound-2.stderr b/src/test/ui/specialization/deafult-associated-type-bound-2.stderr new file mode 100644 index 0000000000000..34bbd21ee5019 --- /dev/null +++ b/src/test/ui/specialization/deafult-associated-type-bound-2.stderr @@ -0,0 +1,14 @@ +error[E0277]: can't compare `&'static B` with `B` + --> $DIR/deafult-associated-type-bound-2.rs:15:5 + | +LL | type U: PartialEq; + | --------------------- required by `X::U` +... +LL | default type U = &'static B; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&'static B == B` + | + = help: the trait `std::cmp::PartialEq` is not implemented for `&'static B` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.rs b/src/test/ui/specialization/deafult-generic-associated-type-bound.rs new file mode 100644 index 0000000000000..81ebfc4c9ca13 --- /dev/null +++ b/src/test/ui/specialization/deafult-generic-associated-type-bound.rs @@ -0,0 +1,26 @@ +// Check that default generics associated types are validated. + +#![feature(specialization)] +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete + +trait X { + type U<'a>: PartialEq<&'a Self>; + fn unsafe_compare<'b>(x: Option>, y: Option<&'b Self>) { + match (x, y) { + (Some(a), Some(b)) => a == b, + _ => false, + }; + } +} + +impl X for T { + default type U<'a> = &'a T; + //~^ ERROR can't compare `T` with `T` +} + +struct NotComparable; + +pub fn main() { + ::unsafe_compare(None, None); +} diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr new file mode 100644 index 0000000000000..e7cac5347d424 --- /dev/null +++ b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr @@ -0,0 +1,28 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/deafult-generic-associated-type-bound.rs:4:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0277]: can't compare `T` with `T` + --> $DIR/deafult-generic-associated-type-bound.rs:18:5 + | +LL | type U<'a>: PartialEq<&'a Self>; + | -------------------------------- required by `X::U` +... +LL | default type U<'a> = &'a T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T == T` + | + = help: the trait `std::cmp::PartialEq` is not implemented for `T` + = note: required because of the requirements on the impl of `std::cmp::PartialEq` for `&'a T` +help: consider further restricting this bound + | +LL | impl X for T { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/where-clauses/where-lifetime-resolution.rs b/src/test/ui/where-clauses/where-lifetime-resolution.rs index 0d426386768c8..d8677ee959abd 100644 --- a/src/test/ui/where-clauses/where-lifetime-resolution.rs +++ b/src/test/ui/where-clauses/where-lifetime-resolution.rs @@ -7,7 +7,6 @@ fn f() where //~^ ERROR use of undeclared lifetime name `'a` for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, //~^ ERROR use of undeclared lifetime name `'b` - //~| ERROR nested quantification of lifetimes {} fn main() {} diff --git a/src/test/ui/where-clauses/where-lifetime-resolution.stderr b/src/test/ui/where-clauses/where-lifetime-resolution.stderr index 49799a93017eb..6c52664154bbf 100644 --- a/src/test/ui/where-clauses/where-lifetime-resolution.stderr +++ b/src/test/ui/where-clauses/where-lifetime-resolution.stderr @@ -7,12 +7,6 @@ LL | for<'a> dyn Trait1<'a>: Trait1<'a>, // OK LL | (dyn for<'a> Trait1<'a>): Trait1<'a>, | ^^ undeclared lifetime -error[E0316]: nested quantification of lifetimes - --> $DIR/where-lifetime-resolution.rs:8:17 - | -LL | for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, - | ^^^^^^^^^^^^^^^^^^^^^^ - error[E0261]: use of undeclared lifetime name `'b` --> $DIR/where-lifetime-resolution.rs:8:52 | @@ -22,6 +16,6 @@ LL | fn f() where LL | for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, | ^^ undeclared lifetime -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0261`.