diff options
| author | Mara Bos <m-ou.se@m-ou.se> | 2021-02-05 12:25:50 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-02-05 12:25:50 +0100 |
| commit | deec6a96d428d20250bfad2317c00fc67e4b70f0 (patch) | |
| tree | ddccb276fd47d1190b34019bd505e5f9bcc2ecaf | |
| parent | 9e5d58fb420a487ae30f38141eccdc8d79fb8d58 (diff) | |
| parent | 12d411febb37d4ddfd423415554714265609cb72 (diff) | |
| download | rust-deec6a96d428d20250bfad2317c00fc67e4b70f0.tar.gz rust-deec6a96d428d20250bfad2317c00fc67e4b70f0.zip | |
Rollup merge of #79554 - b-naber:generic-associated-types-in-trait-paths, r=jackh726
Generic associated types in trait paths This is the second part of https://github.com/rust-lang/rust/pull/78978 This should fix: Fixes #67510 Fixes #68648 Fixes #68649 Fixes #68650 Fixes #68652 Fixes #74684 Fixes #76535 Fixes #79422 Fixes #80433 and implement the remaining functionality needed for https://github.com/rust-lang/rust/issues/44265 r? ``@matthewjasper``
43 files changed, 1051 insertions, 112 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b7f227da73e..f076dca5cf5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1076,16 +1076,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_assoc_ty_constraint( &mut self, constraint: &AssocTyConstraint, - itctx: ImplTraitContext<'_, 'hir>, + mut itctx: ImplTraitContext<'_, 'hir>, ) -> hir::TypeBinding<'hir> { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); - if let Some(ref gen_args) = constraint.gen_args { - self.sess.span_fatal( - gen_args.span(), - "generic associated types in trait paths are currently not implemented", - ); - } + // lower generic arguments of identifier in constraint + let gen_args = if let Some(ref gen_args) = constraint.gen_args { + let gen_args_ctor = match gen_args { + GenericArgs::AngleBracketed(ref data) => { + self.lower_angle_bracketed_parameter_data( + data, + ParamMode::Explicit, + itctx.reborrow(), + ) + .0 + } + GenericArgs::Parenthesized(ref data) => { + let mut err = self.sess.struct_span_err( + gen_args.span(), + "parenthesized generic arguments cannot be used in associated type constraints" + ); + // FIXME: try to write a suggestion here + err.emit(); + self.lower_angle_bracketed_parameter_data( + &data.as_angle_bracketed_args(), + ParamMode::Explicit, + itctx.reborrow(), + ) + .0 + } + }; + self.arena.alloc(gen_args_ctor.into_generic_args(&self.arena)) + } else { + self.arena.alloc(hir::GenericArgs::none()) + }; let kind = match constraint.kind { AssocTyConstraintKind::Equality { ref ty } => { @@ -1182,6 +1206,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TypeBinding { hir_id: self.lower_node_id(constraint.id), ident: constraint.ident, + gen_args, kind, span: constraint.span, } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 9079e26eb50..cb4d5ea6ee6 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -362,7 +362,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_angle_bracketed_parameter_data( + pub(crate) fn lower_angle_bracketed_parameter_data( &mut self, data: &AngleBracketedArgs, param_mode: ParamMode, @@ -426,6 +426,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> hir::TypeBinding<'hir> { let ident = Ident::with_dummy_span(hir::FN_OUTPUT_NAME); let kind = hir::TypeBindingKind::Equality { ty }; - hir::TypeBinding { hir_id: self.next_id(), span, ident, kind } + let args = arena_vec![self;]; + let bindings = arena_vec![self;]; + let gen_args = self.arena.alloc(hir::GenericArgs { args, bindings, parenthesized: false }); + hir::TypeBinding { hir_id: self.next_id(), gen_args, span, ident, kind } } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6487b23a6a6..67a15418ea4 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2015,6 +2015,7 @@ pub struct TypeBinding<'hir> { pub hir_id: HirId, #[stable_hasher(project(name))] pub ident: Ident, + pub gen_args: &'hir GenericArgs<'hir>, pub kind: TypeBindingKind<'hir>, pub span: Span, } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 6c1bee2335a..f8b3f0d9b6e 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -781,6 +781,7 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>( ) { visitor.visit_id(type_binding.hir_id); visitor.visit_ident(type_binding.ident); + visitor.visit_generic_args(type_binding.span, type_binding.gen_args); match type_binding.kind { TypeBindingKind::Equality { ref ty } => { visitor.visit_ty(ty); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index f1c2a6b7e6e..4595855309f 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1840,6 +1840,7 @@ impl<'a> State<'a> { for binding in generic_args.bindings.iter() { start_or_comma(self); self.print_ident(binding.ident); + self.print_generic_args(binding.gen_args, false, false); self.s.space(); match generic_args.bindings[0].kind { hir::TypeBindingKind::Equality { ref ty } => { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 6b4f08d9f93..c1fa84dcb25 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1132,8 +1132,16 @@ impl<'tcx> ProjectionTy<'tcx> { /// For example, if this is a projection of `<T as Iterator>::Item`, /// then this function would return a `T: Iterator` trait reference. pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> { + // FIXME: This method probably shouldn't exist at all, since it's not + // clear what this method really intends to do. Be careful when + // using this method since the resulting TraitRef additionally + // contains the substs for the assoc_item, which strictly speaking + // is not correct let def_id = tcx.associated_item(self.item_def_id).container.id(); - ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)) } + // Include substitutions for generic arguments of associated types + let assoc_item = tcx.associated_item(self.item_def_id); + let substs_assoc_item = self.substs.truncate_to(tcx, tcx.generics_of(assoc_item.def_id)); + ty::TraitRef { def_id, substs: substs_assoc_item } } pub fn self_ty(&self) -> Ty<'tcx> { diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 3852005ee3f..e155f0366e1 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -257,13 +257,11 @@ fn predicates_reference_self( } fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> { - let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id)); tcx.associated_items(trait_def_id) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) .flat_map(|item| tcx.explicit_item_bounds(item.def_id)) - .map(|&(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp)) - .filter_map(|predicate| predicate_references_self(tcx, predicate)) + .filter_map(|pred_span| predicate_references_self(tcx, *pred_span)) .collect() } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 437813ea41b..5659345f0ff 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -112,12 +112,15 @@ pub enum SizedByDefault { No, } +#[derive(Debug)] struct ConvertedBinding<'a, 'tcx> { item_name: Ident, kind: ConvertedBindingKind<'a, 'tcx>, + gen_args: &'a GenericArgs<'a>, span: Span, } +#[derive(Debug)] enum ConvertedBindingKind<'a, 'tcx> { Equality(Ty<'tcx>), Constraint(&'a [hir::GenericBound<'a>]), @@ -323,6 +326,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); let generics = tcx.generics_of(def_id); + debug!("generics: {:?}", generics); if generics.has_self { if generics.parent.is_some() { @@ -557,7 +561,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ConvertedBindingKind::Constraint(bounds) } }; - ConvertedBinding { item_name: binding.ident, kind, span: binding.span } + ConvertedBinding { + item_name: binding.ident, + kind, + gen_args: binding.gen_args, + span: binding.span, + } }) .collect(); @@ -918,60 +927,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { dup_bindings: &mut FxHashMap<DefId, Span>, path_span: Span, ) -> Result<(), ErrorReported> { - let tcx = self.tcx(); - - if !speculative { - // Given something like `U: SomeTrait<T = X>`, we want to produce a - // predicate like `<U as SomeTrait>::T = X`. This is somewhat - // subtle in the event that `T` is defined in a supertrait of - // `SomeTrait`, because in that case we need to upcast. - // - // That is, consider this case: - // - // ``` - // trait SubTrait: SuperTrait<i32> { } - // trait SuperTrait<A> { type T; } - // - // ... B: SubTrait<T = foo> ... - // ``` - // - // We want to produce `<B as SuperTrait<i32>>::T == foo`. - - // Find any late-bound regions declared in `ty` that are not - // declared in the trait-ref. These are not well-formed. - // - // Example: - // - // for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad - // for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok - if let ConvertedBindingKind::Equality(ty) = binding.kind { - let late_bound_in_trait_ref = - tcx.collect_constrained_late_bound_regions(&trait_ref); - let late_bound_in_ty = - tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty)); - debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref); - debug!("late_bound_in_ty = {:?}", late_bound_in_ty); + // Given something like `U: SomeTrait<T = X>`, we want to produce a + // predicate like `<U as SomeTrait>::T = X`. This is somewhat + // subtle in the event that `T` is defined in a supertrait of + // `SomeTrait`, because in that case we need to upcast. + // + // That is, consider this case: + // + // ``` + // trait SubTrait: SuperTrait<i32> { } + // trait SuperTrait<A> { type T; } + // + // ... B: SubTrait<T = foo> ... + // ``` + // + // We want to produce `<B as SuperTrait<i32>>::T == foo`. - // FIXME: point at the type params that don't have appropriate lifetimes: - // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F); - // ---- ---- ^^^^^^^ - self.validate_late_bound_regions( - late_bound_in_trait_ref, - late_bound_in_ty, - |br_name| { - struct_span_err!( - tcx.sess, - binding.span, - E0582, - "binding for associated type `{}` references {}, \ - which does not appear in the trait input types", - binding.item_name, - br_name - ) - }, - ); - } - } + debug!( + "add_predicates_for_ast_type_binding(hir_ref_id {:?}, trait_ref {:?}, binding {:?}, bounds {:?}", + hir_ref_id, trait_ref, binding, bounds + ); + let tcx = self.tcx(); let candidate = if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) { @@ -1030,6 +1006,72 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .or_insert(binding.span); } + // Include substitutions for generic parameters of associated types + let projection_ty = candidate.map_bound(|trait_ref| { + let item_segment = hir::PathSegment { + ident: assoc_ty.ident, + hir_id: None, + res: None, + args: Some(binding.gen_args), + infer_args: false, + }; + + let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item( + tcx, + path_span, + assoc_ty.def_id, + &item_segment, + trait_ref.substs, + ); + + debug!( + "add_predicates_for_ast_type_binding: substs for trait-ref and assoc_item: {:?}", + substs_trait_ref_and_assoc_item + ); + + ty::ProjectionTy { + item_def_id: assoc_ty.def_id, + substs: substs_trait_ref_and_assoc_item, + } + }); + + if !speculative { + // Find any late-bound regions declared in `ty` that are not + // declared in the trait-ref or assoc_ty. These are not well-formed. + // + // Example: + // + // for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad + // for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok + if let ConvertedBindingKind::Equality(ty) = binding.kind { + let late_bound_in_trait_ref = + tcx.collect_constrained_late_bound_regions(&projection_ty); + let late_bound_in_ty = + tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty)); + debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref); + debug!("late_bound_in_ty = {:?}", late_bound_in_ty); + + // FIXME: point at the type params that don't have appropriate lifetimes: + // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F); + // ---- ---- ^^^^^^^ + self.validate_late_bound_regions( + late_bound_in_trait_ref, + late_bound_in_ty, + |br_name| { + struct_span_err!( + tcx.sess, + binding.span, + E0582, + "binding for associated type `{}` references {}, \ + which does not appear in the trait input types", + binding.item_name, + br_name + ) + }, + ); + } + } + match binding.kind { ConvertedBindingKind::Equality(ref ty) => { // "Desugar" a constraint like `T: Iterator<Item = u32>` this to @@ -1037,13 +1079,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // // `<T as Iterator>::Item = u32` bounds.projection_bounds.push(( - candidate.map_bound(|trait_ref| ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy::from_ref_and_name( - tcx, - trait_ref, - binding.item_name, - ), - ty, + projection_ty.map_bound(|projection_ty| { + debug!( + "add_predicates_for_ast_type_binding: projection_ty {:?}, substs: {:?}", + projection_ty, projection_ty.substs + ); + ty::ProjectionPredicate { projection_ty, ty } }), binding.span, )); @@ -1055,7 +1096,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` // parameter to have a skipped binder. - let param_ty = tcx.mk_projection(assoc_ty.def_id, candidate.skip_binder().substs); + let param_ty = + tcx.mk_projection(assoc_ty.def_id, projection_ty.skip_binder().substs); self.add_bounds(param_ty, ast_bounds, bounds); } } diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs new file mode 100644 index 00000000000..2c543455b6e --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs @@ -0,0 +1,12 @@ +#![feature(generic_associated_types)] + //~^ WARNING: the feature `generic_associated_types` is incomplete + +trait X { + type Y<'x>; +} + +fn main() { + fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {} + //~^ ERROR: use of undeclared lifetime name `'x` + //~| ERROR: binding for associated type `Y` references lifetime +} diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr new file mode 100644 index 00000000000..1c7c107d783 --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr @@ -0,0 +1,29 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:1:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +error[E0261]: use of undeclared lifetime name `'x` + --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:9:35 + | +LL | fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {} + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'x` here: `<'x>` + | + = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes + +error[E0582]: binding for associated type `Y` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:9:33 + | +LL | fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0261, E0582. +For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.rs b/src/test/ui/generic-associated-types/gat-in-trait-path.rs new file mode 100644 index 00000000000..2dbd1840dec --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-in-trait-path.rs @@ -0,0 +1,30 @@ +// check-pass + +#![feature(generic_associated_types)] + //~^ WARNING: the feature `generic_associated_types` is incomplete +#![feature(associated_type_defaults)] + +trait Foo { + type A<'a> where Self: 'a; +} + +struct Fooy; + +impl Foo for Fooy { + type A<'a> = &'a (); +} + +#[derive(Clone)] +struct Fooer<T>(T); + +impl<T> Foo for Fooer<T> { + type A<'x> where T: 'x = &'x (); +} + +fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {} + + +fn main() { + let foo = Fooer(5); + f(Box::new(foo)); +} diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr new file mode 100644 index 00000000000..f3769827f04 --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr @@ -0,0 +1,11 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/gat-in-trait-path.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs new file mode 100644 index 00000000000..cff5a21052f --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs @@ -0,0 +1,16 @@ +#![feature(generic_associated_types)] + //~^ WARNING: the feature `generic_associated_types` is incomplete + +trait Foo { + type F<'a>; + + fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t } +} + +impl <T, T1> Foo for T { + type F<T1> = &[u8]; + //~^ ERROR: the name `T1` is already used for + //~| ERROR: missing lifetime specifier +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr new file mode 100644 index 00000000000..e83af1d0c73 --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr @@ -0,0 +1,32 @@ +error[E0403]: the name `T1` is already used for a generic parameter in this item's generic parameters + --> $DIR/gat-trait-path-generic-type-arg.rs:11:12 + | +LL | impl <T, T1> Foo for T { + | -- first use of `T1` +LL | type F<T1> = &[u8]; + | ^^ already used + +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/gat-trait-path-generic-type-arg.rs:1:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +error[E0106]: missing lifetime specifier + --> $DIR/gat-trait-path-generic-type-arg.rs:11:18 + | +LL | type F<T1> = &[u8]; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type F<'a, T1> = &'a [u8]; + | ^^^ ^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0106, E0403. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs new file mode 100644 index 00000000000..e69e355ba48 --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs @@ -0,0 +1,18 @@ +#![feature(generic_associated_types)] + //~^ WARNING: the feature `generic_associated_types` is incomplete + +trait X { + type Y<'a>; + //~^ ERROR missing generics for + //~| ERROR missing generics for + + fn foo<'a>(t : Self::Y<'a>) -> Self::Y<'a> { t } +} + +impl<T> X for T { + fn foo<'a, T1: X<Y = T1>>(t : T1) -> T1::Y<'a> { + t + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr new file mode 100644 index 00000000000..9c6e2ce3e17 --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr @@ -0,0 +1,44 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/gat-trait-path-missing-lifetime.rs:1:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +error[E0107]: missing generics for associated type `X::Y` + --> $DIR/gat-trait-path-missing-lifetime.rs:5:8 + | +LL | type Y<'a>; + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-missing-lifetime.rs:5:8 + | +LL | type Y<'a>; + | ^ -- +help: use angle brackets to add missing lifetime argument + | +LL | type Y<'a><'a>; + | ^^^^ + +error[E0107]: missing generics for associated type `X::Y` + --> $DIR/gat-trait-path-missing-lifetime.rs:5:8 + | +LL | type Y<'a>; + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-missing-lifetime.rs:5:8 + | +LL | type Y<'a>; + | ^ -- +help: use angle brackets to add missing lifetime argument + | +LL | type Y<'a><'a>; + | ^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs new file mode 100644 index 00000000000..bb1f27a17ca --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs @@ -0,0 +1,15 @@ +#![feature(generic_associated_types)] + //~^ WARNING: the feature `generic_associated_types` is incomplete + +trait X { + type Y<'a>; + //~^ ERROR this associated type + //~| ERROR this associated type +} + +fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} + //~^ ERROR: lifetime in trait object type must be followed by `+` + //~| ERROR: parenthesized generic arguments cannot be used + //~| WARNING: trait objects without an explicit `dyn` are deprecated + +fn main() {} diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr new file mode 100644 index 00000000000..20cb6d88287 --- /dev/null +++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr @@ -0,0 +1,68 @@ +error: lifetime in trait object type must be followed by `+` + --> $DIR/gat-trait-path-parenthesised-args.rs:10:29 + | +LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} + | ^^ + +error: parenthesized generic arguments cannot be used in associated type constraints + --> $DIR/gat-trait-path-parenthesised-args.rs:10:27 + | +LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} + | ^^^^^ + +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/gat-trait-path-parenthesised-args.rs:1:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/gat-trait-path-parenthesised-args.rs:10:29 + | +LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} + | ^^ help: use `dyn`: `dyn 'a` + | + = note: `#[warn(bare_trait_objects)]` on by default + +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/gat-trait-path-parenthesised-args.rs:5:8 + | +LL | type Y<'a>; + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-parenthesised-args.rs:5:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn foo<'a>(arg: Box<dyn X<Y('a'a) = &'a ()>>) {} + | ^^ + +error[E0107]: this associated type takes 0 type arguments but 1 type argument was supplied + --> $DIR/gat-trait-path-parenthesised-args.rs:5:8 + | +LL | type Y<'a>; + | ________^- + | | | + | | expected 0 type arguments +LL | | +LL | | +LL | | } +LL | | +LL | | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} + | |_________________________________________- help: remove these generics + | +note: associated type defined here, with 0 type parameters + --> $DIR/gat-trait-path-parenthesised-args.rs:5:8 + | +LL | type Y<'a>; + | ^ + +error: aborting due to 4 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.rs b/src/test/ui/generic-associated-types/issue-67510-pass.rs new file mode 100644 index 00000000000..ff38b3e93eb --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-67510-pass.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(generic_associated_types)] + //~^ WARNING: the feature `generic_associated_types` is incomplete + +trait X { + type Y<'a>; +} + +fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.stderr b/src/test/ui/generic-associated-types/issue-67510-pass.stderr new file mode 100644 index 00000000000..0fbf704df76 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-67510-pass.stderr @@ -0,0 +1,11 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-67510-pass.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/generic-associated-types/issue-67510.rs b/src/test/ui/generic-associated-types/issue-67510.rs new file mode 100644 index 00000000000..62b22089f91 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-67510.rs @@ -0,0 +1,13 @@ +#![feature(generic_associated_types)] + //~^ WARNING: the feature `generic_associated_types` is incomplete + +trait X { + type Y<'a>; +} + +fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {} + //~^ ERROR: use of undeclared lifetime name `'a` + //~| ERROR: use of undeclared lifetime name `'a` + + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-67510.stderr b/src/test/ui/generic-associated-types/issue-67510.stderr new file mode 100644 index 00000000000..12755c56974 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-67510.stderr @@ -0,0 +1,32 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-67510.rs:1:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/issue-67510.rs:8:21 + | +LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {} + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` + | + = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/issue-67510.rs:8:26 + | +LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {} + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` + | + = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/generic-associated-types/issue-68648-1.rs b/src/test/ui/generic-associated-types/issue-68648-1.rs new file mode 100644 index 00000000000..f294b22f73c --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68648-1.rs @@ -0,0 +1,26 @@ +// check-pass + +#![feature(generic_associated_types)] + //~^ WARNING: the feature `generic_associated_types` is incomplete + + +trait Fun { + type F<'a>; + + fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t } +} + +impl <T> Fun for T { + type F<'a> = Self; +} + +fn bug<'a, T: for<'b> Fun<F<'b> = T>>(t: T) -> T::F<'a> { + T::identity(t) +} + + +fn main() { + let x = 10; + + bug(x); +} diff --git a/src/test/ui/generic-associated-types/issue-68648-1.stderr b/src/test/ui/generic-associated-types/issue-68648-1.stderr new file mode 100644 index 00000000000..322a8f9e13f --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68648-1.stderr @@ -0,0 +1,11 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68648-1.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/generic-associated-types/issue-68648-2.rs b/src/test/ui/generic-associated-types/issue-68648-2.rs new file mode 100644 index 00000000000..e55bfcd4ba2 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68648-2.rs @@ -0,0 +1,24 @@ +#![feature(generic_associated_types)] + //~^ WARNING: the feature `generic_associated_types` is incomplete + +trait Fun { + type F<'a>; + + fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t } +} + +impl <T> Fun for T { + type F<'a> = Self; +} + +fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> { + T::identity(()) + //~^ ERROR: mismatched types +} + + +fn main() { + let x = 10; + + bug(x); +} diff --git a/src/test/ui/generic-associated-types/issue-68648-2.stderr b/src/test/ui/generic-associated-types/issue-68648-2.stderr new file mode 100644 index 00000000000..b51e0bca9f7 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68648-2.stderr @@ -0,0 +1,23 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68648-2.rs:1:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +error[E0308]: mismatched types + --> $DIR/issue-68648-2.rs:15:17 + | +LL | fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> { + | - this type parameter +LL | T::identity(()) + | ^^ expected type parameter `T`, found `()` + | + = note: expected type parameter `T` + found unit type `()` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generic-associated-types/issue-68649-pass.rs b/src/test/ui/generic-associated-types/issue-68649-pass.rs new file mode 100644 index 00000000000..396315302f7 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68649-pass.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(generic_associated_types)] + //~^ WARNING: the feature `generic_associated_types` is incomplete + +trait Fun { + type F<'a>; + + fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t } +} + +impl <T> Fun for T { + type F<'a> = Self; +} + +fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> { + T::identity(t) +} + + +fn main() { + let x = 10; + + bug(x); +} diff --git a/src/test/ui/generic-associated-types/issue-68649-pass.stderr b/src/test/ui/generic-associated-types/issue-68649-pass.stderr new file mode 100644 index 00000000000..e4a2f8d2a64 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68649-pass.stderr @@ -0,0 +1,11 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68649-pass.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/generic-associated-types/issue-74684-1.rs b/src/test/ui/generic-associated-types/issue-74684-1.rs new file mode 100644 index 00000000000..a483da863ff --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-74684-1.rs @@ -0,0 +1,26 @@ +#![feature(generic_associated_types)] + //~^ WARNING: the feature `generic_associated_types` is incomplete + +trait Fun { + type F<'a>: ?Sized; + + fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t } +} + +impl <T> Fun for T { + type F<'a> = [u8]; +} + +fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(_ : Box<T>) -> &'static T::F<'a> { + let a = [0; 1]; + let _x = T::identity(&a); + //~^ ERROR: `a` does not live long enough + todo!() +} + + +fn main() { + let x = 10; + + bug(Box::new(x)); +} diff --git a/src/test/ui/generic-associated-types/issue-74684-1.stderr b/src/test/ui/generic-associated-types/issue-74684-1.stderr new file mode 100644 index 00000000000..651da696827 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-74684-1.stderr @@ -0,0 +1,27 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-74684-1.rs:1:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +error[E0597]: `a` does not live long enough + --> $DIR/issue-74684-1.rs:16:26 + | +LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(_ : Box<T>) -> &'static T::F<'a> { + | -- lifetime `'a` defined here +LL | let a = [0; 1]; +LL | let _x = T::identity(&a); + | ------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'a` +... +LL | } + | - `a` dropped here while still borrowed + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/generic-associated-types/issue-74684-2.rs b/src/test/ui/generic-associated-types/issue-74684-2.rs new file mode 100644 index 00000000000..0caf19cb030 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-74684-2.rs @@ -0,0 +1,26 @@ +#![feature(generic_associated_types)] + //~^ WARNING: the feature `generic_associated_types` is incomplete + +trait Fun { + type F<'a>: ?Sized; + + fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t } +} + +impl <T> Fun for T { + type F<'a> = i32; +} + +fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> { + let a = [0; 1]; + let x = T::identity(&a); + todo!() +} + + +fn main() { + let x = 10; + + bug(Box::new(x)); + //~^ ERROR: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` +} diff --git a/src/test/ui/generic-associated-types/issue-74684-2.stderr b/src/test/ui/generic-associated-types/issue-74684-2.stderr new file mode 100644 index 00000000000..8c3484f9a73 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-74684-2.stderr @@ -0,0 +1,21 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-74684-2.rs:1:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +error[E0271]: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` + --> $DIR/issue-74684-2.rs:24:5 + | +LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> { + | ------------ required by this bound in `bug` +... +LL | bug(Box::new(x)); + | ^^^ expected slice `[u8]`, found `i32` + +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/issue-76535.rs b/src/test/ui/generic-associated-types/issue-76535.rs new file mode 100644 index 00000000000..2b4757d8d15 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-76535.rs @@ -0,0 +1,41 @@ +#![feature(generic_associated_types)] + //~^ WARNING the feature + +pub trait SubTrait {} + +pub trait SuperTrait { + type SubType<'a>: SubTrait; + //~^ ERROR missing generics for associated + + fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>; +} + +pub struct SubStruct<'a> { + sup: &'a mut SuperStruct, +} + +impl<'a> SubTrait for SubStruct<'a> {} + +pub struct SuperStruct { + value: u8, +} + +impl SuperStruct { + pub fn new(value: u8) -> SuperStruct { + SuperStruct { value } + } +} + +impl SuperTrait for SuperStruct { + type SubType<'a> = SubStruct<'a>; + + fn get_sub<'a>(&'a mut self) -> Self::SubType<'a> { + SubStruct { sup: self } + } +} + +fn main() { + let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); + //~^ ERROR the trait + //~| ERROR the trait +} diff --git a/src/test/ui/generic-associated-types/issue-76535.stderr b/src/test/ui/generic-associated-types/issue-76535.stderr new file mode 100644 index 00000000000..ce4875af9c0 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-76535.stderr @@ -0,0 +1,63 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-76535.rs:1:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +error[E0107]: missing generics for associated type `SuperTrait::SubType` + --> $DIR/issue-76535.rs:7:10 + | +LL | type SubType<'a>: SubTrait; + | ^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-76535.rs:7:10 + | +LL | type SubType<'a>: SubTrait; + | ^^^^^^^ -- +help: use angle brackets to add missing lifetime argument + | +LL | type SubType<'a><'a>: SubTrait; + | ^^^^ + +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/issue-76535.rs:38:14 + | +LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | + = help: consider moving `get_sub` to another trait +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-76535.rs:10:37 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +... +LL | fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>; + | ^^^^^^^^^^^^^^^^^ ...because method `get_sub` references the `Self` type in its return type + +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/issue-76535.rs:38:57 + | +LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | + = help: consider moving `get_sub` to another trait +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-76535.rs:10:37 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +... +LL | fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>; + | ^^^^^^^^^^^^^^^^^ ...because method `get_sub` references the `Self` type in its return type + = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>` + = note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>` + +error: aborting due to 3 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/generic-associated-types/issue-79422.rs b/src/test/ui/generic-associated-types/issue-79422.rs new file mode 100644 index 00000000000..26b38430dd9 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-79422.rs @@ -0,0 +1,47 @@ +#![allow(incomplete_features)] +#![feature(generic_associated_types)] + +trait RefCont<'a, T> { + fn t(&'a self) -> &'a T; +} + +impl<'a, T> RefCont<'a, T> for &'a T { + fn t(&'a self) -> &'a T { + self + } +} + +impl<'a, T> RefCont<'a, T> for Box<T> { + fn t(&'a self) -> &'a T { + self.as_ref() + } +} + +trait MapLike<K, V> { + type VRefCont<'a>: RefCont<'a, V>; + //~^ ERROR missing generics + fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>; +} + +impl<K: Ord, V: 'static> MapLike<K, V> for std::collections::BTreeMap<K, V> { + type VRefCont<'a> = &'a V; + fn get<'a>(&'a self, key: &K) -> Option<&'a V> { + std::collections::BTreeMap::get(self, key) + } +} + +struct Source; + +impl<K, V: Default> MapLike<K, V> for Source { + type VRefCont<'a> = Box<V>; + fn get<'a>(&self, _: &K) -> Option<Box<V>> { + Some(Box::new(V::default())) + } +} + +fn main() { + let m = Box::new(std::collections::BTreeMap::<u8, u8>::new()) + as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; + //~^ ERROR the trait + //~^^^ ERROR the trait +} diff --git a/src/test/ui/generic-associated-types/issue-79422.stderr b/src/test/ui/generic-associated-types/issue-79422.stderr new file mode 100644 index 00000000000..d2e12962715 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-79422.stderr @@ -0,0 +1,54 @@ +error[E0107]: missing generics for associated type `MapLike::VRefCont` + --> $DIR/issue-79422.rs:21:10 + | +LL | type VRefCont<'a>: RefCont<'a, V>; + | ^^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-79422.rs:21:10 + | +LL | type VRefCont<'a>: RefCont<'a, V>; + | ^^^^^^^^ -- +help: use angle brackets to add missing lifetime argument + | +LL | type VRefCont<'a><'a>: RefCont<'a, V>; + | ^^^^ + +error[E0038]: the trait `MapLike` cannot be made into an object + --> $DIR/issue-79422.rs:44:12 + | +LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | + = help: consider moving `get` to another trait +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-79422.rs:23:38 + | +LL | trait MapLike<K, V> { + | ------- this trait cannot be made into an object... +... +LL | fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `get` references the `Self` type in its return type + +error[E0038]: the trait `MapLike` cannot be made into an object + --> $DIR/issue-79422.rs:43:13 + | +LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | + = help: consider moving `get` to another trait +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-79422.rs:23:38 + | +LL | trait MapLike<K, V> { + | ------- this trait cannot be made into an object... +... +LL | fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `get` references the `Self` type in its return type + = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>` + = note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/generic-associated-types/issue-80433-reduced.rs b/src/test/ui/generic-associated-types/issue-80433-reduced.rs new file mode 100644 index 00000000000..7c1673edc51 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-80433-reduced.rs @@ -0,0 +1,24 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(generic_associated_types)] + +struct E {} + +trait TestMut { + type Output<'a>; + fn test_mut(&mut self) -> Self::Output<'static>; +} + +impl TestMut for E { + type Output<'a> = usize; + fn test_mut(&mut self) -> Self::Output<'static> { + todo!() + } +} + +fn test_simpler<'a>(_: impl TestMut<Output<'a> = usize>) {} + +fn main() { + test_simpler(E {}); +} diff --git a/src/test/ui/generic-associated-types/issue-80433.rs b/src/test/ui/generic-associated-types/issue-80433.rs new file mode 100644 index 00000000000..ea65f05de23 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-80433.rs @@ -0,0 +1,35 @@ +#![feature(generic_associated_types)] +#![allow(incomplete_features)] + +#[derive(Default)] +struct E<T> { + data: T, +} + +trait TestMut { + type Output<'a>; + //~^ ERROR missing generics + fn test_mut<'a>(&'a mut self) -> Self::Output<'a>; +} + +impl<T> TestMut for E<T> +where + T: 'static, +{ + type Output<'a> = &'a mut T; + fn test_mut<'a>(&'a mut self) -> Self::Output<'a> { + &mut self.data + } +} + +fn test_simpler<'a>(dst: &'a mut impl TestMut<Output = &'a mut f32>) +{ + for n in 0i16..100 { + *dst.test_mut() = n.into(); + } +} + +fn main() { + let mut t1: E<f32> = Default::default(); + test_simpler(&mut t1); +} diff --git a/src/test/ui/generic-associated-types/issue-80433.stderr b/src/test/ui/generic-associated-types/issue-80433.stderr new file mode 100644 index 00000000000..5398920fafd --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-80433.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `TestMut::Output` + --> $DIR/issue-80433.rs:10:10 + | +LL | type Output<'a>; + | ^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-80433.rs:10:10 + | +LL | type Output<'a>; + | ^^^^^^ -- +help: use angle brackets to add missing lifetime argument + | +LL | type Output<'a><'a>; + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs index e203a5e0d2d..2d38770bcdf 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs +++ b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs @@ -1,10 +1,14 @@ #![feature(generic_associated_types)] + //~^ the feature `generic_associated_types` is incomplete trait X { type Y<'a>; + //~^ ERROR this associated type + //~| ERROR this associated type } const _: () = { fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {} - //~^ ERROR: generic associated types in trait paths are currently not implemented }; + +fn main() {} diff --git a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr index e59a72a99ee..60b8fb9bcaa 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr @@ -1,8 +1,49 @@ -error: generic associated types in trait paths are currently not implemented - --> $DIR/trait-path-type-error-once-implemented.rs:8:30 +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/trait-path-type-error-once-implemented.rs:1:12 | -LL | fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {} - | ^^^ +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information + +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/trait-path-type-error-once-implemented.rs:5:10 + | +LL | type Y<'a>; + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/trait-path-type-error-once-implemented.rs:5:10 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn f2<'a>(arg : Box<dyn X<Y<'a1> = &'a ()>>) {} + | ^^ + +error[E0107]: this associated type takes 0 const arguments but 1 const argument was supplied + --> $DIR/trait-path-type-error-once-implemented.rs:5:10 + | +LL | type Y<'a>; + | __________^- + | | | + | | expected 0 const arguments +LL | | +LL | | +LL | | } +LL | | +LL | | const _: () = { +LL | | fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {} + | |________________________________- help: remove these generics + | +note: associated type defined here, with 0 const parameters + --> $DIR/trait-path-type-error-once-implemented.rs:5:10 + | +LL | type Y<'a>; + | ^ -error: aborting due to previous error +error: aborting due to 2 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs b/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs deleted file mode 100644 index 02d53d5faee..00000000000 --- a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(generic_associated_types)] - -trait X { - type Y<'a>; -} - -const _: () = { - fn f1<'a>(arg : Box<dyn X<Y<'a> = &'a ()>>) {} - //~^ ERROR: generic associated types in trait paths are currently not implemented -}; - -const _: () = { - fn f1<'a>(arg : Box<dyn X<Y('a) = &'a ()>>) {} - //~^ ERROR: lifetime in trait object type must be followed by `+` -}; - -fn main() {} diff --git a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr b/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr deleted file mode 100644 index 1fba9cebd24..00000000000 --- a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: lifetime in trait object type must be followed by `+` - --> $DIR/trait-path-unimplemented.rs:13:31 - | -LL | fn f1<'a>(arg : Box<dyn X<Y('a) = &'a ()>>) {} - | ^^ - -error: generic associated types in trait paths are currently not implemented - --> $DIR/trait-path-unimplemented.rs:8:30 - | -LL | fn f1<'a>(arg : Box<dyn X<Y<'a> = &'a ()>>) {} - | ^^^^ - -error: aborting due to 2 previous errors - |
