Auto merge of #126161 - Bryanskiy:delegation-generics-4, r=petrochenkov
Delegation: support generics in associated delegation items This is a continuation of https://github.com/rust-lang/rust/pull/125929. [design](https://github.com/Bryanskiy/posts/blob/master/delegation%20in%20generic%20contexts.md) Generic parameters inheritance was implemented in all contexts. Generic arguments are not yet supported. r? `@petrochenkov`
This commit is contained in:
commit
ec867f03bc
16 changed files with 778 additions and 446 deletions
|
@ -59,6 +59,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||||
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
||||||
|
|
||||||
let node = tcx.hir_node(hir_id);
|
let node = tcx.hir_node(hir_id);
|
||||||
|
if let Some(sig) = node.fn_sig()
|
||||||
|
&& let Some(sig_id) = sig.decl.opt_delegation_sig_id()
|
||||||
|
{
|
||||||
|
return inherit_generics_for_delegation_item(tcx, def_id, sig_id);
|
||||||
|
}
|
||||||
|
|
||||||
let parent_def_id = match node {
|
let parent_def_id = match node {
|
||||||
Node::ImplItem(_)
|
Node::ImplItem(_)
|
||||||
| Node::TraitItem(_)
|
| Node::TraitItem(_)
|
||||||
|
@ -229,16 +235,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||||
// inherit the generics of the item.
|
// inherit the generics of the item.
|
||||||
Some(parent.to_def_id())
|
Some(parent.to_def_id())
|
||||||
}
|
}
|
||||||
ItemKind::Fn(sig, _, _) => {
|
|
||||||
// For a delegation item inherit generics from callee.
|
|
||||||
if let Some(sig_id) = sig.decl.opt_delegation_sig_id()
|
|
||||||
&& let Some(generics) =
|
|
||||||
inherit_generics_for_delegation_item(tcx, def_id, sig_id)
|
|
||||||
{
|
|
||||||
return generics;
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
@ -138,6 +138,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
||||||
let node = tcx.hir_node(hir_id);
|
let node = tcx.hir_node(hir_id);
|
||||||
|
|
||||||
|
if let Some(sig) = node.fn_sig()
|
||||||
|
&& let Some(sig_id) = sig.decl.opt_delegation_sig_id()
|
||||||
|
{
|
||||||
|
return inherit_predicates_for_delegation_item(tcx, def_id, sig_id);
|
||||||
|
}
|
||||||
|
|
||||||
let mut is_trait = None;
|
let mut is_trait = None;
|
||||||
let mut is_default_impl_trait = None;
|
let mut is_default_impl_trait = None;
|
||||||
|
|
||||||
|
@ -164,16 +170,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => {
|
ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => {
|
||||||
is_trait = Some(self_bounds);
|
is_trait = Some(self_bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::Fn(sig, _, _) => {
|
|
||||||
// For a delegation item inherit predicates from callee.
|
|
||||||
if let Some(sig_id) = sig.decl.opt_delegation_sig_id()
|
|
||||||
&& let Some(predicates) =
|
|
||||||
inherit_predicates_for_delegation_item(tcx, def_id, sig_id)
|
|
||||||
{
|
|
||||||
return predicates;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
//! Support inheriting generic parameters and predicates for function delegation.
|
||||||
|
//!
|
||||||
|
//! For more information about delegation design, see the tracking issue #118212.
|
||||||
|
|
||||||
use std::assert_matches::debug_assert_matches;
|
use std::assert_matches::debug_assert_matches;
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
@ -5,7 +9,7 @@ use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::ErrorGuaranteed;
|
use rustc_span::{ErrorGuaranteed, Span};
|
||||||
use rustc_type_ir::visit::TypeVisitableExt;
|
use rustc_type_ir::visit::TypeVisitableExt;
|
||||||
|
|
||||||
type RemapTable = FxHashMap<u32, u32>;
|
type RemapTable = FxHashMap<u32, u32>;
|
||||||
|
@ -76,20 +80,63 @@ fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_generic_args<'tcx>(
|
/// Given the current context(caller and callee `FnKind`), it specifies
|
||||||
tcx: TyCtxt<'tcx>,
|
/// the policy of predicates and generic parameters inheritance.
|
||||||
def_id: LocalDefId,
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
sig_id: DefId,
|
enum InheritanceKind {
|
||||||
) -> ty::GenericArgsRef<'tcx> {
|
/// Copying all predicates and parameters, including those of the parent
|
||||||
let caller_generics = tcx.generics_of(def_id);
|
/// container.
|
||||||
let callee_generics = tcx.generics_of(sig_id);
|
///
|
||||||
|
/// Boolean value defines whether the `Self` parameter or `Self: Trait`
|
||||||
|
/// predicate are copied. It's always equal to `false` except when
|
||||||
|
/// delegating from a free function to a trait method.
|
||||||
|
///
|
||||||
|
/// FIXME(fn_delegation): This often leads to type inference
|
||||||
|
/// errors. Support providing generic arguments or restrict use sites.
|
||||||
|
WithParent(bool),
|
||||||
|
/// The trait implementation should be compatible with the original trait.
|
||||||
|
/// Therefore, for trait implementations only the method's own parameters
|
||||||
|
/// and predicates are copied.
|
||||||
|
Own,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GenericsBuilder<'tcx> {
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
sig_id: DefId,
|
||||||
|
parent: Option<DefId>,
|
||||||
|
inh_kind: InheritanceKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> GenericsBuilder<'tcx> {
|
||||||
|
fn new(tcx: TyCtxt<'tcx>, sig_id: DefId) -> GenericsBuilder<'tcx> {
|
||||||
|
GenericsBuilder { tcx, sig_id, parent: None, inh_kind: InheritanceKind::WithParent(false) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_parent(mut self, parent: DefId) -> Self {
|
||||||
|
self.parent = Some(parent);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self {
|
||||||
|
self.inh_kind = inh_kind;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build(self) -> ty::Generics {
|
||||||
|
let mut own_params = vec![];
|
||||||
|
|
||||||
|
let sig_generics = self.tcx.generics_of(self.sig_id);
|
||||||
|
if let InheritanceKind::WithParent(has_self) = self.inh_kind
|
||||||
|
&& let Some(parent_def_id) = sig_generics.parent
|
||||||
|
{
|
||||||
|
let sig_parent_generics = self.tcx.generics_of(parent_def_id);
|
||||||
|
own_params.append(&mut sig_parent_generics.own_params.clone());
|
||||||
|
if !has_self {
|
||||||
|
own_params.remove(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
own_params.append(&mut sig_generics.own_params.clone());
|
||||||
|
|
||||||
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 will be reported in `check_constraints`.
|
|
||||||
match (caller_kind, callee_kind) {
|
|
||||||
(FnKind::Free, _) => {
|
|
||||||
// Lifetime parameters must be declared before type and const parameters.
|
// Lifetime parameters must be declared before type and const parameters.
|
||||||
// Therefore, When delegating from a free function to a associated function,
|
// Therefore, When delegating from a free function to a associated function,
|
||||||
// generic parameters need to be reordered:
|
// generic parameters need to be reordered:
|
||||||
|
@ -103,54 +150,28 @@ fn create_generic_args<'tcx>(
|
||||||
// fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
|
// fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
|
||||||
// Trait::foo(...)
|
// Trait::foo(...)
|
||||||
// }
|
// }
|
||||||
let mut remap_table = RemapTable::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);
|
|
||||||
}
|
|
||||||
let mut folder = ParamIndexRemapper { tcx, remap_table };
|
|
||||||
ty::GenericArgs::identity_for_item(tcx, sig_id).fold_with(&mut folder)
|
|
||||||
}
|
|
||||||
// FIXME(fn_delegation): 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);
|
|
||||||
tcx.mk_args_from_iter(std::iter::once(generic_self_ty))
|
|
||||||
}
|
|
||||||
_ => ty::GenericArgs::identity_for_item(tcx, sig_id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
def_id: LocalDefId,
|
|
||||||
sig_id: DefId,
|
|
||||||
) -> Option<ty::Generics> {
|
|
||||||
// FIXME(fn_delegation): Support generics on associated delegation items.
|
|
||||||
// Error will be reported in `check_constraints`.
|
|
||||||
if fn_kind(tcx, def_id.into()) != FnKind::Free {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut own_params = vec![];
|
|
||||||
|
|
||||||
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());
|
own_params.sort_by_key(|key| key.kind.is_ty_or_const());
|
||||||
|
|
||||||
|
let param_def_id_to_index =
|
||||||
|
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)
|
||||||
|
};
|
||||||
|
|
||||||
for (idx, param) in own_params.iter_mut().enumerate() {
|
for (idx, param) in own_params.iter_mut().enumerate() {
|
||||||
param.index = idx as u32;
|
param.index = (idx + parent_count) as u32;
|
||||||
// Default parameters are not inherited: they are not allowed
|
// FIXME(fn_delegation): Default parameters are not inherited, because they are
|
||||||
// in fn's.
|
// not permitted in functions. Therefore, there are 2 options here:
|
||||||
|
//
|
||||||
|
// - We can create non-default generic parameters.
|
||||||
|
// - We can substitute default parameters into the signature.
|
||||||
|
//
|
||||||
|
// At the moment, first option has been selected as the most general.
|
||||||
if let ty::GenericParamDefKind::Type { has_default, .. }
|
if let ty::GenericParamDefKind::Type { has_default, .. }
|
||||||
| ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
|
| ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
|
||||||
{
|
{
|
||||||
|
@ -158,45 +179,282 @@ pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let param_def_id_to_index =
|
ty::Generics {
|
||||||
own_params.iter().map(|param| (param.def_id, param.index)).collect();
|
parent: self.parent,
|
||||||
|
parent_count,
|
||||||
Some(ty::Generics {
|
|
||||||
parent: None,
|
|
||||||
parent_count: 0,
|
|
||||||
own_params,
|
own_params,
|
||||||
param_def_id_to_index,
|
param_def_id_to_index,
|
||||||
has_self: false,
|
has_self,
|
||||||
has_late_bound_regions: callee_generics.has_late_bound_regions,
|
has_late_bound_regions: sig_generics.has_late_bound_regions,
|
||||||
host_effect_index: callee_generics.host_effect_index,
|
host_effect_index: sig_generics.host_effect_index,
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PredicatesBuilder<'tcx> {
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
sig_id: DefId,
|
||||||
|
parent: Option<DefId>,
|
||||||
|
inh_kind: InheritanceKind,
|
||||||
|
args: ty::GenericArgsRef<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> PredicatesBuilder<'tcx> {
|
||||||
|
fn new(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
args: ty::GenericArgsRef<'tcx>,
|
||||||
|
sig_id: DefId,
|
||||||
|
) -> PredicatesBuilder<'tcx> {
|
||||||
|
PredicatesBuilder {
|
||||||
|
tcx,
|
||||||
|
sig_id,
|
||||||
|
parent: None,
|
||||||
|
inh_kind: InheritanceKind::WithParent(false),
|
||||||
|
args,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_parent(mut self, parent: DefId) -> Self {
|
||||||
|
self.parent = Some(parent);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self {
|
||||||
|
self.inh_kind = inh_kind;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build(self) -> ty::GenericPredicates<'tcx> {
|
||||||
|
struct PredicatesCollector<'tcx> {
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
preds: Vec<(ty::Clause<'tcx>, Span)>,
|
||||||
|
args: ty::GenericArgsRef<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> PredicatesCollector<'tcx> {
|
||||||
|
fn new(tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> PredicatesCollector<'tcx> {
|
||||||
|
PredicatesCollector { tcx, preds: vec![], args }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_own_preds(
|
||||||
|
mut self,
|
||||||
|
f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
|
) -> Self {
|
||||||
|
let preds = f(def_id).instantiate_own(self.tcx, self.args);
|
||||||
|
self.preds.extend(preds);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_preds(
|
||||||
|
mut self,
|
||||||
|
f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy,
|
||||||
|
def_id: DefId,
|
||||||
|
) -> Self {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let collector = PredicatesCollector::new(self.tcx, self.args);
|
||||||
|
|
||||||
|
// `explicit_predicates_of` is used here to avoid copying `Self: Trait` predicate.
|
||||||
|
// Note: `predicates_of` query can also add inferred outlives predicates, but that
|
||||||
|
// is not the case here as `sig_id` is either a trait or a function.
|
||||||
|
let preds = match self.inh_kind {
|
||||||
|
InheritanceKind::WithParent(false) => {
|
||||||
|
collector.with_preds(|def_id| self.tcx.explicit_predicates_of(def_id), self.sig_id)
|
||||||
|
}
|
||||||
|
InheritanceKind::WithParent(true) => {
|
||||||
|
collector.with_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id)
|
||||||
|
}
|
||||||
|
InheritanceKind::Own => {
|
||||||
|
collector.with_own_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.preds;
|
||||||
|
|
||||||
|
ty::GenericPredicates {
|
||||||
|
parent: self.parent,
|
||||||
|
predicates: self.tcx.arena.alloc_from_iter(preds),
|
||||||
|
// FIXME(fn_delegation): Support effects.
|
||||||
|
effects_min_tys: ty::List::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = ParamIndexRemapper { 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,
|
||||||
|
) -> 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);
|
||||||
|
match (caller_kind, callee_kind) {
|
||||||
|
(FnKind::Free, FnKind::Free)
|
||||||
|
| (FnKind::Free, FnKind::AssocTrait)
|
||||||
|
| (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)
|
||||||
|
}
|
||||||
|
|
||||||
|
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
|
||||||
|
let callee_generics = tcx.generics_of(sig_id);
|
||||||
|
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));
|
||||||
|
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 trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
|
||||||
|
let trait_args = builder.build_from_args(trait_args);
|
||||||
|
|
||||||
|
let args = std::iter::once(generic_self_ty).chain(trait_args.iter().skip(1));
|
||||||
|
tcx.mk_args_from_iter(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For trait impl's `sig_id` is always equal to the corresponding trait method.
|
||||||
|
(FnKind::AssocTraitImpl, _)
|
||||||
|
| (_, FnKind::AssocTraitImpl)
|
||||||
|
// Delegation to inherent methods is not yet supported.
|
||||||
|
| (_, FnKind::AssocInherentImpl) => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME(fn_delegation): Move generics inheritance to the AST->HIR lowering.
|
||||||
|
// For now, generic parameters are not propagated to the generated call,
|
||||||
|
// which leads to inference errors:
|
||||||
|
//
|
||||||
|
// fn foo<T>(x: i32) {}
|
||||||
|
//
|
||||||
|
// reuse foo as bar;
|
||||||
|
// desugaring:
|
||||||
|
// fn bar<T>() {
|
||||||
|
// foo::<_>() // ERROR: type annotations needed
|
||||||
|
// }
|
||||||
|
pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
def_id: LocalDefId,
|
||||||
|
sig_id: DefId,
|
||||||
|
) -> ty::Generics {
|
||||||
|
let builder = GenericsBuilder::new(tcx, sig_id);
|
||||||
|
|
||||||
|
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_inheritance_kind(InheritanceKind::WithParent(true)).build(),
|
||||||
|
|
||||||
|
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
|
||||||
|
builder
|
||||||
|
.with_parent(tcx.parent(def_id.into()))
|
||||||
|
.with_inheritance_kind(InheritanceKind::Own)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
(FnKind::AssocInherentImpl, FnKind::AssocTrait)
|
||||||
|
| (FnKind::AssocTrait, FnKind::AssocTrait) => {
|
||||||
|
builder
|
||||||
|
.with_parent(tcx.parent(def_id.into()))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
(FnKind::AssocInherentImpl, FnKind::Free)
|
||||||
|
| (FnKind::AssocTrait, FnKind::Free) => {
|
||||||
|
builder
|
||||||
|
.with_parent(tcx.parent(def_id.into()))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
// For trait impl's `sig_id` is always equal to the 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_predicates_for_delegation_item<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
sig_id: DefId,
|
sig_id: DefId,
|
||||||
) -> Option<ty::GenericPredicates<'tcx>> {
|
) -> ty::GenericPredicates<'tcx> {
|
||||||
// FIXME(fn_delegation): Support generics on associated delegation items.
|
|
||||||
// Error will be reported in `check_constraints`.
|
|
||||||
if fn_kind(tcx, def_id.into()) != FnKind::Free {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let callee_predicates = tcx.predicates_of(sig_id);
|
|
||||||
let args = create_generic_args(tcx, def_id, sig_id);
|
let args = create_generic_args(tcx, def_id, sig_id);
|
||||||
|
let builder = PredicatesBuilder::new(tcx, args, sig_id);
|
||||||
|
|
||||||
let mut preds = vec![];
|
let caller_kind = fn_kind(tcx, def_id.into());
|
||||||
if let Some(parent_id) = callee_predicates.parent {
|
let callee_kind = fn_kind(tcx, sig_id);
|
||||||
preds.extend(tcx.predicates_of(parent_id).instantiate_own(tcx, args));
|
match (caller_kind, callee_kind) {
|
||||||
|
(FnKind::Free, FnKind::Free)
|
||||||
|
| (FnKind::Free, FnKind::AssocTrait) => {
|
||||||
|
builder.with_inheritance_kind(InheritanceKind::WithParent(true)).build()
|
||||||
}
|
}
|
||||||
preds.extend(callee_predicates.instantiate_own(tcx, args));
|
|
||||||
|
|
||||||
Some(ty::GenericPredicates {
|
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
|
||||||
parent: None,
|
builder
|
||||||
predicates: tcx.arena.alloc_from_iter(preds),
|
.with_parent(tcx.parent(def_id.into()))
|
||||||
effects_min_tys: ty::List::empty(),
|
.with_inheritance_kind(InheritanceKind::Own)
|
||||||
})
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
(FnKind::AssocInherentImpl, FnKind::AssocTrait)
|
||||||
|
| (FnKind::AssocTrait, FnKind::AssocTrait)
|
||||||
|
| (FnKind::AssocInherentImpl, FnKind::Free)
|
||||||
|
| (FnKind::AssocTrait, FnKind::Free) => {
|
||||||
|
builder
|
||||||
|
.with_parent(tcx.parent(def_id.into()))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
// For trait impl's `sig_id` is always equal to the corresponding trait method.
|
||||||
|
(FnKind::AssocTraitImpl, _)
|
||||||
|
| (_, FnKind::AssocTraitImpl)
|
||||||
|
// Delegation to inherent methods is not yet supported.
|
||||||
|
| (_, FnKind::AssocInherentImpl) => unreachable!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_constraints<'tcx>(
|
fn check_constraints<'tcx>(
|
||||||
|
@ -224,19 +482,6 @@ fn check_constraints<'tcx>(
|
||||||
emit("recursive delegation is not supported yet");
|
emit("recursive delegation is not supported yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
if fn_kind(tcx, def_id.into()) != 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_has_self = parent_generics.has_self as usize;
|
|
||||||
let sig_has_self = sig_generics.has_self as usize;
|
|
||||||
|
|
||||||
if sig_generics.count() > sig_has_self || parent_generics.count() > parent_has_self {
|
|
||||||
emit("early bound generics are not supported for associated delegation items");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1296,6 +1296,9 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
|
||||||
&& let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
|
&& let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
|
||||||
&& self.tecx.tcx.trait_of_item(def_id).is_some()
|
&& self.tecx.tcx.trait_of_item(def_id).is_some()
|
||||||
&& !has_impl_trait(def_id)
|
&& !has_impl_trait(def_id)
|
||||||
|
// FIXME(fn_delegation): In delegation item argument spans are equal to last path
|
||||||
|
// segment. This leads to ICE's when emitting `multipart_suggestion`.
|
||||||
|
&& tcx.hir().opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
|
||||||
{
|
{
|
||||||
let successor =
|
let successor =
|
||||||
method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
|
method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
|
||||||
|
|
29
tests/ui/delegation/generics/impl-to-free-fn-pass.rs
Normal file
29
tests/ui/delegation/generics/impl-to-free-fn-pass.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
//@ run-pass
|
||||||
|
#![feature(fn_delegation)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
mod to_reuse {
|
||||||
|
pub fn foo<T, U>(_: T, y: U) -> U { y }
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Trait<T> {
|
||||||
|
fn foo(&self, x: T) -> T { x }
|
||||||
|
}
|
||||||
|
struct F;
|
||||||
|
impl<T> Trait<T> for F {}
|
||||||
|
|
||||||
|
struct S<T>(F, T);
|
||||||
|
|
||||||
|
impl<T, U> Trait<T> for S<U> {
|
||||||
|
reuse to_reuse::foo { &self.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> S<T> {
|
||||||
|
reuse to_reuse::foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let s = S(F, 42);
|
||||||
|
assert_eq!(S::<i32>::foo(F, 1), 1);
|
||||||
|
assert_eq!(<S<_> as Trait<_>>::foo(&s, 1), 1);
|
||||||
|
}
|
44
tests/ui/delegation/generics/impl-to-trait-method.rs
Normal file
44
tests/ui/delegation/generics/impl-to-trait-method.rs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#![feature(fn_delegation)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
mod bounds {
|
||||||
|
trait Trait0 {}
|
||||||
|
|
||||||
|
trait Trait1<T> {
|
||||||
|
fn foo<U>(&self)
|
||||||
|
where
|
||||||
|
T: Trait0,
|
||||||
|
U: Trait0,
|
||||||
|
Self: Trait0,
|
||||||
|
//~^ ERROR the trait bound `bounds::S: Trait0` is not satisfied
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct F;
|
||||||
|
impl<T> Trait1<T> for F {}
|
||||||
|
|
||||||
|
struct S(F);
|
||||||
|
|
||||||
|
impl<T> Trait1<T> for S {
|
||||||
|
reuse Trait1::<T>::foo { &self.0 }
|
||||||
|
//~^ ERROR the trait bound `bounds::F: Trait0` is not satisfied
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod unconstrained_parameter {
|
||||||
|
trait Trait<T> {
|
||||||
|
fn foo(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct F;
|
||||||
|
impl<T> Trait<T> for F {}
|
||||||
|
|
||||||
|
struct S(F);
|
||||||
|
impl S {
|
||||||
|
reuse Trait::foo { &self.0 }
|
||||||
|
//~^ ERROR type annotations needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
49
tests/ui/delegation/generics/impl-to-trait-method.stderr
Normal file
49
tests/ui/delegation/generics/impl-to-trait-method.stderr
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
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:34
|
||||||
|
|
|
||||||
|
LL | reuse Trait1::<T>::foo { &self.0 }
|
||||||
|
| --- ^^^^^^^ 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<U>(&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 for type parameter `T` declared on the trait `Trait`
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0277, E0282.
|
||||||
|
For more information about an error, try `rustc --explain E0277`.
|
|
@ -0,0 +1,77 @@
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
#![feature(fn_delegation)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
use std::iter::{Iterator, Map};
|
||||||
|
|
||||||
|
pub mod same_trait {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub struct MapOuter<I, F> {
|
||||||
|
pub inner: Map<I, F>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, I: Iterator, F> Iterator for MapOuter<I, F>
|
||||||
|
where
|
||||||
|
F: FnMut(I::Item) -> B,
|
||||||
|
{
|
||||||
|
type Item = <Map<I, F> as Iterator>::Item;
|
||||||
|
|
||||||
|
reuse Iterator::{next, fold} { self.inner }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
use same_trait::MapOuter;
|
||||||
|
|
||||||
|
mod another_trait {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
trait ZipImpl<A, B> {
|
||||||
|
type Item;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Zip<A, B> {
|
||||||
|
pub a: A,
|
||||||
|
pub b: B,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Iterator, B: Iterator> ZipImpl<A, B> for Zip<A, B> {
|
||||||
|
type Item = (A::Item, B::Item);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<(A::Item, B::Item)> {
|
||||||
|
let x = self.a.next()?;
|
||||||
|
let y = self.b.next()?;
|
||||||
|
Some((x, y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Iterator, B: Iterator> Iterator for Zip<A, B> {
|
||||||
|
type Item = (A::Item, B::Item);
|
||||||
|
|
||||||
|
// Parameters are inherited from `Iterator::next`, not from `ZipImpl::next`.
|
||||||
|
// Otherwise, there would be a compilation error due to an unconstrained parameter.
|
||||||
|
reuse ZipImpl::next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
use another_trait::Zip;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
{
|
||||||
|
let x = vec![1, 2, 3];
|
||||||
|
let iter = x.iter().map(|val| val * 2);
|
||||||
|
let outer_iter = MapOuter { inner: iter };
|
||||||
|
let val = outer_iter.fold(0, |acc, x| acc + x);
|
||||||
|
assert_eq!(val, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let x = vec![1, 2];
|
||||||
|
let y = vec![4, 5];
|
||||||
|
|
||||||
|
let mut zip = Zip { a: x.iter(), b: y.iter() };
|
||||||
|
assert_eq!(zip.next(), Some((&1, &4)));
|
||||||
|
assert_eq!(zip.next(), Some((&2, &5)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
#![feature(fn_delegation)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
trait Trait<T> {
|
||||||
|
fn foo<U>(&self, x: T, y: U) -> (T, U) {
|
||||||
|
(x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Trait<T> for () {}
|
||||||
|
struct S<T>(T, ());
|
||||||
|
|
||||||
|
impl<T> S<T> {
|
||||||
|
reuse Trait::foo { self.1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let s = S((), ());
|
||||||
|
assert_eq!(s.foo(1u32, 2i32), (1u32, 2i32));
|
||||||
|
}
|
30
tests/ui/delegation/generics/trait-method-to-other-pass.rs
Normal file
30
tests/ui/delegation/generics/trait-method-to-other-pass.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
#![feature(fn_delegation)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
mod to_reuse {
|
||||||
|
pub fn foo<T>(x: T) -> T { x }
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Trait1<T, U> {
|
||||||
|
fn foo(&self, _: T, x: U) -> U { x }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct F;
|
||||||
|
|
||||||
|
impl<T, U> Trait1<T, U> for F {}
|
||||||
|
|
||||||
|
trait Trait2<T> {
|
||||||
|
fn get_f(&self) -> &F { &F }
|
||||||
|
reuse Trait1::foo as bar { self.get_f() }
|
||||||
|
reuse to_reuse::foo as baz;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait2<u64> for F {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(F.bar(1u8, 2u16), 2u16);
|
||||||
|
assert_eq!(F::baz(1u8), 1u8);
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
#![feature(fn_delegation)]
|
#![feature(fn_delegation)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
// FIXME(fn_delegation): `recursive delegation` error should be emitted here
|
||||||
trait Trait {
|
trait Trait {
|
||||||
reuse Trait::foo { &self.0 }
|
reuse Trait::foo { &self.0 }
|
||||||
//~^ ERROR recursive delegation is not supported yet
|
//~^ ERROR cycle detected when computing generics of `Trait::foo`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(fn_delegation): `recursive delegation` error should be emitted here
|
|
||||||
reuse foo;
|
reuse foo;
|
||||||
//~^ ERROR cycle detected when computing generics of `foo`
|
//~^ ERROR cycle detected when computing generics of `foo`
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
error: recursive delegation is not supported yet
|
error[E0391]: cycle detected when computing generics of `Trait::foo`
|
||||||
--> $DIR/ice-issue-124347.rs:5:18
|
--> $DIR/ice-issue-124347.rs:6:18
|
||||||
|
|
|
|
||||||
LL | reuse Trait::foo { &self.0 }
|
LL | reuse Trait::foo { &self.0 }
|
||||||
| ^^^ callee defined here
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: ...which immediately requires computing generics of `Trait::foo` again
|
||||||
|
note: cycle used when inheriting delegation signature
|
||||||
|
--> $DIR/ice-issue-124347.rs:6:18
|
||||||
|
|
|
||||||
|
LL | reuse Trait::foo { &self.0 }
|
||||||
|
| ^^^
|
||||||
|
= 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 generics of `foo`
|
error[E0391]: cycle detected when computing generics of `foo`
|
||||||
--> $DIR/ice-issue-124347.rs:10:7
|
--> $DIR/ice-issue-124347.rs:10:7
|
||||||
|
|
|
@ -1,116 +0,0 @@
|
||||||
#![feature(const_trait_impl)]
|
|
||||||
#![feature(c_variadic)]
|
|
||||||
#![feature(effects)]
|
|
||||||
#![feature(fn_delegation)]
|
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
mod generics {
|
|
||||||
trait GenericTrait<T> {
|
|
||||||
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<T>(&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<T> GenericTrait<T> for F {}
|
|
||||||
|
|
||||||
struct S(F);
|
|
||||||
|
|
||||||
impl<T> GenericTrait<T> for S {
|
|
||||||
reuse <F as GenericTrait<T>>::bar { &self.0 }
|
|
||||||
//~^ ERROR early bound generics are not supported for associated delegation items
|
|
||||||
reuse GenericTrait::<T>::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 <F as Trait>::foo3;
|
|
||||||
//~^ ERROR early bound generics are not supported for associated delegation items
|
|
||||||
//~| ERROR lifetime parameters or bounds on associated function `foo3` do not match the trait declaration
|
|
||||||
}
|
|
||||||
|
|
||||||
struct GenericS<T>(T);
|
|
||||||
impl<T> Trait for GenericS<T> {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
mod effects {
|
|
||||||
#[const_trait]
|
|
||||||
trait Trait {
|
|
||||||
fn foo();
|
|
||||||
}
|
|
||||||
|
|
||||||
reuse Trait::foo;
|
|
||||||
//~^ ERROR delegation to a function with effect parameter is not supported yet
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,204 +0,0 @@
|
||||||
error: using `#![feature(effects)]` without enabling next trait solver globally
|
|
||||||
|
|
|
||||||
= note: the next trait solver must be enabled globally for the effects feature to work correctly
|
|
||||||
= help: use `-Znext-solver` to enable
|
|
||||||
|
|
||||||
error: early bound generics are not supported for associated delegation items
|
|
||||||
--> $DIR/not-supported.rs:18: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
|
|
||||||
--> $DIR/not-supported.rs:20:29
|
|
||||||
|
|
|
||||||
LL | fn bar1() {}
|
|
||||||
| --------- callee defined here
|
|
||||||
...
|
|
||||||
LL | reuse GenericTrait::bar1;
|
|
||||||
| ^^^^
|
|
||||||
|
|
||||||
error: early bound generics are not supported for associated delegation items
|
|
||||||
--> $DIR/not-supported.rs:31:39
|
|
||||||
|
|
|
||||||
LL | fn bar(&self, x: T) -> T { x }
|
|
||||||
| ------------------------ callee defined here
|
|
||||||
...
|
|
||||||
LL | reuse <F as GenericTrait<T>>::bar { &self.0 }
|
|
||||||
| ^^^
|
|
||||||
|
|
||||||
error: early bound generics are not supported for associated delegation items
|
|
||||||
--> $DIR/not-supported.rs:33:34
|
|
||||||
|
|
|
||||||
LL | fn bar1() {}
|
|
||||||
| --------- callee defined here
|
|
||||||
...
|
|
||||||
LL | reuse GenericTrait::<T>::bar1;
|
|
||||||
| ^^^^
|
|
||||||
|
|
||||||
error: early bound generics are not supported for associated delegation items
|
|
||||||
--> $DIR/not-supported.rs:38: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
|
|
||||||
--> $DIR/not-supported.rs:40:29
|
|
||||||
|
|
|
||||||
LL | fn bar1() {}
|
|
||||||
| --------- callee defined here
|
|
||||||
...
|
|
||||||
LL | reuse GenericTrait::bar1;
|
|
||||||
| ^^^^
|
|
||||||
|
|
||||||
error: early bound generics are not supported for associated delegation items
|
|
||||||
--> $DIR/not-supported.rs:45: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:51:22
|
|
||||||
|
|
|
||||||
LL | fn foo2<T>(&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
|
|
||||||
--> $DIR/not-supported.rs:54:29
|
|
||||||
|
|
|
||||||
LL | fn foo3<'a: 'a>(_: &'a u32) {}
|
|
||||||
| --------------------------- callee defined here
|
|
||||||
...
|
|
||||||
LL | reuse <F as Trait>::foo3;
|
|
||||||
| ^^^^
|
|
||||||
|
|
||||||
error[E0195]: lifetime parameters or bounds on associated function `foo3` do not match the trait declaration
|
|
||||||
--> $DIR/not-supported.rs:54:29
|
|
||||||
|
|
|
||||||
LL | fn foo3<'a: 'a>(_: &'a u32) {}
|
|
||||||
| -------- lifetimes in impl do not match this associated function in trait
|
|
||||||
...
|
|
||||||
LL | reuse <F as Trait>::foo3;
|
|
||||||
| ^^^^ lifetimes do not match associated function in trait
|
|
||||||
|
|
||||||
error: delegation to a function with effect parameter is not supported yet
|
|
||||||
--> $DIR/not-supported.rs:112:18
|
|
||||||
|
|
|
||||||
LL | fn foo();
|
|
||||||
| --------- callee defined here
|
|
||||||
...
|
|
||||||
LL | reuse Trait::foo;
|
|
||||||
| ^^^
|
|
||||||
|
|
||||||
error: early bound generics are not supported for associated delegation items
|
|
||||||
--> $DIR/not-supported.rs:61: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
|
|
||||||
--> $DIR/not-supported.rs:51:22
|
|
||||||
|
|
|
||||||
LL | fn foo2<T>(&self, x: T) -> T { x }
|
|
||||||
| ---------------------------- callee defined here
|
|
||||||
...
|
|
||||||
LL | reuse Trait::foo2 { &self.0 }
|
|
||||||
| ^^^^
|
|
||||||
|
|
||||||
warning: this function depends on never type fallback being `()`
|
|
||||||
--> $DIR/not-supported.rs:79: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 <https://github.com/rust-lang/rust/issues/123748>
|
|
||||||
= help: specify the types explicitly
|
|
||||||
note: in edition 2024, the requirement `!: opaque::Trait` will fail
|
|
||||||
--> $DIR/not-supported.rs:79: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::<impl at $DIR/not-supported.rs:85:5: 85:24>::{synthetic#0}`
|
|
||||||
--> $DIR/not-supported.rs:86: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:86:25
|
|
||||||
|
|
|
||||||
LL | reuse to_reuse::opaque_ret;
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
= note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:85:5: 85:24>::{synthetic#0}`, completing the cycle
|
|
||||||
note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:85:5: 85:24>` is well-formed
|
|
||||||
--> $DIR/not-supported.rs:85: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:73: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 <https://github.com/rust-lang/rust/issues/123748>
|
|
||||||
= help: specify the types explicitly
|
|
||||||
note: in edition 2024, the requirement `!: opaque::Trait` will fail
|
|
||||||
--> $DIR/not-supported.rs:73:32
|
|
||||||
|
|
|
||||||
LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
|
|
||||||
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:88:5: 88:25>::{synthetic#0}`
|
|
||||||
--> $DIR/not-supported.rs:89: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:89:24
|
|
||||||
|
|
|
||||||
LL | reuse ToReuse::opaque_ret;
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
= note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:88:5: 88:25>::{synthetic#0}`, completing the cycle
|
|
||||||
note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:88:5: 88:25>` is well-formed
|
|
||||||
--> $DIR/not-supported.rs:88: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:102:22
|
|
||||||
|
|
|
||||||
LL | pub reuse to_reuse2::foo;
|
|
||||||
| --- callee defined here
|
|
||||||
...
|
|
||||||
LL | reuse to_reuse1::foo;
|
|
||||||
| ^^^
|
|
||||||
|
|
||||||
error: aborting due to 17 previous errors; 2 warnings emitted
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0049, E0195, E0391.
|
|
||||||
For more information about an error, try `rustc --explain E0049`.
|
|
57
tests/ui/delegation/unsupported.rs
Normal file
57
tests/ui/delegation/unsupported.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#![feature(const_trait_impl)]
|
||||||
|
#![feature(c_variadic)]
|
||||||
|
#![feature(effects)]
|
||||||
|
#![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 { 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
|
||||||
|
}
|
||||||
|
|
||||||
|
mod effects {
|
||||||
|
#[const_trait]
|
||||||
|
trait Trait {
|
||||||
|
fn foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
reuse Trait::foo;
|
||||||
|
//~^ ERROR delegation to a function with effect parameter is not supported yet
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
95
tests/ui/delegation/unsupported.stderr
Normal file
95
tests/ui/delegation/unsupported.stderr
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
error: using `#![feature(effects)]` without enabling next trait solver globally
|
||||||
|
|
|
||||||
|
= note: the next trait solver must be enabled globally for the effects feature to work correctly
|
||||||
|
= help: use `-Znext-solver` to enable
|
||||||
|
|
||||||
|
warning: this function depends on never type fallback being `()`
|
||||||
|
--> $DIR/unsupported.rs:20: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 <https://github.com/rust-lang/rust/issues/123748>
|
||||||
|
= help: specify the types explicitly
|
||||||
|
note: in edition 2024, the requirement `!: opaque::Trait` will fail
|
||||||
|
--> $DIR/unsupported.rs:20: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::<impl at $DIR/unsupported.rs:26:5: 26:24>::{synthetic#0}`
|
||||||
|
--> $DIR/unsupported.rs:27: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:27:25
|
||||||
|
|
|
||||||
|
LL | reuse to_reuse::opaque_ret;
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>::{synthetic#0}`, completing the cycle
|
||||||
|
note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>` is well-formed
|
||||||
|
--> $DIR/unsupported.rs:26: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/unsupported.rs:14: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 <https://github.com/rust-lang/rust/issues/123748>
|
||||||
|
= help: specify the types explicitly
|
||||||
|
note: in edition 2024, the requirement `!: opaque::Trait` will fail
|
||||||
|
--> $DIR/unsupported.rs:14:32
|
||||||
|
|
|
||||||
|
LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>::{synthetic#0}`
|
||||||
|
--> $DIR/unsupported.rs:30: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:30:24
|
||||||
|
|
|
||||||
|
LL | reuse ToReuse::opaque_ret;
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>::{synthetic#0}`, completing the cycle
|
||||||
|
note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>` is well-formed
|
||||||
|
--> $DIR/unsupported.rs:29: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:43:22
|
||||||
|
|
|
||||||
|
LL | pub reuse to_reuse2::foo;
|
||||||
|
| --- callee defined here
|
||||||
|
...
|
||||||
|
LL | reuse to_reuse1::foo;
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: delegation to a function with effect parameter is not supported yet
|
||||||
|
--> $DIR/unsupported.rs:53:18
|
||||||
|
|
|
||||||
|
LL | fn foo();
|
||||||
|
| --------- callee defined here
|
||||||
|
...
|
||||||
|
LL | reuse Trait::foo;
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors; 2 warnings emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0391`.
|
Loading…
Add table
Add a link
Reference in a new issue