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