mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #125929 - Bryanskiy:delegation-generics-3, r=petrochenkov
Delegation: support generics for delegation from free functions (The PR was split from https://github.com/rust-lang/rust/pull/123958, explainer - https://github.com/Bryanskiy/posts/blob/master/delegation%20in%20generic%20contexts.md) This PR implements generics inheritance from free functions to free functions and trait methods. #### free functions to free functions: ```rust fn to_reuse<T: Clone>(_: T) {} reuse to_reuse as bar; // desugaring: fn bar<T: Clone>(x: T) { to_reuse(x) } ``` Generics, predicates and signature are simply copied. Generic arguments in paths are ignored during generics inheritance: ```rust fn to_reuse<T: Clone>(_: T) {} reuse to_reuse::<u8> as bar; // desugaring: fn bar<T: Clone>(x: T) { to_reuse::<u8>(x) // ERROR: mismatched types } ``` Due to implementation limitations callee path is lowered without modifications. Therefore, it is a compilation error at the moment. #### free functions to trait methods: ```rust trait Trait<'a, A> { fn foo<'b, B>(&self, x: A, y: B) {...} } reuse Trait::foo; // desugaring: fn foo<'a, 'b, This: Trait<'a, A>, A, B>(this: &This, x: A, y: B) { Trait::foo(this, x, y) } ``` The inheritance is similar to the previous case but with some corrections: - `Self` parameter converted into `T: Trait` - generic parameters need to be reordered so that lifetimes go first Arguments are similarly ignored. --- In the future, we plan to support generic inheritance for delegating from all contexts to all contexts (from free/trait/impl to free/trait /impl). These cases were considered first as the simplest from the implementation perspective.
This commit is contained in:
commit
1ddedbaa59
@ -33,7 +33,7 @@
|
||||
//! HIR ty lowering.
|
||||
//!
|
||||
//! Similarly generics, predicates and header are set to the "default" values.
|
||||
//! In case of discrepancy with callee function the `NotSupportedDelegation` error will
|
||||
//! In case of discrepancy with callee function the `UnsupportedDelegation` error will
|
||||
//! also be emitted during HIR ty lowering.
|
||||
|
||||
use std::iter;
|
||||
|
@ -341,8 +341,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
|
||||
hir_analysis_not_supported_delegation = {$descr}
|
||||
.label = callee defined here
|
||||
|
||||
hir_analysis_only_current_traits_adt = `{$name}` is not defined in the current crate
|
||||
|
@ -10,6 +10,7 @@ use rustc_session::lint;
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::delegation::inherit_generics_for_delegation_item;
|
||||
use crate::middle::resolve_bound_vars as rbv;
|
||||
|
||||
#[instrument(level = "debug", skip(tcx), ret)]
|
||||
@ -53,6 +54,13 @@ 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;
|
||||
}
|
||||
|
||||
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
||||
|
||||
let node = tcx.hir_node(hir_id);
|
||||
|
@ -12,6 +12,7 @@ use rustc_span::{Span, DUMMY_SP};
|
||||
use crate::bounds::Bounds;
|
||||
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};
|
||||
|
||||
/// Returns a list of all type predicates (explicit and implicit) for the definition with
|
||||
@ -114,6 +115,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
None => {}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
||||
let node = tcx.hir_node(hir_id);
|
||||
|
||||
|
259
compiler/rustc_hir_analysis/src/delegation.rs
Normal file
259
compiler/rustc_hir_analysis/src/delegation.rs
Normal file
@ -0,0 +1,259 @@
|
||||
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_type_ir::visit::TypeVisitableExt;
|
||||
|
||||
type RemapTable = FxHashMap<u32, u32>;
|
||||
|
||||
struct ParamIndexRemapper<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
remap_table: RemapTable,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamIndexRemapper<'tcx> {
|
||||
fn cx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if !ty.has_param() {
|
||||
return ty;
|
||||
}
|
||||
|
||||
if let ty::Param(param) = ty.kind()
|
||||
&& let Some(index) = self.remap_table.get(¶m.index)
|
||||
{
|
||||
return Ty::new_param(self.tcx, *index, 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()
|
||||
&& let Some(index) = self.remap_table.get(¶m.index).copied()
|
||||
{
|
||||
return ty::Region::new_early_param(
|
||||
self.tcx,
|
||||
ty::EarlyParamRegion { index, 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)]
|
||||
enum FnKind {
|
||||
Free,
|
||||
AssocInherentImpl,
|
||||
AssocTrait,
|
||||
AssocTraitImpl,
|
||||
}
|
||||
|
||||
fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind {
|
||||
debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn));
|
||||
|
||||
let parent = tcx.parent(def_id);
|
||||
match tcx.def_kind(parent) {
|
||||
DefKind::Trait => FnKind::AssocTrait,
|
||||
DefKind::Impl { of_trait: true } => FnKind::AssocTraitImpl,
|
||||
DefKind::Impl { of_trait: false } => FnKind::AssocInherentImpl,
|
||||
_ => FnKind::Free,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_generic_args<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
sig_id: DefId,
|
||||
) -> ty::GenericArgsRef<'tcx> {
|
||||
let caller_generics = tcx.generics_of(def_id);
|
||||
let callee_generics = tcx.generics_of(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 will be reported in `check_constraints`.
|
||||
match (caller_kind, callee_kind) {
|
||||
(FnKind::Free, _) => {
|
||||
// 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(...)
|
||||
// }
|
||||
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());
|
||||
|
||||
for (idx, param) in own_params.iter_mut().enumerate() {
|
||||
param.index = idx as u32;
|
||||
// Default parameters are not inherited: they are not allowed
|
||||
// in fn's.
|
||||
if let ty::GenericParamDefKind::Type { has_default, .. }
|
||||
| ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
|
||||
{
|
||||
*has_default = false;
|
||||
}
|
||||
}
|
||||
|
||||
let param_def_id_to_index =
|
||||
own_params.iter().map(|param| (param.def_id, param.index)).collect();
|
||||
|
||||
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: callee_generics.host_effect_index,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
sig_id: DefId,
|
||||
) -> Option<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 mut preds = vec![];
|
||||
if let Some(parent_id) = callee_predicates.parent {
|
||||
preds.extend(tcx.predicates_of(parent_id).instantiate_own(tcx, args));
|
||||
}
|
||||
preds.extend(callee_predicates.instantiate_own(tcx, args));
|
||||
|
||||
Some(ty::GenericPredicates {
|
||||
parent: None,
|
||||
predicates: tcx.arena.alloc_from_iter(preds),
|
||||
effects_min_tys: ty::List::empty(),
|
||||
})
|
||||
}
|
||||
|
||||
fn check_constraints<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
sig_id: DefId,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let mut ret = Ok(());
|
||||
|
||||
let mut emit = |descr| {
|
||||
ret = Err(tcx.dcx().emit_err(crate::errors::UnsupportedDelegation {
|
||||
span: tcx.def_span(def_id),
|
||||
descr,
|
||||
callee_span: tcx.def_span(sig_id),
|
||||
}));
|
||||
};
|
||||
|
||||
if tcx.has_host_param(sig_id) {
|
||||
emit("delegation to a function with effect parameter is not supported yet");
|
||||
}
|
||||
|
||||
if let Some(local_sig_id) = sig_id.as_local()
|
||||
&& tcx.hir().opt_delegation_sig_id(local_sig_id).is_some()
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
) -> &'tcx [Ty<'tcx>] {
|
||||
let sig_id = tcx.hir().delegation_sig_id(def_id);
|
||||
let caller_sig = tcx.fn_sig(sig_id);
|
||||
if let Err(err) = check_constraints(tcx, def_id, sig_id) {
|
||||
let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1;
|
||||
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);
|
||||
|
||||
// Bound vars are also inherited from `sig_id`.
|
||||
// They will be rebound later in `lower_fn_ty`.
|
||||
let sig = caller_sig.instantiate(tcx, args).skip_binder();
|
||||
let sig_iter = sig.inputs().iter().cloned().chain(std::iter::once(sig.output()));
|
||||
tcx.arena.alloc_from_iter(sig_iter)
|
||||
}
|
@ -1575,7 +1575,7 @@ pub struct RefOfMutStatic<'a> {
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_not_supported_delegation)]
|
||||
pub struct NotSupportedDelegation<'a> {
|
||||
pub struct UnsupportedDelegation<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub descr: &'a str,
|
||||
|
@ -2007,93 +2007,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
self.lower_ty_common(hir_ty, false, true)
|
||||
}
|
||||
|
||||
fn check_delegation_constraints(&self, sig_id: DefId, span: Span, emit: bool) -> bool {
|
||||
let mut error_occured = false;
|
||||
let sig_span = self.tcx().def_span(sig_id);
|
||||
let mut try_emit = |descr| {
|
||||
if emit {
|
||||
self.dcx().emit_err(crate::errors::NotSupportedDelegation {
|
||||
span,
|
||||
descr,
|
||||
callee_span: sig_span,
|
||||
});
|
||||
}
|
||||
error_occured = true;
|
||||
};
|
||||
|
||||
if let Some(node) = self.tcx().hir().get_if_local(sig_id)
|
||||
&& let Some(decl) = node.fn_decl()
|
||||
&& let hir::FnRetTy::Return(ty) = decl.output
|
||||
&& let hir::TyKind::InferDelegation(_, _) = ty.kind
|
||||
{
|
||||
try_emit("recursive delegation");
|
||||
}
|
||||
|
||||
let sig_generics = self.tcx().generics_of(sig_id);
|
||||
let parent = self.tcx().local_parent(self.item_def_id());
|
||||
let parent_generics = self.tcx().generics_of(parent);
|
||||
|
||||
let parent_is_trait = (self.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 {
|
||||
try_emit("delegation with early bound generics");
|
||||
}
|
||||
|
||||
// There is no way to instantiate `Self` param for caller if
|
||||
// 1. callee is a trait method
|
||||
// 2. delegation item isn't an associative item
|
||||
if let DefKind::AssocFn = self.tcx().def_kind(sig_id)
|
||||
&& let DefKind::Fn = self.tcx().def_kind(self.item_def_id())
|
||||
&& self.tcx().associated_item(sig_id).container
|
||||
== ty::AssocItemContainer::TraitContainer
|
||||
{
|
||||
try_emit("delegation to a trait method from a free function");
|
||||
}
|
||||
|
||||
error_occured
|
||||
}
|
||||
|
||||
fn lower_delegation_ty(
|
||||
&self,
|
||||
sig_id: DefId,
|
||||
idx: hir::InferDelegationKind,
|
||||
span: Span,
|
||||
) -> Ty<'tcx> {
|
||||
if self.check_delegation_constraints(sig_id, span, idx == hir::InferDelegationKind::Output)
|
||||
{
|
||||
let e = self.dcx().span_delayed_bug(span, "not supported delegation case");
|
||||
return Ty::new_error(self.tcx(), e);
|
||||
};
|
||||
let sig = self.tcx().fn_sig(sig_id);
|
||||
let sig_generics = self.tcx().generics_of(sig_id);
|
||||
|
||||
let parent = self.tcx().local_parent(self.item_def_id());
|
||||
let parent_def_kind = self.tcx().def_kind(parent);
|
||||
|
||||
let sig = if let DefKind::Impl { .. } = parent_def_kind
|
||||
&& sig_generics.has_self
|
||||
{
|
||||
// Generic params can't be here except the trait self type.
|
||||
// They are not supported yet.
|
||||
assert_eq!(sig_generics.count(), 1);
|
||||
assert_eq!(self.tcx().generics_of(parent).count(), 0);
|
||||
|
||||
let self_ty = self.tcx().type_of(parent).instantiate_identity();
|
||||
let generic_self_ty = ty::GenericArg::from(self_ty);
|
||||
let args = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
|
||||
sig.instantiate(self.tcx(), args)
|
||||
} else {
|
||||
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();
|
||||
|
||||
fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
|
||||
let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
|
||||
match idx {
|
||||
hir::InferDelegationKind::Input(id) => sig.inputs()[id],
|
||||
hir::InferDelegationKind::Output => sig.output(),
|
||||
hir::InferDelegationKind::Input(idx) => delegation_sig[idx],
|
||||
hir::InferDelegationKind::Output => *delegation_sig.last().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -2110,9 +2028,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let result_ty = match &hir_ty.kind {
|
||||
hir::TyKind::InferDelegation(sig_id, idx) => {
|
||||
self.lower_delegation_ty(*sig_id, *idx, hir_ty.span)
|
||||
}
|
||||
hir::TyKind::InferDelegation(_, idx) => self.lower_delegation_ty(*idx),
|
||||
hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.lower_ty(ty)),
|
||||
hir::TyKind::Ptr(mt) => Ty::new_ptr(tcx, self.lower_ty(mt.ty), mt.mutbl),
|
||||
hir::TyKind::Ref(region, mt) => {
|
||||
|
@ -83,6 +83,7 @@ pub mod autoderef;
|
||||
mod bounds;
|
||||
mod check_unused;
|
||||
mod coherence;
|
||||
mod delegation;
|
||||
pub mod hir_ty_lowering;
|
||||
// FIXME: This module shouldn't be public.
|
||||
pub mod collect;
|
||||
@ -146,6 +147,10 @@ pub fn provide(providers: &mut Providers) {
|
||||
variance::provide(providers);
|
||||
outlives::provide(providers);
|
||||
hir_wf_check::provide(providers);
|
||||
*providers = Providers {
|
||||
inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
||||
pub fn check_crate(tcx: TyCtxt<'_>) {
|
||||
|
@ -746,6 +746,21 @@ impl<'hir> Map<'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn opt_delegation_sig_id(self, def_id: LocalDefId) -> Option<DefId> {
|
||||
if let Some(ret) = self.get_fn_output(def_id)
|
||||
&& let FnRetTy::Return(ty) = ret
|
||||
&& let TyKind::InferDelegation(sig_id, _) = ty.kind
|
||||
{
|
||||
return Some(sig_id);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn delegation_sig_id(self, def_id: LocalDefId) -> DefId {
|
||||
self.opt_delegation_sig_id(def_id).unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn opt_ident(self, id: HirId) -> Option<Ident> {
|
||||
match self.tcx.hir_node(id) {
|
||||
|
@ -1722,6 +1722,10 @@ rustc_queries! {
|
||||
desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) }
|
||||
}
|
||||
|
||||
query inherit_sig_for_delegation_item(def_id: LocalDefId) -> &'tcx [Ty<'tcx>] {
|
||||
desc { "inheriting delegation signature" }
|
||||
}
|
||||
|
||||
/// Does lifetime resolution on items. Importantly, we can't resolve
|
||||
/// lifetimes directly on things like trait methods, because of trait params.
|
||||
/// See `rustc_resolve::late::lifetimes` for details.
|
||||
|
@ -22,9 +22,7 @@ mod fn_to_other {
|
||||
use super::*;
|
||||
|
||||
reuse Trait::foo1;
|
||||
//~^ ERROR delegation to a trait method from a free function is not supported yet
|
||||
reuse <S as Trait>::foo2;
|
||||
//~^ ERROR delegation to a trait method from a free function is not supported yet
|
||||
reuse to_reuse::foo3;
|
||||
reuse S::foo4;
|
||||
//~^ ERROR cannot find function `foo4` in `S`
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0407]: method `foo3` is not a member of trait `Trait`
|
||||
--> $DIR/explicit-paths.rs:51:9
|
||||
--> $DIR/explicit-paths.rs:49:9
|
||||
|
|
||||
LL | reuse to_reuse::foo3;
|
||||
| ^^^^^^^^^^^^^^^^----^
|
||||
@ -8,7 +8,7 @@ LL | reuse to_reuse::foo3;
|
||||
| not a member of trait `Trait`
|
||||
|
||||
error[E0407]: method `foo4` is not a member of trait `Trait`
|
||||
--> $DIR/explicit-paths.rs:53:9
|
||||
--> $DIR/explicit-paths.rs:51:9
|
||||
|
|
||||
LL | reuse F::foo4 { &self.0 }
|
||||
| ^^^^^^^^^----^^^^^^^^^^^^
|
||||
@ -17,49 +17,49 @@ LL | reuse F::foo4 { &self.0 }
|
||||
| not a member of trait `Trait`
|
||||
|
||||
error[E0425]: cannot find function `foo4` in `S`
|
||||
--> $DIR/explicit-paths.rs:29:14
|
||||
--> $DIR/explicit-paths.rs:27:14
|
||||
|
|
||||
LL | reuse S::foo4;
|
||||
| ^^^^ not found in `S`
|
||||
|
||||
error[E0425]: cannot find function `foo4` in `F`
|
||||
--> $DIR/explicit-paths.rs:40:18
|
||||
--> $DIR/explicit-paths.rs:38:18
|
||||
|
|
||||
LL | reuse F::foo4 { &self.0 }
|
||||
| ^^^^ not found in `F`
|
||||
|
|
||||
note: function `fn_to_other::foo4` exists but is inaccessible
|
||||
--> $DIR/explicit-paths.rs:29:5
|
||||
--> $DIR/explicit-paths.rs:27:5
|
||||
|
|
||||
LL | reuse S::foo4;
|
||||
| ^^^^^^^^^^^^^^ not accessible
|
||||
|
||||
error[E0425]: cannot find function `foo4` in `F`
|
||||
--> $DIR/explicit-paths.rs:53:18
|
||||
--> $DIR/explicit-paths.rs:51:18
|
||||
|
|
||||
LL | reuse F::foo4 { &self.0 }
|
||||
| ^^^^ not found in `F`
|
||||
|
|
||||
note: function `fn_to_other::foo4` exists but is inaccessible
|
||||
--> $DIR/explicit-paths.rs:29:5
|
||||
--> $DIR/explicit-paths.rs:27:5
|
||||
|
|
||||
LL | reuse S::foo4;
|
||||
| ^^^^^^^^^^^^^^ not accessible
|
||||
|
||||
error[E0425]: cannot find function `foo4` in `F`
|
||||
--> $DIR/explicit-paths.rs:67:18
|
||||
--> $DIR/explicit-paths.rs:65:18
|
||||
|
|
||||
LL | reuse F::foo4 { &F }
|
||||
| ^^^^ not found in `F`
|
||||
|
|
||||
note: function `fn_to_other::foo4` exists but is inaccessible
|
||||
--> $DIR/explicit-paths.rs:29:5
|
||||
--> $DIR/explicit-paths.rs:27:5
|
||||
|
|
||||
LL | reuse S::foo4;
|
||||
| ^^^^^^^^^^^^^^ not accessible
|
||||
|
||||
error[E0119]: conflicting implementations of trait `Trait` for type `S`
|
||||
--> $DIR/explicit-paths.rs:76:5
|
||||
--> $DIR/explicit-paths.rs:74:5
|
||||
|
|
||||
LL | impl Trait for S {
|
||||
| ---------------- first implementation here
|
||||
@ -67,26 +67,8 @@ LL | impl Trait for S {
|
||||
LL | impl Trait for S {
|
||||
| ^^^^^^^^^^^^^^^^ conflicting implementation for `S`
|
||||
|
||||
error: delegation to a trait method from a free function is not supported yet
|
||||
--> $DIR/explicit-paths.rs:24:18
|
||||
|
|
||||
LL | fn foo1(&self, x: i32) -> i32 { x }
|
||||
| ----------------------------- callee defined here
|
||||
...
|
||||
LL | reuse Trait::foo1;
|
||||
| ^^^^
|
||||
|
||||
error: delegation to a trait method from a free function is not supported yet
|
||||
--> $DIR/explicit-paths.rs:26:25
|
||||
|
|
||||
LL | fn foo2(x: i32) -> i32 { x }
|
||||
| ---------------------- callee defined here
|
||||
...
|
||||
LL | reuse <S as Trait>::foo2;
|
||||
| ^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/explicit-paths.rs:63:36
|
||||
--> $DIR/explicit-paths.rs:61:36
|
||||
|
|
||||
LL | trait Trait2 : Trait {
|
||||
| -------------------- found this type parameter
|
||||
@ -104,7 +86,7 @@ LL | fn foo1(&self, x: i32) -> i32 { x }
|
||||
| ^^^^ -----
|
||||
|
||||
error[E0277]: the trait bound `S2: Trait` is not satisfied
|
||||
--> $DIR/explicit-paths.rs:78:16
|
||||
--> $DIR/explicit-paths.rs:76:16
|
||||
|
|
||||
LL | reuse <S2 as Trait>::foo1;
|
||||
| ^^ the trait `Trait` is not implemented for `S2`
|
||||
@ -114,7 +96,7 @@ LL | reuse <S2 as Trait>::foo1;
|
||||
S
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/explicit-paths.rs:78:30
|
||||
--> $DIR/explicit-paths.rs:76:30
|
||||
|
|
||||
LL | reuse <S2 as Trait>::foo1;
|
||||
| ^^^^
|
||||
@ -130,7 +112,7 @@ note: method defined here
|
||||
LL | fn foo1(&self, x: i32) -> i32 { x }
|
||||
| ^^^^ -----
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0119, E0277, E0308, E0407, E0425.
|
||||
For more information about an error, try `rustc --explain E0119`.
|
||||
|
28
tests/ui/delegation/generics/free-fn-to-free-fn-pass.rs
Normal file
28
tests/ui/delegation/generics/free-fn-to-free-fn-pass.rs
Normal file
@ -0,0 +1,28 @@
|
||||
//@ run-pass
|
||||
#![feature(fn_delegation)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
mod to_reuse {
|
||||
pub fn types<T, U>(x: U, y: T) -> (T, U) {
|
||||
(y, x)
|
||||
}
|
||||
pub fn late<'a, 'b>(x: &'a u8, y: &'b u8) -> u8 {
|
||||
*x + *y
|
||||
}
|
||||
pub fn early<'a: 'a>(x: &'a str) -> &'a str {
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
reuse to_reuse::types;
|
||||
reuse to_reuse::late;
|
||||
reuse to_reuse::early;
|
||||
|
||||
fn main() {
|
||||
assert_eq!(types(0, "str"), ("str", 0));
|
||||
assert_eq!(late(&1u8, &2u8), 3);
|
||||
{
|
||||
let s: &'static str = "hello world";
|
||||
assert_eq!(early::<'static>(s), "hello world");
|
||||
}
|
||||
}
|
27
tests/ui/delegation/generics/free-fn-to-free-fn.rs
Normal file
27
tests/ui/delegation/generics/free-fn-to-free-fn.rs
Normal file
@ -0,0 +1,27 @@
|
||||
#![feature(fn_delegation)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
mod to_reuse {
|
||||
pub fn consts<const N: i32>() -> i32 {
|
||||
N
|
||||
}
|
||||
pub fn late<'a>(x: &'a u8) -> u8 {
|
||||
*x
|
||||
}
|
||||
pub fn bounds<T: Clone>(_: T) {}
|
||||
}
|
||||
|
||||
// FIXME(fn_delegation): this is supposed to work eventually
|
||||
reuse to_reuse::consts;
|
||||
//~^ ERROR type annotations needed
|
||||
reuse to_reuse::late;
|
||||
reuse to_reuse::bounds;
|
||||
|
||||
fn main() {
|
||||
late::<'static>(&0u8);
|
||||
//~^ ERROR cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
|
||||
|
||||
struct S;
|
||||
bounds(S);
|
||||
//~^ ERROR the trait bound `S: Clone` is not satisfied
|
||||
}
|
54
tests/ui/delegation/generics/free-fn-to-free-fn.stderr
Normal file
54
tests/ui/delegation/generics/free-fn-to-free-fn.stderr
Normal file
@ -0,0 +1,54 @@
|
||||
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`
|
||||
|
|
||||
note: required by a const generic parameter in `to_reuse::consts`
|
||||
--> $DIR/free-fn-to-free-fn.rs:5:19
|
||||
|
|
||||
LL | pub fn consts<const N: i32>() -> i32 {
|
||||
| ^^^^^^^^^^^^ required by this const generic parameter in `consts`
|
||||
help: consider specifying the generic argument
|
||||
|
|
||||
LL | reuse to_reuse::consts::<N>;
|
||||
| +++++
|
||||
|
||||
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
|
||||
--> $DIR/free-fn-to-free-fn.rs:21:12
|
||||
|
|
||||
LL | late::<'static>(&0u8);
|
||||
| ^^^^^^^
|
||||
|
|
||||
note: the late bound lifetime parameter is introduced here
|
||||
--> $DIR/free-fn-to-free-fn.rs:8:17
|
||||
|
|
||||
LL | pub fn late<'a>(x: &'a u8) -> u8 {
|
||||
| ^^
|
||||
|
||||
error[E0277]: the trait bound `S: Clone` is not satisfied
|
||||
--> $DIR/free-fn-to-free-fn.rs:25:12
|
||||
|
|
||||
LL | bounds(S);
|
||||
| ------ ^ the trait `Clone` is not implemented for `S`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `bounds`
|
||||
--> $DIR/free-fn-to-free-fn.rs:11:22
|
||||
|
|
||||
LL | pub fn bounds<T: Clone>(_: T) {}
|
||||
| ^^^^^ required by this bound in `bounds`
|
||||
...
|
||||
LL | reuse to_reuse::bounds;
|
||||
| ------ required by a bound in this function
|
||||
help: consider annotating `S` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct S;
|
||||
|
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0284, E0794.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
30
tests/ui/delegation/generics/free-fn-to-trait-method-pass.rs
Normal file
30
tests/ui/delegation/generics/free-fn-to-trait-method-pass.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//@ run-pass
|
||||
#![feature(fn_delegation)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
mod types {
|
||||
pub trait Trait<T> {
|
||||
fn foo<U>(&self, x: U, y: T) -> (T, U) {(y, x)}
|
||||
}
|
||||
impl<T> Trait<T> for u8 {}
|
||||
}
|
||||
|
||||
mod types_and_lifetimes {
|
||||
pub trait Trait<'a, T> {
|
||||
fn foo<'b, U>(&self, _: &'b U, _: &'a T) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
impl<'a, T> Trait<'a, T> for u8 {}
|
||||
}
|
||||
|
||||
reuse types::Trait::foo as types;
|
||||
reuse types_and_lifetimes::Trait::foo as types_and_lifetimes;
|
||||
|
||||
fn main() {
|
||||
assert_eq!(types(&2, "str", 1), (1, "str"));
|
||||
|
||||
struct T;
|
||||
struct U;
|
||||
assert_eq!(types_and_lifetimes::<u8, T, U>(&1, &U, &T), true);
|
||||
}
|
56
tests/ui/delegation/generics/free-fn-to-trait-method.rs
Normal file
56
tests/ui/delegation/generics/free-fn-to-trait-method.rs
Normal file
@ -0,0 +1,56 @@
|
||||
#![feature(fn_delegation)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
mod default_param {
|
||||
pub trait Trait<T = u32> {
|
||||
fn foo(&self, _: T) {}
|
||||
}
|
||||
|
||||
impl<T> Trait<T> for u8 {}
|
||||
}
|
||||
|
||||
mod types_and_lifetimes {
|
||||
pub trait Trait<'a, T> {
|
||||
fn foo<'b: 'b>(&'a self, x: &'b T) {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
impl<'a, T> Trait<'a, T> for u8 {}
|
||||
}
|
||||
|
||||
mod bounds {
|
||||
pub trait Trait<T> {
|
||||
fn foo<U: Clone>(&self, t: T, u: U) where T: Copy {}
|
||||
}
|
||||
|
||||
impl<T> Trait<T> for u8 {}
|
||||
}
|
||||
|
||||
mod generic_arguments {
|
||||
trait Trait<T> {
|
||||
fn foo<U>(&self, _: U, _: T) {}
|
||||
}
|
||||
|
||||
impl<T> Trait<T> for u8 {}
|
||||
|
||||
reuse Trait::<_>::foo::<i32> as generic_arguments1;
|
||||
//~^ ERROR mismatched types
|
||||
reuse <u8 as Trait<_>>::foo as generic_arguments2;
|
||||
//~^ ERROR mismatched types
|
||||
reuse <_ as Trait<_>>::foo as generic_arguments3; // OK
|
||||
}
|
||||
|
||||
reuse default_param::Trait::foo as default_param;
|
||||
reuse types_and_lifetimes::Trait::foo as types_and_lifetimes;
|
||||
reuse bounds::Trait::foo as bounds;
|
||||
|
||||
fn main() {
|
||||
default_param(&0u8, "hello world"); // OK, default params are not substituted
|
||||
types_and_lifetimes::<'static, 'static, _, _>(&0u8, &0u16); // OK, lifetimes go first
|
||||
|
||||
struct S;
|
||||
struct U;
|
||||
bounds(&0u8, S, U);
|
||||
//~^ ERROR the trait bound `S: Copy` is not satisfied
|
||||
//~| ERROR the trait bound `U: Clone` is not satisfied
|
||||
}
|
88
tests/ui/delegation/generics/free-fn-to-trait-method.stderr
Normal file
88
tests/ui/delegation/generics/free-fn-to-trait-method.stderr
Normal file
@ -0,0 +1,88 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/free-fn-to-trait-method.rs:36:23
|
||||
|
|
||||
LL | fn foo<U>(&self, _: U, _: T) {}
|
||||
| - found this type parameter
|
||||
...
|
||||
LL | reuse Trait::<_>::foo::<i32> as generic_arguments1;
|
||||
| ^^^
|
||||
| |
|
||||
| expected `i32`, found type parameter `U`
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected type `i32`
|
||||
found type parameter `U`
|
||||
note: method defined here
|
||||
--> $DIR/free-fn-to-trait-method.rs:31:12
|
||||
|
|
||||
LL | fn foo<U>(&self, _: U, _: T) {}
|
||||
| ^^^ ----
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/free-fn-to-trait-method.rs:38:29
|
||||
|
|
||||
LL | trait Trait<T> {
|
||||
| -------------- found this type parameter
|
||||
...
|
||||
LL | reuse <u8 as Trait<_>>::foo as generic_arguments2;
|
||||
| ^^^
|
||||
| |
|
||||
| expected `&u8`, found `&Self`
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected reference `&u8`
|
||||
found reference `&Self`
|
||||
note: method defined here
|
||||
--> $DIR/free-fn-to-trait-method.rs:31:12
|
||||
|
|
||||
LL | fn foo<U>(&self, _: U, _: T) {}
|
||||
| ^^^ -----
|
||||
|
||||
error[E0277]: the trait bound `S: Copy` is not satisfied
|
||||
--> $DIR/free-fn-to-trait-method.rs:53:18
|
||||
|
|
||||
LL | bounds(&0u8, S, U);
|
||||
| ------ ^ the trait `Copy` is not implemented for `S`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `bounds`
|
||||
--> $DIR/free-fn-to-trait-method.rs:23:54
|
||||
|
|
||||
LL | fn foo<U: Clone>(&self, t: T, u: U) where T: Copy {}
|
||||
| ^^^^ required by this bound in `bounds`
|
||||
...
|
||||
LL | reuse bounds::Trait::foo as bounds;
|
||||
| ------ required by a bound in this function
|
||||
help: consider annotating `S` with `#[derive(Copy)]`
|
||||
|
|
||||
LL + #[derive(Copy)]
|
||||
LL | struct S;
|
||||
|
|
||||
|
||||
error[E0277]: the trait bound `U: Clone` is not satisfied
|
||||
--> $DIR/free-fn-to-trait-method.rs:53:21
|
||||
|
|
||||
LL | bounds(&0u8, S, U);
|
||||
| ------ ^ the trait `Clone` is not implemented for `U`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `bounds`
|
||||
--> $DIR/free-fn-to-trait-method.rs:23:19
|
||||
|
|
||||
LL | fn foo<U: Clone>(&self, t: T, u: U) where T: Copy {}
|
||||
| ^^^^^ required by this bound in `bounds`
|
||||
...
|
||||
LL | reuse bounds::Trait::foo as bounds;
|
||||
| ------ required by a bound in this function
|
||||
help: consider annotating `U` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct U;
|
||||
|
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
@ -6,7 +6,8 @@ trait Trait {
|
||||
//~^ ERROR recursive delegation is not supported yet
|
||||
}
|
||||
|
||||
// FIXME(fn_delegation): `recursive delegation` error should be emitted here
|
||||
reuse foo;
|
||||
//~^ ERROR recursive delegation is not supported yet
|
||||
//~^ ERROR cycle detected when computing generics of `foo`
|
||||
|
||||
fn main() {}
|
||||
|
@ -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
|
||||
--> $DIR/ice-issue-124347.rs:9:7
|
||||
error[E0391]: cycle detected when computing generics of `foo`
|
||||
--> $DIR/ice-issue-124347.rs:10:7
|
||||
|
|
||||
LL | reuse foo;
|
||||
| ^^^ callee defined here
|
||||
| ^^^
|
||||
|
|
||||
= note: ...which immediately requires computing generics of `foo` again
|
||||
note: cycle used when checking that `foo` is well-formed
|
||||
--> $DIR/ice-issue-124347.rs:10:7
|
||||
|
|
||||
LL | reuse foo;
|
||||
| ^^^
|
||||
= 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`.
|
||||
|
@ -1,4 +1,6 @@
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(c_variadic)]
|
||||
#![feature(effects)]
|
||||
#![feature(fn_delegation)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
@ -14,9 +16,9 @@ mod generics {
|
||||
fn foo3<'a: 'a>(_: &'a u32) {}
|
||||
|
||||
reuse GenericTrait::bar;
|
||||
//~^ ERROR delegation with early bound generics is not supported yet
|
||||
//~^ ERROR early bound generics are not supported for associated delegation items
|
||||
reuse GenericTrait::bar1;
|
||||
//~^ ERROR delegation with early bound generics is not supported yet
|
||||
//~^ ERROR early bound generics are not supported for associated delegation items
|
||||
}
|
||||
|
||||
struct F;
|
||||
@ -27,37 +29,37 @@ mod generics {
|
||||
|
||||
impl<T> GenericTrait<T> for S {
|
||||
reuse <F as GenericTrait<T>>::bar { &self.0 }
|
||||
//~^ ERROR delegation with early bound generics is not supported yet
|
||||
//~^ ERROR early bound generics are not supported for associated delegation items
|
||||
reuse GenericTrait::<T>::bar1;
|
||||
//~^ ERROR delegation with early bound generics is not supported yet
|
||||
//~^ ERROR early bound generics are not supported for associated delegation items
|
||||
}
|
||||
|
||||
impl GenericTrait<()> for () {
|
||||
reuse GenericTrait::bar { &F }
|
||||
//~^ ERROR delegation with early bound generics is not supported yet
|
||||
//~^ ERROR early bound generics are not supported for associated delegation items
|
||||
reuse GenericTrait::bar1;
|
||||
//~^ ERROR delegation with early bound generics is not supported yet
|
||||
//~^ ERROR early bound generics are not supported for associated delegation items
|
||||
}
|
||||
|
||||
impl Trait for &S {
|
||||
reuse Trait::foo;
|
||||
//~^ ERROR delegation with early bound generics is not supported yet
|
||||
//~^ 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 delegation with early bound generics is not supported yet
|
||||
//~^ 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 delegation with early bound generics is not supported yet
|
||||
//~^ 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>(T);
|
||||
impl<T> Trait for GenericS<T> {
|
||||
reuse Trait::foo { &self.0 }
|
||||
//~^ ERROR delegation with early bound generics is not supported yet
|
||||
//~^ ERROR early bound generics are not supported for associated delegation items
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,13 +70,10 @@ mod opaque {
|
||||
mod to_reuse {
|
||||
use super::Trait;
|
||||
|
||||
pub fn opaque_arg(_: impl Trait) -> i32 { 0 }
|
||||
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!
|
||||
}
|
||||
reuse to_reuse::opaque_arg;
|
||||
//~^ ERROR delegation with early bound generics is not supported yet
|
||||
|
||||
trait ToReuse {
|
||||
fn opaque_ret() -> impl Trait { unimplemented!() }
|
||||
@ -104,4 +103,14 @@ mod recursive {
|
||||
//~^ 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,5 +1,10 @@
|
||||
error: delegation with early bound generics is not supported yet
|
||||
--> $DIR/not-supported.rs:16:29
|
||||
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
|
||||
@ -7,8 +12,8 @@ LL | fn bar(&self, x: T) -> T { x }
|
||||
LL | reuse GenericTrait::bar;
|
||||
| ^^^
|
||||
|
||||
error: delegation with early bound generics is not supported yet
|
||||
--> $DIR/not-supported.rs:18:29
|
||||
error: early bound generics are not supported for associated delegation items
|
||||
--> $DIR/not-supported.rs:20:29
|
||||
|
|
||||
LL | fn bar1() {}
|
||||
| --------- callee defined here
|
||||
@ -16,8 +21,8 @@ LL | fn bar1() {}
|
||||
LL | reuse GenericTrait::bar1;
|
||||
| ^^^^
|
||||
|
||||
error: delegation with early bound generics is not supported yet
|
||||
--> $DIR/not-supported.rs:29:39
|
||||
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
|
||||
@ -25,8 +30,8 @@ LL | fn bar(&self, x: T) -> T { x }
|
||||
LL | reuse <F as GenericTrait<T>>::bar { &self.0 }
|
||||
| ^^^
|
||||
|
||||
error: delegation with early bound generics is not supported yet
|
||||
--> $DIR/not-supported.rs:31:34
|
||||
error: early bound generics are not supported for associated delegation items
|
||||
--> $DIR/not-supported.rs:33:34
|
||||
|
|
||||
LL | fn bar1() {}
|
||||
| --------- callee defined here
|
||||
@ -34,8 +39,8 @@ LL | fn bar1() {}
|
||||
LL | reuse GenericTrait::<T>::bar1;
|
||||
| ^^^^
|
||||
|
||||
error: delegation with early bound generics is not supported yet
|
||||
--> $DIR/not-supported.rs:36:29
|
||||
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
|
||||
@ -43,8 +48,8 @@ LL | fn bar(&self, x: T) -> T { x }
|
||||
LL | reuse GenericTrait::bar { &F }
|
||||
| ^^^
|
||||
|
||||
error: delegation with early bound generics is not supported yet
|
||||
--> $DIR/not-supported.rs:38:29
|
||||
error: early bound generics are not supported for associated delegation items
|
||||
--> $DIR/not-supported.rs:40:29
|
||||
|
|
||||
LL | fn bar1() {}
|
||||
| --------- callee defined here
|
||||
@ -52,8 +57,8 @@ LL | fn bar1() {}
|
||||
LL | reuse GenericTrait::bar1;
|
||||
| ^^^^
|
||||
|
||||
error: delegation with early bound generics is not supported yet
|
||||
--> $DIR/not-supported.rs:43:22
|
||||
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
|
||||
@ -62,7 +67,7 @@ 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
|
||||
--> $DIR/not-supported.rs:51:22
|
||||
|
|
||||
LL | fn foo2<T>(&self, x: T) -> T { x }
|
||||
| - expected 1 type parameter
|
||||
@ -70,8 +75,8 @@ LL | fn foo2<T>(&self, x: T) -> T { x }
|
||||
LL | reuse Trait::foo2 { &self.0 }
|
||||
| ^^^^ found 0 type parameters
|
||||
|
||||
error: delegation with early bound generics is not supported yet
|
||||
--> $DIR/not-supported.rs:52:29
|
||||
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
|
||||
@ -80,7 +85,7 @@ LL | reuse <F as Trait>::foo3;
|
||||
| ^^^^
|
||||
|
||||
error[E0195]: lifetime parameters or bounds on method `foo3` do not match the trait declaration
|
||||
--> $DIR/not-supported.rs:52:29
|
||||
--> $DIR/not-supported.rs:54:29
|
||||
|
|
||||
LL | fn foo3<'a: 'a>(_: &'a u32) {}
|
||||
| -------- lifetimes in impl do not match this method in trait
|
||||
@ -88,8 +93,17 @@ LL | fn foo3<'a: 'a>(_: &'a u32) {}
|
||||
LL | reuse <F as Trait>::foo3;
|
||||
| ^^^^ lifetimes do not match method in trait
|
||||
|
||||
error: delegation with early bound generics is not supported yet
|
||||
--> $DIR/not-supported.rs:59:22
|
||||
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
|
||||
@ -97,8 +111,8 @@ LL | fn foo(&self, x: i32) -> i32 { x }
|
||||
LL | reuse Trait::foo { &self.0 }
|
||||
| ^^^
|
||||
|
||||
error: delegation with early bound generics is not supported yet
|
||||
--> $DIR/not-supported.rs:49:22
|
||||
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
|
||||
@ -106,17 +120,8 @@ LL | fn foo2<T>(&self, x: T) -> T { x }
|
||||
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
|
||||
--> $DIR/not-supported.rs:79:9
|
||||
|
|
||||
LL | fn opaque_ret() -> impl Trait { unimplemented!() }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -125,33 +130,33 @@ LL | fn opaque_ret() -> impl Trait { unimplemented!() }
|
||||
= 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:80:28
|
||||
--> $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:86:5: 86:24>::{synthetic#0}`
|
||||
--> $DIR/not-supported.rs:87:25
|
||||
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:87:25
|
||||
--> $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:86:5: 86:24>::{synthetic#0}`, completing the cycle
|
||||
note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:86:5: 86:24>` is well-formed
|
||||
--> $DIR/not-supported.rs:86:5
|
||||
= 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:72:9
|
||||
--> $DIR/not-supported.rs:73:9
|
||||
|
|
||||
LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -160,32 +165,32 @@ LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
|
||||
= 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:72:32
|
||||
--> $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:89:5: 89:25>::{synthetic#0}`
|
||||
--> $DIR/not-supported.rs:90:24
|
||||
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:90:24
|
||||
--> $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:89:5: 89:25>::{synthetic#0}`, completing the cycle
|
||||
note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:89:5: 89:25>` is well-formed
|
||||
--> $DIR/not-supported.rs:89:5
|
||||
= 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:103:22
|
||||
--> $DIR/not-supported.rs:102:22
|
||||
|
|
||||
LL | pub reuse to_reuse2::foo;
|
||||
| --- callee defined here
|
||||
@ -193,7 +198,7 @@ LL | pub reuse to_reuse2::foo;
|
||||
LL | reuse to_reuse1::foo;
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 16 previous errors; 2 warnings emitted
|
||||
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`.
|
||||
|
@ -14,9 +14,7 @@ fn foo(x: i32) -> i32 { x }
|
||||
|
||||
fn bar<T: Default>(_: T) {
|
||||
reuse Trait::static_method {
|
||||
//~^ ERROR delegation to a trait method from a free function is not supported yet
|
||||
//~| ERROR delegation with early bound generics is not supported yet
|
||||
//~| ERROR mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
let _ = T::Default();
|
||||
//~^ ERROR can't use generic parameters from outer item
|
||||
}
|
||||
@ -25,7 +23,6 @@ fn bar<T: Default>(_: T) {
|
||||
fn main() {
|
||||
let y = 0;
|
||||
reuse <S as Trait>::static_method {
|
||||
//~^ ERROR delegation to a trait method from a free function is not supported yet
|
||||
let x = y;
|
||||
//~^ ERROR can't capture dynamic environment in a fn item
|
||||
foo(self);
|
||||
|
@ -1,16 +1,16 @@
|
||||
error[E0401]: can't use generic parameters from outer item
|
||||
--> $DIR/target-expr.rs:20:17
|
||||
--> $DIR/target-expr.rs:18:17
|
||||
|
|
||||
LL | fn bar<T: Default>(_: T) {
|
||||
| - type parameter from outer item
|
||||
LL | reuse Trait::static_method {
|
||||
| - help: try introducing a local generic parameter here: `T,`
|
||||
...
|
||||
LL |
|
||||
LL | let _ = T::Default();
|
||||
| ^^^^^^^^^^ use of generic parameter from outer item
|
||||
|
||||
error[E0434]: can't capture dynamic environment in a fn item
|
||||
--> $DIR/target-expr.rs:29:17
|
||||
--> $DIR/target-expr.rs:26:17
|
||||
|
|
||||
LL | let x = y;
|
||||
| ^
|
||||
@ -18,7 +18,7 @@ LL | let x = y;
|
||||
= help: use the `|| { ... }` closure form instead
|
||||
|
||||
error[E0424]: expected value, found module `self`
|
||||
--> $DIR/target-expr.rs:36:5
|
||||
--> $DIR/target-expr.rs:33:5
|
||||
|
|
||||
LL | fn main() {
|
||||
| ---- this function can't have a `self` parameter
|
||||
@ -27,58 +27,29 @@ LL | self.0;
|
||||
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter
|
||||
|
||||
error[E0425]: cannot find value `x` in this scope
|
||||
--> $DIR/target-expr.rs:38:13
|
||||
--> $DIR/target-expr.rs:35:13
|
||||
|
|
||||
LL | let z = x;
|
||||
| ^
|
||||
|
|
||||
help: the binding `x` is available in a different scope in the same function
|
||||
--> $DIR/target-expr.rs:29:13
|
||||
--> $DIR/target-expr.rs:26:13
|
||||
|
|
||||
LL | let x = y;
|
||||
| ^
|
||||
|
||||
error: delegation with early bound generics is not supported yet
|
||||
--> $DIR/target-expr.rs:16:18
|
||||
|
|
||||
LL | fn static_method(x: i32) -> i32 { x }
|
||||
| ------------------------------- callee defined here
|
||||
...
|
||||
LL | reuse Trait::static_method {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: delegation to a trait method from a free function is not supported yet
|
||||
--> $DIR/target-expr.rs:16:18
|
||||
|
|
||||
LL | fn static_method(x: i32) -> i32 { x }
|
||||
| ------------------------------- callee defined here
|
||||
...
|
||||
LL | reuse Trait::static_method {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: delegation to a trait method from a free function is not supported yet
|
||||
--> $DIR/target-expr.rs:27:25
|
||||
|
|
||||
LL | fn static_method(x: i32) -> i32 { x }
|
||||
| ------------------------------- callee defined here
|
||||
...
|
||||
LL | reuse <S as Trait>::static_method {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/target-expr.rs:16:32
|
||||
|
|
||||
LL | reuse Trait::static_method {
|
||||
| ________________________________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let _ = T::Default();
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____^ expected `i32`, found `()`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0401, E0424, E0425, E0434.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
Loading…
Reference in New Issue
Block a user