diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index d390934f3b172..834571334ae56 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -43,14 +43,17 @@ use hir::def::{DefKind, Res}; use hir::{BodyId, HirId}; use rustc_abi::ExternAbi; use rustc_ast as ast; -use rustc_ast::*; -use rustc_data_structures::fx::FxHashSet; +use rustc_ast::{Block, Delegation, NodeId, StmtKind}; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::ErrorGuaranteed; use rustc_hir::attrs::{AttributeKind, InlineAttr}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, FnDeclFlags}; use rustc_middle::span_bug; -use rustc_middle::ty::Asyncness; +use rustc_middle::ty::{ + self, Asyncness, ClauseKind, ConstKind, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, + TypeVisitable, TypeVisitor, +}; use rustc_span::symbol::kw; use rustc_span::{Ident, Span, Symbol}; use smallvec::SmallVec; @@ -143,11 +146,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let (param_count, c_variadic) = self.param_count(sig_id); - let mut generics = - self.uplift_delegation_generics(delegation, sig_id, item_id, is_method); + let mut generics = self.uplift_delegation_generics(delegation, sig_id, is_method); let body_id = self.lower_delegation_body( delegation, + sig_id, is_method, param_count, &mut generics, @@ -162,8 +165,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let generics = self.arena.alloc(hir::Generics { has_where_clause_predicates: false, - params: self.arena.alloc_from_iter(generics.all_params(span, self)), - predicates: self.arena.alloc_from_iter(generics.all_predicates(span, self)), + params: self.arena.alloc_from_iter(generics.all_params()), + predicates: self.arena.alloc_from_iter(generics.all_predicates()), span, where_clause_span: span, }); @@ -398,6 +401,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_delegation_body( &mut self, delegation: &Delegation, + sig_id: DefId, is_method: bool, param_count: usize, generics: &mut GenericsGenerationResults<'hir>, @@ -442,7 +446,7 @@ impl<'hir> LoweringContext<'_, 'hir> { args.push(this.lower_target_expr(&block)); } - let final_expr = this.finalize_body_lowering(delegation, args, generics, span); + let final_expr = this.finalize_body_lowering(delegation, sig_id, args, generics, span); (this.arena.alloc_from_iter(parameters), final_expr) }) @@ -461,6 +465,105 @@ impl<'hir> LoweringContext<'_, 'hir> { self.mk_expr(hir::ExprKind::Block(block, None), block.span) } + fn find_used_parent_generics(&self, sig_id: DefId) -> &'hir FxIndexSet { + struct UsedParentGenericsCollector { + parent_count: u32, + used_parent_generics: FxIndexSet, + } + + impl<'tcx> TypeVisitor> for UsedParentGenericsCollector { + fn visit_ty(&mut self, ty: Ty<'tcx>) { + if let ty::Param(param) = ty.kind() { + self.check_if_parent_param(param.index); + } + + ty.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) { + if let ty::ReEarlyParam(param) = r.kind() { + self.check_if_parent_param(param.index); + } + } + + fn visit_const(&mut self, ct: ty::Const<'tcx>) { + if let ConstKind::Param(param) = ct.kind() { + self.check_if_parent_param(param.index); + } + + ct.super_visit_with(self) + } + } + + impl UsedParentGenericsCollector { + fn check_if_parent_param(&mut self, index: u32) { + // Don't consider usage of Self. + if index > 0 && index < self.parent_count { + self.used_parent_generics.insert(index); + } + } + } + + // If parent is not a trait then we have no parent generics, so exit early. + let parent = self.tcx.parent(sig_id); + if !matches!(self.tcx.def_kind(parent), DefKind::Trait) { + return self.arena.alloc(Default::default()); + } + + let mut collector = UsedParentGenericsCollector { + parent_count: self.tcx.generics_of(sig_id).parent_count as u32, + used_parent_generics: Default::default(), + }; + + // Find used parent generics in signature and in predicates of sig. function. + self.tcx.fn_sig(sig_id).skip_binder().visit_with(&mut collector); + for (pred, _) in self.tcx.predicates_of(sig_id).predicates { + pred.visit_with(&mut collector); + } + + // Next iterate over sig. function parent predicates and collect additional + // generic params that are used in those predicates. + // We start with parent generics that are used in signature or predicates of sig. function. + // The process will stop when no new generic params are added in `used_parent_generics` set. + loop { + let current_params = collector.used_parent_generics.clone(); + for ¶m in ¤t_params { + for (pred, _) in self.tcx.predicates_of(parent).predicates { + // Consider predicates of the following pattern: `T: Predicate`, where + // `T` is either a type parameter (i.e., `T: Bound<'a, TOther>`, `T: 'static + 'a`) + // or lifetime (i.e., `'a: 'b + 'c`). + let should_visit = match pred.as_predicate().kind().skip_binder() { + PredicateKind::Clause(clause_kind) => match clause_kind { + ClauseKind::Trait(trait_pred) => trait_pred.self_ty().is_param(param), + ClauseKind::RegionOutlives(outlives_predicate) => { + match outlives_predicate.0.kind() { + ty::ReEarlyParam(lifetime) if lifetime.index == param => true, + _ => false, + } + } + ClauseKind::TypeOutlives(outlives_predicate) => { + outlives_predicate.0.is_param(param) + } + _ => false, + }, + _ => false, + }; + + if should_visit { + pred.visit_with(&mut collector); + } + } + } + + // Stop when no new used parent generics params were found. + if collector.used_parent_generics.len() == current_params.len() { + break; + } + } + + self.arena.alloc(collector.used_parent_generics) + } + // Generates expression for the resulting body. If possible, `MethodCall` is used // to allow autoref/autoderef for target expression. For example in: // @@ -479,6 +582,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn finalize_body_lowering( &mut self, delegation: &Delegation, + sig_id: DefId, args: Vec>, generics: &mut GenericsGenerationResults<'hir>, span: Span, @@ -506,11 +610,25 @@ impl<'hir> LoweringContext<'_, 'hir> { None, ); - // FIXME(fn_delegation): proper support for parent generics propagation - // in method call scenario. let segment = self.process_segment(span, &segment, &mut generics.child); let segment = self.arena.alloc(segment); + // If `Self` generic param was generated then we will have to add all parent generics, + // as we will have a predicate `Self: Trait`. + let parent_generics = + (!generics.generated_self).then(|| self.find_used_parent_generics(sig_id)); + + // We do not propagate parent generics in method call but still need to uplift them + // so they are generated in delegation. + generics.parent.generics.into_hir_generics(self, parent_generics, span); + + let parent_generics = parent_generics.map_or(hir::MethodCallParentGenerics::All, |g| { + hir::MethodCallParentGenerics::Selected(g) + }); + + let parent_generics = hir::DelegationParentGenerics::MethodCall(parent_generics); + generics.parent.args_segment_id = Some(parent_generics); + self.arena.alloc(hir::Expr { hir_id: self.next_id(), kind: hir::ExprKind::MethodCall(segment, &args[0], &args[1..], span), @@ -575,16 +693,18 @@ impl<'hir> LoweringContext<'_, 'hir> { self.mk_expr(hir::ExprKind::Block(block, None), span) } - fn process_segment( + fn process_segment>( &mut self, span: Span, segment: &hir::PathSegment<'hir>, - result: &mut GenericsGenerationResult<'hir>, + result: &mut GenericsGenerationResult<'hir, T>, ) -> hir::PathSegment<'hir> { let details = result.generics.args_propagation_details(); + // Always uplift generic params, as if they are not empty then they + // should be generated in delegation. + let generics = result.generics.into_hir_generics(self, None, span); let segment = if details.should_propagate { - let generics = result.generics.into_hir_generics(self, span); let args = generics.into_generic_args(self, span); // Needed for better error messages (`trait-impl-wrong-args-count.rs` test). @@ -596,7 +716,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }; if details.use_args_in_sig_inheritance { - result.args_segment_id = Some(segment.hir_id); + result.args_segment_id = Some(T::from(segment.hir_id)); } segment diff --git a/compiler/rustc_ast_lowering/src/delegation/generics.rs b/compiler/rustc_ast_lowering/src/delegation/generics.rs index afffc20adf4b3..9822d48516c49 100644 --- a/compiler/rustc_ast_lowering/src/delegation/generics.rs +++ b/compiler/rustc_ast_lowering/src/delegation/generics.rs @@ -1,6 +1,7 @@ use hir::HirId; use hir::def::{DefKind, Res}; use rustc_ast::*; +use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::GenericParamDefKind; @@ -74,16 +75,17 @@ pub(super) enum HirOrTyGenerics<'hir> { Hir(DelegationGenerics<&'hir hir::Generics<'hir>>), } -pub(super) struct GenericsGenerationResult<'hir> { +pub(super) struct GenericsGenerationResult<'hir, T> { pub(super) generics: HirOrTyGenerics<'hir>, - pub(super) args_segment_id: Option, + pub(super) args_segment_id: Option, } pub(super) struct GenericsGenerationResults<'hir> { - pub(super) parent: GenericsGenerationResult<'hir>, - pub(super) child: GenericsGenerationResult<'hir>, + pub(super) parent: GenericsGenerationResult<'hir, hir::DelegationParentGenerics<'hir>>, + pub(super) child: GenericsGenerationResult<'hir, HirId>, pub(super) self_ty_id: Option, pub(super) propagate_self_ty: bool, + pub(super) generated_self: bool, } pub(super) struct GenericArgsPropagationDetails { @@ -115,11 +117,13 @@ impl<'hir> HirOrTyGenerics<'hir> { pub(super) fn into_hir_generics( &mut self, ctx: &mut LoweringContext<'_, 'hir>, + filter: Option<&'hir FxIndexSet>, span: Span, ) -> &mut HirOrTyGenerics<'hir> { if let HirOrTyGenerics::Ty(ty) = self { let rename_self = matches!(ty.pos, GenericsPosition::Child); - let params = ctx.uplift_delegation_generic_params(span, ty.generics, rename_self); + let params = + ctx.uplift_delegation_generic_params(span, ty.generics, rename_self, filter); *self = HirOrTyGenerics::Hir(DelegationGenerics { generics: params, @@ -162,31 +166,18 @@ impl<'hir> HirOrTyGenerics<'hir> { } } -impl<'hir> GenericsGenerationResult<'hir> { +impl<'hir, T> GenericsGenerationResult<'hir, T> { fn new( generics: DelegationGenerics<&'hir [ty::GenericParamDef]>, - ) -> GenericsGenerationResult<'hir> { + ) -> GenericsGenerationResult<'hir, T> { GenericsGenerationResult { generics: HirOrTyGenerics::Ty(generics), args_segment_id: None } } } impl<'hir> GenericsGenerationResults<'hir> { - pub(super) fn all_params( - &mut self, - span: Span, - ctx: &mut LoweringContext<'_, 'hir>, - ) -> impl Iterator> { - // Now we always call `into_hir_generics` both on child and parent, - // however in future we would not do that, when scenarios like - // method call will be supported (if HIR generics were not obtained - // then it means that we did not propagated them, thus we do not need - // to generate params). - let mut create_params = |result: &mut GenericsGenerationResult<'hir>| { - result.generics.into_hir_generics(ctx, span).hir_generics_or_empty().params - }; - - let parent = create_params(&mut self.parent); - let child = create_params(&mut self.child); + pub(super) fn all_params(&mut self) -> impl Iterator> { + let parent = self.parent.generics.hir_generics_or_empty().params; + let child = self.child.generics.hir_generics_or_empty().params; // Order generics, first we have parent and child lifetimes, // then parent and child types and consts. @@ -205,24 +196,14 @@ impl<'hir> GenericsGenerationResults<'hir> { /// and `generate_lifetime_predicate` functions) we need to add them to delegation generics. /// Those predicates will not affect resulting predicate inheritance and folding /// in `rustc_hir_analysis`, as we inherit all predicates from delegation signature. - pub(super) fn all_predicates( - &mut self, - span: Span, - ctx: &mut LoweringContext<'_, 'hir>, - ) -> impl Iterator> { - // Now we always call `into_hir_generics` both on child and parent, - // however in future we would not do that, when scenarios like - // method call will be supported (if HIR generics were not obtained - // then it means that we did not propagated them, thus we do not need - // to generate predicates). - let mut create_predicates = |result: &mut GenericsGenerationResult<'hir>| { - result.generics.into_hir_generics(ctx, span).hir_generics_or_empty().predicates - }; - - let parent = create_predicates(&mut self.parent); - let child = create_predicates(&mut self.child); - - parent.into_iter().chain(child).copied() + pub(super) fn all_predicates(&mut self) -> impl Iterator> { + self.parent + .generics + .hir_generics_or_empty() + .predicates + .into_iter() + .chain(self.child.generics.hir_generics_or_empty().predicates) + .copied() } } @@ -231,17 +212,14 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, 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))); - + let delegation_id = self.current_hir_id_owner.def_id; let segments = &delegation.path.segments; let len = segments.len(); let child_user_specified = segments[len - 1].args.is_some(); - let sig_params = &self.tcx.generics_of(sig_id).own_params[..]; + let delegation_parent_kind = self.tcx.def_kind(self.tcx.local_parent(delegation_id)); // If we are in trait impl always generate function whose generics matches // those that are defined in trait. @@ -264,6 +242,7 @@ impl<'hir> LoweringContext<'_, 'hir> { child, self_ty_id: None, propagate_self_ty: false, + generated_self: false, }; } @@ -322,6 +301,7 @@ impl<'hir> LoweringContext<'_, 'hir> { child: GenericsGenerationResult::new(child_generics), self_ty_id: None, propagate_self_ty: free_to_trait_delegation && !generate_self, + generated_self: generate_self, } } @@ -330,66 +310,73 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, params: &'hir [ty::GenericParamDef], rename_self: bool, + filter: Option<&'hir FxIndexSet>, ) -> &'hir hir::Generics<'hir> { - let params = self.arena.alloc_from_iter(params.iter().map(|p| { - let def_kind = match p.kind { - GenericParamDefKind::Lifetime => DefKind::LifetimeParam, - GenericParamDefKind::Type { .. } => DefKind::TyParam, - GenericParamDefKind::Const { .. } => DefKind::ConstParam, - }; - - // Rename Self generic param to This so it is properly propagated. - // If the user will create a function `fn foo() {}` with generic - // param "Self" then it will not be generated in HIR, the same thing - // applies to traits, `trait Trait {}` will be represented as - // `trait Trait {}` in HIR and "unexpected keyword `Self` in generic parameters" - // error will be emitted. - // Note that we do not rename `Self` to `This` after non-recursive reuse - // from Trait, in this case the `Self` should not be propagated - // (we rely that implicit `Self` generic param of a trait is named "Self") - // and it is OK to have Self generic param generated during lowering. - let param_name = - if rename_self && p.name == kw::SelfUpper { sym::This } else { p.name }; - - let param_ident = Ident::new(param_name, span); - let def_name = Some(param_ident.name); - let node_id = self.next_node_id(); - - let def_id = self.create_def(node_id, def_name, def_kind, span); - - let kind = match p.kind { - GenericParamDefKind::Lifetime => { - hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } - } - GenericParamDefKind::Type { synthetic, .. } => { - hir::GenericParamKind::Type { default: None, synthetic } - } - GenericParamDefKind::Const { .. } => { - let hir_id = self.next_id(); - let kind = hir::TyKind::InferDelegation(hir::InferDelegation::DefId(p.def_id)); - - hir::GenericParamKind::Const { - ty: self.arena.alloc(hir::Ty { kind, hir_id, span }), - default: None, + let params = self.arena.alloc_from_iter( + params + .iter() + .filter(|p| p.name == kw::SelfUpper || filter.is_none_or(|f| f.contains(&p.index))) + .map(|p| { + let def_kind = match p.kind { + GenericParamDefKind::Lifetime => DefKind::LifetimeParam, + GenericParamDefKind::Type { .. } => DefKind::TyParam, + GenericParamDefKind::Const { .. } => DefKind::ConstParam, + }; + + // Rename Self generic param to This so it is properly propagated. + // If the user will create a function `fn foo() {}` with generic + // param "Self" then it will not be generated in HIR, the same thing + // applies to traits, `trait Trait {}` will be represented as + // `trait Trait {}` in HIR and "unexpected keyword `Self` in generic parameters" + // error will be emitted. + // Note that we do not rename `Self` to `This` after non-recursive reuse + // from Trait, in this case the `Self` should not be propagated + // (we rely that implicit `Self` generic param of a trait is named "Self") + // and it is OK to have Self generic param generated during lowering. + let param_name = + if rename_self && p.name == kw::SelfUpper { sym::This } else { p.name }; + + let param_ident = Ident::new(param_name, span); + let def_name = Some(param_ident.name); + let node_id = self.next_node_id(); + + let def_id = self.create_def(node_id, def_name, def_kind, span); + + let kind = match p.kind { + GenericParamDefKind::Lifetime => hir::GenericParamKind::Lifetime { + kind: hir::LifetimeParamKind::Explicit, + }, + GenericParamDefKind::Type { synthetic, .. } => { + hir::GenericParamKind::Type { default: None, synthetic } + } + GenericParamDefKind::Const { .. } => { + let hir_id = self.next_id(); + let kind = + hir::TyKind::InferDelegation(hir::InferDelegation::DefId(p.def_id)); + + hir::GenericParamKind::Const { + ty: self.arena.alloc(hir::Ty { kind, hir_id, span }), + default: None, + } + } + }; + + // Important: we don't use `self.next_id()` as we want to execute + // `lower_node_id` routine so param's id is added to `self.children`. + let hir_id = self.lower_node_id(node_id); + + hir::GenericParam { + hir_id, + colon_span: Some(span), + def_id, + kind, + name: hir::ParamName::Plain(param_ident), + pure_wrt_drop: p.pure_wrt_drop, + source: hir::GenericParamSource::Generics, + span, } - } - }; - - // Important: we don't use `self.next_id()` as we want to execute - // `lower_node_id` routine so param's id is added to `self.children`. - let hir_id = self.lower_node_id(node_id); - - hir::GenericParam { - hir_id, - colon_span: Some(span), - def_id, - kind, - name: hir::ParamName::Plain(param_ident), - pure_wrt_drop: p.pure_wrt_drop, - source: hir::GenericParamSource::Generics, - span, - } - })); + }), + ); // HACK: for now we generate predicates such that all lifetimes are early bound, // we can not not generate early-bound lifetimes, but we can't know which of them diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index 180cb6497e7ab..53e59fbb13a86 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -9,6 +9,7 @@ macro_rules! arena_types { [] attribute: rustc_hir::Attribute, [] owner_info: rustc_hir::OwnerInfo<'tcx>, [] macro_def: rustc_ast::MacroDef, + [] index_set: rustc_data_structures::fx::FxIndexSet, ]); ) } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d8e675c6c56b4..5016750bc2329 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -17,6 +17,7 @@ pub use rustc_ast::{ MetaItemInner, MetaItemLit, Movability, Mutability, Pinnedness, UnOp, }; use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::tagged_ptr::TaggedRef; use rustc_error_messages::{DiagArgValue, IntoDiagArg}; @@ -3757,10 +3758,37 @@ pub enum OpaqueTyOrigin { }, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)] +pub enum MethodCallParentGenerics<'hir> { + All, + Selected(&'hir FxIndexSet), +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)] +pub enum DelegationParentGenerics<'hir> { + UserSpecified(HirId), + MethodCall(MethodCallParentGenerics<'hir>), +} + +impl From for DelegationParentGenerics<'_> { + fn from(value: HirId) -> Self { + Self::UserSpecified(value) + } +} + +impl Into> for DelegationParentGenerics<'_> { + fn into(self) -> Option { + match self { + DelegationParentGenerics::UserSpecified(hir_id) => Some(hir_id), + _ => None, + } + } +} + // Ids of parent (or child) path segment that contains user-specified args #[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)] -pub struct DelegationGenerics { - pub parent_args_segment_id: Option, +pub struct DelegationGenerics<'hir> { + pub parent_args_segment_id: Option>, pub child_args_segment_id: Option, pub self_ty_id: Option, pub propagate_self_ty: bool, @@ -3770,7 +3798,7 @@ pub struct DelegationGenerics { pub enum InferDelegationSig<'hir> { Input(usize), // Place generics info here, as we always specify output type for delegations. - Output(&'hir DelegationGenerics), + Output(&'hir DelegationGenerics<'hir>), } #[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)] @@ -4057,7 +4085,7 @@ impl<'hir> FnDecl<'hir> { None } - pub fn opt_delegation_generics(&self) -> Option<&'hir DelegationGenerics> { + pub fn opt_delegation_generics(&self) -> Option<&'hir DelegationGenerics<'hir>> { if let FnRetTy::Return(ty) = self.output && let TyKind::InferDelegation(InferDelegation::Sig(_, kind)) = ty.kind && let InferDelegationSig::Output(generics) = kind diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index be8a8e228c47a..a1dc33e569d65 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -3,13 +3,17 @@ //! For more information about delegation design, see the tracking issue #118212. use std::debug_assert_matches; +use std::ops::ControlFlow; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{DelegationGenerics, HirId, PathSegment}; +use rustc_hir::{ + DelegationGenerics, DelegationParentGenerics, HirId, MethodCallParentGenerics, PathSegment, +}; use rustc_middle::ty::{ - self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, + TypeVisitable, TypeVisitableExt, TypeVisitor, }; use rustc_span::{ErrorGuaranteed, Span, kw}; @@ -18,6 +22,44 @@ use crate::hir_ty_lowering::HirTyLowerer; type RemapTable = FxHashMap; +impl<'tcx> TypeVisitor> for ParamIndexRemapper<'tcx> { + type Result = ControlFlow<()>; + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { + if !ty.has_param() { + return ControlFlow::Continue(()); + } + + if let ty::Param(param) = ty.kind() + && !self.remap_table.contains_key(¶m.index) + { + return ControlFlow::Break(()); + } + + ty.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { + if let ty::ReEarlyParam(param) = r.kind() + && !self.remap_table.contains_key(¶m.index) + { + return ControlFlow::Break(()); + } + + ControlFlow::Continue(()) + } + + fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result { + if let ty::ConstKind::Param(param) = ct.kind() + && !self.remap_table.contains_key(¶m.index) + { + return ControlFlow::Break(()); + } + + ct.super_visit_with(self) + } +} + struct ParamIndexRemapper<'tcx> { tcx: TyCtxt<'tcx>, remap_table: RemapTable, @@ -70,7 +112,10 @@ enum SelfPositionKind { None, } -fn get_delegation_generics(tcx: TyCtxt<'_>, delegation_id: LocalDefId) -> &DelegationGenerics { +fn get_delegation_generics<'tcx>( + tcx: TyCtxt<'tcx>, + delegation_id: LocalDefId, +) -> &'tcx DelegationGenerics<'tcx> { tcx.hir_node(tcx.local_def_id_to_hir_id(delegation_id)) .fn_sig() .expect("processing delegation") @@ -141,6 +186,19 @@ enum InheritanceKind { Own, } +fn used_parent_generic_params<'tcx>( + tcx: TyCtxt<'tcx>, + delegation_id: LocalDefId, +) -> Option<&'tcx FxIndexSet> { + get_delegation_generics(tcx, delegation_id).parent_args_segment_id.and_then(|pg| { + if let DelegationParentGenerics::MethodCall(MethodCallParentGenerics::Selected(used)) = pg { + Some(used) + } else { + None + } + }) +} + /// Maps sig generics into generic args of delegation. Delegation generics has the following pattern: /// /// [SELF | maybe self in the beginning] @@ -172,11 +230,14 @@ fn create_mapping<'tcx>( let sig_generics = tcx.generics_of(sig_id); let process_sig_parent_generics = matches!(fn_kind(tcx, sig_id), FnKind::AssocTrait); + let used_parent_params = used_parent_generic_params(tcx, def_id); if process_sig_parent_generics { for i in (sig_generics.has_self as usize)..sig_generics.parent_count { let param = sig_generics.param_at(i, tcx); - if !param.kind.is_ty_or_const() { + if !param.kind.is_ty_or_const() + && used_parent_params.is_none_or(|used| used.contains(¶m.index)) + { mapping.insert(param.index, args_index as u32); args_index += 1; } @@ -201,7 +262,9 @@ fn create_mapping<'tcx>( if process_sig_parent_generics { for i in (sig_generics.has_self as usize)..sig_generics.parent_count { let param = sig_generics.param_at(i, tcx); - if param.kind.is_ty_or_const() { + if param.kind.is_ty_or_const() + && used_parent_params.is_none_or(|used| used.contains(¶m.index)) + { mapping.insert(param.index, args_index as u32); args_index += 1; } @@ -516,6 +579,13 @@ pub(crate) fn inherit_predicates_for_delegation_item<'tcx>( continue; } + // Check if all generic params are generated for the predicate. If we + // generate method call we may not generate all parent generics, thus + // we do not need their predicates. + if pred.0.visit_with(&mut self.folder).is_break() { + 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(), @@ -643,14 +713,17 @@ fn get_delegation_user_specified_args<'tcx>( let ctx = ItemCtxt::new(tcx, delegation_id); let lowerer = ctx.lowerer(); - let parent_args = info.parent_args_segment_id.and_then(get_segment).map(|(segment, def_id)| { - let self_ty = get_delegation_self_ty(tcx, delegation_id); - - lowerer - .lower_generic_args_of_path(segment.ident.span, def_id, &[], segment, self_ty) - .0 - .as_slice() - }); + let parent_args = + info.parent_args_segment_id.and_then(|id| id.into()).and_then(get_segment).map( + |(segment, def_id)| { + let self_ty = get_delegation_self_ty(tcx, delegation_id); + + lowerer + .lower_generic_args_of_path(segment.ident.span, def_id, &[], segment, self_ty) + .0 + .as_slice() + }, + ); let child_args = info .child_args_segment_id diff --git a/tests/ui/delegation/generics/generics-aux-pass.rs b/tests/ui/delegation/generics/generics-aux-pass.rs index 06f5c6d4d212e..cf73a5070925d 100644 --- a/tests/ui/delegation/generics/generics-aux-pass.rs +++ b/tests/ui/delegation/generics/generics-aux-pass.rs @@ -50,13 +50,13 @@ fn main() { X::bar::(); X::bar::<'static, 'static, i32, i32, 1>(); X::bar1(); - x.trait_foo::<'static, 'static, i32, 1, String, true>(); + x.trait_foo::<'static, String, true>(); x.trait_foo1(); ::bar::(); ::bar::<'static, 'static, i32, i32, 1>(); ::bar1(); - 1usize.trait_foo::<'static, 'static, i32, 1, String, true>(); + 1usize.trait_foo::<'static, String, true>(); 1usize.trait_foo1(); } diff --git a/tests/ui/delegation/generics/mapping/trait-to-trait-pass.rs b/tests/ui/delegation/generics/mapping/trait-to-trait-pass.rs index aac835c904637..6a8aa7f6fe5f7 100644 --- a/tests/ui/delegation/generics/mapping/trait-to-trait-pass.rs +++ b/tests/ui/delegation/generics/mapping/trait-to-trait-pass.rs @@ -32,14 +32,6 @@ mod test_1 { reuse Trait::<'static, 'static, 'static, i32>::foo as bar3 { self.get_self() } reuse Trait::<'static, 'static, 'static, i32>::foo::<'static, String, false> as bar4 { self.get_self() } - - // FIXME(fn_delegation): Uncomment those tests when proper support for - // generics when method call is generated is added - - // reuse Trait::foo::<'static, String, false> as bar5 { Self::get() } - // reuse Trait::foo as bar6 { Self::get() } - // reuse Trait::foo::<'static, String, false> as bar7 { self.get_self() } - // reuse Trait::foo as bar8 { self.get_self() } } trait Trait3 { diff --git a/tests/ui/delegation/generics/method-call-parent-args.rs b/tests/ui/delegation/generics/method-call-parent-args.rs new file mode 100644 index 0000000000000..1e76e8eae2690 --- /dev/null +++ b/tests/ui/delegation/generics/method-call-parent-args.rs @@ -0,0 +1,372 @@ +//@ compile-flags: -Z deduplicate-diagnostics=yes + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod test_1 { + trait Trait<'b, T>: Sized { + fn foo(&self) {} + } + + impl<'a, T> Trait<'a, T> for u8 {} + + reuse Trait::foo:: as bar1; + reuse Trait::foo as bar2; + reuse Trait::<'static, ()>::foo:: as bar3; + reuse Trait::<'static, ()>::foo as bar4; + + fn check1() { + // Method call is generated but parent generics too as Self is present. + bar1::<'static, u8, ()>(&1); + bar2::<'static, u8, (), (), false>(&2); + // Method call is not generated as generic args specified in parent. + bar3::(&3); + bar4::(&4); + } + + reuse ::foo:: as bar5; + reuse ::foo as bar6; + reuse >::foo:: as bar7; + reuse >::foo as bar8; + + fn check2() { + // Method call is not generated as qself present. + bar5::<'static, ()>(&1); + bar6::<'static, (), (), false>(&2); + bar7(&3); + bar8::<(), false>(&4); + } + + trait Trait2<'a, 'b, 'c, X, Y, Z>: Sized { + fn get() -> &'static u8 { + &0 + } + fn get_self(&self) -> &'static u8 { + &0 + } + + reuse Trait::foo:: as bar1 { Self::get() } + //~^ ERROR: type annotations needed + reuse Trait::foo as bar2 { Self::get() } + //~^ ERROR: type annotations needed + reuse Trait::<'static, ()>::foo:: as bar3 { Self::get() } + reuse Trait::<'static, ()>::foo as bar4 { Self::get() } + + reuse Trait::foo:: as bar5 { self.get_self() } + //~^ ERROR: type annotations needed + reuse Trait::foo as bar6 { self.get_self() } + //~^ ERROR: type annotations needed + reuse Trait::<'static, ()>::foo:: as bar7 { self.get_self() } + reuse Trait::<'static, ()>::foo as bar8 { self.get_self() } + + reuse ::foo:: as bar9 { Self::get() } + reuse ::foo as bar10 { Self::get() } + reuse >::foo:: as bar11 { Self::get() } + reuse >::foo as bar12 { Self::get() } + + reuse ::foo:: as bar13 { self.get_self() } + reuse ::foo as bar14 { self.get_self() } + reuse >::foo:: as bar15 { self.get_self() } + reuse >::foo as bar16 { self.get_self() } + + fn check(&self) { + // Method call is generated so no parent generics. + self.bar1(); + self.bar2::<(), false>(); + // Method call is not generated as generic args specified in parent. + self.bar3(); + self.bar4::<(), false>(); + + // Method call is generated so no parent generics. + self.bar5(); + self.bar6::<(), false>(); + // Method call is not generated as generic args specified in parent. + self.bar7(); + self.bar8::<(), false>(); + + // Method call is not generated (because qself is present). + self.bar9::<'static, ()>(); + self.bar10::<'static, (), (), false>(); + self.bar11(); + self.bar12::<(), false>(); + + // Method call is not generated (because qself is present). + self.bar13::<'static, ()>(); + self.bar14::<'static, (), (), false>(); + self.bar15(); + self.bar16::<(), false>(); + } + } + + struct X; + + impl X { + fn get() -> &'static u8 { + &0 + } + fn get_self(&self) -> &'static u8 { + &0 + } + + reuse Trait::foo:: as bar1 { Self::get() } + //~^ ERROR: type annotations needed + reuse Trait::foo as bar2 { Self::get() } + //~^ ERROR: type annotations needed + reuse Trait::<'static, usize>::foo:: as bar3 { Self::get() } + reuse Trait::<'static, usize>::foo as bar4 { Self::get() } + + reuse Trait::foo:: as bar5 { self.get_self() } + //~^ ERROR: type annotations needed + reuse Trait::foo as bar6 { self.get_self() } + //~^ ERROR: type annotations needed + reuse Trait::<'static, usize>::foo:: as bar7 { self.get_self() } + reuse Trait::<'static, usize>::foo as bar8 { self.get_self() } + + reuse ::foo:: as bar9 { Self::get() } + reuse ::foo as bar10 { Self::get() } + reuse >::foo:: as bar11 { Self::get() } + reuse >::foo as bar12 { Self::get() } + + reuse ::foo:: as bar13 { self.get_self() } + reuse ::foo as bar14 { self.get_self() } + reuse >::foo:: as bar15 { self.get_self() } + reuse >::foo as bar16 { self.get_self() } + + fn check(&self) { + // Method call is generated so no parent generics. + self.bar1(); + self.bar2::<(), false>(); + // Method call is not generated as generic args specified in parent. + self.bar3(); + self.bar4::<(), false>(); + + // Method call is generated so no parent generics. + self.bar5(); + self.bar6::<(), false>(); + // Method call is not generated as generic args specified in parent. + self.bar7(); + self.bar8::<(), false>(); + + // Method call is not generated (because qself is present). + self.bar9::<'static, ()>(); + self.bar10::<'static, (), (), false>(); + self.bar11(); + self.bar12::<(), false>(); + + // Method call is not generated (because qself is present). + self.bar13::<'static, ()>(); + self.bar14::<'static, (), (), false>(); + self.bar15(); + self.bar16::<(), false>(); + } + } +} + +mod test_2 { + trait Trait<'b, T>: Sized { + fn foo(&self) {} + } + + impl Trait<'static, usize> for u8 {} + impl Trait<'static, String> for u8 {} + + trait Trait2<'a, 'b, 'c, X, Y, Z>: Sized { + fn get_self(&self) -> &'static u8 { + &0 + } + + reuse Trait::foo:: as bar1 { self.get_self() } + //~^ ERROR: type annotations needed + reuse Trait::foo as bar2 { self.get_self() } + //~^ ERROR: type annotations needed + reuse Trait::<'static, usize>::foo:: as bar3 { self.get_self() } + reuse Trait::<'static, ()>::foo as bar4 { self.get_self() } + //~^ ERROR: the trait bound `u8: test_2::Trait<'static, ()>` is not satisfied + + fn check(&self) { + // Method call is generated so no parent generics. + self.bar1(); + self.bar2::<(), false>(); + // Method call is not generated as generic args specified in parent. + self.bar3(); + self.bar4::<(), false>(); + } + } +} + +// Testing that if other unused in signature generic param +// is in bounds of other used parent's generic param it will be generated. +mod test_3 { + trait Bound {} + trait Trait, B: Bound, C> { + fn foo(&self, b: B) {} + } + + impl, B: Bound, C> Trait for usize {} + + impl Bound for usize {} + impl Bound for () {} + + trait Trait2<'a, 'b, 'c, X, Y, Z>: Sized { + fn get_self(&self) -> &'static u8 { + &0 + } + + fn get_self2(&self) -> &'static usize { + &0 + } + + reuse Trait::foo:: as bar1 { self.get_self() } + //~^ ERROR: no method named `foo` found for reference `&'static u8` in the current scope + reuse Trait::foo as bar2 { self.get_self() } + //~^ ERROR: no method named `foo` found for reference `&'static u8` in the current scope + reuse Trait::<(), usize, ()>::foo:: as bar3 { self.get_self() } + //~^ ERROR: the trait bound `u8: test_3::Trait<(), usize, ()>` is not satisfied + reuse Trait::<(), (), ()>::foo as bar4 { self.get_self() } + //~^ ERROR: the trait bound `u8: test_3::Trait<(), (), ()>` is not satisfied + + reuse Trait::<(), usize, ()>::foo as bar5 { self.get_self() } + //~^ ERROR: the trait bound `u8: test_3::Trait<(), usize, ()>` is not satisfied + + reuse Trait::foo:: as bar6 { self.get_self2() } + reuse Trait::foo as bar7 { self.get_self2() } + reuse Trait::<(), usize, ()>::foo:: as bar8 { self.get_self2() } + reuse Trait::<(), (), ()>::foo as bar9 { self.get_self2() } + reuse Trait::<(), usize, ()>::foo as bar10 { self.get_self2() } + + fn check(&self) { + // Method call is generated and needed parent generics are generated. + self.bar1::<(), (), ()>(()); + self.bar2::<(), (), (), (), false>(()); + // Method call is not generated as generic args specified in parent. + self.bar3(123); + self.bar4::<(), false>(()); + self.bar5::<(), false>(123); + + // Method call is generated and needed parent generics are generated. + self.bar6::<(), (), ()>(()); + self.bar7::<(), (), (), (), false>(()); + // Method call is not generated as generic args specified in parent. + self.bar8(123); + self.bar9::<(), false>(()); + } + } +} + +// Testing that lifetimes from predicates are generated. +mod test_4 { + trait Bound<'a> {} + trait Trait<'a, 'b, C: 'a + 'static, B: Bound<'b>> { + fn foo(&self, b: B, c: C) {} + } + + impl<'a, 'b, C: 'a + 'static, B: Bound<'b>> Trait<'a, 'b, C, B> for () {} + impl Bound<'static> for () {} + + struct X; + impl X { + fn get_self() -> () { + () + } + + reuse Trait::foo { Self::get_self() } + + fn check(&self) { + self.foo::<'static, 'static, (), (), (), false>((), ()); + } + } +} + +// Testing that params from region outlives predicates are generated. +mod test_5 { + trait Trait<'a, 'b: 'static + 'a> { + fn foo(&self, b: &'b str) {} + } + + impl<'a, 'b: 'a + 'static> Trait<'a, 'b> for () {} + + struct X; + impl X { + fn get_self() -> () { + () + } + + reuse Trait::foo { Self::get_self() } + + fn check(&self) { + self.foo::<'static, 'static, (), false>(""); + } + } +} + +// Testing with impl traits. +mod test_6 { + trait Bound {} + trait Trait<'a, 'b: 'static + 'a, A: Bound, B, C> { + fn foo(&self, b: &'b str, f: impl FnOnce() -> usize) {} + fn bar(&self, f: impl FnOnce() -> A) {} + } + + impl<'a, 'b: 'a + 'static, A: Bound, B, C> Trait<'a, 'b, A, B, C> for () {} + + impl Bound for usize {} + + struct X; + impl X { + fn get_self() -> () { + () + } + + // `C` is not generated so type annotation needed error. + reuse Trait::* { Self::get_self() } + //~^ ERROR: type annotations needed + //~| ERROR: type annotations needed + + fn check(&self) { + self.foo::<'static, 'static, (), false>("", || 123); + + self.bar::(|| 123); + self.bar::(|| 123); + //~^ ERROR: the trait bound `usize: test_6::Bound` is not satisfied + } + } + + impl Trait<'static, 'static, usize, u8, String> for ((), ()) {} + struct Y; + impl Y { + fn get_self() -> ((), ()) { + ((), ()) + } + + // `C` is not generated, but not type annotation error as there is a single + // implementation of `Trait` for `((), ())`, however as `Trait` generic args + // are not specified we generate generic param `A` and thus the function type + // is still `FnOnce() -> A` (not `FnOnce() -> usize`), so we get an error. + reuse Trait::* { Self::get_self() } + //~^ ERROR: expected `impl FnOnce() -> A` to return `usize`, but it returns `A` + + fn check(&self) { + self.foo::<'static, 'static, (), false>("", || 123); + + self.bar::(|| 123); + self.bar::(|| 123); + //~^ ERROR: the trait bound `usize: test_6::Bound` is not satisfied + } + + // Method call is not generated as `Trait`'s args are specified, so we have to explicitly + // use `&Self::get_self()` instead of `Self::get_self()`. + + // FIXME(fn_delegation): do we still want this behavior? We need those args for signature + // inheritance as we use HirId of path segment to extract them, but we can probably + // do it at delayed AST -> HIR lowering, moreover we would need those args for + // inherent methods resolution, so we will have to obtain them at AST -> HIR lowering + // anyway. + reuse Trait::<'static, 'static, usize, u8, String>::bar as bar1 { &Self::get_self() } + + fn check1(&self) { + self.bar1::(|| 123usize); + } + } +} + +fn main() {} diff --git a/tests/ui/delegation/generics/method-call-parent-args.stderr b/tests/ui/delegation/generics/method-call-parent-args.stderr new file mode 100644 index 0000000000000..4ac595b987c8d --- /dev/null +++ b/tests/ui/delegation/generics/method-call-parent-args.stderr @@ -0,0 +1,265 @@ +error[E0282]: type annotations needed + --> $DIR/method-call-parent-args.rs:48:22 + | +LL | reuse Trait::foo:: as bar1 { Self::get() } + | ^^^ cannot infer type for type parameter `T` declared on the trait `Trait` + +error[E0282]: type annotations needed + --> $DIR/method-call-parent-args.rs:50:22 + | +LL | reuse Trait::foo as bar2 { Self::get() } + | ^^^ cannot infer type for type parameter `T` declared on the trait `Trait` + +error[E0282]: type annotations needed + --> $DIR/method-call-parent-args.rs:55:22 + | +LL | reuse Trait::foo:: as bar5 { self.get_self() } + | ^^^ cannot infer type for type parameter `T` declared on the trait `Trait` + +error[E0282]: type annotations needed + --> $DIR/method-call-parent-args.rs:57:22 + | +LL | reuse Trait::foo as bar6 { self.get_self() } + | ^^^ cannot infer type for type parameter `T` declared on the trait `Trait` + +error[E0282]: type annotations needed + --> $DIR/method-call-parent-args.rs:111:22 + | +LL | reuse Trait::foo:: as bar1 { Self::get() } + | ^^^ cannot infer type for type parameter `T` declared on the trait `Trait` + +error[E0282]: type annotations needed + --> $DIR/method-call-parent-args.rs:113:22 + | +LL | reuse Trait::foo as bar2 { Self::get() } + | ^^^ cannot infer type for type parameter `T` declared on the trait `Trait` + +error[E0282]: type annotations needed + --> $DIR/method-call-parent-args.rs:118:22 + | +LL | reuse Trait::foo:: as bar5 { self.get_self() } + | ^^^ cannot infer type for type parameter `T` declared on the trait `Trait` + +error[E0282]: type annotations needed + --> $DIR/method-call-parent-args.rs:120:22 + | +LL | reuse Trait::foo as bar6 { self.get_self() } + | ^^^ cannot infer type for type parameter `T` declared on the trait `Trait` + +error[E0283]: type annotations needed + --> $DIR/method-call-parent-args.rs:178:22 + | +LL | reuse Trait::foo:: as bar1 { self.get_self() } + | ^^^ cannot infer type for type parameter `T` declared on the trait `Trait` + | +note: multiple `impl`s satisfying `u8: test_2::Trait<'_, _>` found + --> $DIR/method-call-parent-args.rs:170:5 + | +LL | impl Trait<'static, usize> for u8 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Trait<'static, String> for u8 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0283]: type annotations needed + --> $DIR/method-call-parent-args.rs:180:22 + | +LL | reuse Trait::foo as bar2 { self.get_self() } + | ^^^ cannot infer type for type parameter `T` declared on the trait `Trait` + | +note: multiple `impl`s satisfying `u8: test_2::Trait<'_, _>` found + --> $DIR/method-call-parent-args.rs:170:5 + | +LL | impl Trait<'static, usize> for u8 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Trait<'static, String> for u8 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `u8: test_2::Trait<'static, ()>` is not satisfied + --> $DIR/method-call-parent-args.rs:183:51 + | +LL | reuse Trait::<'static, ()>::foo as bar4 { self.get_self() } + | --- ^^^^^^^^^^^^^^^ the trait `test_2::Trait<'static, ()>` is not implemented for `u8` + | | + | required by a bound introduced by this call + | + = note: `u8` implements similarly named trait `test_1::Trait`, but not `test_2::Trait<'static, ()>` +help: `u8` implements trait `test_2::Trait<'b, T>` + --> $DIR/method-call-parent-args.rs:170:5 + | +LL | impl Trait<'static, usize> for u8 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `test_2::Trait<'_, usize>` +LL | impl Trait<'static, String> for u8 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `test_2::Trait<'_, String>` + +error[E0599]: no method named `foo` found for reference `&'static u8` in the current scope + --> $DIR/method-call-parent-args.rs:219:22 + | +LL | reuse Trait::foo:: as bar1 { self.get_self() } + | ^^^ method not found in `&'static u8` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following traits define an item `foo`, perhaps you need to implement one of them: + candidate #1: `test_1::Trait` + candidate #2: `test_2::Trait` + candidate #3: `test_3::Trait` + candidate #4: `test_4::Trait` + candidate #5: `test_5::Trait` + candidate #6: `test_6::Trait` + +error[E0599]: no method named `foo` found for reference `&'static u8` in the current scope + --> $DIR/method-call-parent-args.rs:221:22 + | +LL | reuse Trait::foo as bar2 { self.get_self() } + | ^^^ method not found in `&'static u8` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following traits define an item `foo`, perhaps you need to implement one of them: + candidate #1: `test_1::Trait` + candidate #2: `test_2::Trait` + candidate #3: `test_3::Trait` + candidate #4: `test_4::Trait` + candidate #5: `test_5::Trait` + candidate #6: `test_6::Trait` + +error[E0277]: the trait bound `u8: test_3::Trait<(), usize, ()>` is not satisfied + --> $DIR/method-call-parent-args.rs:223:70 + | +LL | reuse Trait::<(), usize, ()>::foo:: as bar3 { self.get_self() } + | --- ^^^^^^^^^^^^^^^ the trait `test_3::Trait<(), usize, ()>` is not implemented for `u8` + | | + | required by a bound introduced by this call + | +help: the trait `test_3::Trait<(), usize, ()>` is not implemented for `u8` + but it is implemented for `usize` + --> $DIR/method-call-parent-args.rs:205:5 + | +LL | impl, B: Bound, C> Trait for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: for that trait implementation, expected `usize`, found `u8` + +error[E0277]: the trait bound `u8: test_3::Trait<(), (), ()>` is not satisfied + --> $DIR/method-call-parent-args.rs:225:50 + | +LL | reuse Trait::<(), (), ()>::foo as bar4 { self.get_self() } + | --- ^^^^^^^^^^^^^^^ the trait `test_3::Trait<(), (), ()>` is not implemented for `u8` + | | + | required by a bound introduced by this call + | +help: the trait `test_3::Trait<(), (), ()>` is not implemented for `u8` + but it is implemented for `usize` + --> $DIR/method-call-parent-args.rs:205:5 + | +LL | impl, B: Bound, C> Trait for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: for that trait implementation, expected `usize`, found `u8` + +error[E0277]: the trait bound `u8: test_3::Trait<(), usize, ()>` is not satisfied + --> $DIR/method-call-parent-args.rs:228:53 + | +LL | reuse Trait::<(), usize, ()>::foo as bar5 { self.get_self() } + | --- ^^^^^^^^^^^^^^^ the trait `test_3::Trait<(), usize, ()>` is not implemented for `u8` + | | + | required by a bound introduced by this call + | +help: the trait `test_3::Trait<(), usize, ()>` is not implemented for `u8` + but it is implemented for `usize` + --> $DIR/method-call-parent-args.rs:205:5 + | +LL | impl, B: Bound, C> Trait for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: for that trait implementation, expected `usize`, found `u8` + +error[E0283]: type annotations needed + --> $DIR/method-call-parent-args.rs:321:22 + | +LL | reuse Trait::* { Self::get_self() } + | ^ cannot infer type for type parameter `A` declared on the trait `Trait` + | + = note: the type must implement `test_6::Bound<_>` +help: the trait `test_6::Bound` is implemented for `usize` + --> $DIR/method-call-parent-args.rs:312:5 + | +LL | impl Bound for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `test_6::Trait::foo` + --> $DIR/method-call-parent-args.rs:305:42 + | +LL | trait Trait<'a, 'b: 'static + 'a, A: Bound, B, C> { + | ^^^^^^^^ required by this bound in `Trait::foo` +LL | fn foo(&self, b: &'b str, f: impl FnOnce() -> usize) {} + | --- required by a bound in this associated function + +error[E0282]: type annotations needed + --> $DIR/method-call-parent-args.rs:321:22 + | +LL | reuse Trait::* { Self::get_self() } + | ^ cannot infer type for type parameter `C` declared on the trait `Trait` + +error[E0277]: the trait bound `usize: test_6::Bound` is not satisfied + --> $DIR/method-call-parent-args.rs:329:24 + | +LL | self.bar::(|| 123); + | --- ^^^^^ the trait `test_6::Bound` is not implemented for `usize` + | | + | required by a bound introduced by this call + | + = note: `usize` implements similarly named trait `test_3::Bound`, but not `test_6::Bound` +help: the trait `Bound` is not implemented for `usize` + but trait `Bound` is implemented for it + --> $DIR/method-call-parent-args.rs:312:5 + | +LL | impl Bound for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = help: for that trait implementation, expected `u8`, found `u32` +note: required by a bound in `test_6::X::bar` + --> $DIR/method-call-parent-args.rs:305:42 + | +LL | trait Trait<'a, 'b: 'static + 'a, A: Bound, B, C> { + | ^^^^^^^^ required by this bound in `X::bar` +... +LL | reuse Trait::* { Self::get_self() } + | - required by a bound in this associated function + +error[E0271]: expected `impl FnOnce() -> A` to return `usize`, but it returns `A` + --> $DIR/method-call-parent-args.rs:345:22 + | +LL | reuse Trait::* { Self::get_self() } + | ^ expected `usize`, found type parameter `A` + | + = note: expected type `usize` + found type parameter `A` +note: required by a bound in `test_6::Trait::bar` + --> $DIR/method-call-parent-args.rs:307:58 + | +LL | fn bar(&self, f: impl FnOnce() -> A) {} + | ^ required by this bound in `Trait::bar` + +error[E0277]: the trait bound `usize: test_6::Bound` is not satisfied + --> $DIR/method-call-parent-args.rs:352:24 + | +LL | self.bar::(|| 123); + | --- ^^^^^ the trait `test_6::Bound` is not implemented for `usize` + | | + | required by a bound introduced by this call + | + = note: `usize` implements similarly named trait `test_3::Bound`, but not `test_6::Bound` +help: the trait `Bound` is not implemented for `usize` + but trait `Bound` is implemented for it + --> $DIR/method-call-parent-args.rs:312:5 + | +LL | impl Bound for usize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = help: for that trait implementation, expected `u8`, found `u32` +note: required by a bound in `Y::bar` + --> $DIR/method-call-parent-args.rs:305:42 + | +LL | trait Trait<'a, 'b: 'static + 'a, A: Bound, B, C> { + | ^^^^^^^^ required by this bound in `Y::bar` +... +LL | reuse Trait::* { Self::get_self() } + | - required by a bound in this associated function + +error: aborting due to 21 previous errors + +Some errors have detailed explanations: E0271, E0277, E0282, E0283, E0599. +For more information about an error, try `rustc --explain E0271`.