From 12fe21b4744cdc8ee55a413f23dd113edb070335 Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Wed, 5 Jun 2024 13:27:14 +0300 Subject: [PATCH] Delegation: support generics in associated items --- compiler/rustc_hir_analysis/messages.ftl | 2 +- .../src/collect/generics_of.rs | 6 +- .../src/collect/predicates_of.rs | 7 +- compiler/rustc_hir_analysis/src/delegation.rs | 433 +++++++++++++----- .../src/hir_ty_lowering/mod.rs | 3 +- .../generics/free-fn-to-free-fn.stderr | 13 +- .../generics/free-fn-to-trait-method.stderr | 16 +- .../generics/impl-to-free-fn-pass.rs | 29 ++ .../generics/impl-to-trait-method-pass.rs | 107 +++++ .../generics/impl-to-trait-method.rs | 44 ++ .../generics/impl-to-trait-method.stderr | 56 +++ .../generics/impl-trait-to-trait.stderr | 44 ++ .../generics/trait-method-to-other-pass.rs | 29 ++ tests/ui/delegation/ice-issue-124347.rs | 2 +- tests/ui/delegation/ice-issue-124347.stderr | 13 +- tests/ui/delegation/not-supported.rs | 104 ----- tests/ui/delegation/not-supported.stderr | 199 -------- tests/ui/delegation/unsupported.rs | 41 ++ tests/ui/delegation/unsupported.stderr | 50 ++ 19 files changed, 743 insertions(+), 455 deletions(-) create mode 100644 tests/ui/delegation/generics/impl-to-free-fn-pass.rs create mode 100644 tests/ui/delegation/generics/impl-to-trait-method-pass.rs create mode 100644 tests/ui/delegation/generics/impl-to-trait-method.rs create mode 100644 tests/ui/delegation/generics/impl-to-trait-method.stderr create mode 100644 tests/ui/delegation/generics/impl-trait-to-trait.stderr create mode 100644 tests/ui/delegation/generics/trait-method-to-other-pass.rs delete mode 100644 tests/ui/delegation/not-supported.rs delete mode 100644 tests/ui/delegation/not-supported.stderr create mode 100644 tests/ui/delegation/unsupported.rs create mode 100644 tests/ui/delegation/unsupported.stderr diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 24c5377a3b125..a9cf41e28dde1 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -316,7 +316,7 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args hir_analysis_not_supported_delegation = - {$descr} is not supported yet + {$descr} .label = callee defined here hir_analysis_only_current_traits_adt = `{$name}` is not defined in the current crate diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index c55a9dfdf970d..2c876be09ced8 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -56,10 +56,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { } // For a delegation item inherit generics from callee. - if let Some(sig_id) = tcx.hir().opt_delegation_sig_id(def_id) - && let Some(generics) = inherit_generics_for_delegation_item(tcx, def_id, sig_id) - { - return generics; + if let Some(sig_id) = tcx.hir().opt_delegation_sig_id(def_id) { + return inherit_generics_for_delegation_item(tcx, def_id, sig_id); } let hir_id = tcx.local_def_id_to_hir_id(def_id); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index ab87434c41435..27c94066f33c0 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -3,7 +3,6 @@ use crate::collect::ItemCtxt; use crate::constrained_generic_params as cgp; use crate::delegation::inherit_predicates_for_delegation_item; use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason}; -use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter}; use hir::{HirId, Node}; use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; @@ -117,10 +116,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } // For a delegation item inherit predicates from callee. - if let Some(sig_id) = tcx.hir().opt_delegation_sig_id(def_id) - && let Some(predicates) = inherit_predicates_for_delegation_item(tcx, def_id, sig_id) - { - return predicates; + if let Some(sig_id) = tcx.hir().opt_delegation_sig_id(def_id) { + return inherit_predicates_for_delegation_item(tcx, def_id, sig_id); } let hir_id = tcx.local_def_id_to_hir_id(def_id); diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 1348a27305b6d..4cf34771ebce9 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -1,9 +1,11 @@ +use itertools::Itertools; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::ErrorGuaranteed; +use rustc_span::{ErrorGuaranteed, Span}; +use rustc_type_ir::visit::TypeVisitableExt; type RemapTable = FxHashMap; @@ -13,26 +15,44 @@ struct IndicesFolder<'tcx, 'a> { } impl<'tcx, 'a> TypeFolder> for IndicesFolder<'tcx, 'a> { - fn interner(&self) -> TyCtxt<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Param(param) = ty.kind() { - return Ty::new_param(self.tcx, self.remap_table[¶m.index], param.name); + if !ty.has_param() { + return ty; + } + + if let ty::Param(param) = ty.kind() + && let Some(idx) = self.remap_table.get(¶m.index) + { + return Ty::new_param(self.tcx, *idx, param.name); } ty.super_fold_with(self) } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if let ty::ReEarlyParam(param) = r.kind() { + if let ty::ReEarlyParam(param) = r.kind() + && let Some(idx) = self.remap_table.get(¶m.index) + { return ty::Region::new_early_param( self.tcx, - ty::EarlyParamRegion { index: self.remap_table[¶m.index], name: param.name }, + ty::EarlyParamRegion { index: *idx, name: param.name }, ); } r } + + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + if let ty::ConstKind::Param(param) = ct.kind() + && let Some(idx) = self.remap_table.get(¶m.index) + { + let param = ty::ParamConst::new(*idx, param.name); + return ty::Const::new_param(self.tcx, param); + } + ct.super_fold_with(self) + } } #[derive(Clone, Copy, Debug, PartialEq)] @@ -55,120 +75,318 @@ fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind { } } -// Lifetime parameters must be declared before type and const parameters. -// Therefore, When delegating from a free function to a associated function, -// generic parameters need to be reordered: -// -// trait Trait<'a, A> { -// fn foo<'b, B>(...) {...} -// } -// -// reuse Trait::foo; -// desugaring: -// fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) { -// Trait::foo(...) -// } -fn create_remap_table<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, sig_id: DefId) -> RemapTable { - let caller_generics = tcx.generics_of(def_id); - let callee_generics = tcx.generics_of(sig_id); - let mut remap_table: RemapTable = FxHashMap::default(); - for caller_param in &caller_generics.own_params { - let callee_index = callee_generics.param_def_id_to_index(tcx, caller_param.def_id).unwrap(); - remap_table.insert(callee_index, caller_param.index); - } - remap_table +type OwnParams = Vec; + +struct GenericsBuilder<'tcx> { + tcx: TyCtxt<'tcx>, + sig_id: DefId, + parent: Option, + own_params: OwnParams, } -pub(crate) fn inherit_generics_for_delegation_item<'tcx>( +impl<'tcx> GenericsBuilder<'tcx> { + fn new(tcx: TyCtxt<'tcx>, sig_id: DefId) -> GenericsBuilder<'tcx> { + GenericsBuilder { tcx, sig_id, parent: None, own_params: vec![] } + } + + fn with_parent(mut self, parent: DefId) -> Self { + self.parent = Some(parent); + self + } + + fn with_own_generics(mut self, def_id: DefId) -> Self { + let generics = self.tcx.generics_of(def_id); + self.own_params.append(&mut generics.own_params.clone()); + self + } + + fn with_generics(mut self, def_id: DefId) -> Self { + let generics = self.tcx.generics_of(def_id); + if let Some(parent_def_id) = generics.parent { + self = self.with_own_generics(parent_def_id); + } + self.with_own_generics(def_id) + } + + fn skip_self(mut self) -> Self { + self.own_params = self.own_params.iter().skip(1).cloned().collect_vec(); + self + } + + // Lifetime parameters must be declared before type and const parameters. + // Therefore, When delegating from a free function to a associated function, + // generic parameters need to be reordered: + // + // trait Trait<'a, A> { + // fn foo<'b, B>(...) {...} + // } + // + // reuse Trait::foo; + // desugaring: + // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) { + // Trait::foo(...) + // } + fn sort(mut self) -> Self { + self.own_params.sort_by_key(|key| key.kind.is_ty_or_const()); + self + } + + fn build(mut self) -> ty::Generics { + let param_def_id_to_index = + self.own_params.iter().map(|param| (param.def_id, param.index)).collect(); + + let (parent_count, has_self) = if let Some(def_id) = self.parent { + let parent_generics = self.tcx.generics_of(def_id); + let parent_kind = self.tcx.def_kind(def_id); + (parent_generics.count(), parent_kind == DefKind::Trait) + } else { + (0, false) + }; + + let callee_generics = self.tcx.generics_of(self.sig_id); + + for (idx, param) in self.own_params.iter_mut().enumerate() { + param.index = (idx + parent_count) as u32; + // Default type parameters are not inherited: they are not allowed + // in fn's. + if let ty::GenericParamDefKind::Type { synthetic, .. } = param.kind { + param.kind = ty::GenericParamDefKind::Type { has_default: false, synthetic } + } + } + + ty::Generics { + parent: self.parent, + parent_count, + own_params: self.own_params, + param_def_id_to_index, + has_self, + has_late_bound_regions: callee_generics.has_late_bound_regions, + host_effect_index: callee_generics.host_effect_index, + } + } +} + +struct PredicatesBuilder<'tcx> { + tcx: TyCtxt<'tcx>, + args: ty::GenericArgsRef<'tcx>, + parent: Option, + preds: Vec<(ty::Clause<'tcx>, Span)>, +} + +impl<'tcx> PredicatesBuilder<'tcx> { + fn new(tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> PredicatesBuilder<'tcx> { + PredicatesBuilder { tcx, args, parent: None, preds: vec![] } + } + + fn with_parent(mut self, parent: DefId) -> Self { + self.parent = Some(parent); + self + } + + fn with_own_preds(mut self, f: F, def_id: DefId) -> Self + where + F: Fn(DefId) -> ty::GenericPredicates<'tcx>, + { + let preds = f(def_id).instantiate_own(self.tcx, self.args); + self.preds.extend(preds); + self + } + + fn with_preds(mut self, f: F, def_id: DefId) -> Self + where + F: Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy, + { + let preds = f(def_id); + if let Some(parent_def_id) = preds.parent { + self = self.with_own_preds(f, parent_def_id); + } + self.with_own_preds(f, def_id) + } + + fn build(self) -> ty::GenericPredicates<'tcx> { + ty::GenericPredicates { + parent: self.parent, + predicates: self.tcx.arena.alloc_from_iter(self.preds), + effects_min_tys: ty::List::empty(), // FIXME(fn_delegation): Support effects. + } + } +} + +struct GenericArgsBuilder<'tcx> { + tcx: TyCtxt<'tcx>, + remap_table: RemapTable, + sig_id: DefId, + def_id: LocalDefId, +} + +impl<'tcx> GenericArgsBuilder<'tcx> { + fn new(tcx: TyCtxt<'tcx>, sig_id: DefId, def_id: LocalDefId) -> GenericArgsBuilder<'tcx> { + GenericArgsBuilder { tcx, remap_table: FxHashMap::default(), sig_id, def_id } + } + + fn build_from_args(mut self, args: ty::GenericArgsRef<'tcx>) -> ty::GenericArgsRef<'tcx> { + let caller_generics = self.tcx.generics_of(self.def_id); + let callee_generics = self.tcx.generics_of(self.sig_id); + + for caller_param in &caller_generics.own_params { + let callee_index = + callee_generics.param_def_id_to_index(self.tcx, caller_param.def_id).unwrap(); + self.remap_table.insert(callee_index, caller_param.index); + } + + let mut folder = IndicesFolder { tcx: self.tcx, remap_table: &self.remap_table }; + args.fold_with(&mut folder) + } +} + +fn create_generic_args<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, sig_id: DefId, -) -> Option { +) -> ty::GenericArgsRef<'tcx> { + let builder = GenericArgsBuilder::new(tcx, sig_id, def_id); + let caller_kind = fn_kind(tcx, def_id.into()); let callee_kind = fn_kind(tcx, sig_id); - - // FIXME(fn_delegation): Support generics on associated delegation items. - // Error was reported in `check_delegation_constraints`. + // FIXME(fn_delegation): early bound generics are only supported for trait + // implementations and free functions. Error was reported in `check_constraints`. match (caller_kind, callee_kind) { - (FnKind::Free, _) => { - let mut own_params = vec![]; - + (FnKind::Free, FnKind::Free) + | (FnKind::Free, FnKind::AssocTrait) => { + let args = ty::GenericArgs::identity_for_item(tcx, sig_id); + builder.build_from_args(args) + } + (FnKind::AssocTraitImpl, FnKind::AssocTrait) => { let callee_generics = tcx.generics_of(sig_id); - if let Some(parent_sig_id) = callee_generics.parent { - let parent_sig_generics = tcx.generics_of(parent_sig_id); - own_params.append(&mut parent_sig_generics.own_params.clone()); - } - own_params.append(&mut callee_generics.own_params.clone()); - - // lifetimes go first - own_params.sort_by_key(|key| key.kind.is_ty_or_const()); - - for (idx, param) in own_params.iter_mut().enumerate() { - param.index = idx as u32; - // Default type parameters are not inherited: they are not allowed - // in fn's. - if let ty::GenericParamDefKind::Type { synthetic, .. } = param.kind { - param.kind = ty::GenericParamDefKind::Type { has_default: false, synthetic } - } - } + let parent = tcx.parent(def_id.into()); + let parent_args = + tcx.impl_trait_header(parent).unwrap().trait_ref.instantiate_identity().args; + + let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id); + let method_args = tcx.mk_args_from_iter(trait_args.iter().skip(callee_generics.parent_count)); + // For trait implementations only the method's own parameters are copied. + // They need to be reindexed adjusted for impl parameters. + let method_args = builder.build_from_args(method_args); + + tcx.mk_args_from_iter(parent_args.iter().chain(method_args)) + } + (FnKind::AssocInherentImpl, FnKind::AssocTrait) => { + let parent = tcx.parent(def_id.into()); + let self_ty = tcx.type_of(parent).instantiate_identity(); + let generic_self_ty = ty::GenericArg::from(self_ty); - let param_def_id_to_index = - own_params.iter().map(|param| (param.def_id, param.index)).collect(); + let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id); + let trait_args = builder.build_from_args(trait_args); - Some(ty::Generics { - parent: None, - parent_count: 0, - own_params, - param_def_id_to_index, - has_self: false, - has_late_bound_regions: callee_generics.has_late_bound_regions, - host_effect_index: None, - }) + let args = std::iter::once(generic_self_ty).chain(trait_args.iter().skip(1)); + tcx.mk_args_from_iter(args) } - _ => None, + (FnKind::AssocInherentImpl, FnKind::Free) + | (FnKind::AssocTrait, FnKind::Free) + | (FnKind::AssocTrait, FnKind::AssocTrait) => { + let args = ty::GenericArgs::identity_for_item(tcx, sig_id); + builder.build_from_args(args) + } + // `sig_id` is taken from corresponding trait method. + (FnKind::AssocTraitImpl, _) | + (_, FnKind::AssocTraitImpl) | + // delegation to inherent methods is not yet supported + (_, FnKind::AssocInherentImpl) => unreachable!(), } } -pub(crate) fn inherit_predicates_for_delegation_item<'tcx>( +pub(crate) fn inherit_generics_for_delegation_item<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, sig_id: DefId, -) -> Option> { +) -> ty::Generics { + let builder = GenericsBuilder::new(tcx, sig_id); + let parent = tcx.parent(def_id.into()); + let caller_kind = fn_kind(tcx, def_id.into()); let callee_kind = fn_kind(tcx, sig_id); - - // FIXME(fn_delegation): Support generics on associated delegation items. - // Error was reported in `check_delegation_constraints`. match (caller_kind, callee_kind) { - (FnKind::Free, _) => { - let mut predicates = vec![]; - let callee_predicates = tcx.predicates_of(sig_id); - if let Some(parent_sig_id) = callee_predicates.parent { - let parent_sig_predicates = tcx.predicates_of(parent_sig_id); - predicates.extend_from_slice(parent_sig_predicates.predicates); - } - predicates.extend_from_slice(callee_predicates.predicates); + (FnKind::Free, FnKind::Free) + | (FnKind::Free, FnKind::AssocTrait) => builder.with_generics(sig_id).sort().build(), + (FnKind::AssocTraitImpl, FnKind::AssocTrait) => { + builder + .with_parent(parent) + .with_own_generics(sig_id) + .build() + } + (FnKind::AssocInherentImpl, FnKind::AssocTrait) + | (FnKind::AssocTrait, FnKind::AssocTrait) => { + builder + .with_parent(parent) + .with_generics(sig_id) + .skip_self() + .sort() + .build() + } + (FnKind::AssocInherentImpl, FnKind::Free) + | (FnKind::AssocTrait, FnKind::Free) => { + builder + .with_parent(parent) + .with_generics(sig_id) + .build() + } + // `sig_id` is taken from corresponding trait method. + (FnKind::AssocTraitImpl, _) | + (_, FnKind::AssocTraitImpl) | + // delegation to inherent methods is not yet supported + (_, FnKind::AssocInherentImpl) => unreachable!(), + } +} - let remap_table = create_remap_table(tcx, def_id, sig_id); - let mut folder = IndicesFolder { tcx, remap_table: &remap_table }; - let predicates = predicates.fold_with(&mut folder); +pub(crate) fn inherit_predicates_for_delegation_item<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + sig_id: DefId, +) -> ty::GenericPredicates<'tcx> { + let args = create_generic_args(tcx, def_id, sig_id); + let builder = PredicatesBuilder::new(tcx, args); + let parent = tcx.parent(def_id.into()); - Some(ty::GenericPredicates { - parent: None, - predicates: tcx.arena.alloc_from_iter(predicates), - }) + let caller_kind = fn_kind(tcx, def_id.into()); + let callee_kind = fn_kind(tcx, sig_id); + match (caller_kind, callee_kind) { + (FnKind::Free, FnKind::Free) + | (FnKind::Free, FnKind::AssocTrait) => { + builder.with_preds(|sig_id| tcx.predicates_of(sig_id), sig_id).build() } - _ => None, + (FnKind::AssocTraitImpl, FnKind::AssocTrait) => { + builder + .with_parent(parent) + .with_own_preds(|sig_id| tcx.predicates_of(sig_id), sig_id) + .build() + } + (FnKind::AssocInherentImpl, FnKind::AssocTrait) + | (FnKind::AssocTrait, FnKind::AssocTrait) + | (FnKind::AssocInherentImpl, FnKind::Free) + | (FnKind::AssocTrait, FnKind::Free) => { + // `explicit_predicates_of` is used here to avoid + // `Self: Trait` bound. + builder + .with_parent(parent) + .with_preds(|sig_id| tcx.explicit_predicates_of(sig_id), sig_id) + .build() + } + // `sig_id` is taken from corresponding trait method. + (FnKind::AssocTraitImpl, _) | + (_, FnKind::AssocTraitImpl) | + // delegation to inherent methods is not yet supported + (_, FnKind::AssocInherentImpl) => unreachable!(), } } fn check_constraints<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { let mut ret = Ok(()); let sig_id = tcx.hir().delegation_sig_id(def_id); + let span = tcx.def_span(def_id); let mut emit = |descr| { ret = Err(tcx.dcx().emit_err(crate::errors::UnsupportedDelegation { - span: tcx.def_span(def_id), + span, descr, callee_span: tcx.def_span(sig_id), })); @@ -177,21 +395,7 @@ fn check_constraints<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Result<(), if let Some(local_sig_id) = sig_id.as_local() && tcx.hir().opt_delegation_sig_id(local_sig_id).is_some() { - emit("recursive delegation"); - } - - let caller_kind = fn_kind(tcx, def_id.into()); - if caller_kind != FnKind::Free { - let sig_generics = tcx.generics_of(sig_id); - let parent = tcx.parent(def_id.into()); - let parent_generics = tcx.generics_of(parent); - - let parent_is_trait = (tcx.def_kind(parent) == DefKind::Trait) as usize; - let sig_has_self = sig_generics.has_self as usize; - - if sig_generics.count() > sig_has_self || parent_generics.count() > parent_is_trait { - emit("early bound generics are not supported for associated delegation items"); - } + emit("recursive delegation is not supported yet"); } ret @@ -208,32 +412,11 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>( let err_type = Ty::new_error(tcx, err); return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type)); } + let args = create_generic_args(tcx, def_id, sig_id); - let caller_kind = fn_kind(tcx, def_id.into()); - let callee_kind = fn_kind(tcx, sig_id); - - // FIXME(fn_delegation): Support generics on associated delegation items. - // Error was reported in `check_constraints`. - let sig = match (caller_kind, callee_kind) { - (FnKind::Free, _) => { - let remap_table = create_remap_table(tcx, def_id, sig_id); - let mut folder = IndicesFolder { tcx, remap_table: &remap_table }; - caller_sig.instantiate_identity().fold_with(&mut folder) - } - // only `Self` param supported here - (FnKind::AssocTraitImpl, FnKind::AssocTrait) - | (FnKind::AssocInherentImpl, FnKind::AssocTrait) => { - let parent = tcx.parent(def_id.into()); - let self_ty = tcx.type_of(parent).instantiate_identity(); - let generic_self_ty = ty::GenericArg::from(self_ty); - let args = tcx.mk_args_from_iter(std::iter::once(generic_self_ty)); - caller_sig.instantiate(tcx, args) - } - _ => caller_sig.instantiate_identity(), - }; // Bound vars are also inherited from `sig_id`. // They will be rebound later in `lower_fn_ty`. - let sig = sig.skip_binder(); + let sig = caller_sig.instantiate(tcx, args).skip_binder(); let sig_it = sig.inputs().iter().cloned().chain(std::iter::once(sig.output())); tcx.arena.alloc_from_iter(sig_it) } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index dbfe7da1d8cdf..343f2c029fbbc 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1939,8 +1939,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> { - let delegation_sig = - self.tcx().inherit_sig_for_delegation_item(self.item_def_id()); + let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id()); match idx { hir::InferDelegationKind::Input(idx) => delegation_sig[idx], hir::InferDelegationKind::Output => *delegation_sig.last().unwrap(), diff --git a/tests/ui/delegation/generics/free-fn-to-free-fn.stderr b/tests/ui/delegation/generics/free-fn-to-free-fn.stderr index 763f90c6e52bb..9ceb6e7b52f93 100644 --- a/tests/ui/delegation/generics/free-fn-to-free-fn.stderr +++ b/tests/ui/delegation/generics/free-fn-to-free-fn.stderr @@ -1,9 +1,14 @@ -error[E0282]: type annotations needed - --> $DIR/free-fn-to-free-fn.rs:15:7 +error[E0284]: type annotations needed + --> $DIR/free-fn-to-free-fn.rs:15:17 | LL | reuse to_reuse::consts; - | ^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `consts` + | ^^^^^^ cannot infer the value of the const parameter `N` declared on the function `consts` | +note: required by a const generic parameter in `to_reuse::consts` + --> $DIR/free-fn-to-free-fn.rs:5:19 + | +LL | pub fn consts() -> i32 { + | ^^^^^^^^^^^^ required by this const generic parameter in `consts` help: consider specifying the generic argument | LL | reuse to_reuse::consts::; @@ -45,5 +50,5 @@ LL | struct S; error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0282, E0794. +Some errors have detailed explanations: E0277, E0284, E0794. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/generics/free-fn-to-trait-method.stderr b/tests/ui/delegation/generics/free-fn-to-trait-method.stderr index b004512c14645..7aa268c15793f 100644 --- a/tests/ui/delegation/generics/free-fn-to-trait-method.stderr +++ b/tests/ui/delegation/generics/free-fn-to-trait-method.stderr @@ -5,10 +5,10 @@ LL | fn foo(&self, _: U, _: T) {} | - found this type parameter ... LL | reuse generic_arguments::Trait::<_>::foo:: as generic_arguments1; - | -------------------------------^^^------- - | | | - | | expected `i32`, found type parameter `U` - | arguments to this function are incorrect + | ^^^ + | | + | expected `i32`, found type parameter `U` + | arguments to this function are incorrect | = note: expected type `i32` found type parameter `U` @@ -25,10 +25,10 @@ LL | pub trait Trait { | ------------------ found this type parameter ... LL | reuse >::foo as generic_arguments2; - | -------------------------------------^^^ - | | | - | | expected `&u8`, found `&Self` - | arguments to this function are incorrect + | ^^^ + | | + | expected `&u8`, found `&Self` + | arguments to this function are incorrect | = note: expected reference `&u8` found reference `&Self` diff --git a/tests/ui/delegation/generics/impl-to-free-fn-pass.rs b/tests/ui/delegation/generics/impl-to-free-fn-pass.rs new file mode 100644 index 0000000000000..2cd5f2ea63686 --- /dev/null +++ b/tests/ui/delegation/generics/impl-to-free-fn-pass.rs @@ -0,0 +1,29 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod to_reuse { + pub fn foo(_: T, y: U) -> U { y } +} + +trait Trait { + fn foo(&self, x: T) -> T { x } +} +struct F; +impl Trait for F {} + +struct S(F, T); + +impl Trait for S { + reuse to_reuse::foo { &self.0 } +} + +impl S { + reuse to_reuse::foo; +} + +fn main() { + let s = S(F, 42); + assert_eq!(S::::foo(2, 1), 1); + assert_eq!( as Trait<_>>::foo(&s, 1), 1); +} diff --git a/tests/ui/delegation/generics/impl-to-trait-method-pass.rs b/tests/ui/delegation/generics/impl-to-trait-method-pass.rs new file mode 100644 index 0000000000000..1bb85aecb9123 --- /dev/null +++ b/tests/ui/delegation/generics/impl-to-trait-method-pass.rs @@ -0,0 +1,107 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +trait GenericTrait { + fn bar(&self, x: T, y: U) -> (U, T) { (y, x) } +} +trait Trait { + fn foo1(&self) -> i32 { 1 } + fn foo2(&self, x: T) -> T { x } +} + +#[derive(Debug, PartialEq)] +struct F; +impl GenericTrait for F {} +impl Trait for F {} + +struct S(F); +struct GenericTy(F, T); + +mod generic_trait { + use super::*; + + impl GenericTrait for S { + reuse GenericTrait::bar { &self.0 } + } + + impl S { + reuse GenericTrait::bar { &self.0 } + } + + pub fn check() { + let s = S(F); + assert_eq!(s.bar(F, 1).1, F); + assert_eq!(>::bar(&s, F, 1).1, F); + } +} + +mod generic_trait_and_type { + use super::*; + + impl GenericTrait for GenericTy { + reuse GenericTrait::bar { &self.0 } + } + + impl GenericTy { + reuse GenericTrait::bar { &self.0 } + } + + pub fn check() { + let ty = GenericTy(F, F); + assert_eq!(ty.bar("str", 1u8).1, "str"); + assert_eq!( as GenericTrait<_>>::bar(&ty, "str", 1u8).1, "str"); + } +} + +mod generic_type { + use super::*; + + impl Trait for GenericTy { + reuse Trait::{foo1, foo2} { &self.0 } + } + + impl GenericTy { + reuse Trait::{foo1, foo2} { &self.0 } + } + + pub fn check() { + let ty = GenericTy(F, "str"); + assert_eq!(ty.foo1(), 1); + assert_eq!(ty.foo2(F), F); + + assert_eq!( as Trait>::foo1(&ty), 1); + assert_eq!( as Trait>::foo2(&ty, 1u16), 1u16); + } +} + +mod lifetimes { + struct Struct<'a>(&'a u8); + trait Trait<'a> { + fn foo<'b>(&'a self, x: &'b u8) -> &'b u8 { x } + } + + impl<'a> Trait<'a> for u8 {} + + impl<'a> Trait<'a> for Struct<'a> { + reuse Trait::foo { self.0 } + } + + impl<'a> Struct<'a> { + reuse Trait::foo { self.0 } + } + + pub fn check() { + let s = Struct(&1); + let val = &2; + assert_eq!(*s.foo(val), *val); + assert_eq!(*::foo(&s, val), *val); + } +} + +fn main() { + generic_trait::check(); + generic_trait_and_type::check(); + generic_type::check(); + lifetimes::check(); +} diff --git a/tests/ui/delegation/generics/impl-to-trait-method.rs b/tests/ui/delegation/generics/impl-to-trait-method.rs new file mode 100644 index 0000000000000..39e32e2ed1500 --- /dev/null +++ b/tests/ui/delegation/generics/impl-to-trait-method.rs @@ -0,0 +1,44 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod bounds { + trait Trait0 {} + + trait Trait1 { + fn foo(&self) + where + T: Trait0, + U: Trait0, + Self: Trait0, + //~^ ERROR the trait bound `bounds::S: Trait0` is not satisfied + { + } + } + + struct F; + impl Trait1 for F {} + + struct S(F); + + impl Trait1 for S { + reuse Trait1::::foo { &self.0 } + //~^ ERROR the trait bound `bounds::F: Trait0` is not satisfied + } +} + +mod unconstrained_parameter { + trait Trait { + fn foo(&self) {} + } + + struct F; + impl Trait for F {} + + struct S(F); + impl S { + reuse Trait::foo { &self.0 } + //~^ ERROR type annotations needed + } +} + +fn main() {} diff --git a/tests/ui/delegation/generics/impl-to-trait-method.stderr b/tests/ui/delegation/generics/impl-to-trait-method.stderr new file mode 100644 index 0000000000000..7db95e6acdf97 --- /dev/null +++ b/tests/ui/delegation/generics/impl-to-trait-method.stderr @@ -0,0 +1,56 @@ +error[E0277]: the trait bound `bounds::S: Trait0` is not satisfied + --> $DIR/impl-to-trait-method.rs:12:19 + | +LL | Self: Trait0, + | ^^^^^^ the trait `Trait0` is not implemented for `bounds::S` + | +help: this trait has no implementations, consider adding one + --> $DIR/impl-to-trait-method.rs:5:5 + | +LL | trait Trait0 {} + | ^^^^^^^^^^^^ + = help: see issue #48214 +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | +LL + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `bounds::F: Trait0` is not satisfied + --> $DIR/impl-to-trait-method.rs:24:32 + | +LL | reuse Trait1::::foo { &self.0 } + | --- ^^-------^^ + | | | | + | | | this tail expression is of type `&F` + | | the trait `Trait0` is not implemented for `bounds::F` + | required by a bound introduced by this call + | +help: this trait has no implementations, consider adding one + --> $DIR/impl-to-trait-method.rs:5:5 + | +LL | trait Trait0 {} + | ^^^^^^^^^^^^ +note: required by a bound in `Trait1::foo` + --> $DIR/impl-to-trait-method.rs:12:19 + | +LL | fn foo(&self) + | --- required by a bound in this associated function +... +LL | Self: Trait0, + | ^^^^^^ required by this bound in `Trait1::foo` + +error[E0282]: type annotations needed + --> $DIR/impl-to-trait-method.rs:39:22 + | +LL | reuse Trait::foo { &self.0 } + | ^^^ cannot infer type of the type parameter `T` declared on the trait `Trait` + | +help: consider specifying the generic argument + | +LL | reuse Trait::::foo { &self.0 } + | +++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0282. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/generics/impl-trait-to-trait.stderr b/tests/ui/delegation/generics/impl-trait-to-trait.stderr new file mode 100644 index 0000000000000..08361b4484e7e --- /dev/null +++ b/tests/ui/delegation/generics/impl-trait-to-trait.stderr @@ -0,0 +1,44 @@ +error[E0277]: the trait bound `S: Trait0` is not satisfied + --> $DIR/impl-trait-to-trait.rs:12:19 + | +LL | Self: Trait0, + | ^^^^^^ the trait `Trait0` is not implemented for `S` + | +help: this trait has no implementations, consider adding one + --> $DIR/impl-trait-to-trait.rs:5:5 + | +LL | trait Trait0 {} + | ^^^^^^^^^^^^ + = help: see issue #48214 +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | +LL + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `F: Trait0` is not satisfied + --> $DIR/impl-trait-to-trait.rs:24:32 + | +LL | reuse Trait1::::foo { &self.0 } + | --- ^^-------^^ + | | | | + | | | this tail expression is of type `&F` + | | the trait `Trait0` is not implemented for `F` + | required by a bound introduced by this call + | +help: this trait has no implementations, consider adding one + --> $DIR/impl-trait-to-trait.rs:5:5 + | +LL | trait Trait0 {} + | ^^^^^^^^^^^^ +note: required by a bound in `Trait1::foo` + --> $DIR/impl-trait-to-trait.rs:12:19 + | +LL | fn foo(&self) + | --- required by a bound in this associated function +... +LL | Self: Trait0, + | ^^^^^^ required by this bound in `Trait1::foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/generics/trait-method-to-other-pass.rs b/tests/ui/delegation/generics/trait-method-to-other-pass.rs new file mode 100644 index 0000000000000..b16ba31345e75 --- /dev/null +++ b/tests/ui/delegation/generics/trait-method-to-other-pass.rs @@ -0,0 +1,29 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod to_reuse { + pub fn foo(x: T) -> T { x } +} + +trait Trait1 { + fn foo(&self, _: T, x: U) -> U { x } +} + +#[derive(Default)] +struct F; + +impl Trait1 for F {} + +trait Trait2 { + fn get_f(&self) -> &F { &F } + reuse Trait1::foo as bar { self.get_f() } + reuse to_reuse::foo as baz; +} + +impl Trait2 for F {} + +fn main() { + assert_eq!(F.bar(1u8, 2u16), 2u16); + assert_eq!(F::baz(1u8), 1u8); +} diff --git a/tests/ui/delegation/ice-issue-124347.rs b/tests/ui/delegation/ice-issue-124347.rs index 82a96055099c7..d18d940d122e3 100644 --- a/tests/ui/delegation/ice-issue-124347.rs +++ b/tests/ui/delegation/ice-issue-124347.rs @@ -7,6 +7,6 @@ trait Trait { } reuse foo; -//~^ ERROR recursive delegation is not supported yet +//~^ ERROR cycle detected when computing generics of `foo` fn main() {} diff --git a/tests/ui/delegation/ice-issue-124347.stderr b/tests/ui/delegation/ice-issue-124347.stderr index 5a3f4525d29e5..b7e8dd621baa6 100644 --- a/tests/ui/delegation/ice-issue-124347.stderr +++ b/tests/ui/delegation/ice-issue-124347.stderr @@ -4,11 +4,20 @@ error: recursive delegation is not supported yet LL | reuse Trait::foo { &self.0 } | ^^^ callee defined here -error: recursive delegation is not supported yet +error[E0391]: cycle detected when computing generics of `foo` + --> $DIR/ice-issue-124347.rs:9:7 + | +LL | reuse foo; + | ^^^ + | + = note: ...which immediately requires computing generics of `foo` again +note: cycle used when checking that `foo` is well-formed --> $DIR/ice-issue-124347.rs:9:7 | LL | reuse foo; - | ^^^ callee defined here + | ^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs deleted file mode 100644 index d7653aaaecc71..0000000000000 --- a/tests/ui/delegation/not-supported.rs +++ /dev/null @@ -1,104 +0,0 @@ -#![feature(c_variadic)] -#![feature(fn_delegation)] -#![allow(incomplete_features)] - -mod generics { - trait GenericTrait { - fn bar(&self, x: T) -> T { x } - fn bar1() {} - } - trait Trait { - fn foo(&self, x: i32) -> i32 { x } - fn foo1<'a>(&self, x: &'a i32) -> &'a i32 { x } - fn foo2(&self, x: T) -> T { x } - fn foo3<'a: 'a>(_: &'a u32) {} - - reuse GenericTrait::bar; - //~^ ERROR early bound generics are not supported for associated delegation items - reuse GenericTrait::bar1; - //~^ ERROR early bound generics are not supported for associated delegation items - } - - struct F; - impl Trait for F {} - impl GenericTrait for F {} - - struct S(F); - - impl GenericTrait for S { - reuse >::bar { &self.0 } - //~^ ERROR early bound generics are not supported for associated delegation items - reuse GenericTrait::::bar1; - //~^ ERROR early bound generics are not supported for associated delegation items - } - - impl GenericTrait<()> for () { - reuse GenericTrait::bar { &F } - //~^ ERROR early bound generics are not supported for associated delegation items - reuse GenericTrait::bar1; - //~^ ERROR early bound generics are not supported for associated delegation items - } - - impl Trait for &S { - reuse Trait::foo; - //~^ ERROR early bound generics are not supported for associated delegation items - } - - impl Trait for S { - reuse Trait::foo1 { &self.0 } - reuse Trait::foo2 { &self.0 } - //~^ ERROR early bound generics are not supported for associated delegation items - //~| ERROR method `foo2` has 0 type parameters but its trait declaration has 1 type parameter - reuse ::foo3; - //~^ ERROR early bound generics are not supported for associated delegation items - //~| ERROR lifetime parameters or bounds on method `foo3` do not match the trait declaration - } - - struct GenericS(T); - impl Trait for GenericS { - reuse Trait::foo { &self.0 } - //~^ ERROR early bound generics are not supported for associated delegation items - } -} - -mod opaque { - trait Trait {} - impl Trait for () {} - - mod to_reuse { - use super::Trait; - - pub fn opaque_ret() -> impl Trait { unimplemented!() } - //~^ warn: this function depends on never type fallback being `()` - //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - } - - trait ToReuse { - fn opaque_ret() -> impl Trait { unimplemented!() } - //~^ warn: this function depends on never type fallback being `()` - //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - } - - // FIXME: Inherited `impl Trait`s create query cycles when used inside trait impls. - impl ToReuse for u8 { - reuse to_reuse::opaque_ret; //~ ERROR cycle detected when computing type - } - impl ToReuse for u16 { - reuse ToReuse::opaque_ret; //~ ERROR cycle detected when computing type - } -} - -mod recursive { - mod to_reuse1 { - pub mod to_reuse2 { - pub fn foo() {} - } - - pub reuse to_reuse2::foo; - } - - reuse to_reuse1::foo; - //~^ ERROR recursive delegation is not supported yet -} - -fn main() {} diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr deleted file mode 100644 index 25e599ab808b4..0000000000000 --- a/tests/ui/delegation/not-supported.stderr +++ /dev/null @@ -1,199 +0,0 @@ -error: early bound generics are not supported for associated delegation items is not supported yet - --> $DIR/not-supported.rs:16:29 - | -LL | fn bar(&self, x: T) -> T { x } - | ------------------------ callee defined here -... -LL | reuse GenericTrait::bar; - | ^^^ - -error: early bound generics are not supported for associated delegation items is not supported yet - --> $DIR/not-supported.rs:18:29 - | -LL | fn bar1() {} - | --------- callee defined here -... -LL | reuse GenericTrait::bar1; - | ^^^^ - -error: early bound generics are not supported for associated delegation items is not supported yet - --> $DIR/not-supported.rs:29:39 - | -LL | fn bar(&self, x: T) -> T { x } - | ------------------------ callee defined here -... -LL | reuse >::bar { &self.0 } - | ^^^ - -error: early bound generics are not supported for associated delegation items is not supported yet - --> $DIR/not-supported.rs:31:34 - | -LL | fn bar1() {} - | --------- callee defined here -... -LL | reuse GenericTrait::::bar1; - | ^^^^ - -error: early bound generics are not supported for associated delegation items is not supported yet - --> $DIR/not-supported.rs:36:29 - | -LL | fn bar(&self, x: T) -> T { x } - | ------------------------ callee defined here -... -LL | reuse GenericTrait::bar { &F } - | ^^^ - -error: early bound generics are not supported for associated delegation items is not supported yet - --> $DIR/not-supported.rs:38:29 - | -LL | fn bar1() {} - | --------- callee defined here -... -LL | reuse GenericTrait::bar1; - | ^^^^ - -error: early bound generics are not supported for associated delegation items is not supported yet - --> $DIR/not-supported.rs:43:22 - | -LL | fn foo(&self, x: i32) -> i32 { x } - | ---------------------------- callee defined here -... -LL | reuse Trait::foo; - | ^^^ - -error[E0049]: method `foo2` has 0 type parameters but its trait declaration has 1 type parameter - --> $DIR/not-supported.rs:49:22 - | -LL | fn foo2(&self, x: T) -> T { x } - | - expected 1 type parameter -... -LL | reuse Trait::foo2 { &self.0 } - | ^^^^ found 0 type parameters - -error: early bound generics are not supported for associated delegation items is not supported yet - --> $DIR/not-supported.rs:52:29 - | -LL | fn foo3<'a: 'a>(_: &'a u32) {} - | --------------------------- callee defined here -... -LL | reuse ::foo3; - | ^^^^ - -error[E0195]: lifetime parameters or bounds on method `foo3` do not match the trait declaration - --> $DIR/not-supported.rs:52:29 - | -LL | fn foo3<'a: 'a>(_: &'a u32) {} - | -------- lifetimes in impl do not match this method in trait -... -LL | reuse ::foo3; - | ^^^^ lifetimes do not match method in trait - -error: early bound generics are not supported for associated delegation items is not supported yet - --> $DIR/not-supported.rs:59:22 - | -LL | fn foo(&self, x: i32) -> i32 { x } - | ---------------------------- callee defined here -... -LL | reuse Trait::foo { &self.0 } - | ^^^ - -error: early bound generics are not supported for associated delegation items is not supported yet - --> $DIR/not-supported.rs:49:22 - | -LL | fn foo2(&self, x: T) -> T { x } - | ---------------------------- callee defined here -... -LL | reuse Trait::foo2 { &self.0 } - | ^^^^ - -error: delegation with early bound generics is not supported yet - --> $DIR/not-supported.rs:76:21 - | -LL | pub fn opaque_arg(_: impl Trait) -> i32 { 0 } - | --------------------------------------- callee defined here -... -LL | reuse to_reuse::opaque_arg; - | ^^^^^^^^^^ - -warning: this function depends on never type fallback being `()` - --> $DIR/not-supported.rs:80:9 - | -LL | fn opaque_ret() -> impl Trait { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #123748 - = help: specify the types explicitly -note: in edition 2024, the requirement `!: opaque::Trait` will fail - --> $DIR/not-supported.rs:80:28 - | -LL | fn opaque_ret() -> impl Trait { unimplemented!() } - | ^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default - -error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` - --> $DIR/not-supported.rs:87:25 - | -LL | reuse to_reuse::opaque_ret; - | ^^^^^^^^^^ - | -note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/not-supported.rs:87:25 - | -LL | reuse to_reuse::opaque_ret; - | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::` is well-formed - --> $DIR/not-supported.rs:86:5 - | -LL | impl ToReuse for u8 { - | ^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -warning: this function depends on never type fallback being `()` - --> $DIR/not-supported.rs:72:9 - | -LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #123748 - = help: specify the types explicitly -note: in edition 2024, the requirement `!: opaque::Trait` will fail - --> $DIR/not-supported.rs:72:32 - | -LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } - | ^^^^^^^^^^ - -error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` - --> $DIR/not-supported.rs:90:24 - | -LL | reuse ToReuse::opaque_ret; - | ^^^^^^^^^^ - | -note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/not-supported.rs:90:24 - | -LL | reuse ToReuse::opaque_ret; - | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::` is well-formed - --> $DIR/not-supported.rs:89:5 - | -LL | impl ToReuse for u16 { - | ^^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: recursive delegation is not supported yet - --> $DIR/not-supported.rs:103:22 - | -LL | pub reuse to_reuse2::foo; - | --- callee defined here -... -LL | reuse to_reuse1::foo; - | ^^^ - -error: aborting due to 16 previous errors; 2 warnings emitted - -Some errors have detailed explanations: E0049, E0195, E0391. -For more information about an error, try `rustc --explain E0049`. diff --git a/tests/ui/delegation/unsupported.rs b/tests/ui/delegation/unsupported.rs new file mode 100644 index 0000000000000..7e89485304380 --- /dev/null +++ b/tests/ui/delegation/unsupported.rs @@ -0,0 +1,41 @@ +#![feature(c_variadic)] +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod opaque { + trait Trait {} + impl Trait for () {} + + mod to_reuse { + use super::Trait; + + pub fn opaque_ret() -> impl Trait { () } + } + + trait ToReuse { + fn opaque_ret() -> impl Trait { () } + } + + // FIXME: Inherited `impl Trait`s create query cycles when used inside trait impls. + impl ToReuse for u8 { + reuse to_reuse::opaque_ret; //~ ERROR cycle detected when computing type + } + impl ToReuse for u16 { + reuse ToReuse::opaque_ret; //~ ERROR cycle detected when computing type + } +} + +mod recursive { + mod to_reuse1 { + pub mod to_reuse2 { + pub fn foo() {} + } + + pub reuse to_reuse2::foo; + } + + reuse to_reuse1::foo; + //~^ ERROR recursive delegation is not supported yet +} + +fn main() {} diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr new file mode 100644 index 0000000000000..d1f90302b1de3 --- /dev/null +++ b/tests/ui/delegation/unsupported.stderr @@ -0,0 +1,50 @@ +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/unsupported.rs:21:25 + | +LL | reuse to_reuse::opaque_ret; + | ^^^^^^^^^^ + | +note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... + --> $DIR/unsupported.rs:21:25 + | +LL | reuse to_reuse::opaque_ret; + | ^^^^^^^^^^ + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/unsupported.rs:20:5 + | +LL | impl ToReuse for u8 { + | ^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/unsupported.rs:24:24 + | +LL | reuse ToReuse::opaque_ret; + | ^^^^^^^^^^ + | +note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... + --> $DIR/unsupported.rs:24:24 + | +LL | reuse ToReuse::opaque_ret; + | ^^^^^^^^^^ + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/unsupported.rs:23:5 + | +LL | impl ToReuse for u16 { + | ^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: recursive delegation is not supported yet + --> $DIR/unsupported.rs:37:22 + | +LL | pub reuse to_reuse2::foo; + | --- callee defined here +... +LL | reuse to_reuse1::foo; + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0391`.