From abd8c38a28aa6ccb43426add1e87ac65b53e64fc Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Wed, 22 Apr 2026 15:24:30 +0300 Subject: [PATCH] Support self ty propagation for functions in free to trait reuse --- compiler/rustc_ast_lowering/src/delegation.rs | 11 +- .../src/delegation/generics.rs | 15 +- compiler/rustc_hir/src/hir.rs | 2 + compiler/rustc_hir_analysis/src/delegation.rs | 106 ++++++++++---- tests/pretty/delegation-inherit-attributes.pp | 4 +- .../generics/free-fn-to-trait-infer.rs | 2 +- .../generics/free-fn-to-trait-infer.stderr | 28 ++-- .../generics/free-to-trait-self-reuse.rs | 56 ++++++++ .../generics/free-to-trait-self-reuse.stderr | 123 +++++++++++++++++ .../generics/free-to-trait-static-reuse.rs | 46 +++++++ .../free-to-trait-static-reuse.stderr | 129 ++++++++++++++++++ .../generics/mapping/free-to-trait-pass.rs | 10 +- .../generics/synth-params-ice-154780.rs | 4 +- 13 files changed, 477 insertions(+), 59 deletions(-) create mode 100644 tests/ui/delegation/generics/free-to-trait-self-reuse.rs create mode 100644 tests/ui/delegation/generics/free-to-trait-self-reuse.stderr create mode 100644 tests/ui/delegation/generics/free-to-trait-static-reuse.rs create mode 100644 tests/ui/delegation/generics/free-to-trait-static-reuse.stderr diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 01382a69f2ec..593eac2df489 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -143,7 +143,8 @@ pub(crate) fn lower_delegation( let (param_count, c_variadic) = self.param_count(sig_id); - let mut generics = self.uplift_delegation_generics(delegation, sig_id, item_id); + let mut generics = + self.uplift_delegation_generics(delegation, sig_id, item_id, is_method); let body_id = self.lower_delegation_body( delegation, @@ -301,6 +302,8 @@ fn lower_delegation_decl( hir::InferDelegationSig::Output(self.arena.alloc(hir::DelegationGenerics { child_args_segment_id: generics.child.args_segment_id, parent_args_segment_id: generics.parent.args_segment_id, + self_ty_id: generics.self_ty_id, + propagate_self_ty: generics.propagate_self_ty, })), )), span, @@ -554,6 +557,12 @@ fn finalize_body_lowering( } }; + generics.self_ty_id = match new_path { + hir::QPath::Resolved(ty, _) => ty, + hir::QPath::TypeRelative(ty, _) => Some(ty), + } + .map(|ty| ty.hir_id); + let callee_path = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(new_path), span)); self.arena.alloc(self.mk_expr(hir::ExprKind::Call(callee_path, args), span)) }; diff --git a/compiler/rustc_ast_lowering/src/delegation/generics.rs b/compiler/rustc_ast_lowering/src/delegation/generics.rs index 01b17438bc7f..201f6bfb4bd6 100644 --- a/compiler/rustc_ast_lowering/src/delegation/generics.rs +++ b/compiler/rustc_ast_lowering/src/delegation/generics.rs @@ -67,6 +67,8 @@ pub(super) struct GenericsGenerationResult<'hir> { pub(super) struct GenericsGenerationResults<'hir> { pub(super) parent: GenericsGenerationResult<'hir>, pub(super) child: GenericsGenerationResult<'hir>, + pub(super) self_ty_id: Option, + pub(super) propagate_self_ty: bool, } pub(super) struct GenericArgsPropagationDetails { @@ -209,6 +211,7 @@ pub(super) fn uplift_delegation_generics( delegation: &Delegation, sig_id: DefId, item_id: NodeId, + is_method: bool, ) -> GenericsGenerationResults<'hir> { let delegation_parent_kind = self.tcx.def_kind(self.tcx.local_parent(self.local_def_id(item_id))); @@ -230,7 +233,12 @@ pub(super) fn uplift_delegation_generics( let child = DelegationGenerics::trait_impl(sig_params, child_user_specified); let child = GenericsGenerationResult::new(child); - return GenericsGenerationResults { parent, child }; + return GenericsGenerationResults { + parent, + child, + self_ty_id: None, + propagate_self_ty: false, + }; } let delegation_in_free_ctx = @@ -238,13 +246,14 @@ pub(super) fn uplift_delegation_generics( let sig_parent = self.tcx.parent(sig_id); let sig_in_trait = matches!(self.tcx.def_kind(sig_parent), DefKind::Trait); + let free_to_trait_delegation = delegation_in_free_ctx && sig_in_trait; + let generate_self = free_to_trait_delegation && is_method && delegation.qself.is_none(); let can_add_generics_to_parent = len >= 2 && self.get_resolution_id(segments[len - 2].id).is_some_and(|def_id| { matches!(self.tcx.def_kind(def_id), DefKind::Trait | DefKind::TraitAlias) }); - let generate_self = delegation_in_free_ctx && sig_in_trait; let parent_generics = if can_add_generics_to_parent { let sig_parent_params = &self.tcx.generics_of(sig_parent).own_params[..]; @@ -278,6 +287,8 @@ pub(super) fn uplift_delegation_generics( GenericsGenerationResults { parent: GenericsGenerationResult::new(parent_generics), child: GenericsGenerationResult::new(child_generics), + self_ty_id: None, + propagate_self_ty: free_to_trait_delegation && !generate_self, } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d8149b4e30a5..3055682bf04c 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3761,6 +3761,8 @@ pub enum OpaqueTyOrigin { pub struct DelegationGenerics { pub parent_args_segment_id: Option, pub child_args_segment_id: Option, + pub self_ty_id: Option, + pub propagate_self_ty: bool, } #[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)] diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index da9d3f229089..be8a8e228c47 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{HirId, PathSegment}; +use rustc_hir::{DelegationGenerics, HirId, PathSegment}; use rustc_middle::ty::{ self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -65,19 +65,35 @@ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { } enum SelfPositionKind { - AfterLifetimes, + AfterLifetimes(bool /* Should propagate self ty */), Zero, None, } -fn create_self_position_kind(caller_kind: FnKind, callee_kind: FnKind) -> SelfPositionKind { - match (caller_kind, callee_kind) { +fn get_delegation_generics(tcx: TyCtxt<'_>, delegation_id: LocalDefId) -> &DelegationGenerics { + tcx.hir_node(tcx.local_def_id_to_hir_id(delegation_id)) + .fn_sig() + .expect("processing delegation") + .decl + .opt_delegation_generics() + .expect("processing delegation") +} + +fn create_self_position_kind( + tcx: TyCtxt<'_>, + delegation_id: LocalDefId, + sig_id: DefId, +) -> SelfPositionKind { + match (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id)) { (FnKind::AssocInherentImpl, FnKind::AssocTrait) | (FnKind::AssocTraitImpl, FnKind::AssocTrait) | (FnKind::AssocTrait, FnKind::AssocTrait) | (FnKind::AssocTrait, FnKind::Free) => SelfPositionKind::Zero, - (FnKind::Free, FnKind::AssocTrait) => SelfPositionKind::AfterLifetimes, + (FnKind::Free, FnKind::AssocTrait) => { + let propagate_self_ty = get_delegation_generics(tcx, delegation_id).propagate_self_ty; + SelfPositionKind::AfterLifetimes(propagate_self_ty) + } _ => SelfPositionKind::None, } @@ -141,8 +157,7 @@ fn create_mapping<'tcx>( ) -> FxHashMap { let mut mapping: FxHashMap = Default::default(); - let (caller_kind, callee_kind) = (fn_kind(tcx, def_id), fn_kind(tcx, sig_id)); - let self_pos_kind = create_self_position_kind(caller_kind, callee_kind); + let self_pos_kind = create_self_position_kind(tcx, def_id, sig_id); let is_self_at_zero = matches!(self_pos_kind, SelfPositionKind::Zero); // Is self at zero? If so insert mapping, self in sig parent is always at 0. @@ -156,7 +171,7 @@ fn create_mapping<'tcx>( args_index += get_delegation_parent_args_count_without_self(tcx, def_id, sig_id); let sig_generics = tcx.generics_of(sig_id); - let process_sig_parent_generics = matches!(callee_kind, FnKind::AssocTrait); + let process_sig_parent_generics = matches!(fn_kind(tcx, sig_id), FnKind::AssocTrait); if process_sig_parent_generics { for i in (sig_generics.has_self as usize)..sig_generics.parent_count { @@ -176,7 +191,9 @@ fn create_mapping<'tcx>( } // If self after lifetimes insert mapping, relying that self is at 0 in sig parent. - if matches!(self_pos_kind, SelfPositionKind::AfterLifetimes) { + // If self ty is propagated (meaning there is no generic param `Self`), the specified + // self ty will be inserted in args in `create_generic_args`. + if matches!(self_pos_kind, SelfPositionKind::AfterLifetimes { .. }) { mapping.insert(0, args_index as u32); args_index += 1; } @@ -259,6 +276,22 @@ fn get_parent_and_inheritance_kind<'tcx>( } } +fn get_delegation_self_ty_or_err(tcx: TyCtxt<'_>, delegation_id: LocalDefId) -> Ty<'_> { + get_delegation_generics(tcx, delegation_id) + .self_ty_id + .map(|id| { + let ctx = ItemCtxt::new(tcx, delegation_id); + ctx.lower_ty(tcx.hir_node(id).expect_ty()) + }) + .unwrap_or_else(|| { + Ty::new_error_with_message( + tcx, + tcx.def_span(delegation_id), + "the self type must be specified", + ) + }) +} + fn get_delegation_self_ty<'tcx>(tcx: TyCtxt<'tcx>, delegation_id: LocalDefId) -> Option> { let sig_id = tcx.hir_opt_delegation_sig_id(delegation_id).expect("Delegation must have sig_id"); let (caller_kind, callee_kind) = (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id)); @@ -269,15 +302,19 @@ fn get_delegation_self_ty<'tcx>(tcx: TyCtxt<'tcx>, delegation_id: LocalDefId) -> | (FnKind::Free, FnKind::Free) | (FnKind::AssocTrait, FnKind::Free) | (FnKind::AssocTrait, FnKind::AssocTrait) => { - match create_self_position_kind(caller_kind, callee_kind) { + match create_self_position_kind(tcx, delegation_id, sig_id) { SelfPositionKind::None => None, - SelfPositionKind::AfterLifetimes => { - // Both sig parent and child lifetimes are in included in this count. - Some(tcx.generics_of(delegation_id).own_counts().lifetimes) + SelfPositionKind::AfterLifetimes(propagate_self_ty) => { + if propagate_self_ty { + Some(get_delegation_self_ty_or_err(tcx, delegation_id)) + } else { + // Both sig parent and child lifetimes are in included in this count. + let index = tcx.generics_of(delegation_id).own_counts().lifetimes; + Some(Ty::new_param(tcx, index as u32, kw::SelfUpper)) + } } - SelfPositionKind::Zero => Some(0), + SelfPositionKind::Zero => Some(Ty::new_param(tcx, 0, kw::SelfUpper)), } - .map(|self_index| Ty::new_param(tcx, self_index as u32, kw::SelfUpper)) } (FnKind::AssocTraitImpl, FnKind::AssocTrait) @@ -366,7 +403,7 @@ fn create_generic_args<'tcx>( let mut new_args = vec![]; - let self_pos_kind = create_self_position_kind(caller_kind, callee_kind); + let self_pos_kind = create_self_position_kind(tcx, delegation_id, sig_id); let mut lifetimes_end_pos; if !parent_args.is_empty() { @@ -374,7 +411,7 @@ fn create_generic_args<'tcx>( parent_args.iter().filter(|a| a.as_region().is_some()).count(); match self_pos_kind { - SelfPositionKind::AfterLifetimes => { + SelfPositionKind::AfterLifetimes { .. } => { new_args.extend(&parent_args[1..1 + parent_args_lifetimes_count]); lifetimes_end_pos = parent_args_lifetimes_count; @@ -407,6 +444,15 @@ fn create_generic_args<'tcx>( .count(); new_args.extend_from_slice(args); + + // Parent args are empty, then if we should propagate self ty (meaning Self generic + // param was not generated) then we should insert it, as it won't be in `args`. + if matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(true)) { + new_args.insert( + lifetimes_end_pos, + ty::GenericArg::from(get_delegation_self_ty_or_err(tcx, delegation_id)), + ); + } } if !child_args.is_empty() { @@ -427,7 +473,8 @@ fn create_generic_args<'tcx>( new_args.insert(lifetimes_end_pos + i, child_args[i]); } - let skip_self = matches!(self_pos_kind, SelfPositionKind::AfterLifetimes); + // If self_ty is propagated it means that Self generic param was not generated. + let skip_self = matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(false)); new_args.extend(&child_args[child_lifetimes_count + skip_self as usize..]); } @@ -446,6 +493,7 @@ struct PredicatesCollector<'tcx> { preds: Vec<(ty::Clause<'tcx>, Span)>, args: Vec>, folder: ParamIndexRemapper<'tcx>, + filter_self_preds: bool, } impl<'tcx> PredicatesCollector<'tcx> { @@ -458,6 +506,16 @@ fn with_own_preds( let args = self.args.as_slice(); for pred in preds.predicates { + // If self ty is specified then there will be no generic param `Self`, + // so we do not need its predicates. + if self.filter_self_preds + && let Some(trait_pred) = pred.0.as_trait_clause() + // Rely that `Self` has zero index. + && trait_pred.self_ty().skip_binder().is_param(0) + { + continue; + } + let new_pred = pred.0.fold_with(&mut self.folder); self.preds.push(( EarlyBinder::bind(new_pred).instantiate(self.tcx, args).skip_norm_wip(), @@ -484,8 +542,10 @@ fn with_preds( let (parent_args, child_args) = get_delegation_user_specified_args(tcx, def_id); let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args); - let collector = PredicatesCollector { tcx, preds: vec![], args, folder }; + let self_pos_kind = create_self_position_kind(tcx, def_id, sig_id); + let filter_self_preds = matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(true)); + let collector = PredicatesCollector { tcx, preds: vec![], args, folder, filter_self_preds }; let (parent, inh_kind) = get_parent_and_inheritance_kind(tcx, def_id, sig_id); // `explicit_predicates_of` is used here to avoid copying `Self: Trait` predicate. @@ -573,13 +633,7 @@ fn get_delegation_user_specified_args<'tcx>( tcx: TyCtxt<'tcx>, delegation_id: LocalDefId, ) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) { - let info = tcx - .hir_node(tcx.local_def_id_to_hir_id(delegation_id)) - .fn_sig() - .expect("Lowering delegation") - .decl - .opt_delegation_generics() - .expect("Lowering delegation"); + let info = get_delegation_generics(tcx, delegation_id); let get_segment = |hir_id: HirId| -> Option<(&'tcx PathSegment<'tcx>, DefId)> { let segment = tcx.hir_node(hir_id).expect_path_segment(); diff --git a/tests/pretty/delegation-inherit-attributes.pp b/tests/pretty/delegation-inherit-attributes.pp index 242e7161aa84..e29f76089256 100644 --- a/tests/pretty/delegation-inherit-attributes.pp +++ b/tests/pretty/delegation-inherit-attributes.pp @@ -114,10 +114,10 @@ mod recursive { #[attr = MustUse {reason: "some reason"}] #[attr = Inline(Hint)] - fn foo(self: _, arg1: _) -> _ { ::foo(self + 1, arg1) } + fn foo(self: _, arg1: _) -> _ { ::foo(self + 1, arg1) } #[attr = MustUse {reason: "some reason"}] #[attr = Inline(Hint)] - fn bar(arg0: _, arg1: _) -> _ { foo(self + 1, arg1) } + fn bar(arg0: _, arg1: _) -> _ { foo(self + 1, arg1) } } } diff --git a/tests/ui/delegation/generics/free-fn-to-trait-infer.rs b/tests/ui/delegation/generics/free-fn-to-trait-infer.rs index 905fc8cf21d7..f89c17fe266c 100644 --- a/tests/ui/delegation/generics/free-fn-to-trait-infer.rs +++ b/tests/ui/delegation/generics/free-fn-to-trait-infer.rs @@ -13,8 +13,8 @@ impl Trait for u8 {} //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions reuse >::foo as generic_arguments2; //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions -//~| ERROR mismatched types reuse <_ as Trait<_>>::foo as generic_arguments3; //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions +//~| ERROR the placeholder `_` is not allowed within types on item signatures for functions fn main() {} diff --git a/tests/ui/delegation/generics/free-fn-to-trait-infer.stderr b/tests/ui/delegation/generics/free-fn-to-trait-infer.stderr index a20b28c16402..05956f045a27 100644 --- a/tests/ui/delegation/generics/free-fn-to-trait-infer.stderr +++ b/tests/ui/delegation/generics/free-fn-to-trait-infer.stderr @@ -11,29 +11,17 @@ LL | reuse >::foo as generic_arguments2; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/free-fn-to-trait-infer.rs:17:19 + --> $DIR/free-fn-to-trait-infer.rs:16:8 + | +LL | reuse <_ as Trait<_>>::foo as generic_arguments3; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/free-fn-to-trait-infer.rs:16:19 | LL | reuse <_ as Trait<_>>::foo as generic_arguments3; | ^ not allowed in type signatures -error[E0308]: mismatched types - --> $DIR/free-fn-to-trait-infer.rs:14:25 - | -LL | reuse >::foo as generic_arguments2; - | ^^^ - | | - | expected `&u8`, found `&Self` - | arguments to this function are incorrect - | - = note: expected reference `&u8` - found reference `&Self` -note: method defined here - --> $DIR/free-fn-to-trait-infer.rs:7:8 - | -LL | fn foo(&self, _: U, _: T) {} - | ^^^ ----- - error: aborting due to 4 previous errors -Some errors have detailed explanations: E0121, E0308. -For more information about an error, try `rustc --explain E0121`. +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/delegation/generics/free-to-trait-self-reuse.rs b/tests/ui/delegation/generics/free-to-trait-self-reuse.rs new file mode 100644 index 000000000000..4714fa471432 --- /dev/null +++ b/tests/ui/delegation/generics/free-to-trait-self-reuse.rs @@ -0,0 +1,56 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +trait Bound {} + +trait Trait<'a, T, const X: usize> +where + Self: Bound + Sized, +{ + fn method(&self, x: U) {} + fn method2(self, x: U) {} + fn method3(&mut self, x: U) {} +} + +impl<'a, T, const X: usize> Trait<'a, T, X> for usize {} +impl Bound for usize {} + +reuse >::method as foo; +reuse >::method:: as foo2; +reuse ::method as bar; +reuse ::method::, false> as bar2; + +reuse Trait::<'static, i32, 123>::method as foo3; +reuse Trait::<'static, i32, 123>::method2:: as foo4; +reuse Trait::method3 as bar3; +reuse Trait::method3::, false> as bar4; + +reuse ::method as error5; +//~^ ERROR: the trait bound `String: Trait<'a, T, X>` is not satisfied + +struct Struct; +impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} +//~^ ERROR: the trait bound `Struct: Bound` is not satisfied + +reuse ::method as error6; +//~^ ERROR: the trait bound `Struct: Bound` is not satisfied + +fn main() { + foo::<&'static str, true>(&123, ""); + foo2(&123, "".to_string()); + bar::<'static, i32, 123, String, false>(&123, "".to_string()); + bar2::<'static, usize, 321>(&123, vec![213, 123]); + + foo3::(&123, "".to_string()); + //~^ ERROR: function takes 3 generic arguments but 2 generic arguments were supplied + foo4(123, "".to_string()); + bar3::<'static, i32, 123, bool, false>(&mut 123, true); + //~^ ERROR: function takes 5 generic arguments but 4 generic arguments were supplied + bar4::<'static, usize, 321>(&mut 123, vec![123]); + //~^ ERROR: function takes 3 generic arguments but 2 generic arguments were supplied + + foo3::(&123, "".to_string()); + foo4::(123, "".to_string()); + bar3::<'static, usize, i32, 123, String, false>(&mut 123, "".to_string()); + bar4::<'static, usize, usize, 321>(&mut 123, vec![123]); +} diff --git a/tests/ui/delegation/generics/free-to-trait-self-reuse.stderr b/tests/ui/delegation/generics/free-to-trait-self-reuse.stderr new file mode 100644 index 000000000000..842f4cd4eb39 --- /dev/null +++ b/tests/ui/delegation/generics/free-to-trait-self-reuse.stderr @@ -0,0 +1,123 @@ +error[E0277]: the trait bound `Struct: Bound` is not satisfied + --> $DIR/free-to-trait-self-reuse.rs:32:49 + | +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} + | ^^^^^^ unsatisfied trait bound + | +help: the trait `Bound` is not implemented for `Struct` + --> $DIR/free-to-trait-self-reuse.rs:31:1 + | +LL | struct Struct; + | ^^^^^^^^^^^^^ +help: the trait `Bound` is implemented for `usize` + --> $DIR/free-to-trait-self-reuse.rs:16:1 + | +LL | impl Bound for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `Trait` + --> $DIR/free-to-trait-self-reuse.rs:8:11 + | +LL | trait Trait<'a, T, const X: usize> + | ----- required by a bound in this trait +LL | where +LL | Self: Bound + Sized, + | ^^^^^^^^ required by this bound in `Trait` + +error[E0277]: the trait bound `String: Trait<'a, T, X>` is not satisfied + --> $DIR/free-to-trait-self-reuse.rs:28:8 + | +LL | reuse ::method as error5; + | ^^^^^^ the trait `Trait<'a, T, X>` is not implemented for `String` + | +help: the following other types implement trait `Trait<'a, T, X>` + --> $DIR/free-to-trait-self-reuse.rs:15:1 + | +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `usize` +... +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Struct` + +error[E0277]: the trait bound `Struct: Bound` is not satisfied + --> $DIR/free-to-trait-self-reuse.rs:35:8 + | +LL | reuse ::method as error6; + | ^^^^^^ unsatisfied trait bound + | +help: the trait `Bound` is not implemented for `Struct` + --> $DIR/free-to-trait-self-reuse.rs:31:1 + | +LL | struct Struct; + | ^^^^^^^^^^^^^ +help: the trait `Bound` is implemented for `usize` + --> $DIR/free-to-trait-self-reuse.rs:16:1 + | +LL | impl Bound for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `Trait::method` + --> $DIR/free-to-trait-self-reuse.rs:8:11 + | +LL | Self: Bound + Sized, + | ^^^^^^^^ required by this bound in `Trait::method` +LL | { +LL | fn method(&self, x: U) {} + | ------ required by a bound in this associated function + +error[E0107]: function takes 3 generic arguments but 2 generic arguments were supplied + --> $DIR/free-to-trait-self-reuse.rs:44:5 + | +LL | foo3::(&123, "".to_string()); + | ^^^^ ------ ---- supplied 2 generic arguments + | | + | expected 3 generic arguments + | +note: function defined here, with 3 generic parameters: `Self`, `U`, `B` + --> $DIR/free-to-trait-self-reuse.rs:23:45 + | +LL | reuse Trait::<'static, i32, 123>::method as foo3; + | ------ ^^^^ +help: add missing generic argument + | +LL | foo3::(&123, "".to_string()); + | +++ + +error[E0107]: function takes 5 generic arguments but 4 generic arguments were supplied + --> $DIR/free-to-trait-self-reuse.rs:47:5 + | +LL | bar3::<'static, i32, 123, bool, false>(&mut 123, true); + | ^^^^ --- --- ---- ----- supplied 4 generic arguments + | | + | expected 5 generic arguments + | +note: function defined here, with 5 generic parameters: `Self`, `T`, `X`, `U`, `B` + --> $DIR/free-to-trait-self-reuse.rs:25:25 + | +LL | reuse Trait::method3 as bar3; + | ------- ^^^^ +help: add missing generic argument + | +LL | bar3::<'static, i32, 123, bool, false, B>(&mut 123, true); + | +++ + +error[E0107]: function takes 3 generic arguments but 2 generic arguments were supplied + --> $DIR/free-to-trait-self-reuse.rs:49:5 + | +LL | bar4::<'static, usize, 321>(&mut 123, vec![123]); + | ^^^^ ----- --- supplied 2 generic arguments + | | + | expected 3 generic arguments + | +note: function defined here, with 3 generic parameters: `Self`, `T`, `X` + --> $DIR/free-to-trait-self-reuse.rs:26:44 + | +LL | reuse Trait::method3::, false> as bar4; + | ------- ^^^^ +help: add missing generic argument + | +LL | bar4::<'static, usize, 321, X>(&mut 123, vec![123]); + | +++ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0107, E0277. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/delegation/generics/free-to-trait-static-reuse.rs b/tests/ui/delegation/generics/free-to-trait-static-reuse.rs new file mode 100644 index 000000000000..b82e3fcac1b3 --- /dev/null +++ b/tests/ui/delegation/generics/free-to-trait-static-reuse.rs @@ -0,0 +1,46 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +trait Bound {} + +trait Trait<'a, T, const X: usize> +where + Self: Bound, +{ + fn static_method<'c: 'c, U, const B: bool>(x: usize) {} +} + +impl<'a, T, const X: usize> Trait<'a, T, X> for usize {} +impl Bound for usize {} + +reuse >::static_method as foo { self + 2 } +reuse >::static_method::<'static, String, false> as foo2; +reuse ::static_method as bar { self + 1 } +reuse ::static_method::<'static, Vec, false> as bar2; + +reuse Trait::static_method as error { self - 123 } +//~^ ERROR: type annotations needed +reuse Trait::<'static, i32, 123>::static_method as error2; +//~^ ERROR: type annotations needed +reuse Trait::<'static, i32, 123>::static_method::<'static, String, false> as error3; +//~^ ERROR: type annotations needed +reuse Trait::static_method::<'static, Vec, false> as error4 { self + 4 } +//~^ ERROR: type annotations needed + +reuse ::static_method as error5; +//~^ ERROR: the trait bound `String: Trait<'a, T, X>` is not satisfied + +struct Struct; +impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} +//~^ ERROR: the trait bound `Struct: Bound` is not satisfied + +reuse ::static_method as error6; +//~^ ERROR: the trait bound `Struct: Bound` is not satisfied + +fn main() { + foo::<'static, String, true>(123); + foo2(123); + + bar::<'static, 'static, i32, 123, String, false>(123); + bar2::<'static, usize, 321>(123); +} diff --git a/tests/ui/delegation/generics/free-to-trait-static-reuse.stderr b/tests/ui/delegation/generics/free-to-trait-static-reuse.stderr new file mode 100644 index 000000000000..4ccbd0b072c3 --- /dev/null +++ b/tests/ui/delegation/generics/free-to-trait-static-reuse.stderr @@ -0,0 +1,129 @@ +error[E0277]: the trait bound `Struct: Bound` is not satisfied + --> $DIR/free-to-trait-static-reuse.rs:34:49 + | +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} + | ^^^^^^ unsatisfied trait bound + | +help: the trait `Bound` is not implemented for `Struct` + --> $DIR/free-to-trait-static-reuse.rs:33:1 + | +LL | struct Struct; + | ^^^^^^^^^^^^^ +help: the trait `Bound` is implemented for `usize` + --> $DIR/free-to-trait-static-reuse.rs:14:1 + | +LL | impl Bound for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `Trait` + --> $DIR/free-to-trait-static-reuse.rs:8:11 + | +LL | trait Trait<'a, T, const X: usize> + | ----- required by a bound in this trait +LL | where +LL | Self: Bound, + | ^^^^^^^^ required by this bound in `Trait` + +error[E0283]: type annotations needed + --> $DIR/free-to-trait-static-reuse.rs:21:14 + | +LL | reuse Trait::static_method as error { self - 123 } + | ^^^^^^^^^^^^^ cannot infer type + | +note: multiple `impl`s satisfying `_: Trait<'a, T, X>` found + --> $DIR/free-to-trait-static-reuse.rs:13:1 + | +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0283]: type annotations needed + --> $DIR/free-to-trait-static-reuse.rs:23:35 + | +LL | reuse Trait::<'static, i32, 123>::static_method as error2; + | ^^^^^^^^^^^^^ cannot infer type + | +note: multiple `impl`s satisfying `_: Trait<'static, i32, 123>` found + --> $DIR/free-to-trait-static-reuse.rs:13:1 + | +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0283]: type annotations needed + --> $DIR/free-to-trait-static-reuse.rs:25:35 + | +LL | reuse Trait::<'static, i32, 123>::static_method::<'static, String, false> as error3; + | ^^^^^^^^^^^^^ cannot infer type + | +note: multiple `impl`s satisfying `_: Trait<'static, i32, 123>` found + --> $DIR/free-to-trait-static-reuse.rs:13:1 + | +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0283]: type annotations needed + --> $DIR/free-to-trait-static-reuse.rs:27:14 + | +LL | reuse Trait::static_method::<'static, Vec, false> as error4 { self + 4 } + | ^^^^^^^^^^^^^ cannot infer type + | +note: multiple `impl`s satisfying `_: Trait<'a, T, X>` found + --> $DIR/free-to-trait-static-reuse.rs:13:1 + | +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `String: Trait<'a, T, X>` is not satisfied + --> $DIR/free-to-trait-static-reuse.rs:30:8 + | +LL | reuse ::static_method as error5; + | ^^^^^^ the trait `Trait<'a, T, X>` is not implemented for `String` + | +help: the following other types implement trait `Trait<'a, T, X>` + --> $DIR/free-to-trait-static-reuse.rs:13:1 + | +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `usize` +... +LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Struct` + +error[E0277]: the trait bound `Struct: Bound` is not satisfied + --> $DIR/free-to-trait-static-reuse.rs:37:8 + | +LL | reuse ::static_method as error6; + | ^^^^^^ unsatisfied trait bound + | +help: the trait `Bound` is not implemented for `Struct` + --> $DIR/free-to-trait-static-reuse.rs:33:1 + | +LL | struct Struct; + | ^^^^^^^^^^^^^ +help: the trait `Bound` is implemented for `usize` + --> $DIR/free-to-trait-static-reuse.rs:14:1 + | +LL | impl Bound for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `Trait::static_method` + --> $DIR/free-to-trait-static-reuse.rs:8:11 + | +LL | Self: Bound, + | ^^^^^^^^ required by this bound in `Trait::static_method` +LL | { +LL | fn static_method<'c: 'c, U, const B: bool>(x: usize) {} + | ------------- required by a bound in this associated function + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0277, E0283. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/generics/mapping/free-to-trait-pass.rs b/tests/ui/delegation/generics/mapping/free-to-trait-pass.rs index cd779a9887a2..112688183669 100644 --- a/tests/ui/delegation/generics/mapping/free-to-trait-pass.rs +++ b/tests/ui/delegation/generics/mapping/free-to-trait-pass.rs @@ -171,14 +171,14 @@ impl<'b, 'c, T> Trait<'b, 'c, T> for u8 {} pub fn check() { fn with_ctx<'a, 'b, 'c, A, B, C, const N: usize, const M: bool>() { reuse ::foo as bar; - bar::<'a, 'b, 'c, u8, C, A, M>(); - bar::<'static, 'static, 'static, u8, i32, i32, false>(); + bar::<'a, 'b, 'c, C, A, M>(); + bar::<'static, 'static, 'static, i32, i32, false>(); reuse >::foo as bar1; - bar1::<'static, u8, i32, true>(); + bar1::<'static, i32, true>(); reuse >::foo::<'static, u32, true> as bar2; - bar2::(); + bar2(); } with_ctx::(); @@ -211,7 +211,7 @@ impl Bound2>>> for Struct {} pub fn check<'b>() { reuse ::foo; - foo::<'static, 'b, usize, u32, Struct, String, false>(); + foo::<'static, 'b, u32, Struct, String, false>(); } } diff --git a/tests/ui/delegation/generics/synth-params-ice-154780.rs b/tests/ui/delegation/generics/synth-params-ice-154780.rs index 96af4ed86b4c..3ea52818a8f0 100644 --- a/tests/ui/delegation/generics/synth-params-ice-154780.rs +++ b/tests/ui/delegation/generics/synth-params-ice-154780.rs @@ -36,8 +36,8 @@ impl<'a, A, const B: bool> Trait<'a, A, B> for X {} reuse ::bar as bar2; pub fn check() { - assert_eq!(foo2::<'static, 'static, X, (), true, false, (), ()>(X, || 123), 123); - assert_eq!(bar2::<'static, X, (), true>(X, || 123), 123); + assert_eq!(foo2::<'static, 'static, (), true, false, (), ()>(X, || 123), 123); + assert_eq!(bar2::<'static, (), true>(X, || 123), 123); } }