Move bounds on associated types to the type
Given `trait X { type U; }` the bound `<Self as X>::U` now lives on the type, rather than the trait. This is feature gated on `feature(generic_associated_types)` for now until more testing can be done. The also enabled type-generic associated types since we no longer need "implies bounds".
This commit is contained in:
parent
9818bc08d3
commit
db4826dd6c
@ -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 @@ fn declared_projection_bounds_from_trait(
|
||||
fn region_bounds_declared_on_associated_item(
|
||||
&self,
|
||||
assoc_item_def_id: DefId,
|
||||
) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> {
|
||||
) -> impl Iterator<Item = ty::Region<'tcx>> {
|
||||
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`.
|
||||
|
@ -25,8 +25,6 @@
|
||||
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
|
||||
|
@ -136,6 +136,16 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
/// 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<ty::Predicate<'tcx>> {
|
||||
desc { |tcx| "finding projection predicates for `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
|
@ -371,34 +371,45 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
|
||||
/// (`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 trait's identity substs to
|
||||
/// 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> <Self as X<'b>>::U: Clone` can't be used, as in
|
||||
/// `hr-associated-type-bound-1.rs`.
|
||||
fn associated_type_projection_predicates(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: DefId,
|
||||
assoc_item_def_id: DefId,
|
||||
) -> &'_ ty::List<ty::Predicate<'_>> {
|
||||
let trait_id = tcx.associated_item(def_id).container.id();
|
||||
let trait_substs = InternalSubsts::identity_for_item(tcx, trait_id);
|
||||
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 generic_trait_bounds = tcx.predicates_of(trait_id);
|
||||
let trait_bounds = generic_trait_bounds.instantiate_identity(tcx);
|
||||
let trait_predicates = util::elaborate_predicates(tcx, trait_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 = trait_predicates.filter_map(|obligation| {
|
||||
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.item_def_id == def_id && p.substs.starts_with(trait_substs) {
|
||||
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.item_def_id == def_id && p.substs.starts_with(trait_substs) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -409,7 +420,11 @@ fn associated_type_projection_predicates(
|
||||
});
|
||||
|
||||
let result = tcx.mk_predicates(predicates);
|
||||
debug!("associated_type_projection_predicates({}) = {:?}", tcx.def_path_str(def_id), result);
|
||||
debug!(
|
||||
"associated_type_projection_predicates({}) = {:?}",
|
||||
tcx.def_path_str(assoc_item_def_id),
|
||||
result
|
||||
);
|
||||
result
|
||||
}
|
||||
|
||||
@ -422,9 +437,9 @@ fn opaque_type_projection_predicates(
|
||||
) -> &'_ ty::List<ty::Predicate<'_>> {
|
||||
let substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||
|
||||
let generics_bounds = tcx.predicates_of(def_id);
|
||||
let bounds = generics_bounds.instantiate_identity(tcx);
|
||||
let predicates = util::elaborate_predicates(tcx, bounds.predicates.into_iter());
|
||||
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;
|
||||
@ -445,6 +460,18 @@ fn opaque_type_projection_predicates(
|
||||
}
|
||||
}
|
||||
}
|
||||
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,
|
||||
_ => {}
|
||||
}
|
||||
tcx.sess.delay_span_bug(
|
||||
|
@ -1189,8 +1189,8 @@ fn compare_projection_bounds<'tcx>(
|
||||
impl_ty_span: Span,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
) -> Result<(), ErrorReported> {
|
||||
let is_gat = !tcx.generics_of(impl_ty.def_id).params.is_empty();
|
||||
if impl_ty.defaultness.is_final() && !is_gat {
|
||||
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(());
|
||||
@ -1198,7 +1198,9 @@ fn compare_projection_bounds<'tcx>(
|
||||
|
||||
let param_env = tcx.param_env(impl_ty.def_id);
|
||||
|
||||
let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.container.id());
|
||||
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.
|
||||
@ -1211,32 +1213,9 @@ fn compare_projection_bounds<'tcx>(
|
||||
// function would translate and partially normalize
|
||||
// `[<Self as X<A>>::Y<'a>, A]` to `[&'a u32, &'x u32]`.
|
||||
let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| {
|
||||
let normalized_self = if !is_gat {
|
||||
// projection_predicates only includes projections where the
|
||||
// substs of the trait ref are exactly the trait's identity
|
||||
// substs, so we can simply return the value from the impl.
|
||||
impl_ty_value
|
||||
} else {
|
||||
let predicate_self_ty = predicate_substs.type_at(0);
|
||||
let impl_ty_substs = if let ty::Projection(p) = predicate_self_ty.kind {
|
||||
assert!(
|
||||
p.item_def_id == trait_ty.def_id,
|
||||
"projection_predicates returned predicate for the wrong type: {}",
|
||||
predicate_self_ty,
|
||||
);
|
||||
p.substs.rebase_onto(tcx, impl_trait_ref.def_id, impl_substs)
|
||||
} else {
|
||||
bug!(
|
||||
"projection_predicates returned predicate for the wrong type `{}`",
|
||||
predicate_self_ty,
|
||||
);
|
||||
};
|
||||
impl_ty_value.subst(tcx, impl_ty_substs)
|
||||
};
|
||||
|
||||
tcx.mk_substs(
|
||||
iter::once(normalized_self.into())
|
||||
.chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, impl_trait_ref.substs))),
|
||||
iter::once(impl_ty_value.into())
|
||||
.chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, rebased_substs))),
|
||||
)
|
||||
};
|
||||
|
||||
@ -1275,10 +1254,15 @@ fn compare_projection_bounds<'tcx>(
|
||||
substs: projection_substs,
|
||||
item_def_id: projection.projection_ty.item_def_id,
|
||||
},
|
||||
ty: projection.ty.subst(tcx, impl_trait_ref.substs),
|
||||
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),
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
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};
|
||||
@ -1692,6 +1692,7 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
|
||||
|
||||
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();
|
||||
@ -1701,7 +1702,12 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
|
||||
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,
|
||||
|
||||
@ -1925,10 +1931,21 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
|
||||
}
|
||||
}
|
||||
|
||||
// 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_bounds(tcx, def_id, bounds, projection_ty, span))
|
||||
}
|
||||
} else if let Some((self_trait_ref, trait_items)) = is_trait {
|
||||
// Current behavior: bounds declared on associate type are predicates
|
||||
// of its parent trait.
|
||||
predicates.extend(trait_items.iter().flat_map(|trait_item_ref| {
|
||||
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)
|
||||
}))
|
||||
}
|
||||
|
||||
@ -1958,7 +1975,7 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
|
||||
result
|
||||
}
|
||||
|
||||
fn associated_item_predicates(
|
||||
fn trait_associated_item_predicates(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
self_trait_ref: ty::TraitRef<'tcx>,
|
||||
@ -1971,92 +1988,40 @@ fn associated_item_predicates(
|
||||
_ => return Vec::new(),
|
||||
};
|
||||
|
||||
let is_gat = !tcx.generics_of(item_def_id).params.is_empty();
|
||||
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 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 \
|
||||
<https://github.com/rust-lang/rust/issues/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.ty_error().into()
|
||||
}
|
||||
ty::GenericParamDefKind::Const => {
|
||||
unimplemented_error("const");
|
||||
tcx.const_error(tcx.type_of(param.def_id)).into()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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>
|
||||
// <Self as X<'a, B, const C: 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(), bound_substs);
|
||||
|
||||
let bounds = AstConv::compute_bounds(
|
||||
&ItemCtxt::new(tcx, def_id),
|
||||
assoc_ty,
|
||||
bounds,
|
||||
SizedByDefault::Yes,
|
||||
trait_item.span,
|
||||
let assoc_ty = tcx.mk_projection(
|
||||
tcx.hir().local_def_id(trait_item.hir_id).to_def_id(),
|
||||
self_trait_ref.substs,
|
||||
);
|
||||
|
||||
let predicates = bounds.predicates(tcx, assoc_ty);
|
||||
associated_item_bounds(tcx, def_id, bounds, assoc_ty, trait_item.span)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
fn associated_item_bounds(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
projection_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> Vec<(ty::Predicate<'tcx>, Span)> {
|
||||
let bounds = AstConv::compute_bounds(
|
||||
&ItemCtxt::new(tcx, def_id),
|
||||
projection_ty,
|
||||
bounds,
|
||||
SizedByDefault::Yes,
|
||||
span,
|
||||
);
|
||||
|
||||
let predicates = bounds.predicates(tcx, projection_ty);
|
||||
|
||||
predicates
|
||||
}
|
||||
|
||||
/// Converts a specific `GenericBound` from the AST into a set of
|
||||
|
@ -3,11 +3,9 @@
|
||||
trait PointerFamily<U> {
|
||||
type Pointer<T>: Deref<Target = T>;
|
||||
//~^ ERROR generic associated types are unstable
|
||||
//~| ERROR type-generic associated types are not yet implemented
|
||||
type Pointer2<T>: Deref<Target = T> 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;
|
||||
|
@ -8,7 +8,7 @@ LL | type Pointer<T>: Deref<Target = T>;
|
||||
= 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<T>: Deref<Target = T> where T: Clone, U: Clone;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -17,7 +17,7 @@ LL | type Pointer2<T>: Deref<Target = T> 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<T>: Deref<Target = T> where T: Clone, U: Clone;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -26,7 +26,7 @@ LL | type Pointer2<T>: Deref<Target = T> 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<Usize> = Box<Usize>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -35,7 +35,7 @@ LL | type Pointer<Usize> = Box<Usize>;
|
||||
= 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<U32> = Box<U32>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -44,7 +44,7 @@ LL | type Pointer2<U32> = Box<U32>;
|
||||
= 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 <https://github.com/rust-lang/rust/issues/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<T>: Deref<Target = T>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/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<T>: Deref<Target = T> where T: Clone, U: Clone;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/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`.
|
||||
|
@ -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<T> {
|
||||
type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
|
||||
type Family: CollectionFamily;
|
||||
// Test associated type defaults with parameters
|
||||
type Sibling<U>: Collection<U> =
|
||||
<<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
|
||||
|
||||
fn empty() -> Self;
|
||||
|
||||
fn add(&mut self, value: T);
|
||||
|
||||
fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>;
|
||||
}
|
||||
|
||||
trait CollectionFamily {
|
||||
type Member<T>: Collection<T, Family = Self>;
|
||||
}
|
||||
|
||||
struct VecFamily;
|
||||
|
||||
impl CollectionFamily for VecFamily {
|
||||
type Member<T> = Vec<T>;
|
||||
}
|
||||
|
||||
impl<T> Collection<T> for Vec<T> {
|
||||
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<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
|
||||
where
|
||||
C: Collection<i32>,
|
||||
{
|
||||
let mut res = <C::Family as CollectionFamily>::Member::<f32>::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();
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/collections-project-default.rs:60:5
|
||||
|
|
||||
LL | fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
|
||||
| ------------------------------------ expected `<C as Collection<i32>>::Sibling<f32>` because of return type
|
||||
...
|
||||
LL | res
|
||||
| ^^^ expected Collection::Sibling, found CollectionFamily::Member
|
||||
|
|
||||
= note: expected associated type `<C as Collection<i32>>::Sibling<f32>`
|
||||
found associated type `<<C as Collection<i32>>::Family as CollectionFamily>::Member<f32>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -6,13 +6,14 @@
|
||||
// http://smallcultfollowing.com/babysteps/blog/2016/11/03/
|
||||
// associated-type-constructors-part-2-family-traits/
|
||||
|
||||
// run-pass
|
||||
|
||||
trait Collection<T> {
|
||||
type Iter<'iter>: Iterator<Item=&'iter T>;
|
||||
type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
|
||||
type Family: CollectionFamily;
|
||||
// Test associated type defaults with parameters
|
||||
type Sibling<U>: Collection<U> =
|
||||
<<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
|
||||
//~^^ ERROR type-generic associated types are not yet implemented
|
||||
|
||||
fn empty() -> Self;
|
||||
|
||||
@ -23,7 +24,6 @@ trait Collection<T> {
|
||||
|
||||
trait CollectionFamily {
|
||||
type Member<T>: Collection<T, Family = Self>;
|
||||
//~^ ERROR type-generic associated types are not yet implemented
|
||||
}
|
||||
|
||||
struct VecFamily;
|
||||
@ -33,7 +33,7 @@ impl CollectionFamily for VecFamily {
|
||||
}
|
||||
|
||||
impl<T> Collection<T> for Vec<T> {
|
||||
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<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>
|
||||
where
|
||||
C: Collection<i32>,
|
||||
{
|
||||
let mut res = C::Family::Member::<f32>::empty();
|
||||
for &v in ints.iterate() {
|
||||
res.add(v as f32);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
|
||||
where
|
||||
C: Collection<i32>,
|
||||
{
|
||||
let mut res = C::Family::Member::<f32>::empty();
|
||||
let mut res = <C::Family as CollectionFamily>::Member::<f32>::empty();
|
||||
for &v in ints.iterate() {
|
||||
res.add(v as f32);
|
||||
}
|
||||
@ -72,11 +61,11 @@ fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/collections.rs:13:5
|
||||
|
|
||||
LL | / type Sibling<U>: Collection<U> =
|
||||
LL | | <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
|
||||
| |_________________________________________________________________________^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/collections.rs:25:5
|
||||
|
|
||||
LL | type Member<T>: Collection<T, Family = Self>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -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<T> Baz for T where T: Foo {
|
||||
//~^ ERROR type mismatch resolving
|
||||
type Quux<'a> where T: 'a = T;
|
||||
|
||||
type Baa<'a> where T: 'a = &'a <T as Foo>::Bar<'a, 'static>;
|
||||
|
@ -1,18 +0,0 @@
|
||||
error[E0271]: type mismatch resolving `for<'a> <<T as Baz>::Baa<'a> as std::ops::Deref>::Target == <<T as Baz>::Quux<'a> as Foo>::Bar<'a, 'static>`
|
||||
--> $DIR/construct_with_other_type.rs:19:9
|
||||
|
|
||||
LL | impl<T> Baz for T where T: Foo {
|
||||
| - ^^^ expected type parameter `T`, found associated type
|
||||
| |
|
||||
| this type parameter
|
||||
|
|
||||
= note: expected associated type `<T as Foo>::Bar<'_, 'static>`
|
||||
found associated type `<<T as Baz>::Quux<'_> as Foo>::Bar<'_, 'static>`
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
LL | impl<T> Baz for T where T: Foo + Baz<Quux = T> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
@ -6,7 +6,6 @@
|
||||
trait MyTrait {
|
||||
type Item<T>;
|
||||
//~^ ERROR generic associated types are unstable [E0658]
|
||||
//~| ERROR type-generic associated types are not yet implemented
|
||||
}
|
||||
|
||||
impl MyTrait for Foo {
|
||||
|
@ -8,7 +8,7 @@ LL | type Item<T>;
|
||||
= 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> = T;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -16,14 +16,6 @@ LL | type Item<T> = T;
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/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<T>;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/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`.
|
||||
|
@ -9,11 +9,8 @@
|
||||
trait Foo {
|
||||
type Assoc where Self: Sized;
|
||||
type Assoc2<T> where T: Display;
|
||||
//~^ ERROR type-generic associated types are not yet implemented
|
||||
type Assoc3<T>;
|
||||
//~^ ERROR type-generic associated types are not yet implemented
|
||||
type WithDefault<'a, T: Debug + 'a> = dyn Iterator<Item=T>;
|
||||
//~^ ERROR type-generic associated types are not yet implemented
|
||||
type WithDefault<'a, T: Debug + 'a>: ?Sized = dyn Iterator<Item=T>;
|
||||
type NoGenerics;
|
||||
}
|
||||
|
||||
@ -23,6 +20,7 @@ impl Foo for Bar {
|
||||
type Assoc = usize;
|
||||
type Assoc2<T> = Vec<T>;
|
||||
type Assoc3<T> where T: Iterator = Vec<T>;
|
||||
//~^ impl has stricter requirements than trait
|
||||
type WithDefault<'a, T: Debug + 'a> = &'a dyn Iterator<Item=T>;
|
||||
type NoGenerics = ::std::cell::Cell<i32>;
|
||||
}
|
||||
|
@ -1,26 +1,12 @@
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/generic-associated-types-where.rs:11:5
|
||||
|
|
||||
LL | type Assoc2<T> where T: Display;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/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<T>;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
| --------------- definition of `Assoc3` from trait
|
||||
...
|
||||
LL | type Assoc3<T> where T: Iterator = Vec<T>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::iter::Iterator`
|
||||
|
||||
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<Item=T>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0276`.
|
||||
|
@ -5,13 +5,13 @@
|
||||
|
||||
trait Foo {
|
||||
type Assoc3<T>;
|
||||
//~^ type-generic associated types are not yet implemented
|
||||
}
|
||||
|
||||
struct Bar;
|
||||
|
||||
impl Foo for Bar {
|
||||
type Assoc3<T> where T: Iterator = Vec<T>;
|
||||
//~^ ERROR impl has stricter requirements than trait
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -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<T>;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
| --------------- definition of `Assoc3` from trait
|
||||
...
|
||||
LL | type Assoc3<T> where T: Iterator = Vec<T>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::iter::Iterator`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0276`.
|
||||
|
@ -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> <Self as Iterator>::Item<'a>: 'a` is not satisfied
|
||||
}
|
||||
|
||||
impl Iterator for () {
|
||||
type Item<'a> = &'a ();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,10 +0,0 @@
|
||||
error[E0280]: the requirement `for<'a> <Self as Iterator>::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
|
||||
|
@ -7,7 +7,6 @@ trait Trait1 {
|
||||
trait Trait2 {
|
||||
type Type1<B>: Trait1<A=B>;
|
||||
//~^ ERROR: generic associated types are unstable
|
||||
//~| ERROR: type-generic associated types are not yet implemented
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -7,14 +7,6 @@ LL | type Type1<B>: Trait1<A=B>;
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/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<B>: Trait1<A=B>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/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`.
|
||||
|
@ -10,8 +10,8 @@ LL | #![feature(generic_associated_types)]
|
||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/issue-68641-check-gat-bounds.rs:15:5
|
||||
|
|
||||
LL | trait UnsafeCopy {
|
||||
| ---------------- required by `UnsafeCopy`
|
||||
LL | type Item<'a>: Copy;
|
||||
| -------------------- required by `UnsafeCopy::Item`
|
||||
...
|
||||
LL | type Item<'a> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
@ -10,8 +10,8 @@ LL | #![feature(generic_associated_types)]
|
||||
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
|
||||
--> $DIR/issue-68642-broken-llvm-ir.rs:15:5
|
||||
|
|
||||
LL | trait Fun {
|
||||
| --------- required by `Fun`
|
||||
LL | type F<'a>: Fn() -> u32;
|
||||
| ------------------------ required by `Fun::F`
|
||||
...
|
||||
LL | type F<'a> = Self;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
||||
|
@ -10,8 +10,8 @@ LL | #![feature(generic_associated_types)]
|
||||
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
|
||||
--> $DIR/issue-68643-broken-mir.rs:15:5
|
||||
|
|
||||
LL | trait Fun {
|
||||
| --------- required by `Fun`
|
||||
LL | type F<'a>: Fn() -> u32;
|
||||
| ------------------------ required by `Fun::F`
|
||||
...
|
||||
LL | type F<'a> = Self;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
||||
|
@ -10,8 +10,8 @@ LL | #![feature(generic_associated_types)]
|
||||
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
|
||||
--> $DIR/issue-68644-codegen-selection.rs:15:5
|
||||
|
|
||||
LL | trait Fun {
|
||||
| --------- required by `Fun`
|
||||
LL | type F<'a>: Fn() -> u32;
|
||||
| ------------------------ required by `Fun::F`
|
||||
...
|
||||
LL | type F<'a> = Self;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
||||
|
@ -10,8 +10,8 @@ LL | #![feature(generic_associated_types)]
|
||||
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
|
||||
--> $DIR/issue-68645-codegen-fulfillment.rs:15:5
|
||||
|
|
||||
LL | trait Fun {
|
||||
| --------- required by `Fun`
|
||||
LL | type F<'a>: Fn() -> u32;
|
||||
| ------------------------ required by `Fun::F`
|
||||
...
|
||||
LL | type F<'a> = Self;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
||||
|
@ -10,8 +10,8 @@ LL | #![feature(generic_associated_types)]
|
||||
error[E0271]: type mismatch resolving `<T as std::ops::Deref>::Target == T`
|
||||
--> $DIR/issue-68656-unsized-values.rs:16:5
|
||||
|
|
||||
LL | trait UnsafeCopy<T: Copy> {
|
||||
| ------------------------- required by `UnsafeCopy`
|
||||
LL | type Item<'a>: std::ops::Deref<Target = T>;
|
||||
| ------------------------------------------- required by `UnsafeCopy::Item`
|
||||
...
|
||||
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T {
|
||||
| - this type parameter
|
||||
|
@ -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<T> Iterable for Vec<T> {
|
||||
type Item<'a> where T: 'a = <std::slice::Iter<'a, T> 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<T> Iterable for [T] {
|
||||
type Item<'a> where T: 'a = <std::slice::Iter<'a, T> 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<I::Item<'a>> {
|
||||
fn get_first<'a, I: Iterable + ?Sized>(it: &'a I) -> Option<I::Item<'a>> {
|
||||
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::<Vec<_>>());
|
||||
assert_eq!(v, make_iter(&*v).copied().collect::<Vec<_>>());
|
||||
assert_eq!(Some(&1), get_first(&v));
|
||||
assert_eq!(Some(&1), get_first(&*v));
|
||||
}
|
||||
|
@ -1,59 +0,0 @@
|
||||
error[E0271]: type mismatch resolving `for<'a> <<std::vec::Vec<T> as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <std::vec::Vec<T> as Iterable>::Item<'a>`
|
||||
--> $DIR/iterable.rs:15:33
|
||||
|
|
||||
LL | type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type
|
||||
|
|
||||
= note: expected reference `&T`
|
||||
found associated type `<std::vec::Vec<T> as Iterable>::Item<'_>`
|
||||
= help: consider constraining the associated type `<std::vec::Vec<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> <<[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 = <std::slice::Iter<'a, T> 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> <<std::vec::Vec<T> as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <std::vec::Vec<T> 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<Item = Self::Item<'a>> 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 `<std::vec::Vec<T> as Iterable>::Item<'_>`
|
||||
found reference `&T`
|
||||
= help: consider constraining the associated type `<std::vec::Vec<T> as Iterable>::Item<'_>` to `&_` or calling a method that returns `<std::vec::Vec<T> 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<Item = Self::Item<'a>> 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`.
|
@ -34,12 +34,11 @@ impl<B: std::ops::Add<Output = B>> Add for D<B> {
|
||||
|
||||
struct E<B>(B);
|
||||
|
||||
impl<B: Add> Add for E<B> where B: Add<Output = B>, B: std::ops::Add<Output = B> {
|
||||
//~^ ERROR equality constraints are not yet supported in `where` clauses
|
||||
impl<B: Add> Add for E<B> where B: Add<Output = B> {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
Self(self.0 + rhs.0) //~ ERROR mismatched types
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,12 +34,11 @@ fn add(self, rhs: Self) -> Self {
|
||||
|
||||
struct E<B>(B);
|
||||
|
||||
impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
||||
//~^ ERROR equality constraints are not yet supported in `where` clauses
|
||||
impl<B: Add> Add for E<B> where B: Add<Output = B> {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
Self(self.0 + rhs.0) //~ ERROR mismatched types
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,3 @@
|
||||
error: equality constraints are not yet supported in `where` clauses
|
||||
--> $DIR/missing-bounds.rs:37:33
|
||||
|
|
||||
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ not supported
|
||||
|
|
||||
= note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
|
||||
help: if `Output` is an associated type you're trying to set, use the associated type binding syntax
|
||||
|
|
||||
LL | impl<B: Add> Add for E<B> where B: Add<Output = B> {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/missing-bounds.rs:11:11
|
||||
|
|
||||
@ -55,23 +43,7 @@ help: consider restricting type parameter `B`
|
||||
LL | impl<B: std::ops::Add<Output = B>> Add for D<B> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/missing-bounds.rs:42:14
|
||||
|
|
||||
LL | impl<B: Add> Add for E<B> where <B as Add>::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 `<B as std::ops::Add>::Output`
|
||||
help: consider further restricting type parameter `B`
|
||||
|
|
||||
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B, B: std::ops::Add<Output = B> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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`.
|
||||
|
@ -7,18 +7,14 @@ trait Foo {
|
||||
type B<'a, 'b>;
|
||||
type C;
|
||||
type D<T>;
|
||||
//~^ 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<T> = 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<T> = 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() {}
|
||||
|
@ -1,53 +1,21 @@
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/parameter_number_and_kind.rs:9:5
|
||||
|
|
||||
LL | type D<T>;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/parameter_number_and_kind.rs:14:5
|
||||
|
|
||||
LL | type FOk<T> = Self::E<'static, T>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/parameter_number_and_kind.rs:19:5
|
||||
|
|
||||
LL | type FErr2<T> = Self::E<'static, T, u32>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/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<T> = 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`.
|
||||
|
@ -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 @@
|
||||
|
||||
trait PointerFamily {
|
||||
type Pointer<T>: Deref<Target = T>;
|
||||
//~^ ERROR type-generic associated types are not yet implemented
|
||||
fn new<T>(value: T) -> Self::Pointer<T>;
|
||||
}
|
||||
|
||||
|
@ -1,10 +0,0 @@
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/pointer_family.rs:11:5
|
||||
|
|
||||
LL | type Pointer<T>: Deref<Target = T>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -18,12 +18,10 @@ impl<'a> NoShadow<'a> for &'a u32 {
|
||||
trait ShadowT<T> {
|
||||
type Bar<T>;
|
||||
//~^ ERROR the name `T` is already used
|
||||
//~| ERROR type-generic associated types are not yet implemented
|
||||
}
|
||||
|
||||
trait NoShadowT<T> {
|
||||
type Bar<U>; // OK
|
||||
//~^ ERROR type-generic associated types are not yet implemented
|
||||
}
|
||||
|
||||
impl<T> NoShadowT<T> for Option<T> {
|
||||
|
@ -7,7 +7,7 @@ LL | type Bar<T>;
|
||||
| ^ 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<T> NoShadowT<T> for Option<T> {
|
||||
| - 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<T>;
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/shadowing.rs:25:5
|
||||
|
|
||||
LL | type Bar<U>; // OK
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/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`.
|
||||
|
@ -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() {}
|
@ -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`.
|
@ -1,5 +1,5 @@
|
||||
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-38091.rs:2:12
|
||||
--> $DIR/issue-38091.rs:1:12
|
||||
|
|
||||
LL | #![feature(specialization)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
@ -8,14 +8,14 @@ LL | #![feature(specialization)]
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
|
||||
error[E0277]: the trait bound `(): Valid` is not satisfied
|
||||
--> $DIR/issue-38091.rs:8:5
|
||||
--> $DIR/issue-38091.rs:9:5
|
||||
|
|
||||
LL | trait Iterate<'a> {
|
||||
| ----------------- required by `Iterate`
|
||||
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
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -10,8 +10,8 @@ LL | #![feature(specialization)]
|
||||
error[E0277]: the trait bound `str: std::clone::Clone` is not satisfied
|
||||
--> $DIR/deafult-associated-type-bound-1.rs:18:5
|
||||
|
|
||||
LL | trait X {
|
||||
| ------- required by `X`
|
||||
LL | type U: Clone;
|
||||
| -------------- required by `X::U`
|
||||
...
|
||||
LL | default type U = str;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `str`
|
||||
|
@ -10,8 +10,8 @@ LL | #![feature(specialization)]
|
||||
error[E0277]: can't compare `&'static B` with `B`
|
||||
--> $DIR/deafult-associated-type-bound-2.rs:16:5
|
||||
|
|
||||
LL | trait X<T> {
|
||||
| ---------- required by `X`
|
||||
LL | type U: PartialEq<T>;
|
||||
| --------------------- required by `X::U`
|
||||
...
|
||||
LL | default type U = &'static B;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&'static B == B`
|
||||
|
@ -18,14 +18,14 @@ LL | #![feature(generic_associated_types)]
|
||||
error[E0277]: can't compare `T` with `T`
|
||||
--> $DIR/deafult-generic-associated-type-bound.rs:19:5
|
||||
|
|
||||
LL | trait X {
|
||||
| ------- required by `X`
|
||||
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 `for<'a> std::cmp::PartialEq` for `&'a 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<T: 'static + std::cmp::PartialEq> X for T {
|
||||
|
Loading…
Reference in New Issue
Block a user