Support self ty propagation for functions in free to trait reuse

This commit is contained in:
aerooneqq
2026-04-22 15:24:30 +03:00
parent e22c616e4e
commit abd8c38a28
13 changed files with 477 additions and 59 deletions
+10 -1
View File
@@ -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,
}
}
+2
View File
@@ -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)]
+80 -26
View File
@@ -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);
}
}