diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation/delegation.rs similarity index 85% rename from compiler/rustc_ast_lowering/src/delegation.rs rename to compiler/rustc_ast_lowering/src/delegation/delegation.rs index cccfb112ec2b7..6ea3cf2f94d9e 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation/delegation.rs @@ -46,7 +46,6 @@ use rustc_ast::*; use rustc_attr_parsing::{AttributeParser, ShouldEmit}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::ErrorGuaranteed; -use rustc_hir::Target; use rustc_hir::attrs::{AttributeKind, InlineAttr}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::span_bug; @@ -56,9 +55,12 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol}; use smallvec::SmallVec; use {rustc_ast as ast, rustc_hir as hir}; -use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode}; +use crate::delegation::generics::{GenericsGenerationResult, GenericsGenerationResults}; use crate::errors::{CycleInDelegationSignatureResolution, UnresolvedDelegationCallee}; -use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt}; +use crate::{ + AllowReturnTypeNotation, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext, + ParamMode, ResolverAstLoweringExt, +}; pub(crate) struct DelegationResults<'hir> { pub body_id: hir::BodyId, @@ -107,7 +109,7 @@ type DelegationIdsVec = SmallVec<[DefId; 1]>; // As delegations can now refer to another delegation, we have a delegation path // of the following type: reuse (current delegation) <- reuse (delegee_id) <- ... <- reuse <- function (root_function_id). // In its most basic and widely used form: reuse (current delegation) <- function (delegee_id, root_function_id) -struct DelegationIds { +pub(super) struct DelegationIds { path: DelegationIdsVec, } @@ -118,13 +120,13 @@ impl DelegationIds { } // Id of the first function in (non)local crate that is being reused - fn root_function_id(&self) -> DefId { + pub(super) fn root_function_id(&self) -> DefId { *self.path.last().expect("Ids vector can't be empty") } // Id of the first definition which is being reused, // can be either function, in this case `root_id == delegee_id`, or other delegation - fn delegee_id(&self) -> DefId { + pub(super) fn delegee_id(&self) -> DefId { *self.path.first().expect("Ids vector can't be empty") } } @@ -184,18 +186,42 @@ impl<'hir> LoweringContext<'_, 'hir> { // we need a function to extract this information let (param_count, c_variadic) = self.param_count(root_function_id); + let mut generics = self.lower_delegation_generics(delegation, &ids, item_id); + + let body_id = self.lower_delegation_body( + delegation, + item_id, + is_method, + param_count, + &mut generics, + span, + ); + + let ident = self.lower_ident(delegation.ident); + // Here we use `delegee_id`, as this id will then be used to calculate parent for generics // inheritance, and we want this id to point on a delegee, not on the original // function (see https://github.com/rust-lang/rust/issues/150152#issuecomment-3674834654) - let decl = self.lower_delegation_decl(delegee_id, param_count, c_variadic, span); + let decl = self.lower_delegation_decl( + delegee_id, + param_count, + c_variadic, + span, + &generics, + ); // Here we pass `root_function_id` as we want to inherit signature (including consts, async) // from the root function that started delegation let sig = self.lower_delegation_sig(root_function_id, decl, span); - let body_id = self.lower_delegation_body(delegation, is_method, param_count, span); - let ident = self.lower_ident(delegation.ident); - let generics = self.lower_delegation_generics(span); + let generics = self.arena.alloc(hir::Generics { + has_where_clause_predicates: false, + params: self.arena.alloc_from_iter(generics.all_params(item_id, span, self)), + predicates: self.arena.alloc_from_iter(generics.all_predicates()), + span, + where_clause_span: span, + }); + DelegationResults { body_id, sig, ident, generics } } Err(err) => self.generate_delegation_error(err, span, delegation), @@ -292,7 +318,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.tcx.sess, attrs, None, - Target::Fn, + hir::Target::Fn, DUMMY_SP, DUMMY_NODE_ID, Some(self.tcx.features()), @@ -357,20 +383,10 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn get_resolution_id(&self, node_id: NodeId) -> Option { + pub(super) fn get_resolution_id(&self, node_id: NodeId) -> Option { self.resolver.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id()) } - fn lower_delegation_generics(&mut self, span: Span) -> &'hir hir::Generics<'hir> { - self.arena.alloc(hir::Generics { - params: &[], - predicates: &[], - has_where_clause_predicates: false, - where_clause_span: span, - span, - }) - } - // Function parameter count, including C variadic `...` if present. fn param_count(&self, def_id: DefId) -> (usize, bool /*c_variadic*/) { if let Some(local_sig_id) = def_id.as_local() { @@ -390,6 +406,7 @@ impl<'hir> LoweringContext<'_, 'hir> { param_count: usize, c_variadic: bool, span: Span, + generics: &GenericsGenerationResults<'hir>, ) -> &'hir hir::FnDecl<'hir> { // The last parameter in C variadic functions is skipped in the signature, // like during regular lowering. @@ -402,7 +419,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let output = self.arena.alloc(hir::Ty { hir_id: self.next_id(), - kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output), + kind: hir::TyKind::InferDelegation( + sig_id, + hir::InferDelegationKind::Output( + self.arena.alloc(generics.create_hir_delegation_generics()), + ), + ), span, }); @@ -457,6 +479,7 @@ impl<'hir> LoweringContext<'_, 'hir> { abi: sig.abi, } }; + hir::FnSig { decl, header, span } } @@ -498,6 +521,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } else { Symbol::intern(&format!("arg{idx}")) }; + let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment { ident: Ident::with_dummy_span(name), hir_id: self.next_id(), @@ -513,8 +537,10 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_delegation_body( &mut self, delegation: &Delegation, + item_id: NodeId, is_method: bool, param_count: usize, + generics: &mut GenericsGenerationResults<'hir>, span: Span, ) -> BodyId { let block = delegation.body.as_deref(); @@ -545,7 +571,8 @@ impl<'hir> LoweringContext<'_, 'hir> { args.push(arg); } - let final_expr = this.finalize_body_lowering(delegation, args, span); + let final_expr = this.finalize_body_lowering(delegation, item_id, args, generics, span); + (this.arena.alloc_from_iter(parameters), final_expr) }) } @@ -581,7 +608,9 @@ impl<'hir> LoweringContext<'_, 'hir> { fn finalize_body_lowering( &mut self, delegation: &Delegation, + item_id: NodeId, args: Vec>, + generics: &mut GenericsGenerationResults<'hir>, span: Span, ) -> hir::Expr<'hir> { let args = self.arena.alloc_from_iter(args); @@ -606,6 +635,10 @@ impl<'hir> LoweringContext<'_, 'hir> { ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); + + // FIXME(fn_delegation): proper support for parent generics propagation + // in method call scenario. + let segment = self.process_segment(item_id, span, &segment, &mut generics.child, false); let segment = self.arena.alloc(segment); self.arena.alloc(hir::Expr { @@ -624,9 +657,41 @@ impl<'hir> LoweringContext<'_, 'hir> { None, ); - let callee_path = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(path), span)); + let new_path = match path { + hir::QPath::Resolved(ty, path) => { + let mut new_path = path.clone(); + let len = new_path.segments.len(); + + new_path.segments = self.arena.alloc_from_iter( + new_path.segments.iter().enumerate().map(|(idx, segment)| { + let mut process_segment = |result, add_lifetimes| { + self.process_segment(item_id, span, segment, result, add_lifetimes) + }; + + if idx + 2 == len { + process_segment(&mut generics.parent, true) + } else if idx + 1 == len { + process_segment(&mut generics.child, false) + } else { + segment.clone() + } + }), + ); + + hir::QPath::Resolved(ty, self.arena.alloc(new_path)) + } + hir::QPath::TypeRelative(ty, segment) => { + let segment = + self.process_segment(item_id, span, segment, &mut generics.child, false); + + hir::QPath::TypeRelative(ty, self.arena.alloc(segment)) + } + }; + + 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)) }; + let block = self.arena.alloc(hir::Block { stmts: &[], expr: Some(call), @@ -639,14 +704,43 @@ impl<'hir> LoweringContext<'_, 'hir> { self.mk_expr(hir::ExprKind::Block(block, None), span) } + fn process_segment( + &mut self, + item_id: NodeId, + span: Span, + segment: &hir::PathSegment<'hir>, + result: &mut GenericsGenerationResult<'hir>, + add_lifetimes: bool, + ) -> hir::PathSegment<'hir> { + // The first condition is needed when there is SelfAndUserSpecified case, + // we don't want to propagate generics params in this situation. + let segment = if !result.generics.is_user_specified() + && let Some(args) = result + .generics + .into_hir_generics(self, item_id, span) + .into_generic_args(self, add_lifetimes) + { + let mut new_segment = segment.clone(); + new_segment.args = Some(args); + + new_segment + } else { + segment.clone() + }; + + if result.generics.is_user_specified() { + result.args_segment_id = Some(segment.hir_id); + } + + segment + } + fn generate_delegation_error( &mut self, err: ErrorGuaranteed, span: Span, delegation: &Delegation, ) -> DelegationResults<'hir> { - let generics = self.lower_delegation_generics(span); - let decl = self.arena.alloc(hir::FnDecl { inputs: &[], output: hir::FnRetTy::DefaultReturn(span), @@ -664,10 +758,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let body_expr = match delegation.body.as_ref() { Some(box block) => { // Generates a block when we failed to resolve delegation, where a target expression is its only statement, - // thus there will be no ICEs on further stages of analysis (see #144594) + // thus there will be no ICEs on further stages of analysis (see #144594). // As we generate a void function we want to convert target expression to statement to avoid additional - // errors, such as mismatched return type + // errors, such as mismatched return type. let stmts = this.arena.alloc_from_iter([hir::Stmt { hir_id: this.next_id(), kind: rustc_hir::StmtKind::Semi( @@ -693,6 +787,7 @@ impl<'hir> LoweringContext<'_, 'hir> { (&[], this.mk_expr(body_expr, span)) }); + let generics = hir::Generics::empty(); DelegationResults { ident, generics, body_id, sig } } diff --git a/compiler/rustc_ast_lowering/src/delegation/generics.rs b/compiler/rustc_ast_lowering/src/delegation/generics.rs new file mode 100644 index 0000000000000..df23f83f29eac --- /dev/null +++ b/compiler/rustc_ast_lowering/src/delegation/generics.rs @@ -0,0 +1,538 @@ +use hir::HirId; +use hir::def::{DefKind, Res}; +use rustc_ast::*; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; +use rustc_middle::ty; +use rustc_middle::ty::GenericParamDefKind; +use rustc_span::sym::{self}; +use rustc_span::symbol::kw; +use rustc_span::{DUMMY_SP, Ident, Span}; +use thin_vec::{ThinVec, thin_vec}; + +use crate::{AstOwner, LoweringContext}; + +impl<'hir> LoweringContext<'_, 'hir> { + pub(super) fn lower_delegation_generics( + &mut self, + delegation: &Delegation, + ids: &super::delegation::DelegationIds, + item_id: NodeId, + ) -> GenericsGenerationResults<'hir> { + let delegation_in_free_ctx = self + .tcx + .opt_parent(self.local_def_id(item_id).to_def_id()) + .is_none_or(|p| !matches!(self.tcx.def_kind(p), DefKind::Trait | DefKind::Impl { .. })); + + let root_function_in_trait = self + .tcx + .opt_parent(ids.root_function_id()) + .is_some_and(|p| matches!(self.tcx.def_kind(p), DefKind::Trait)); + + let generate_self = delegation_in_free_ctx && root_function_in_trait; + + let parent_generics_factory = |this: &mut Self, user_specified: bool| { + this.get_parent_generics( + this.tcx.opt_parent(ids.root_function_id()), + generate_self, + user_specified, + ) + }; + + let segments = &delegation.path.segments; + let len = segments.len(); + + let parent_generics = if len >= 2 && self.can_add_generics_to(segments[len - 2].id) { + if segments[len - 2].args.is_some() { + if generate_self { + DelegationGenerics::SelfAndUserSpecified(parent_generics_factory(self, true)) + } else { + DelegationGenerics::UserSpecified + } + } else { + DelegationGenerics::Default(parent_generics_factory(self, false)) + } + } else { + DelegationGenerics::Default(None) + }; + + let child_generics = if segments[len - 1].args.is_some() { + DelegationGenerics::UserSpecified + } else { + DelegationGenerics::Default(self.get_fn_like_generics(ids.root_function_id())) + }; + + GenericsGenerationResults { + parent: GenericsGenerationResult::new(parent_generics), + child: GenericsGenerationResult::new(child_generics), + } + } + + fn can_add_generics_to(&self, node_id: NodeId) -> bool { + self.get_resolution_id(node_id).is_some_and(|def_id| { + matches!(self.tcx.def_kind(def_id), DefKind::Trait | DefKind::TraitAlias) + }) + } + + fn lower_ast_generics( + &mut self, + item_id: NodeId, + span: Span, + generics: &DelegationGenerics, + ) -> DelegationGenerics<&'hir hir::Generics<'hir>> { + let mut process_params = |generics: &Option| { + generics + .as_ref() + .map(|g| self.lower_delegation_generic_params(item_id, span, g.params.clone())) + }; + + match generics { + DelegationGenerics::UserSpecified => DelegationGenerics::UserSpecified, + DelegationGenerics::Default(generics) => { + DelegationGenerics::Default(process_params(generics)) + } + DelegationGenerics::SelfAndUserSpecified(generics) => { + DelegationGenerics::SelfAndUserSpecified(process_params(generics)) + } + } + } + + fn lower_delegation_generic_params( + &mut self, + item_id: NodeId, + span: Span, + mut params: ThinVec, + ) -> &'hir hir::Generics<'hir> { + for p in &mut params { + // We want to create completely new params, so we generate + // a new id, otherwise assertions will be triggered. + p.id = self.next_node_id(); + + // Remove default params, as they are not supported on functions + // and there will duplicate DefId when we try to lower them later. + match &mut p.kind { + GenericParamKind::Lifetime => {} + GenericParamKind::Type { default } => *default = None, + GenericParamKind::Const { default, .. } => *default = None, + } + + // Note that we use self.disambiguator here, if we will create new every time + // we will get ICE if params have the same name. + self.resolver.node_id_to_def_id.insert( + p.id, + self.tcx + .create_def( + self.resolver.node_id_to_def_id[&item_id], + Some(p.ident.name), + match p.kind { + GenericParamKind::Lifetime => DefKind::LifetimeParam, + GenericParamKind::Type { .. } => DefKind::TyParam, + GenericParamKind::Const { .. } => DefKind::ConstParam, + }, + None, + &mut self.disambiguator, + ) + .def_id(), + ); + } + + // Fallback to default generic param lowering, we modified them in the loop above. + let params = self.arena.alloc_from_iter( + params.iter().map(|p| self.lower_generic_param(p, hir::GenericParamSource::Generics)), + ); + + // HACK: for now we generate predicates such that all lifetimes are early bound, + // we can not not generate early-bound lifetimes, but we can't know which of them + // are late-bound at this level of compilation. + // FIXME(fn_delegation): proper support for late bound lifetimes. + self.arena.alloc(hir::Generics { + params, + predicates: self.arena.alloc_from_iter( + params + .iter() + .filter_map(|p| p.is_lifetime().then(|| self.generate_lifetime_predicate(p))), + ), + has_where_clause_predicates: false, + where_clause_span: span, + span, + }) + } + + fn generate_lifetime_predicate( + &mut self, + p: &hir::GenericParam<'hir>, + ) -> hir::WherePredicate<'hir> { + let create_lifetime = |this: &mut Self| -> &'hir hir::Lifetime { + this.arena.alloc(hir::Lifetime { + hir_id: this.next_id(), + ident: p.name.ident(), + kind: rustc_hir::LifetimeKind::Param(p.def_id), + source: rustc_hir::LifetimeSource::Path { + angle_brackets: rustc_hir::AngleBrackets::Full, + }, + syntax: rustc_hir::LifetimeSyntax::ExplicitBound, + }) + }; + + hir::WherePredicate { + hir_id: self.next_id(), + span: DUMMY_SP, + kind: self.arena.alloc(hir::WherePredicateKind::RegionPredicate( + hir::WhereRegionPredicate { + in_where_clause: true, + lifetime: create_lifetime(self), + bounds: self + .arena + .alloc_slice(&[hir::GenericBound::Outlives(create_lifetime(self))]), + }, + )), + } + } + + fn create_generics_args_from_params( + &mut self, + params: &[hir::GenericParam<'hir>], + add_lifetimes: bool, + ) -> &'hir hir::GenericArgs<'hir> { + self.arena.alloc(hir::GenericArgs { + args: self.arena.alloc_from_iter(params.iter().filter_map(|p| { + // Skip self generic arg, we do not need to propagate it. + if p.name.ident().name == kw::SelfUpper { + return None; + } + + let create_path = |this: &mut Self| { + let res = Res::Def( + match p.kind { + hir::GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam, + hir::GenericParamKind::Type { .. } => DefKind::TyParam, + hir::GenericParamKind::Const { .. } => DefKind::ConstParam, + }, + p.def_id.to_def_id(), + ); + + hir::QPath::Resolved( + None, + self.arena.alloc(hir::Path { + segments: this.arena.alloc_slice(&[hir::PathSegment { + args: None, + hir_id: this.next_id(), + ident: p.name.ident(), + infer_args: false, + res, + }]), + res, + span: p.span, + }), + ) + }; + + match p.kind { + hir::GenericParamKind::Lifetime { .. } => match add_lifetimes { + true => Some(hir::GenericArg::Lifetime(self.arena.alloc(hir::Lifetime { + hir_id: self.next_id(), + ident: p.name.ident(), + kind: hir::LifetimeKind::Param(p.def_id), + source: hir::LifetimeSource::Path { + angle_brackets: hir::AngleBrackets::Full, + }, + syntax: hir::LifetimeSyntax::ExplicitBound, + }))), + false => None, + }, + hir::GenericParamKind::Type { .. } => { + Some(hir::GenericArg::Type(self.arena.alloc(hir::Ty { + hir_id: self.next_id(), + span: p.span, + kind: hir::TyKind::Path(create_path(self)), + }))) + } + hir::GenericParamKind::Const { .. } => { + Some(hir::GenericArg::Const(self.arena.alloc(hir::ConstArg { + hir_id: self.next_id(), + kind: hir::ConstArgKind::Path(create_path(self)), + span: p.span, + }))) + } + } + })), + constraints: &[], + parenthesized: hir::GenericArgsParentheses::No, + span_ext: DUMMY_SP, + }) + } + + fn get_fn_like_generics(&mut self, id: DefId) -> Option { + if let Some(local_id) = id.as_local() { + match self.ast_accessor.get(local_id) { + Some(AstOwner::Item(item)) if let ItemKind::Fn(f) = &item.kind => { + Some(f.generics.clone()) + } + Some(AstOwner::AssocItem(item, _)) if let AssocItemKind::Fn(f) = &item.kind => { + Some(f.generics.clone()) + } + _ => None, + } + } else { + self.get_external_generics(id, false) + } + } + + fn get_external_generics(&mut self, id: DefId, processing_parent: bool) -> Option { + let generics = self.tcx.generics_of(id); + if generics.own_params.is_empty() { + return None; + } + + // Skip first Self parameter if we are in trait, it will be added later. + let to_skip = (processing_parent && generics.has_self) as usize; + + Some(Generics { + params: generics + .own_params + .iter() + .skip(to_skip) + .map(|p| GenericParam { + attrs: Default::default(), + bounds: Default::default(), + colon_span: None, + id: self.next_node_id(), + ident: Ident::with_dummy_span(p.name), + is_placeholder: false, + kind: match p.kind { + GenericParamDefKind::Lifetime => GenericParamKind::Lifetime, + GenericParamDefKind::Type { .. } => { + GenericParamKind::Type { default: None } + } + GenericParamDefKind::Const { .. } => self.map_const_kind(p), + }, + }) + .collect(), + where_clause: Default::default(), + span: DUMMY_SP, + }) + } + + fn map_const_kind(&mut self, p: &ty::GenericParamDef) -> GenericParamKind { + let const_type = self.tcx.type_of(p.def_id).instantiate_identity().kind(); + + let (type_symbol, res) = match const_type { + ty::Bool => (sym::bool, Res::PrimTy(hir::PrimTy::Bool)), + ty::Uint(uint) => (uint.name(), Res::PrimTy(hir::PrimTy::Uint(*uint))), + ty::Int(int) => (int.name(), Res::PrimTy(hir::PrimTy::Int(*int))), + ty::Char => (sym::char, Res::PrimTy(hir::PrimTy::Char)), + _ => (sym::dummy, Res::Err), + }; + + let node_id = self.next_node_id(); + + self.resolver.partial_res_map.insert(node_id, hir::def::PartialRes::new(res)); + + GenericParamKind::Const { + ty: Box::new(Ty { + id: node_id, + kind: TyKind::Path( + None, + Path { + segments: thin_vec![PathSegment { + ident: Ident::with_dummy_span(type_symbol), + id: self.next_node_id(), + args: None + }], + span: DUMMY_SP, + tokens: None, + }, + ), + span: DUMMY_SP, + tokens: None, + }), + span: DUMMY_SP, + default: None, + } + } + + fn get_parent_generics( + &mut self, + id: Option, + add_self: bool, + user_specified: bool, + ) -> Option { + let id = if let Some(id) = id { id } else { return None }; + + // If args are user-specified we still maybe need to add self + let mut generics = if user_specified { + None + } else { + if let Some(local_id) = id.as_local() { + if let Some(AstOwner::Item(item)) = self.ast_accessor.get(local_id) + && matches!(item.kind, ItemKind::Trait(..)) + { + item.opt_generics().cloned() + } else { + None + } + } else { + self.get_external_generics(id, true) + } + }; + + if add_self { + generics = Some(generics.unwrap_or(Generics::default())); + + generics.as_mut().unwrap().params.insert( + 0, + GenericParam { + id: self.next_node_id(), + ident: Ident::new(kw::SelfUpper, DUMMY_SP), + attrs: Default::default(), + bounds: vec![], + is_placeholder: false, + kind: GenericParamKind::Type { default: None }, + colon_span: None, + }, + ); + } + + generics + } +} + +pub(super) enum HirOrAstGenerics<'hir> { + Ast(DelegationGenerics), + Hir(DelegationGenerics<&'hir hir::Generics<'hir>>), +} + +impl<'hir> HirOrAstGenerics<'hir> { + pub(super) fn into_hir_generics( + &mut self, + ctx: &mut LoweringContext<'_, 'hir>, + item_id: NodeId, + span: Span, + ) -> &mut Self { + match self { + HirOrAstGenerics::Ast(delegation_generics) => { + *self = Self::Hir(ctx.lower_ast_generics(item_id, span, delegation_generics)); + } + HirOrAstGenerics::Hir(_) => {} + } + + self + } + + fn hir_generics_or_empty(&self) -> &'hir hir::Generics<'hir> { + match self { + HirOrAstGenerics::Ast(_) => hir::Generics::empty(), + HirOrAstGenerics::Hir(hir_generics) => match hir_generics { + DelegationGenerics::UserSpecified => hir::Generics::empty(), + DelegationGenerics::Default(generics) + | DelegationGenerics::SelfAndUserSpecified(generics) => { + generics.as_ref().unwrap_or(&hir::Generics::empty()) + } + }, + } + } + + pub(super) fn into_generic_args( + &self, + ctx: &mut LoweringContext<'_, 'hir>, + add_lifetimes: bool, + ) -> Option<&'hir hir::GenericArgs<'hir>> { + match self { + HirOrAstGenerics::Ast(_) => None, + HirOrAstGenerics::Hir(hir_generics) => match hir_generics { + DelegationGenerics::UserSpecified => None, + DelegationGenerics::Default(generics) + | DelegationGenerics::SelfAndUserSpecified(generics) => generics.map(|generics| { + ctx.create_generics_args_from_params(generics.params, add_lifetimes) + }), + }, + } + } + + pub(super) fn is_user_specified(&self) -> bool { + match self { + HirOrAstGenerics::Ast(ast_generics) => ast_generics.is_user_specified(), + HirOrAstGenerics::Hir(hir_generics) => hir_generics.is_user_specified(), + } + } +} + +pub(super) struct GenericsGenerationResult<'hir> { + pub(super) generics: HirOrAstGenerics<'hir>, + pub(super) args_segment_id: Option, +} + +impl<'a> GenericsGenerationResult<'a> { + fn new(generics: DelegationGenerics) -> Self { + Self { generics: HirOrAstGenerics::Ast(generics), args_segment_id: None } + } +} + +pub(super) struct GenericsGenerationResults<'hir> { + pub(super) parent: GenericsGenerationResult<'hir>, + pub(super) child: GenericsGenerationResult<'hir>, +} + +impl<'hir> GenericsGenerationResults<'hir> { + pub(super) fn all_params( + &mut self, + item_id: NodeId, + span: Span, + ctx: &mut LoweringContext<'_, 'hir>, + ) -> impl Iterator> { + let parent = self + .parent + .generics + .into_hir_generics(ctx, item_id, span) + .hir_generics_or_empty() + .params; + + let child = self + .child + .generics + .into_hir_generics(ctx, item_id, span) + .hir_generics_or_empty() + .params; + + // Order generics, firstly we have parent and child lifetimes, + // then parent and child types and consts. + // `generics_of` in `rustc_hir_analysis` will order them anyway, + // however we want the order to be consistent in HIR too. + parent + .iter() + .filter(|p| p.is_lifetime()) + .chain(child.iter().filter(|p| p.is_lifetime())) + .chain(parent.iter().filter(|p| !p.is_lifetime())) + .chain(child.iter().filter(|p| !p.is_lifetime())) + .map(|p| *p) + } + + pub(super) fn all_predicates(&self) -> impl Iterator> { + self.parent + .generics + .hir_generics_or_empty() + .predicates + .into_iter() + .chain(self.child.generics.hir_generics_or_empty().predicates.into_iter()) + .map(|p| *p) + } + + pub(super) fn create_hir_delegation_generics(&self) -> hir::DelegationGenerics { + hir::DelegationGenerics { + child_args_segment_id: self.child.args_segment_id, + parent_args_segment_id: self.parent.args_segment_id, + } + } +} + +pub(super) enum DelegationGenerics { + UserSpecified, + Default(Option), + SelfAndUserSpecified(Option), +} + +impl DelegationGenerics { + fn is_user_specified(&self) -> bool { + matches!(self, Self::UserSpecified | Self::SelfAndUserSpecified { .. }) + } +} diff --git a/compiler/rustc_ast_lowering/src/delegation/mod.rs b/compiler/rustc_ast_lowering/src/delegation/mod.rs new file mode 100644 index 0000000000000..14ddb4523546a --- /dev/null +++ b/compiler/rustc_ast_lowering/src/delegation/mod.rs @@ -0,0 +1,2 @@ +mod delegation; +mod generics; diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b497c6beeb984..17c089cf1cd76 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -57,7 +57,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { owner: NodeId, f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>, ) { - let mut lctx = LoweringContext::new(self.tcx, self.resolver); + let mut lctx = LoweringContext::new(self.tcx, self.ast_index, self.resolver); lctx.with_hir_id_owner(owner, |lctx| f(lctx)); for (def_id, info) in lctx.children { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e4f431fd2431c..8c2f4c37add57 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -33,6 +33,7 @@ // tidy-alphabetical-start #![feature(box_patterns)] #![feature(if_let_guard)] +#![recursion_limit = "256"] // tidy-alphabetical-end use std::mem; @@ -88,8 +89,24 @@ mod pat; mod path; pub mod stability; +// During lowering of delegation we need to access AST of other functions +// in order to properly propagate generics, we could have done it at resolve +// stage, however it will require either to firstly identify functions that +// are being reused and store their generics, or to store generics of all functions +// in resolver. This approach helps with those problems, as functions that are reused +// will be in AST index. +struct AstIndexAccessor<'a>(&'a IndexSlice>); + +impl<'a> AstIndexAccessor<'a> { + pub(crate) fn get(&self, id: LocalDefId) -> Option<&'a AstOwner<'a>> { + self.0.get(id) + } +} + struct LoweringContext<'a, 'hir> { tcx: TyCtxt<'hir>, + ast_accessor: AstIndexAccessor<'a>, + resolver: &'a mut ResolverAstLowering, disambiguator: DisambiguatorState, @@ -150,11 +167,16 @@ struct LoweringContext<'a, 'hir> { } impl<'a, 'hir> LoweringContext<'a, 'hir> { - fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self { + fn new( + tcx: TyCtxt<'hir>, + ast_index: &'a IndexSlice>, + resolver: &'a mut ResolverAstLowering, + ) -> Self { let registered_tools = tcx.registered_tools(()).iter().map(|x| x.name).collect(); Self { // Pseudo-globals. tcx, + ast_accessor: AstIndexAccessor(ast_index), resolver, disambiguator: DisambiguatorState::new(), arena: tcx.hir_arena, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4c1bcffa1cf4c..bacc1e52b97d8 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -857,6 +857,10 @@ impl<'hir> GenericParam<'hir> { pub fn is_elided_lifetime(&self) -> bool { matches!(self.kind, GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided(_) }) } + + pub fn is_lifetime(&self) -> bool { + matches!(self.kind, GenericParamKind::Lifetime { .. }) + } } /// Records where the generic parameter originated from. @@ -3722,10 +3726,19 @@ pub enum OpaqueTyOrigin { }, } +// Ids of parent (or child) path segment that contains user-specified args +#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)] +pub struct DelegationGenerics { + pub parent_args_segment_id: Option, + pub child_args_segment_id: Option, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)] -pub enum InferDelegationKind { +pub enum InferDelegationKind<'hir> { Input(usize), - Output, + // Place generics info here, as we always specify output type for delegations, + // and this placement does not require to change asserts about hir structs' sizes + Output(&'hir DelegationGenerics), } /// The various kinds of types recognized by the compiler. @@ -3737,7 +3750,7 @@ pub enum InferDelegationKind { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum TyKind<'hir, Unambig = ()> { /// Actual type should be inherited from `DefId` signature - InferDelegation(DefId, InferDelegationKind), + InferDelegation(DefId, InferDelegationKind<'hir>), /// A variable length slice (i.e., `[T]`). Slice(&'hir Ty<'hir>), /// A fixed length array (i.e., `[T; n]`). @@ -3890,6 +3903,17 @@ impl<'hir> FnDecl<'hir> { } None } + + pub fn opt_delegation_generics_info(&self) -> Option<&'hir DelegationGenerics> { + if let FnRetTy::Return(ty) = self.output + && let TyKind::InferDelegation(_, kind) = ty.kind + && let InferDelegationKind::Output(generics) = kind + { + return Some(generics); + } + + None + } } /// Represents what type of implicit self a function has, if any. diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 511d513216eb2..aa4aa808326b3 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -11,7 +11,6 @@ use rustc_session::lint; use rustc_span::{Span, Symbol, kw}; use tracing::{debug, instrument}; -use crate::delegation::inherit_generics_for_delegation_item; use crate::middle::resolve_bound_vars as rbv; #[instrument(level = "debug", skip(tcx), ret)] @@ -56,13 +55,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { } let hir_id = tcx.local_def_id_to_hir_id(def_id); - let node = tcx.hir_node(hir_id); - if let Some(sig) = node.fn_sig() - && let Some(sig_id) = sig.decl.opt_delegation_sig_id() - { - return inherit_generics_for_delegation_item(tcx, def_id, sig_id); - } let parent_def_id = match node { Node::ImplItem(_) diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index a2236b4263059..dce8ffd785e89 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -137,17 +137,25 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(hir_id); + let icx = ItemCtxt::new(tcx, def_id); + if let Some(sig) = node.fn_sig() && let Some(sig_id) = sig.decl.opt_delegation_sig_id() { - return inherit_predicates_for_delegation_item(tcx, def_id, sig_id); + let (parent_args, child_args) = icx.lowerer().get_delegation_user_specified_args(); + + return inherit_predicates_for_delegation_item( + tcx, + def_id, + sig_id, + parent_args, + child_args, + ); } let mut is_trait = None; let mut is_default_impl_trait = None; - let icx = ItemCtxt::new(tcx, def_id); - const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty(); // We use an `IndexSet` to preserve order of insertion. diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index f64341d755f8c..bd66a79a5ca2a 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -7,7 +7,8 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + self, EarlyBinder, GenericPredicates, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitableExt, }; use rustc_span::{ErrorGuaranteed, Span}; @@ -59,6 +60,33 @@ impl<'tcx> TypeFolder> for ParamIndexRemapper<'tcx> { } } +enum SelfPositionKind { + AfterLifetimes, + Zero, + None, +} + +macro_rules! unsupported_caller_callee_kinds { + () => { + // For trait impl's `sig_id` is always equal to the corresponding trait method. + // For inherent methods delegation is not yet supported. + (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) | (_, FnKind::AssocInherentImpl) + }; +} + +fn create_self_position_kind(caller_kind: FnKind, callee_kind: FnKind) -> SelfPositionKind { + match (caller_kind, callee_kind) { + (FnKind::AssocInherentImpl, FnKind::AssocTrait) + | (FnKind::AssocTraitImpl, FnKind::AssocTrait) + | (FnKind::AssocTrait, FnKind::AssocTrait) + | (FnKind::AssocTrait, FnKind::Free) => SelfPositionKind::Zero, + + (FnKind::Free, FnKind::AssocTrait) => SelfPositionKind::AfterLifetimes, + + _ => SelfPositionKind::None, + } +} + #[derive(Clone, Copy, Debug, PartialEq)] enum FnKind { Free, @@ -99,290 +127,436 @@ enum InheritanceKind { Own, } -fn build_generics<'tcx>( +/// Maps sig generics into generic args of delegation. Delegation generics has the following pattern: +/// +/// [SELF | maybe self in the beginning] +/// [PARENT | args of delegation parent] +/// [SIG PARENT LIFETIMES] +/// [SIG LIFETIMES] +/// [SELF | maybe self after lifetimes, when we reuse trait fn in free context] +/// [SIG PARENT TYPES/CONSTS] +/// [SIG TYPES/CONSTS] +fn create_mapping<'tcx>( tcx: TyCtxt<'tcx>, sig_id: DefId, - parent: Option, - inh_kind: InheritanceKind, -) -> ty::Generics { - let mut own_params = vec![]; + def_id: LocalDefId, + args: &Vec>, +) -> FxHashMap { + let mut mapping: FxHashMap = Default::default(); + + let (caller_kind, callee_kind) = get_caller_and_callee_kind(tcx, def_id, sig_id); + let self_pos_kind = create_self_position_kind(caller_kind, callee_kind); + 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. + if is_self_at_zero { + mapping.insert(0, 0); + } + + let mut args_index = 0; + + args_index += is_self_at_zero as usize; + args_index += get_delegation_parent_args_count_without_self(tcx, def_id, sig_id); let sig_generics = tcx.generics_of(sig_id); - if let InheritanceKind::WithParent(has_self) = inh_kind - && let Some(parent_def_id) = sig_generics.parent - { - let sig_parent_generics = tcx.generics_of(parent_def_id); - own_params.append(&mut sig_parent_generics.own_params.clone()); - if !has_self { - own_params.remove(0); + let process_sig_parent_generics = matches!(callee_kind, FnKind::AssocTrait); + + if process_sig_parent_generics { + for i in (sig_generics.has_self as usize)..sig_generics.parent_count { + let param = sig_generics.param_at(i, tcx); + if !param.kind.is_ty_or_const() { + mapping.insert(param.index, args_index as u32); + args_index += 1; + } } } - own_params.append(&mut sig_generics.own_params.clone()); - - // 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(...) - // } - own_params.sort_by_key(|key| key.kind.is_ty_or_const()); - - let (parent_count, has_self) = if let Some(def_id) = parent { - let parent_generics = tcx.generics_of(def_id); - let parent_kind = tcx.def_kind(def_id); - (parent_generics.count(), parent_kind == DefKind::Trait) - } else { - (0, false) - }; - for (idx, param) in own_params.iter_mut().enumerate() { - param.index = (idx + parent_count) as u32; - // FIXME(fn_delegation): Default parameters are not inherited, because they are - // not permitted in functions. Therefore, there are 2 options here: - // - // - We can create non-default generic parameters. - // - We can substitute default parameters into the signature. - // - // At the moment, first option has been selected as the most general. - if let ty::GenericParamDefKind::Type { has_default, .. } - | ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind - { - *has_default = false; + for param in &sig_generics.own_params { + if !param.kind.is_ty_or_const() { + mapping.insert(param.index, args_index as u32); + args_index += 1; } } - let param_def_id_to_index = - own_params.iter().map(|param| (param.def_id, param.index)).collect(); + // If there are still unmapped lifetimes left and we are to map types and maybe self + // then skip them, now it is the case when we generated more lifetimes then needed. + // FIXME(fn_delegation): proper support for late bound lifetimes. + while args_index < args.len() && args[args_index].as_region().is_some() { + args_index += 1; + } + + // If self after lifetimes insert mapping, relying that self is at 0 in sig parent + if matches!(self_pos_kind, SelfPositionKind::AfterLifetimes) { + mapping.insert(0, args_index as u32); + args_index += 1; + } + + if process_sig_parent_generics { + for i in (sig_generics.has_self as usize)..sig_generics.parent_count { + let param = sig_generics.param_at(i, tcx); + if param.kind.is_ty_or_const() { + mapping.insert(param.index, args_index as u32); + args_index += 1; + } + } + } - ty::Generics { - parent, - parent_count, - own_params, - param_def_id_to_index, - has_self, - has_late_bound_regions: sig_generics.has_late_bound_regions, + for param in &sig_generics.own_params { + if param.kind.is_ty_or_const() { + mapping.insert(param.index, args_index as u32); + args_index += 1; + } } + + mapping } -fn build_predicates<'tcx>( +fn get_delegation_parent_args_count_without_self<'tcx>( tcx: TyCtxt<'tcx>, + delegation_id: LocalDefId, sig_id: DefId, - parent: Option, - inh_kind: InheritanceKind, - args: ty::GenericArgsRef<'tcx>, -) -> ty::GenericPredicates<'tcx> { - struct PredicatesCollector<'tcx> { - tcx: TyCtxt<'tcx>, - preds: Vec<(ty::Clause<'tcx>, Span)>, - args: ty::GenericArgsRef<'tcx>, +) -> usize { + let delegation_parent_args_count = tcx.generics_of(delegation_id).parent_count; + + match get_caller_and_callee_kind(tcx, delegation_id, sig_id) { + (FnKind::Free, FnKind::Free) + | (FnKind::Free, FnKind::AssocTrait) + | (FnKind::AssocTraitImpl, FnKind::AssocTrait) => 0, + + (FnKind::AssocInherentImpl, FnKind::Free) + | (FnKind::AssocInherentImpl, FnKind::AssocTrait) => { + delegation_parent_args_count /* No Self in AssocInherentImpl */ + } + + (FnKind::AssocTrait, FnKind::Free) | (FnKind::AssocTrait, FnKind::AssocTrait) => { + delegation_parent_args_count - 1 /* Without Self */ + } + + unsupported_caller_callee_kinds!() => unreachable!(), } +} - impl<'tcx> PredicatesCollector<'tcx> { - fn new(tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> PredicatesCollector<'tcx> { - PredicatesCollector { tcx, preds: vec![], args } +fn get_caller_and_callee_kind<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + sig_id: DefId, +) -> (FnKind, FnKind) { + (fn_kind(tcx, def_id.into()), fn_kind(tcx, sig_id)) +} + +fn get_parent_and_inheritance_kind<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + sig_id: DefId, +) -> (Option, InheritanceKind) { + match get_caller_and_callee_kind(tcx, def_id, sig_id) { + (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) => { + (None, InheritanceKind::WithParent(true)) } - fn with_own_preds( - mut self, - f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>, - def_id: DefId, - ) -> Self { - let preds = f(def_id).instantiate_own(self.tcx, self.args); - self.preds.extend(preds); - self + (FnKind::AssocTraitImpl, FnKind::AssocTrait) => { + (Some(tcx.parent(def_id.into())), InheritanceKind::Own) } - fn with_preds( - mut self, - f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy, - def_id: DefId, - ) -> Self { - let preds = f(def_id); - if let Some(parent_def_id) = preds.parent { - self = self.with_own_preds(f, parent_def_id); - } - self.with_own_preds(f, def_id) + (FnKind::AssocInherentImpl, FnKind::AssocTrait) + | (FnKind::AssocTrait, FnKind::AssocTrait) + | (FnKind::AssocInherentImpl, FnKind::Free) + | (FnKind::AssocTrait, FnKind::Free) => { + (Some(tcx.parent(def_id.into())), InheritanceKind::WithParent(false)) } + + unsupported_caller_callee_kinds!() => unreachable!(), } - let collector = PredicatesCollector::new(tcx, args); +} - // `explicit_predicates_of` is used here to avoid copying `Self: Trait` predicate. - // Note: `predicates_of` query can also add inferred outlives predicates, but that - // is not the case here as `sig_id` is either a trait or a function. - let preds = match inh_kind { - InheritanceKind::WithParent(false) => { - collector.with_preds(|def_id| tcx.explicit_predicates_of(def_id), sig_id) +pub(crate) fn get_delegation_self_ty<'tcx>( + tcx: TyCtxt<'tcx>, + delegation_id: LocalDefId, +) -> Option> { + let sig_id = tcx.hir_opt_delegation_sig_id(delegation_id).expect("Delegation must have sig_id"); + let (caller_kind, callee_kind) = get_caller_and_callee_kind(tcx, delegation_id, sig_id); + + match (caller_kind, callee_kind) { + (FnKind::Free, FnKind::Free) => None, + + (FnKind::Free, FnKind::AssocTrait) + | (FnKind::AssocInherentImpl, FnKind::Free) + | (FnKind::AssocTrait, FnKind::Free) + | (FnKind::AssocTrait, FnKind::AssocTrait) => { + match create_self_position_kind(caller_kind, callee_kind) { + SelfPositionKind::None => None, + SelfPositionKind::AfterLifetimes => { + ty::GenericArgs::identity_for_item(tcx, delegation_id) + .iter() + .skip_while(|a| a.as_region().is_some()) + .next() + .map(|a| a.as_type()) + .flatten() + } + SelfPositionKind::Zero => ty::GenericArgs::identity_for_item(tcx, delegation_id) + .first() + .map(|a| a.as_type()) + .flatten(), + } } - InheritanceKind::WithParent(true) => { - collector.with_preds(|def_id| tcx.predicates_of(def_id), sig_id) + + (FnKind::AssocTraitImpl, FnKind::AssocTrait) => { + create_trait_impl_to_trait_parent_args(tcx, delegation_id) + .first() + .map(|a| a.as_type()) + .flatten() } - InheritanceKind::Own => { - collector.with_own_preds(|def_id| tcx.predicates_of(def_id), sig_id) + + (FnKind::AssocInherentImpl, FnKind::AssocTrait) => { + Some(create_inherent_impl_to_trait_self_ty(tcx, delegation_id)) } - } - .preds; - ty::GenericPredicates { parent, predicates: tcx.arena.alloc_from_iter(preds) } + unsupported_caller_callee_kinds!() => unreachable!(), + } } -fn build_generic_args<'tcx>( +fn create_trait_impl_to_trait_parent_args<'tcx>( tcx: TyCtxt<'tcx>, - sig_id: DefId, - def_id: LocalDefId, - args: ty::GenericArgsRef<'tcx>, + delegation_id: LocalDefId, ) -> ty::GenericArgsRef<'tcx> { - let caller_generics = tcx.generics_of(def_id); - let callee_generics = tcx.generics_of(sig_id); - - let mut remap_table = FxHashMap::default(); - for caller_param in &caller_generics.own_params { - let callee_index = callee_generics.param_def_id_to_index(tcx, caller_param.def_id).unwrap(); - remap_table.insert(callee_index, caller_param.index); - } + let parent = tcx.parent(delegation_id.into()); + tcx.impl_trait_header(parent).trait_ref.instantiate_identity().args +} - let mut folder = ParamIndexRemapper { tcx, remap_table }; - args.fold_with(&mut folder) +fn create_inherent_impl_to_trait_self_ty<'tcx>( + tcx: TyCtxt<'tcx>, + delegation_id: LocalDefId, +) -> Ty<'tcx> { + let parent = tcx.parent(delegation_id.into()); + tcx.type_of(parent).instantiate_identity() } +/// Creates generic arguments for further delegation signature and predicates instantiation. +/// Arguments can be user-specified (in this case they are in `parent_args` and `child_args`) +/// or propagated. User can specify either both `parent_args` and `child_args`, one of them or none, +/// that is why we firstly create generic arguments from generic params and then adjust them with +/// user-specified args. +/// +/// The order of produced list is important, it must be of this pattern: +/// +/// [SELF | maybe self in the beginning] +/// [PARENT | args of delegation parent] +/// [SIG PARENT LIFETIMES] <- `lifetimes_end_pos` +/// [SIG LIFETIMES] +/// [SELF | maybe self after lifetimes, when we reuse trait fn in free context] +/// [SIG PARENT TYPES/CONSTS] +/// [SIG TYPES/CONSTS] fn create_generic_args<'tcx>( tcx: TyCtxt<'tcx>, - def_id: LocalDefId, sig_id: DefId, -) -> ty::GenericArgsRef<'tcx> { - let caller_kind = fn_kind(tcx, def_id.into()); - let callee_kind = fn_kind(tcx, sig_id); - match (caller_kind, callee_kind) { + delegation_id: LocalDefId, + mut parent_args: &[ty::GenericArg<'tcx>], + child_args: &[ty::GenericArg<'tcx>], +) -> Vec> { + let (caller_kind, callee_kind) = get_caller_and_callee_kind(tcx, delegation_id, sig_id); + + let delegation_args = ty::GenericArgs::identity_for_item(tcx, delegation_id); + let delegation_parent_args_count = tcx.generics_of(delegation_id).parent_count; + + let deleg_parent_args_without_self_count = + get_delegation_parent_args_count_without_self(tcx, delegation_id, sig_id); + + let args = match (caller_kind, callee_kind) { (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) | (FnKind::AssocInherentImpl, FnKind::Free) | (FnKind::AssocTrait, FnKind::Free) - | (FnKind::AssocTrait, FnKind::AssocTrait) => { - let args = ty::GenericArgs::identity_for_item(tcx, sig_id); - build_generic_args(tcx, sig_id, def_id, args) - } + | (FnKind::AssocTrait, FnKind::AssocTrait) => delegation_args, (FnKind::AssocTraitImpl, FnKind::AssocTrait) => { - let callee_generics = tcx.generics_of(sig_id); - let parent = tcx.parent(def_id.into()); - let parent_args = tcx.impl_trait_header(parent).trait_ref.instantiate_identity().args; + // Special case, as user specifies Trait args in impl trait header, we want to treat + // them as parent args. + parent_args = create_trait_impl_to_trait_parent_args(tcx, delegation_id); + tcx.mk_args(&delegation_args[delegation_parent_args_count..]) + } - let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id); - let method_args = tcx.mk_args(&trait_args[callee_generics.parent_count..]); - let method_args = build_generic_args(tcx, sig_id, def_id, method_args); + (FnKind::AssocInherentImpl, FnKind::AssocTrait) => { + let self_ty = create_inherent_impl_to_trait_self_ty(tcx, delegation_id); - tcx.mk_args_from_iter(parent_args.iter().chain(method_args)) + tcx.mk_args_from_iter( + std::iter::once(ty::GenericArg::from(self_ty)).chain(delegation_args.iter()), + ) } - (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); + unsupported_caller_callee_kinds!() => unreachable!(), + }; - let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id); - let trait_args = build_generic_args(tcx, sig_id, def_id, trait_args); + let mut new_args = vec![]; - let args = std::iter::once(generic_self_ty).chain(trait_args.iter().skip(1)); - tcx.mk_args_from_iter(args) - } + let self_pos_kind = create_self_position_kind(caller_kind, callee_kind); + let mut lifetimes_end_pos; - // For trait impl's `sig_id` is always equal to the corresponding trait method. - // For inherent methods delegation is not yet supported. - (FnKind::AssocTraitImpl, _) - | (_, FnKind::AssocTraitImpl) - | (_, FnKind::AssocInherentImpl) => unreachable!(), + if !parent_args.is_empty() { + let parent_args_lifetimes_count = + parent_args.iter().filter(|a| a.as_region().is_some()).count(); + + match self_pos_kind { + SelfPositionKind::AfterLifetimes => { + new_args.extend(parent_args.iter().skip(1).take(parent_args_lifetimes_count)); + + lifetimes_end_pos = parent_args_lifetimes_count; + + new_args.push(parent_args[0]); + + new_args.extend(parent_args.iter().skip(1 + parent_args_lifetimes_count)); + } + SelfPositionKind::Zero => { + lifetimes_end_pos = 1 /* Self */ + parent_args_lifetimes_count; + new_args.extend_from_slice(parent_args); + + for i in 0..deleg_parent_args_without_self_count { + new_args.insert(1 + i, args[1 + i]); + } + + lifetimes_end_pos += deleg_parent_args_without_self_count; + } + // If we have parent args then we obtained them from trait, then self must be somewhere + SelfPositionKind::None => unreachable!(), + }; + } else { + let self_impact = matches!(self_pos_kind, SelfPositionKind::Zero) as usize; + + lifetimes_end_pos = self_impact + + deleg_parent_args_without_self_count + + args + .iter() + .skip(self_impact) + .skip(deleg_parent_args_without_self_count) + .filter(|a| a.as_region().is_some()) + .count(); + + new_args.extend_from_slice(args); } -} -// FIXME(fn_delegation): Move generics inheritance to the AST->HIR lowering. -// For now, generic parameters are not propagated to the generated call, -// which leads to inference errors: -// -// fn foo(x: i32) {} -// -// reuse foo as bar; -// desugaring: -// fn bar() { -// foo::<_>() // ERROR: type annotations needed -// } -pub(crate) fn inherit_generics_for_delegation_item<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: LocalDefId, - sig_id: DefId, -) -> ty::Generics { - let caller_kind = fn_kind(tcx, def_id.into()); - let callee_kind = fn_kind(tcx, sig_id); - match (caller_kind, callee_kind) { - (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) => { - build_generics(tcx, sig_id, None, InheritanceKind::WithParent(true)) - } + if !child_args.is_empty() { + let child_lifetimes_count = child_args.iter().filter(|a| a.as_region().is_some()).count(); - (FnKind::AssocTraitImpl, FnKind::AssocTrait) => { - build_generics(tcx, sig_id, Some(tcx.parent(def_id.into())), InheritanceKind::Own) + for i in 0..child_lifetimes_count { + new_args.insert(lifetimes_end_pos + i, child_args[i]); } - (FnKind::AssocInherentImpl, FnKind::AssocTrait) - | (FnKind::AssocTrait, FnKind::AssocTrait) - | (FnKind::AssocInherentImpl, FnKind::Free) - | (FnKind::AssocTrait, FnKind::Free) => build_generics( - tcx, - sig_id, - Some(tcx.parent(def_id.into())), - InheritanceKind::WithParent(false), - ), + new_args.extend_from_slice(&child_args[child_lifetimes_count..]); + } else { + if !parent_args.is_empty() { + let child_args = &delegation_args[delegation_parent_args_count..]; - // For trait impl's `sig_id` is always equal to the corresponding trait method. - // For inherent methods delegation is not yet supported. - (FnKind::AssocTraitImpl, _) - | (_, FnKind::AssocTraitImpl) - | (_, FnKind::AssocInherentImpl) => unreachable!(), + let child_lifetimes_count = + child_args.iter().take_while(|a| a.as_region().is_some()).count(); + + for i in 0..child_lifetimes_count { + new_args.insert(lifetimes_end_pos + i, child_args[i]); + } + + let skip_self = matches!(self_pos_kind, SelfPositionKind::AfterLifetimes); + new_args.extend(child_args.iter().skip(child_lifetimes_count).skip(skip_self as usize)); + } } + + new_args } pub(crate) fn inherit_predicates_for_delegation_item<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, sig_id: DefId, + parent_args: &'tcx [ty::GenericArg<'tcx>], + child_args: &'tcx [ty::GenericArg<'tcx>], ) -> ty::GenericPredicates<'tcx> { - let args = create_generic_args(tcx, def_id, sig_id); - let caller_kind = fn_kind(tcx, def_id.into()); - let callee_kind = fn_kind(tcx, sig_id); - match (caller_kind, callee_kind) { - (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) => { - build_predicates(tcx, sig_id, None, InheritanceKind::WithParent(true), args) + struct PredicatesCollector<'tcx> { + tcx: TyCtxt<'tcx>, + preds: Vec<(ty::Clause<'tcx>, Span)>, + args: Vec>, + folder: ParamIndexRemapper<'tcx>, + } + + impl<'tcx> PredicatesCollector<'tcx> { + fn new( + tcx: TyCtxt<'tcx>, + args: Vec>, + folder: ParamIndexRemapper<'tcx>, + ) -> PredicatesCollector<'tcx> { + PredicatesCollector { tcx, preds: vec![], args, folder } + } + + fn with_own_preds( + mut self, + f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>, + def_id: DefId, + ) -> Self { + let preds = f(def_id); + let mut new_predicates = vec![]; + + for pred in preds.predicates { + new_predicates.push((pred.0.fold_with(&mut self.folder), pred.1)); + } + + let preds = GenericPredicates { + parent: preds.parent.clone(), + predicates: self.tcx.arena.alloc_slice(new_predicates.as_slice()), + }; + + let preds = EarlyBinder::bind(preds.predicates) + .iter_instantiated_copied(self.tcx, self.args.as_slice()); + + self.preds.extend(preds); + + self } - (FnKind::AssocTraitImpl, FnKind::AssocTrait) => build_predicates( - tcx, - sig_id, - Some(tcx.parent(def_id.into())), - InheritanceKind::Own, - args, - ), + fn with_preds( + mut self, + f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy, + def_id: DefId, + ) -> Self { + let preds = f(def_id); + if let Some(parent_def_id) = preds.parent { + self = self.with_own_preds(f, parent_def_id); + } - (FnKind::AssocInherentImpl, FnKind::AssocTrait) - | (FnKind::AssocTrait, FnKind::AssocTrait) - | (FnKind::AssocInherentImpl, FnKind::Free) - | (FnKind::AssocTrait, FnKind::Free) => build_predicates( - tcx, - sig_id, - Some(tcx.parent(def_id.into())), - InheritanceKind::WithParent(false), - args, - ), + self.with_own_preds(f, def_id) + } + } - // For trait impl's `sig_id` is always equal to the corresponding trait method. - // For inherent methods delegation is not yet supported. - (FnKind::AssocTraitImpl, _) - | (_, FnKind::AssocTraitImpl) - | (_, FnKind::AssocInherentImpl) => unreachable!(), + let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args); + let collector = PredicatesCollector::new(tcx, args, folder); + + 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. + // Note: `predicates_of` query can also add inferred outlives predicates, but that + // is not the case here as `sig_id` is either a trait or a function. + let preds = match inh_kind { + InheritanceKind::WithParent(false) => { + collector.with_preds(|def_id| tcx.explicit_predicates_of(def_id), sig_id) + } + InheritanceKind::WithParent(true) => { + collector.with_preds(|def_id| tcx.predicates_of(def_id), sig_id) + } + InheritanceKind::Own => { + collector.with_own_preds(|def_id| tcx.predicates_of(def_id), sig_id) + } } + .preds; + + ty::GenericPredicates { parent, predicates: tcx.arena.alloc_from_iter(preds) } +} + +fn create_folder_and_args<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + sig_id: DefId, + parent_args: &'tcx [ty::GenericArg<'tcx>], + child_args: &'tcx [ty::GenericArg<'tcx>], +) -> (ParamIndexRemapper<'tcx>, Vec>) { + let args = create_generic_args(tcx, sig_id, def_id, parent_args, child_args); + let remap_table = create_mapping(tcx, sig_id, def_id, &args); + + (ParamIndexRemapper { tcx, remap_table }, args) } fn check_constraints<'tcx>( @@ -410,20 +584,23 @@ fn check_constraints<'tcx>( pub(crate) fn inherit_sig_for_delegation_item<'tcx>( tcx: TyCtxt<'tcx>, - def_id: LocalDefId, + input: (LocalDefId, &'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]), ) -> &'tcx [Ty<'tcx>] { - let sig_id = tcx.hir_opt_delegation_sig_id(def_id).unwrap(); + let (def_id, parent_args, child_args) = input; + + let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("Delegation must have sig_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 (mut folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args); + let caller_sig = EarlyBinder::bind(caller_sig.skip_binder().fold_with(&mut folder)); + + let sig = caller_sig.instantiate(tcx, args.as_slice()).skip_binder(); let sig_iter = sig.inputs().iter().cloned().chain(std::iter::once(sig.output())); tcx.arena.alloc_from_iter(sig_iter) } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 9f84f652698b4..e25968f58a4c0 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -31,7 +31,7 @@ use rustc_errors::{ use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId, find_attr}; +use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId, PathSegment, find_attr}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::DynCompatibilityViolation; use rustc_macros::{TypeFoldable, TypeVisitable}; @@ -53,6 +53,7 @@ use tracing::{debug, instrument}; use crate::check::check_abi; use crate::check_c_variadic_abi; +use crate::delegation::get_delegation_self_ty; use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; @@ -321,7 +322,7 @@ pub enum IsMethodCall { /// Denotes the "position" of a generic argument, indicating if it is a generic type, /// generic function or generic method call. -#[derive(Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq)] pub(crate) enum GenericArgPosition { Type, Value, // e.g., functions @@ -547,7 +548,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { def_id: DefId, item_segment: &hir::PathSegment<'tcx>, ) -> GenericArgsRef<'tcx> { - let (args, _) = self.lower_generic_args_of_path(span, def_id, &[], item_segment, None); + let (args, _) = self.lower_generic_args_of_path( + span, + def_id, + &[], + item_segment, + None, + GenericArgPosition::Type, + ); if let Some(c) = item_segment.args().constraints.first() { prohibit_assoc_item_constraint(self, c, Some((def_id, item_segment, span))); } @@ -596,6 +604,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { parent_args: &[ty::GenericArg<'tcx>], segment: &hir::PathSegment<'tcx>, self_ty: Option>, + pos: GenericArgPosition, ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, @@ -618,14 +627,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { assert!(self_ty.is_none()); } - let arg_count = check_generic_arg_count( - self, - def_id, - segment, - generics, - GenericArgPosition::Type, - self_ty.is_some(), - ); + let arg_count = + check_generic_arg_count(self, def_id, segment, generics, pos, self_ty.is_some()); // Skip processing if type has no generic parameters. // Traits always have `Self` as a generic parameter, which means they will not return early @@ -788,6 +791,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { infer_args: segment.infer_args, incorrect_args: &arg_count.correct, }; + let args = lower_generic_args( self, def_id, @@ -809,8 +813,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { item_segment: &hir::PathSegment<'tcx>, parent_args: GenericArgsRef<'tcx>, ) -> GenericArgsRef<'tcx> { - let (args, _) = - self.lower_generic_args_of_path(span, item_def_id, parent_args, item_segment, None); + let (args, _) = self.lower_generic_args_of_path( + span, + item_def_id, + parent_args, + item_segment, + None, + GenericArgPosition::Type, + ); if let Some(c) = item_segment.args().constraints.first() { prohibit_assoc_item_constraint(self, c, Some((item_def_id, item_segment, span))); } @@ -922,6 +932,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &[], segment, Some(self_ty), + GenericArgPosition::Type, ); let constraints = segment.args().constraints; @@ -1097,8 +1108,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> ty::TraitRef<'tcx> { self.report_internal_fn_trait(span, trait_def_id, trait_segment, is_impl); - let (generic_args, _) = - self.lower_generic_args_of_path(span, trait_def_id, &[], trait_segment, Some(self_ty)); + let (generic_args, _) = self.lower_generic_args_of_path( + span, + trait_def_id, + &[], + trait_segment, + Some(self_ty), + GenericArgPosition::Type, + ); if let Some(c) = trait_segment.args().constraints.first() { prohibit_assoc_item_constraint(self, c, Some((trait_def_id, trait_segment, span))); } @@ -2844,11 +2861,92 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .map(|l| tcx.at(expr.span).lit_to_const(l)) } - fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> { - let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id()); + // Creates user-specified generic arguments from delegation path, + // they will be used during delegation signature and predicates inheritance. + // Example: reuse Trait::<'static, i32, 1>::foo:: + // we want to extract [Self, 'static, i32, 1] for parent and [A, B] for child. + pub fn get_delegation_user_specified_args( + &self, + ) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) { + let info = self + .tcx() + .hir_node(self.tcx().local_def_id_to_hir_id(self.item_def_id())) + .fn_sig() + .expect("Lowering delegation") + .decl + .opt_delegation_generics_info() + .expect("Lowering delegation"); + + let get_segment = |hir_id: Option| -> Option<(&'tcx PathSegment<'tcx>, DefId)> { + hir_id.map(|hir_id| { + let segment = self.tcx().hir_node(hir_id).expect_path_segment(); + let def_id = segment.res.def_id(); + + (segment, def_id) + }) + }; + + let parent_args = get_segment(info.parent_args_segment_id).map(|(segment, def_id)| { + let self_ty = get_delegation_self_ty(self.tcx(), self.item_def_id()); + + // FIXME(fn_delegation): execute this call with silenced dcx, as now warnings are duplicated, remove + // diagnostics deduplication in `free-fn-to-trait-infer.rs` and `generics-gen-args-errors.rs`. + self.lower_generic_args_of_path( + segment.ident.span, + def_id, + &[], + segment, + self_ty, + GenericArgPosition::Type, + ) + .0 + .as_slice() + }); + + let child_args = get_segment(info.child_args_segment_id).map(|(segment, def_id)| { + let parent_args = if let Some(parent_args) = parent_args { + parent_args + } else { + if let Some(parent) = self.tcx().opt_parent(def_id) + && matches!(self.tcx().def_kind(parent), DefKind::Trait) + { + ty::GenericArgs::identity_for_item(self.tcx(), parent).as_slice() + } else { + &[] + } + }; + + // FIXME(fn_delegation): execute this call with silenced dcx, as now warnings are duplicated, remove + // diagnostics deduplication in `free-fn-to-trait-infer.rs` and `generics-gen-args-errors.rs`. + let args = self + .lower_generic_args_of_path( + segment.ident.span, + def_id, + parent_args, + segment, + None, + GenericArgPosition::Value, + ) + .0; + + &args[parent_args.len()..] + }); + + (parent_args.unwrap_or(&[]), child_args.unwrap_or(&[])) + } + + fn lower_delegation_ty(&self, idx: hir::InferDelegationKind<'tcx>) -> Ty<'tcx> { + let (parent_args, child_args) = self.get_delegation_user_specified_args(); + + let delegation_sig = self.tcx().inherit_sig_for_delegation_item(( + self.item_def_id(), + parent_args, + child_args, + )); + match idx { hir::InferDelegationKind::Input(idx) => delegation_sig[idx], - hir::InferDelegationKind::Output => *delegation_sig.last().unwrap(), + hir::InferDelegationKind::Output { .. } => *delegation_sig.last().unwrap(), } } diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index ca8e5e90318da..7d2518d4c1914 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2097,7 +2097,7 @@ 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>] { + query inherit_sig_for_delegation_item(key: (LocalDefId, &'tcx [GenericArg<'tcx>], &'tcx [GenericArg<'tcx>])) -> &'tcx [Ty<'tcx>] { desc { "inheriting delegation signature" } } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index cccb7d51bd3ed..097b4b800e043 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -380,3 +380,11 @@ impl<'tcx> Key for (ty::Instance<'tcx>, CollectionMode) { self.0.default_span(tcx) } } + +impl<'tcx> Key for (LocalDefId, &'tcx [GenericArg<'tcx>], &'tcx [GenericArg<'tcx>]) { + type Cache = DefaultCache; + + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.0.default_span(tcx) + } +} diff --git a/tests/pretty/delegation-inherit-attributes.pp b/tests/pretty/delegation-inherit-attributes.pp index 9d51a80da7b98..c31f1cae57126 100644 --- a/tests/pretty/delegation-inherit-attributes.pp +++ b/tests/pretty/delegation-inherit-attributes.pp @@ -114,7 +114,7 @@ #[attr = MustUse {reason: "some reason"}] #[attr = Inline(Hint)] - fn foo(self: _, arg1: _) -> _ { ::foo(self + 1, arg1) } + fn foo(self: _, arg1: _) -> _ { ::foo(self + 1, arg1) } #[attr = MustUse {reason: "some reason"}] #[attr = Inline(Hint)] fn bar(self: _, arg1: _) -> _ { foo(self + 1, arg1) } diff --git a/tests/pretty/hir-delegation.pp b/tests/pretty/hir-delegation.pp index 44a1deb750dc0..55c129dbf84d3 100644 --- a/tests/pretty/hir-delegation.pp +++ b/tests/pretty/hir-delegation.pp @@ -12,7 +12,7 @@ trait G { #[attr = Inline(Hint)] - fn b(arg0: _) -> _ { b({ }) } + fn b(arg0: _) -> _ { b::({ }) } } mod m { diff --git a/tests/ui/delegation/generics/ast-hir-engine/free-to-free-pass.rs b/tests/ui/delegation/generics/ast-hir-engine/free-to-free-pass.rs new file mode 100644 index 0000000000000..9c98979c0d5dd --- /dev/null +++ b/tests/ui/delegation/generics/ast-hir-engine/free-to-free-pass.rs @@ -0,0 +1,111 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![allow(warnings)] + +mod free_to_free { + mod test_1 { + fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + + pub fn check() { + reuse foo as bar; + bar::(); + } + } + + mod test_2 { + fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + + pub fn check() { + reuse foo as bar; + bar::(); + } + } + + mod test_3 { + fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + + pub fn check() { + reuse foo as bar; + bar::(); + } + } + + mod test_4 { + fn foo<'a, 'b, T: Clone, U: Clone, const N: usize>(_t: &'a T, _u: &'b U) {} + + pub fn check() { + reuse foo as bar; + bar::(&1, &2); + } + } + + mod test_5 { + fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} + + pub fn check() { + reuse foo as bar; + bar::(&1, &2); + } + } + + mod test_6 { + fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} + + pub fn check() { + reuse foo:: as bar; + bar(&"".to_string(), &"".to_string()); + } + } + + // FIXME(fn_delegation): Uncomment this test when impl Traits in function params are supported + + // mod test_7 { + // fn foo(f: impl FnOnce(T, U) -> U) { + + // } + + // pub fn check() { + // reuse foo as bar; + // bar::(|x, y| y); + // } + // } + + mod test_8 { + pub fn check() { + fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} + + reuse foo:: as bar; + bar(&"".to_string(), &"".to_string()); + } + } + + mod test_9 { + pub fn check() { + let closure = || { + fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} + + reuse foo:: as bar; + bar(&"".to_string(), &"".to_string()); + }; + + closure(); + } + } + + pub fn check() { + test_1::check(); + test_2::check::(); + test_3::check::(); + test_4::check::(); + test_5::check::(); + test_6::check::(); + //test_7::check(); + test_8::check::(); + test_9::check::(); + } +} + +fn main() { + free_to_free::check(); +} diff --git a/tests/ui/delegation/generics/ast-hir-engine/free-to-trait-pass.rs b/tests/ui/delegation/generics/ast-hir-engine/free-to-trait-pass.rs new file mode 100644 index 0000000000000..7bfaf77dd2a72 --- /dev/null +++ b/tests/ui/delegation/generics/ast-hir-engine/free-to-trait-pass.rs @@ -0,0 +1,225 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![allow(warnings)] + +mod free_to_trait { + mod test_1 { + trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + fn foo<'d: 'd, U, const M: bool>(self) {} + } + + impl Trait<'static, 'static, 'static, i32, 1> for u8 {} + + pub fn check() { + fn no_ctx() { + reuse Trait::foo as bar; + bar::<'static, 'static, 'static, 'static, u8, i32, 1, String, true>(123); + } + + fn with_ctx<'a, 'b, 'c, A, B, C, const N: usize, const M: bool>() { + reuse Trait::foo as bar; + bar::<'static, 'static, 'static, 'a, u8, i32, 1, A, M>(123); + } + + no_ctx(); + with_ctx::(); + } + } + + mod test_2 { + trait Trait<'a, T, const N: usize>: Sized { + fn foo<'b: 'b, U, const M: bool>(self) {} + } + + impl Trait<'static, i32, 1> for u8 {} + + pub fn check() { + reuse Trait::<'static, i32, 1>::foo as bar; + + bar::<'static, u8, String, true>(123); + } + } + + mod test_3 { + trait Trait<'a, T, const N: usize>: Sized { + fn foo<'b: 'b, U, const M: bool>(self) {} + } + + impl Trait<'static, String, 1> for u8 {} + + pub fn check() { + reuse Trait::foo::<'static, i32, true> as bar; + + bar::<'static, u8, String, 1>(123); + } + } + + mod test_4 { + trait Trait: Sized { + fn foo<'b: 'b, U, const M: bool>(self) {} + } + + impl Trait for u8 {} + + pub fn check() { + reuse Trait::foo::<'static, i32, true> as bar; + + bar::(123); + } + } + + mod test_5 { + trait Trait: Sized { + fn foo<'b: 'b, U, const M: bool>(self) {} + } + + impl Trait<1> for u8 {} + + pub fn check() { + reuse Trait::foo::<'static, i32, true> as bar; + + bar::(123); + } + } + + mod test_6 { + trait Trait: Sized { + fn foo<'b: 'b, U, const M: bool>(self) {} + } + + impl Trait for u8 {} + + pub fn check() { + reuse Trait::foo::<'static, i32, true> as bar; + + bar::(123); + } + } + + mod test_7 { + trait Trait<'a, T, const N: usize>: Sized { + fn foo(self) {} + } + + impl Trait<'static, i32, 1> for u8 {} + + pub fn check() { + reuse Trait::<'static, i32, 1>::foo as bar; + + bar::(123); + } + } + + mod test_8 { + trait Trait<'a, T, const N: usize>: Sized { + fn foo(self) {} + } + + impl Trait<'static, i32, 1> for u8 {} + + pub fn check() { + reuse Trait::<'static, i32, 1>::foo as bar; + + bar::(123); + } + } + + mod test_9 { + trait Trait<'a, T, const N: usize>: Sized { + fn foo(self) {} + } + + impl Trait<'static, i32, 1> for u8 {} + + pub fn check() { + reuse Trait::<'static, i32, 1>::foo as bar; + + bar::(123); + } + } + + mod test_10 { + trait Trait<'b, 'c, T> { + fn foo<'d: 'd, U, const M: bool>() {} + } + + 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 ::foo as bar; + bar::<'a, 'b, 'c, u8, C, A, M>(); + bar::<'static, 'static, 'static, u8, i32, i32, false>(); + + reuse >::foo as bar1; + bar1::<'static, u8, i32, true>(); + + reuse >::foo::<'static, u32, true> as bar2; + bar2::(); + } + + with_ctx::(); + } + } + + mod test_11 { + trait Bound0 {} + trait Bound1 {} + trait Bound2 {} + + trait Trait<'a: 'static, T, P> + where + Self: Sized, + T: Bound0, + P: Bound2>>>, + { + fn foo<'d: 'd, U: Bound1, const M: bool>() {} + } + + impl Bound0 for u32 {} + impl Bound1 for String {} + impl<'a: 'static, T: Bound0, P: Bound2>>>> Trait<'a, T, P> for usize {} + + struct Struct; + impl Bound2>>> for Struct {} + + pub fn check<'b>() { + reuse ::foo; + foo::<'static, 'b, usize, u32, Struct, String, false>(); + } + } + + mod test_12 { + trait Trait<'a, T = usize, const N: usize = 123>: Sized { + fn foo(self) {} + } + + impl Trait<'static, i32, 1> for u8 {} + + pub fn check() { + reuse Trait::foo as bar; + + bar::(123); + } + } + + pub fn check() { + test_1::check(); + test_2::check(); + test_3::check(); + test_4::check(); + test_5::check(); + test_6::check(); + test_7::check(); + test_8::check(); + test_9::check(); + test_10::check(); + test_11::check(); + test_12::check(); + } +} + +fn main() { + free_to_trait::check(); +} diff --git a/tests/ui/delegation/generics/ast-hir-engine/impl-trait-to-free.rs b/tests/ui/delegation/generics/ast-hir-engine/impl-trait-to-free.rs new file mode 100644 index 0000000000000..0a09fb34b2d28 --- /dev/null +++ b/tests/ui/delegation/generics/ast-hir-engine/impl-trait-to-free.rs @@ -0,0 +1,238 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![allow(warnings)] + +mod test_1 { + mod to_reuse { + pub fn foo<'a: 'a, 'b: 'b, A, B, const N: usize>() {} + pub fn bar<'a: 'a, 'b: 'b, A, B, const N: usize>(x: &super::XX) {} + } + + trait Trait<'a, 'b, 'c, A, B, const N: usize>: Sized { + fn foo<'x: 'x, 'y: 'y, AA, BB, const NN: usize>() {} + fn bar<'x: 'x, 'y: 'y, AA, BB, const NN: usize>(&self) {} + fn oof() {} + fn rab(&self) {} + } + + struct X<'x1, 'x2, 'x3, 'x4, X1, X2, const X3: usize>( + &'x1 X1, &'x2 X2, &'x3 X1, &'x4 [usize; X3]); + type XX = X::<'static, 'static, 'static, 'static, i32, i32, 3>; + + impl<'a, 'b, 'c, A, B, const N: usize> Trait<'a, 'b, 'c, A, B, N> for XX { + reuse to_reuse::foo; + reuse to_reuse::bar; + + reuse to_reuse::foo::<'a, 'c, A, String, 322> as oof; + reuse to_reuse::bar::<'a, 'c, i32, B, 223> as rab; + } + + pub fn check() { + let x = X(&1, &2, &3, &[1, 2, 3]); + + > + ::foo::<'static, 'static, i8, i16, 123>(); + > + ::bar::<'static, 'static, String, i16, 123>(&x); + >::oof(); + >::rab(&x); + } +} + +mod test_2 { + mod to_reuse { + pub fn foo() {} + pub fn bar(x: &super::X) {} + } + + trait Trait<'a, 'b, 'c, A, B, const N: usize>: Sized { + fn foo() {} + fn bar(&self) {} + fn oof() {} + fn rab(&self) {} + } + + struct X; + impl<'a, A, B, const N: usize> Trait<'a, 'static, 'static, A, B, N> for X { + reuse to_reuse::foo; + reuse to_reuse::bar; + + reuse to_reuse::foo:: as oof; + reuse to_reuse::bar:: as rab; + } + + pub fn check() { + >::foo::(); + >::bar::(&X); + >::oof(); + >::rab(&X); + } +} + +mod test_3 { + mod to_reuse { + pub fn foo() {} + pub fn bar(x: &super::X) {} + } + + trait Trait<'a, 'b, 'c, A, B, const N: usize>: Sized { + fn foo() {} + fn bar(&self) {} + } + + struct X; + impl<'a, A, B, const N: usize> Trait<'a, 'static, 'static, A, B, N> for X { + reuse to_reuse::foo; + reuse to_reuse::bar; + } + + pub fn check() { + >::foo(); + >::bar(&X); + } +} + +mod test_4 { + mod to_reuse { + pub fn foo<'a: 'a, 'b: 'b, A, B, const N: usize>() {} + pub fn bar<'a: 'a, 'b: 'b, A, B, const N: usize>(x: &super::X) {} + } + + trait Trait: Sized { + fn foo<'x: 'x, 'y: 'y, AA, BB, const NN: usize>() {} + fn bar<'x: 'x, 'y: 'y, AA, BB, const NN: usize>(&self) {} + fn oof() {} + fn rab(&self) {} + } + + struct X; + impl<'a, 'c, A, B, const N: usize> Trait for X { + reuse to_reuse::foo; + reuse to_reuse::bar; + + reuse to_reuse::foo::<'a, 'c, A, String, 322> as oof; + reuse to_reuse::bar::<'a, 'c, i32, B, 223> as rab; + } + + pub fn check() { + >::foo::<'static, 'static, i8, i16, 123>(); + >::bar::<'static, 'static, X, i16, 123>(&X); + >::oof(); + >::rab(&X); + } +} + +mod test_5 { + mod to_reuse { + pub fn foo<'a: 'a, 'b: 'b, A, B, const N: usize>() {} + pub fn bar<'a: 'a, 'b: 'b, A, B, const N: usize>(x: &super::X::) {} + } + + trait Trait: Sized { + fn foo<'x: 'x, 'y: 'y, AA, BB, const NN: usize>() {} + fn bar<'x: 'x, 'y: 'y, AA, BB, const NN: usize>(&self) {} + fn oof() {} + fn rab(&self) {} + } + + struct X(A, B); + impl<'a, 'c, A, B> Trait for X { + reuse to_reuse::foo::<'a, 'c, A, B, 322> as oof; + reuse to_reuse::bar::<'a, 'c, A, B, 223> as rab; + } + + pub fn check() { + as Trait>::oof(); + as Trait>::rab(&X(1, 2)); + } +} + +mod test_6 { + mod to_reuse { + pub fn foo() {} + pub fn bar(x: &super::X) {} + } + + trait Trait: Sized { + fn foo() {} + fn bar(&self) {} + fn oof() {} + fn rab(&self) {} + } + + struct X; + impl<'a, 'c, A, B, const N: usize> Trait for X { + reuse to_reuse::foo; + reuse to_reuse::bar; + + reuse to_reuse::foo:: as oof; + reuse to_reuse::bar:: as rab; + } + + pub fn check() { + >::foo::(); + >::bar::(&X); + >::oof(); + >::rab(&X); + } +} + +mod test_7 { + mod to_reuse { + pub fn foo() {} + pub fn bar(x: &super::X) {} + } + + trait Trait: Sized { + fn foo() {} + fn bar(&self) {} + } + + struct X; + impl<'a, 'c, A, B, const N: usize> Trait for X { + reuse to_reuse::foo; + reuse to_reuse::bar; + } + + pub fn check() { + >::foo(); + >::bar(&X); + } +} + +mod test_8 { + mod to_reuse { + pub fn foo() {} + pub fn bar(x: &super::X) {} + } + + trait Trait: Sized { + fn foo() {} + fn bar(&self) {} + } + + struct X; + impl Trait for X { + reuse to_reuse::foo; + reuse to_reuse::bar; + } + + pub fn check() { + ::foo(); + ::bar(&X); + X::foo(); + X::bar(&X); + } +} + +fn main() { + test_1::check(); + test_2::check(); + test_3::check(); + test_4::check(); + test_5::check(); + test_6::check(); + test_7::check(); + test_8::check(); +} diff --git a/tests/ui/delegation/generics/ast-hir-engine/impl-trait-to-trait.rs b/tests/ui/delegation/generics/ast-hir-engine/impl-trait-to-trait.rs new file mode 100644 index 0000000000000..118890fb86384 --- /dev/null +++ b/tests/ui/delegation/generics/ast-hir-engine/impl-trait-to-trait.rs @@ -0,0 +1,214 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![allow(warnings)] + +mod test_1 { + trait Trait0 {} + + trait Trait1 { + fn foo(&self) + where + T: Trait0, + U: Trait0, + { + } + } + + struct F; + impl Trait1 for F {} + + struct S<'a, 'b, 'c, A, B>(F, &'a A, &'b B, &'c B); + + impl<'a, 'b, 'c, T, A, B> Trait1 for S<'a, 'b, 'c, A, B> { + reuse Trait1::::foo { &self.0 } + } + + impl Trait0 for u16 {} + + pub fn check() { + let s = S(F, &123, &123, &123); + as Trait1>::foo::(&s); + } +} + +mod test_2 { + trait Trait { + fn foo(&self) {} + } + + struct F; + impl Trait for F {} + + struct S<'a, 'b, 'c, A, B, const C: bool>(F, &'a A, &'b B, &'c B); + + impl<'a, 'b, 'c, A, B, const C: bool> Trait for S<'a, 'b, 'c, A, B, C> { + reuse Trait::foo { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + as Trait>::foo(&s); + } +} + +mod test_3 { + trait Trait<'a, 'b, 'c, X, Y, Z> { + fn foo(&self) {} + } + + struct F; + impl<'a, 'b, 'c, X, Y, Z> Trait<'a, 'b, 'c, X, Y, Z> for F {} + + struct S<'a, 'b, 'c, A, B, const C: bool>(F, &'a A, &'b B, &'c B); + + impl<'a, 'b, 'c, A, B, const C: bool> Trait<'a, 'b, 'static, A, String, bool> + for S<'a, 'b, 'c, A, B, C> { + reuse Trait::<'a, 'b, 'static, A, String, bool>::foo { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + + as Trait<'static, 'static, 'static, i32, String, bool>>::foo(&s); + } +} + +mod test_4 { + trait Trait<'a, 'b, 'c, X, Y, Z> { + fn foo<'x: 'x, 'y: 'y, 'z: 'z, A, B, C, const XX: usize>(&self) {} + } + + struct F; + impl<'a, 'b, 'c, X, Y, Z> Trait<'a, 'b, 'c, X, Y, Z> for F {} + + struct S<'a, 'b, 'c, A, B, const C: bool>(F, &'a A, &'b B, &'c B); + + impl<'a, 'b, 'c, A, B, const C: bool> Trait<'a, 'b, 'static, A, String, bool> + for S<'a, 'b, 'c, A, B, C> { + reuse Trait::<'a, 'b, 'static, A, String, bool>::foo { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + + as Trait<'static, 'static, 'static, i32, String, bool>> + ::foo::<'static, 'static, 'static, i32, i32, i32, 1>(&s); + } +} + +mod test_5 { + trait Trait { + fn foo<'a: 'a, 'b: 'b, 'c: 'c>(&self) {} + } + + struct F; + impl Trait for F {} + + struct S<'a, 'b, 'c, A, B, const C: bool>(F, &'a A, &'b B, &'c B); + + impl<'a, 'b, 'c, A, B, const C: bool> Trait for S<'a, 'b, 'c, A, B, C> { + reuse Trait::::foo { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + as Trait> + ::foo::<'static, 'static, 'static>(&s); + as Trait>::foo(&s); + } +} + +mod test_6 { + trait Trait { + fn foo(&self) {} + } + + struct F; + impl Trait for F {} + + struct S<'a, 'b, 'c, A, B, const C: bool>(F, &'a A, &'b B, &'c B); + + impl<'a, 'b, 'c, A, B, const C: bool> Trait for S<'a, 'b, 'c, A, B, C> { + reuse Trait::::foo { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + as Trait>::foo::(&s); + } +} + +mod test_7 { + trait Trait { + fn foo(&self) {} + } + + struct F; + impl Trait for F {} + + struct S<'a, 'b, 'c, A, B, const C: bool>(F, &'a A, &'b B, &'c B); + + impl<'a, 'b, 'c, A, B, const C: bool> Trait for S<'a, 'b, 'c, A, B, C> { + reuse Trait::::foo { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + as Trait>::foo(&s); + } +} + +mod test_8 { + trait Trait<'a, 'b, 'c> { + fn foo(&self) {} + } + + struct F; + impl<'a, 'b, 'c> Trait<'a, 'b, 'c> for F {} + + struct S<'a, 'b, 'c, A, B, const C: bool>(F, &'a A, &'b B, &'c B); + + impl<'a, 'b, 'c, A, B, const C: bool> Trait<'a, 'b, 'c> for S<'a, 'b, 'c, A, B, C> { + reuse Trait::<'a, 'static, 'b>::foo { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + as Trait<'static, 'static, 'static>>::foo(&s); + } +} + +mod test_9 { + trait Trait<'a, 'b, 'c> { + fn foo<'x: 'x, 'y: 'y>(&self) {} + } + + struct F; + impl<'a, 'b, 'c> Trait<'a, 'b, 'c> for F {} + + struct S<'a, 'b, 'c, A, B, const C: bool>(F, &'a A, &'b B, &'c B); + + impl<'a, 'b, 'c, A, B, const C: bool> Trait<'a, 'b, 'c> for S<'a, 'b, 'c, A, B, C> { + reuse Trait::<'a, 'static, 'b>::foo { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + as Trait<'static, 'static, 'static>>::foo(&s); + as Trait<'static, 'static, 'static>> + ::foo::<'static, 'static>(&s); + } +} + +fn main() { + test_1::check(); + test_2::check(); + test_3::check(); + test_4::check(); + test_5::check(); + test_6::check(); + test_7::check(); + test_8::check(); + test_9::check(); +} diff --git a/tests/ui/delegation/generics/ast-hir-engine/inherent-impl-to-free.rs b/tests/ui/delegation/generics/ast-hir-engine/inherent-impl-to-free.rs new file mode 100644 index 0000000000000..920aa3727df91 --- /dev/null +++ b/tests/ui/delegation/generics/ast-hir-engine/inherent-impl-to-free.rs @@ -0,0 +1,106 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![allow(warnings)] + +mod test_1 { + mod to_reuse { + pub fn foo<'a: 'a, 'b: 'b, A, B, const N: usize>() {} + } + + struct X1<'a, 'b, T, X, const N: usize>(&'a T, &'b X, &'a [i32; N]); + impl<'a, 'b, T, E, const N: usize> X1<'a, 'b, T, E, N> { + reuse to_reuse::foo; + reuse to_reuse::foo::<'static, 'static, i32, String, 1> as bar; + } + + struct X2(T, X, &'static [i32; N]); + impl X2 { + reuse to_reuse::foo; + reuse to_reuse::foo::<'static, 'static, i32, String, 1> as bar; + } + + struct X3; + impl X3 { + reuse to_reuse::foo; + reuse to_reuse::foo::<'static, 'static, i32, String, 1> as bar; + } + + pub fn check() { + X1::<'static, 'static, i32, i32, 1> + ::foo::<'static, 'static, String, String, 123>(); + X1::<'static, 'static, i32, i32, 1>::bar(); + + X2::::foo::<'static, 'static, String, String, 123>(); + X2::::bar(); + + X3::foo::<'static, 'static, String, String, 123>(); + X3::bar(); + } +} + +mod test_2 { + fn foo() {} + + struct X1<'a, 'b, T, X, const N: usize>(&'a T, &'b X, &'a [i32; N]); + impl<'a, 'b, T, E, const N: usize> X1<'a, 'b, T, E, N> { + reuse foo; + reuse foo:: as bar; + } + + struct X2(T, X, &'static [i32; N]); + impl X2 { + reuse foo; + reuse foo:: as bar; + } + + struct X3; + impl X3 { + reuse foo; + reuse foo:: as bar; + } + + pub fn check() { + X1::<'static, 'static, i32, i32, 1>::foo::(); + X1::<'static, 'static, i32, i32, 1>::bar(); + + X2::::foo::(); + X2::::bar(); + + X3::foo::(); + X3::bar(); + } +} + +mod test_3 { + fn foo() {} + + struct X1<'a, 'b, T, X, const N: usize>(&'a T, &'b X, &'a [i32; N]); + impl<'a, 'b, T, E, const N: usize> X1<'a, 'b, T, E, N> { + reuse foo; + } + + struct X2(T, X, &'static [i32; N]); + impl X2 { + reuse foo; + } + + struct X3; + impl X3 { + reuse foo; + } + + pub fn check() { + X1::<'static, 'static, i32, i32, 1>::foo(); + + X2::::foo(); + + X3::foo(); + } +} + +fn main() { + test_1::check(); + test_2::check(); + test_3::check(); +} diff --git a/tests/ui/delegation/generics/ast-hir-engine/inherent-impl-to-trait.rs b/tests/ui/delegation/generics/ast-hir-engine/inherent-impl-to-trait.rs new file mode 100644 index 0000000000000..156f000cb58a0 --- /dev/null +++ b/tests/ui/delegation/generics/ast-hir-engine/inherent-impl-to-trait.rs @@ -0,0 +1,196 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![allow(warnings)] + +mod test_1 { + trait Trait { + fn foo(&self) {} + } + + struct F; + impl Trait for F {} + + struct S<'a, 'b, 'c, A, B>(F, &'a A, &'b B, &'c B); + impl<'a, 'b, 'c, A, B> S<'a, 'b, 'c, A, B> { + reuse Trait::::foo { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + S::<'static, 'static, 'static, i32, i32>::foo(&s); + s.foo(); + } +} + +mod test_2 { + trait Trait<'x, 'y, T, const B: bool> { + fn foo(&self) {} + } + + struct F; + impl<'x, 'y, T, const B: bool> Trait<'x, 'y, T, B> for F {} + + struct S<'a, 'b, 'c, A, B>(F, &'a A, &'b B, &'c B); + impl<'a, 'b, 'c, A, B> S<'a, 'b, 'c, A, B> { + reuse Trait::<'a, 'b, String, true>::foo { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + S::<'static, 'static, 'static, i32, i32>::foo(&s); + s.foo(); + } +} + +mod test_3 { + trait Trait<'x, 'y> { + fn foo(&self) {} + } + + struct F; + impl<'x, 'y> Trait<'x, 'y> for F {} + + struct S<'a, 'b, 'c, A, B>(F, &'a A, &'b B, &'c B); + impl<'a, 'b, 'c, A, B> S<'a, 'b, 'c, A, B> { + reuse Trait::<'a, 'b>::foo { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + S::<'static, 'static, 'static, i32, i32>::foo(&s); + s.foo(); + } +} + +mod test_4 { + trait Trait { + fn foo(&self) {} + } + + struct F; + impl Trait for F {} + + struct S<'a, 'b, 'c, A, B>(F, &'a A, &'b B, &'c B); + impl<'a, 'b, 'c, A, B> S<'a, 'b, 'c, A, B> { + reuse Trait::foo { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + S::<'static, 'static, 'static, i32, i32>::foo(&s); + s.foo(); + } +} + +mod test_5 { + trait Trait { + fn foo<'a: 'a, 'b: 'b>(&self) {} + } + + struct F; + impl Trait for F {} + + struct S<'a, 'b, 'c, A, B>(F, &'a A, &'b B, &'c B); + impl<'a, 'b, 'c, A, B> S<'a, 'b, 'c, A, B> { + reuse Trait::foo::<'a, 'b> { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + S::<'static, 'static, 'static, i32, i32>::foo(&s); + s.foo(); + } +} + +mod test_6 { + trait Trait { + fn foo<'a: 'a, 'b: 'b, A, B, C>(&self) {} + } + + struct F; + impl Trait for F {} + + struct S<'a, 'b, 'c, A, B>(F, &'a A, &'b B, &'c B); + impl<'a, 'b, 'c, A, B> S<'a, 'b, 'c, A, B> { + reuse Trait::foo::<'a, 'b, A, B, String> { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + S::<'static, 'static, 'static, i32, i32>::foo(&s); + s.foo(); + } +} + +mod test_7 { + trait Trait<'x, 'y, 'z> { + fn foo<'a: 'a, 'b: 'b, A, B, C>(&self) {} + } + + struct F; + impl<'a, 'b, 'c> Trait<'a, 'b, 'c> for F {} + + struct S<'a, 'b, 'c, A, B>(F, &'a A, &'b B, &'c B); + impl<'a, 'b, 'c, A, B> S<'a, 'b, 'c, A, B> { + reuse Trait::<'a, 'b, 'c>::foo::<'a, 'b, A, B, String> { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + S::<'static, 'static, 'static, i32, i32>::foo(&s); + s.foo(); + } +} + +mod test_8 { + trait Trait<'x, 'y, 'z, X, Y, Z> { + fn foo<'a: 'a, 'b: 'b, A, B, C>(&self) {} + } + + struct F; + impl<'a, 'b, 'c, X, Y, Z> Trait<'a, 'b, 'c, X, Y, Z> for F {} + + struct S<'a, 'b, 'c, A, B>(F, &'a A, &'b B, &'c B); + impl<'a, 'b, 'c, A, B> S<'a, 'b, 'c, A, B> { + reuse Trait::<'a, 'b, 'c, B, A, i32>::foo::<'a, 'b, A, B, String> { &self.0 } + } + + pub fn check() { + let s = S(F, &123, &123, &123); + S::<'static, 'static, 'static, i32, i32>::foo(&s); + s.foo(); + } +} + +mod test_9 { + trait Trait<'x, 'y, 'z, X, Y, Z> { + fn foo<'a: 'a, 'b: 'b, A, B, C>(&self) {} + } + + struct F; + impl<'a, 'b, 'c, X, Y, Z> Trait<'a, 'b, 'c, X, Y, Z> for F {} + + pub fn check() { + struct S<'a, 'b, 'c, A, B>(F, &'a A, &'b B, &'c B); + impl<'a, 'b, 'c, A, B> S<'a, 'b, 'c, A, B> { + reuse Trait::<'a, 'b, 'c, B, A, i32>::foo::<'a, 'b, A, B, String> { &self.0 } + } + + let s = S(F, &123, &123, &123); + S::<'static, 'static, 'static, i32, i32>::foo(&s); + s.foo(); + } +} + +pub fn main() { + test_1::check(); + test_2::check(); + test_3::check(); + test_4::check(); + test_5::check(); + test_6::check(); + test_7::check(); + test_8::check(); + test_9::check::(); +} diff --git a/tests/ui/delegation/generics/ast-hir-engine/trait-to-free-pass.rs b/tests/ui/delegation/generics/ast-hir-engine/trait-to-free-pass.rs new file mode 100644 index 0000000000000..5297d1558ed53 --- /dev/null +++ b/tests/ui/delegation/generics/ast-hir-engine/trait-to-free-pass.rs @@ -0,0 +1,116 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![allow(warnings)] + +mod test_1 { + fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + + trait Trait<'a, A, B, C, const N: usize> { + reuse foo; + reuse foo::<'static, 'static, i32, String, 1> as bar; + } + + impl Trait<'static, i32, i32, i32, 1> for u32 {} + pub fn check() { + >::foo::<'static, 'static, i32, String, 1>(); + >::bar(); + } +} + +mod test_2 { + fn foo() {} + + trait Trait<'a, A, B, C, const N: usize> { + reuse foo; + reuse foo:: as bar; + } + + impl Trait<'static, i32, i32, i32, 1> for u32 {} + pub fn check() { + >::foo::(); + >::bar(); + } +} + +mod test_3 { + fn foo() {} + + trait Trait<'a, A, B, C, const N: usize> { + reuse foo; + } + + impl Trait<'static, i32, i32, i32, 1> for u32 {} + pub fn check() { + >::foo(); + } +} + +mod test_4 { + fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + + trait Trait { + reuse foo; + reuse foo::<'static, 'static, i32, String, 1> as bar; + } + + impl Trait for u32 {} + pub fn check() { + >::foo::<'static, 'static, i32, String, 1>(); + >::bar(); + } +} + +mod test_5 { + fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + + trait Trait { + reuse foo; + reuse foo::<'static, 'static, i32, String, 1> as bar; + } + + impl Trait for u32 {} + pub fn check() { + ::foo::<'static, 'static, i32, String, 1>(); + ::bar(); + } +} + +mod test_6 { + fn foo() {} + + trait Trait { + reuse foo; + reuse foo:: as bar; + } + + impl Trait for u32 {} + pub fn check() { + ::foo::(); + ::bar(); + } +} + +mod test_7 { + fn foo() {} + + trait Trait { + reuse foo; + } + + impl Trait for u32 {} + pub fn check() { + ::foo(); + } +} + + +pub fn main() { + test_1::check(); + test_2::check(); + test_3::check(); + test_4::check(); + test_5::check(); + test_6::check(); + test_7::check(); +} diff --git a/tests/ui/delegation/generics/ast-hir-engine/trait-to-trait-pass.rs b/tests/ui/delegation/generics/ast-hir-engine/trait-to-trait-pass.rs new file mode 100644 index 0000000000000..99ad57d265f30 --- /dev/null +++ b/tests/ui/delegation/generics/ast-hir-engine/trait-to-trait-pass.rs @@ -0,0 +1,742 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![allow(warnings)] + +mod test_1 { + trait Trait<'b, 'c, 'a, T>: Sized { + fn foo<'d: 'd, U, const M: bool>(&self) {} + } + + impl<'b, 'c, 'a, T> Trait<'b, 'c, 'a, T> for u8 {} + + trait Trait2<'a, 'b, 'c, X, Y, Z> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo::<'static, String, false> as bar2 { + Self::get() + } + + reuse Trait::<'static, 'static, 'static, i32>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static, i32>::foo::<'static, String, false> + as bar4 { self.get_self() } + + // FIXME(fn_delegation): Uncomment those tests when proper support for + // generics when method call is generated is added + + // reuse Trait::foo::<'static, String, false> as bar5 { Self::get() } + // reuse Trait::foo as bar6 { Self::get() } + // reuse Trait::foo::<'static, String, false> as bar7 { self.get_self() } + // reuse Trait::foo as bar8 { self.get_self() } + } + + trait Trait3 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo::<'static, String, false> + as bar2 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static, i32>::foo::<'static, String, false> + as bar4 { self.get_self() } + } + + trait Trait4<'a, 'b, 'c> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo::<'static, String, false> + as bar2 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static, i32>::foo::<'static, String, false> + as bar4 { self.get_self() } + } + + trait Trait5 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo::<'static, String, false> + as bar2 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static, i32>::foo::<'static, String, false> + as bar4 { self.get_self() } + } + + impl<'a, 'b, 'c, X, Y, Z> Trait2<'a, 'b, 'c, X, Y, Z> for u32 {} + impl Trait3 for u32 {} + impl<'a, 'b, 'c> Trait4<'a, 'b, 'c> for u32 {} + impl Trait5 for u32 {} + + pub fn check<'a: 'a>() { + > + ::bar1::<'static, String, true>(&123); + ::bar1::<'static, String, true>(&123); + >::bar1::<'static, String, true>(&123); + >::bar1::<'static, String, true>(&123); + + >::bar2(&123); + ::bar2(&123); + >::bar2(&123); + >::bar2(&123); + + > + ::bar3::<'static, String, true>(&123); + ::bar3::<'static, String, true>(&123); + >::bar3::<'static, String, true>(&123); + >::bar3::<'static, String, true>(&123); + + >::bar4(&123); + ::bar4(&123); + >::bar4(&123); + >::bar4(&123); + } +} + +mod test_2 { + trait Trait: Sized { + fn foo<'d: 'd, U, const M: bool>(&self) {} + } + + impl Trait for u8 {} + + trait Trait2<'a, 'b, 'c, X, Y, Z> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::::foo as bar1 { Self::get() } + reuse Trait::::foo::<'static, String, false> as bar2 { Self::get() } + reuse Trait::::foo as bar3 { self.get_self() } + reuse Trait::::foo::<'static, String, false> as bar4 { self.get_self() } + } + + trait Trait3 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::::foo as bar1 { Self::get() } + reuse Trait::::foo::<'static, String, false> as bar2 { Self::get() } + reuse Trait::::foo as bar3 { self.get_self() } + reuse Trait::::foo::<'static, String, false> as bar4 { self.get_self() } + } + + trait Trait4<'a, 'b, 'c> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::::foo as bar1 { Self::get() } + reuse Trait::::foo::<'static, String, false> as bar2 { Self::get() } + reuse Trait::::foo as bar3 { self.get_self() } + reuse Trait::::foo::<'static, String, false> as bar4 { self.get_self() } + } + + trait Trait5 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::::foo as bar1 { Self::get() } + reuse Trait::::foo::<'static, String, false> as bar2 { Self::get() } + reuse Trait::::foo as bar3 { self.get_self() } + reuse Trait::::foo::<'static, String, false> as bar4 { self.get_self() } + } + + impl<'a, 'b, 'c, X, Y, Z> Trait2<'a, 'b, 'c, X, Y, Z> for u32 {} + impl Trait3 for u32 {} + impl<'a, 'b, 'c> Trait4<'a, 'b, 'c> for u32 {} + impl Trait5 for u32 {} + + pub fn check<'a: 'a>() { + > + ::bar1::<'static, String, true>(&123); + ::bar1::<'static, String, true>(&123); + >::bar1::<'static, String, true>(&123); + >::bar1::<'static, String, true>(&123); + + >::bar2(&123); + ::bar2(&123); + >::bar2(&123); + >::bar2(&123); + + > + ::bar3::<'static, String, true>(&123); + ::bar3::<'static, String, true>(&123); + >::bar3::<'static, String, true>(&123); + >::bar3::<'static, String, true>(&123); + + >::bar4(&123); + ::bar4(&123); + >::bar4(&123); + >::bar4(&123); + } +} + + +mod test_3 { + trait Trait<'b, 'c, 'a>: Sized { + fn foo<'d: 'd, U, const M: bool>(&self) {} + } + + impl<'b, 'c, 'a> Trait<'b, 'c, 'a> for u8 {} + + trait Trait2<'a, 'b, 'c, X, Y, Z> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static>::foo::<'static, String, false> as bar2 { + Self::get() + } + reuse Trait::<'static, 'static, 'static>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static>::foo::<'static, String, false> as bar4 { + self.get_self() + } + } + + trait Trait3 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static>::foo::<'static, String, false> as bar2 { + Self::get() + } + reuse Trait::<'static, 'static, 'static>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static>::foo::<'static, String, false> as bar4 { + self.get_self() + } + } + + trait Trait4<'a, 'b, 'c> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static>::foo::<'static, String, false> as bar2 { + Self::get() + } + reuse Trait::<'static, 'static, 'static>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static>::foo::<'static, String, false> as bar4 { + self.get_self() + } + } + + trait Trait5 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static>::foo::<'static, String, false> + as bar2 { Self::get() } + reuse Trait::<'static, 'static, 'static>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static>::foo::<'static, String, false> + as bar4 { self.get_self() } + } + + impl<'a, 'b, 'c, X, Y, Z> Trait2<'a, 'b, 'c, X, Y, Z> for u32 {} + impl Trait3 for u32 {} + impl<'a, 'b, 'c> Trait4<'a, 'b, 'c> for u32 {} + impl Trait5 for u32 {} + + pub fn check<'a: 'a>() { + > + ::bar1::<'static, String, true>(&123); + ::bar1::<'static, String, true>(&123); + >::bar1::<'static, String, true>(&123); + >::bar1::<'static, String, true>(&123); + + >::bar2(&123); + ::bar2(&123); + >::bar2(&123); + >::bar2(&123); + + > + ::bar3::<'static, String, true>(&123); + ::bar3::<'static, String, true>(&123); + >::bar3::<'static, String, true>(&123); + >::bar3::<'static, String, true>(&123); + + >::bar4(&123); + ::bar4(&123); + >::bar4(&123); + >::bar4(&123); + } +} + +mod test_4 { + trait Trait: Sized { + fn foo<'d: 'd, U, const M: bool>(&self) {} + } + + impl Trait for u8 {} + + trait Trait2<'a, 'b, 'c, X, Y, Z> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::foo as bar1 { Self::get() } + reuse Trait::foo::<'static, String, false> as bar2 { Self::get() } + reuse Trait::foo as bar3 { self.get_self() } + reuse Trait::foo::<'static, String, false> as bar4 { self.get_self() } + } + + trait Trait3 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::foo as bar1 { Self::get() } + reuse Trait::foo::<'static, String, false> as bar2 { Self::get() } + reuse Trait::foo as bar3 { self.get_self() } + reuse Trait::foo::<'static, String, false> as bar4 { self.get_self() } + } + + trait Trait4<'a, 'b, 'c> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::foo as bar1 { Self::get() } + reuse Trait::foo::<'static, String, false> as bar2 { Self::get() } + reuse Trait::foo as bar3 { self.get_self() } + reuse Trait::foo::<'static, String, false> as bar4 { self.get_self() } + } + + trait Trait5 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::foo as bar1 { Self::get() } + reuse Trait::foo::<'static, String, false> as bar2 { Self::get() } + reuse Trait::foo as bar3 { self.get_self() } + reuse Trait::foo::<'static, String, false> as bar4 { self.get_self() } + } + + impl<'a, 'b, 'c, X, Y, Z> Trait2<'a, 'b, 'c, X, Y, Z> for u32 {} + impl Trait3 for u32 {} + impl<'a, 'b, 'c> Trait4<'a, 'b, 'c> for u32 {} + impl Trait5 for u32 {} + + pub fn check<'a: 'a>() { + > + ::bar1::<'static, String, true>(&123); + ::bar1::<'static, String, true>(&123); + >::bar1::<'static, String, true>(&123); + >::bar1::<'static, String, true>(&123); + + >::bar2(&123); + ::bar2(&123); + >::bar2(&123); + >::bar2(&123); + + > + ::bar3::<'static, String, true>(&123); + ::bar3::<'static, String, true>(&123); + >::bar3::<'static, String, true>(&123); + >::bar3::<'static, String, true>(&123); + + >::bar4(&123); + ::bar4(&123); + >::bar4(&123); + >::bar4(&123); + } +} + +mod test_5 { + trait Trait<'b, 'c, 'a, T>: Sized { + fn foo(&self) {} + } + + impl<'b, 'c, 'a, T> Trait<'b, 'c, 'a, T> for u8 {} + + trait Trait2<'a, 'b, 'c, X, Y, Z> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo:: as bar2 { + Self::get() + } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static, i32>::foo:: as bar4 { + self.get_self() + } + } + + trait Trait3 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo:: as bar2 { + Self::get() + } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static, i32>::foo:: as bar4 { + self.get_self() + } + } + + trait Trait4<'a, 'b, 'c> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo:: as bar2 { + Self::get() + } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static, i32>::foo:: as bar4 { + self.get_self() + } + } + + trait Trait5 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo:: as bar2 { + Self::get() + } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static, i32>::foo:: as bar4 { + self.get_self() + } + } + + impl<'a, 'b, 'c, X, Y, Z> Trait2<'a, 'b, 'c, X, Y, Z> for u32 {} + impl Trait3 for u32 {} + impl<'a, 'b, 'c> Trait4<'a, 'b, 'c> for u32 {} + impl Trait5 for u32 {} + + pub fn check<'a: 'a>() { + >::bar1::(&123); + ::bar1::(&123); + >::bar1::(&123); + >::bar1::(&123); + + >::bar2(&123); + ::bar2(&123); + >::bar2(&123); + >::bar2(&123); + + >::bar3::(&123); + ::bar3::(&123); + >::bar3::(&123); + >::bar3::(&123); + + >::bar4(&123); + ::bar4(&123); + >::bar4(&123); + >::bar4(&123); + } +} + +mod test_6 { + trait Trait<'b, 'c, 'a, T>: Sized { + fn foo(&self) {} + } + + impl<'b, 'c, 'a, T> Trait<'b, 'c, 'a, T> for u8 {} + + trait Trait2<'a, 'b, 'c, X, Y, Z> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar3 { self.get_self() } + } + + trait Trait3 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar3 { self.get_self() } + } + + trait Trait4<'a, 'b, 'c> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar3 { self.get_self() } + } + + trait Trait5 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static, i32>::foo as bar3 { self.get_self() } + } + + impl<'a, 'b, 'c, X, Y, Z> Trait2<'a, 'b, 'c, X, Y, Z> for u32 {} + impl Trait3 for u32 {} + impl<'a, 'b, 'c> Trait4<'a, 'b, 'c> for u32 {} + impl Trait5 for u32 {} + + pub fn check<'a: 'a>() { + >::bar1(&123); + ::bar1(&123); + >::bar1(&123); + >::bar1(&123); + + >::bar3(&123); + ::bar3(&123); + >::bar3(&123); + >::bar3(&123); + } +} + +mod test_7 { + trait Trait: Sized { + fn foo(&self) {} + } + + impl Trait for u8 {} + + trait Trait2<'a, 'b, 'c, X, Y, Z> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::::foo as bar1 { Self::get() } + reuse Trait::::foo as bar3 { self.get_self() } + } + + trait Trait3 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::::foo as bar1 { Self::get() } + reuse Trait::::foo as bar3 { self.get_self() } + } + + trait Trait4<'a, 'b, 'c> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::::foo as bar1 { Self::get() } + reuse Trait::::foo as bar3 { self.get_self() } + } + + trait Trait5 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::::foo as bar1 { Self::get() } + reuse Trait::::foo as bar3 { self.get_self() } + } + + impl<'a, 'b, 'c, X, Y, Z> Trait2<'a, 'b, 'c, X, Y, Z> for u32 {} + impl Trait3 for u32 {} + impl<'a, 'b, 'c> Trait4<'a, 'b, 'c> for u32 {} + impl Trait5 for u32 {} + + pub fn check<'a: 'a>() { + >::bar1(&123); + ::bar1(&123); + >::bar1(&123); + >::bar1(&123); + + >::bar3(&123); + ::bar3(&123); + >::bar3(&123); + >::bar3(&123); + } +} + +mod test_8 { + trait Trait: Sized { + fn foo(&self) {} + } + + impl Trait for u8 {} + + trait Trait2<'a, 'b, 'c, X, Y, Z> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::foo as bar1 { Self::get() } + reuse Trait::foo as bar3 { self.get_self() } + } + + trait Trait3 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::foo as bar1 { Self::get() } + reuse Trait::foo as bar3 { self.get_self() } + } + + trait Trait4<'a, 'b, 'c> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::foo as bar1 { Self::get() } + reuse Trait::foo as bar3 { self.get_self() } + } + + trait Trait5 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::foo as bar1 { Self::get() } + reuse Trait::foo as bar3 { self.get_self() } + } + + impl<'a, 'b, 'c, X, Y, Z> Trait2<'a, 'b, 'c, X, Y, Z> for u32 {} + impl Trait3 for u32 {} + impl<'a, 'b, 'c> Trait4<'a, 'b, 'c> for u32 {} + impl Trait5 for u32 {} + + pub fn check<'a: 'a>() { + >::bar1(&123); + ::bar1(&123); + >::bar1(&123); + >::bar1(&123); + + >::bar3(&123); + ::bar3(&123); + >::bar3(&123); + >::bar3(&123); + } +} + +mod test_9 { + trait Trait: Sized { + fn foo<'a: 'a, 'b: 'b>(&self) {} + } + + impl Trait for u8 {} + + trait Trait2<'a, 'b, 'c, X, Y, Z> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::::foo as bar1 { Self::get() } + reuse Trait::::foo::<'static, 'static> as bar2 { Self::get() } + reuse Trait::::foo as bar3 { self.get_self() } + reuse Trait::::foo::<'static, 'static> as bar4 { self.get_self() } + } + + trait Trait3 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::::foo as bar1 { Self::get() } + reuse Trait::::foo::<'static, 'static> as bar2 { Self::get() } + reuse Trait::::foo as bar3 { self.get_self() } + reuse Trait::::foo::<'static, 'static> as bar4 { self.get_self() } + } + + trait Trait4<'a, 'b, 'c> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::::foo as bar1 { Self::get() } + reuse Trait::::foo::<'static, 'static> as bar2 { Self::get() } + reuse Trait::::foo as bar3 { self.get_self() } + reuse Trait::::foo::<'static, 'static> as bar4 { self.get_self() } + } + + trait Trait5 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::::foo as bar1 { Self::get() } + reuse Trait::::foo::<'static, 'static> as bar2 { Self::get() } + reuse Trait::::foo as bar3 { self.get_self() } + reuse Trait::::foo::<'static, 'static> as bar4 { self.get_self() } + } + + impl<'a, 'b, 'c, X, Y, Z> Trait2<'a, 'b, 'c, X, Y, Z> for u32 {} + impl Trait3 for u32 {} + impl<'a, 'b, 'c> Trait4<'a, 'b, 'c> for u32 {} + impl Trait5 for u32 {} + + pub fn check<'a: 'a>() { + > + ::bar1::<'static, 'static>(&123); + ::bar1::<'static, 'static>(&123); + >::bar1::<'a, 'a>(&123); + >::bar1::<'a, 'a>(&123); + + >::bar2(&123); + ::bar2(&123); + >::bar2(&123); + >::bar2(&123); + + > + ::bar3::<'static, 'static>(&123); + ::bar3::<'static, 'static>(&123); + >::bar3::<'static, 'static>(&123); + >::bar3::<'static, 'static>(&123); + + >::bar4(&123); + ::bar4(&123); + >::bar4(&123); + >::bar4(&123); + } +} + +mod test_10 { + trait Trait<'x, 'y, 'z>: Sized { + fn foo<'a: 'a, 'b: 'b>(&self) {} + } + + impl<'x, 'y, 'z> Trait<'x, 'y, 'z> for u8 {} + + trait Trait2<'a, 'b, 'c, X, Y, Z> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'a, 'b, 'static>::foo as bar1 { Self::get() } + reuse Trait::<'a, 'b, 'static>::foo::<'static, 'static> as bar2 { Self::get() } + reuse Trait::<'a, 'b, 'static>::foo as bar3 { self.get_self() } + reuse Trait::<'a, 'b, 'static>::foo::<'static, 'static> as bar4 { self.get_self() } + } + + trait Trait3 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static>::foo::<'static, 'static> as bar2 { + Self::get() + } + reuse Trait::<'static, 'static, 'static>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static>::foo::<'static, 'static> as bar4 { + self.get_self() + } + } + + trait Trait4<'a, 'b, 'c> { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'a, 'b, 'static>::foo as bar1 { Self::get() } + reuse Trait::<'a, 'b, 'static>::foo::<'static, 'static> as bar2 { Self::get() } + reuse Trait::<'a, 'b, 'static>::foo as bar3 { self.get_self() } + reuse Trait::<'a, 'b, 'static>::foo::<'static, 'static> as bar4 { self.get_self() } + } + + trait Trait5 { + fn get() -> &'static u8 { &0 } + fn get_self(&self) -> &'static u8 { &0 } + reuse Trait::<'static, 'static, 'static>::foo as bar1 { Self::get() } + reuse Trait::<'static, 'static, 'static>::foo::<'static, 'static> as bar2 { + Self::get() + } + reuse Trait::<'static, 'static, 'static>::foo as bar3 { self.get_self() } + reuse Trait::<'static, 'static, 'static>::foo::<'static, 'static> as bar4 { + self.get_self() + } + } + + impl<'a, 'b, 'c, X, Y, Z> Trait2<'a, 'b, 'c, X, Y, Z> for u32 {} + impl Trait3 for u32 {} + impl<'a, 'b, 'c> Trait4<'a, 'b, 'c> for u32 {} + impl Trait5 for u32 {} + + pub fn check<'a: 'a>() { + > + ::bar1::<'static, 'static>(&123); + ::bar1::<'static, 'static>(&123); + >::bar1::<'a, 'a>(&123); + >::bar1::<'a, 'a>(&123); + + >::bar2(&123); + ::bar2(&123); + >::bar2(&123); + >::bar2(&123); + + > + ::bar3::<'static, 'static>(&123); + ::bar3::<'static, 'static>(&123); + >::bar3::<'static, 'static>(&123); + >::bar3::<'static, 'static>(&123); + + >::bar4(&123); + ::bar4(&123); + >::bar4(&123); + >::bar4(&123); + } +} + +pub fn main() { + test_1::check(); + test_2::check(); + test_3::check(); + test_4::check(); + test_5::check(); + test_6::check(); + test_7::check(); + test_8::check(); + test_9::check(); + test_10::check(); +} diff --git a/tests/ui/delegation/generics/auxiliary/generics.rs b/tests/ui/delegation/generics/auxiliary/generics.rs new file mode 100644 index 0000000000000..907700d738c03 --- /dev/null +++ b/tests/ui/delegation/generics/auxiliary/generics.rs @@ -0,0 +1,7 @@ +pub fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + +pub trait Trait<'b, T, const N: usize>: Sized { + fn foo<'d: 'd, U, const M: bool>(self) {} +} + +impl Trait<'static, i32, 1> for u8 {} diff --git a/tests/ui/delegation/generics/free-fn-to-free-fn.rs b/tests/ui/delegation/generics/free-fn-to-free-fn.rs index 3741ad664852a..285059e63a75f 100644 --- a/tests/ui/delegation/generics/free-fn-to-free-fn.rs +++ b/tests/ui/delegation/generics/free-fn-to-free-fn.rs @@ -11,15 +11,13 @@ mod to_reuse { pub fn bounds(_: 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() { + // FIXME(fn_delegation): proper support for late bound lifetimes. late::<'static>(&0u8); - //~^ ERROR cannot specify lifetime arguments explicitly if late bound lifetime parameters are present struct S; bounds(S); diff --git a/tests/ui/delegation/generics/free-fn-to-free-fn.stderr b/tests/ui/delegation/generics/free-fn-to-free-fn.stderr index 5ba56ce1718f0..6b6acfc3afff6 100644 --- a/tests/ui/delegation/generics/free-fn-to-free-fn.stderr +++ b/tests/ui/delegation/generics/free-fn-to-free-fn.stderr @@ -1,33 +1,5 @@ -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() -> i32 { - | ^^^^^^^^^^^^ required by this const generic parameter in `consts` -help: consider specifying the generic argument - | -LL | reuse to_reuse::consts::; - | +++++ - -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 + --> $DIR/free-fn-to-free-fn.rs:23:12 | LL | bounds(S); | ------ ^ the trait `Clone` is not implemented for `S` @@ -48,7 +20,6 @@ LL + #[derive(Clone)] LL | struct S; | -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0284, E0794. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/generics/free-fn-to-trait-infer.rs b/tests/ui/delegation/generics/free-fn-to-trait-infer.rs new file mode 100644 index 0000000000000..905fc8cf21d7d --- /dev/null +++ b/tests/ui/delegation/generics/free-fn-to-trait-infer.rs @@ -0,0 +1,20 @@ +//@ compile-flags: -Z deduplicate-diagnostics=yes + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +trait Trait { + fn foo(&self, _: U, _: T) {} +} + +impl Trait for u8 {} + +reuse Trait::<_>::foo:: as generic_arguments1; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions +reuse >::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 + +fn main() {} diff --git a/tests/ui/delegation/generics/free-fn-to-trait-infer.stderr b/tests/ui/delegation/generics/free-fn-to-trait-infer.stderr new file mode 100644 index 0000000000000..ead3c30a6886c --- /dev/null +++ b/tests/ui/delegation/generics/free-fn-to-trait-infer.stderr @@ -0,0 +1,40 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/free-fn-to-trait-infer.rs:12:15 + | +LL | reuse Trait::<_>::foo:: as generic_arguments1; + | ^ 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:14:20 + | +LL | reuse >::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 + | +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 >::foo as generic_arguments2; + | ^^^ + | | + | expected `&u8`, found `&Self` + | found this type parameter + | 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(&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`. diff --git a/tests/ui/delegation/generics/free-fn-to-trait-method.rs b/tests/ui/delegation/generics/free-fn-to-trait-method.rs index 70be1a4ace7c0..eb3a941c8f484 100644 --- a/tests/ui/delegation/generics/free-fn-to-trait-method.rs +++ b/tests/ui/delegation/generics/free-fn-to-trait-method.rs @@ -26,20 +26,6 @@ mod bounds { impl Trait for u8 {} } -mod generic_arguments { - trait Trait { - fn foo(&self, _: U, _: T) {} - } - - impl Trait for u8 {} - - reuse Trait::<_>::foo:: as generic_arguments1; - //~^ ERROR mismatched types - reuse >::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; diff --git a/tests/ui/delegation/generics/free-fn-to-trait-method.stderr b/tests/ui/delegation/generics/free-fn-to-trait-method.stderr index d8299d00c7e94..b35a3188dd94b 100644 --- a/tests/ui/delegation/generics/free-fn-to-trait-method.stderr +++ b/tests/ui/delegation/generics/free-fn-to-trait-method.stderr @@ -1,45 +1,5 @@ -error[E0308]: mismatched types - --> $DIR/free-fn-to-trait-method.rs:36:23 - | -LL | fn foo(&self, _: U, _: T) {} - | - found this type parameter -... -LL | reuse Trait::<_>::foo:: 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(&self, _: U, _: T) {} - | ^^^ ---- - -error[E0308]: mismatched types - --> $DIR/free-fn-to-trait-method.rs:38:29 - | -LL | trait Trait { - | -------------- found this type parameter -... -LL | reuse >::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(&self, _: U, _: T) {} - | ^^^ ----- - error[E0277]: the trait bound `S: Copy` is not satisfied - --> $DIR/free-fn-to-trait-method.rs:53:18 + --> $DIR/free-fn-to-trait-method.rs:39:18 | LL | bounds(&0u8, S, U); | ------ ^ the trait `Copy` is not implemented for `S` @@ -61,7 +21,7 @@ LL | struct S; | error[E0277]: the trait bound `U: Clone` is not satisfied - --> $DIR/free-fn-to-trait-method.rs:53:21 + --> $DIR/free-fn-to-trait-method.rs:39:21 | LL | bounds(&0u8, S, U); | ------ ^ the trait `Clone` is not implemented for `U` @@ -82,7 +42,6 @@ LL + #[derive(Clone)] LL | struct U; | -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/generics/generic-params-defaults.rs b/tests/ui/delegation/generics/generic-params-defaults.rs new file mode 100644 index 0000000000000..66a9195551337 --- /dev/null +++ b/tests/ui/delegation/generics/generic-params-defaults.rs @@ -0,0 +1,13 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +trait Trait<'a, 'b, 'c, A = usize, B = u32, C = String, const N: usize = 123> { + fn foo(&self) { + //~^ ERROR: defaults for generic parameters are not allowed here + //~| WARN: this was previously accepted by the compiler but is being phased out + } +} + +reuse Trait::foo; + +fn main() {} diff --git a/tests/ui/delegation/generics/generic-params-defaults.stderr b/tests/ui/delegation/generics/generic-params-defaults.stderr new file mode 100644 index 0000000000000..76fc3fde4753c --- /dev/null +++ b/tests/ui/delegation/generics/generic-params-defaults.stderr @@ -0,0 +1,23 @@ +error: defaults for generic parameters are not allowed here + --> $DIR/generic-params-defaults.rs:5:12 + | +LL | fn foo(&self) { + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` (part of `#[deny(future_incompatible)]`) on by default + +error: aborting due to 1 previous error + +Future incompatibility report: Future breakage diagnostic: +error: defaults for generic parameters are not allowed here + --> $DIR/generic-params-defaults.rs:5:12 + | +LL | fn foo(&self) { + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` (part of `#[deny(future_incompatible)]`) on by default + diff --git a/tests/ui/delegation/generics/generic-params-same-names.rs b/tests/ui/delegation/generics/generic-params-same-names.rs new file mode 100644 index 0000000000000..03a00be75399b --- /dev/null +++ b/tests/ui/delegation/generics/generic-params-same-names.rs @@ -0,0 +1,20 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +trait Trait<'a, 'b, 'c, A, B, C, const N: usize> { + fn foo<'a, 'b, 'c, A, B, C, const N: usize>(&self) { + //~^ ERROR: lifetime name `'a` shadows a lifetime name that is already in scope + //~| ERROR: lifetime name `'b` shadows a lifetime name that is already in scope + //~| ERROR: lifetime name `'c` shadows a lifetime name that is already in scope + //~| ERROR: the name `A` is already used for a generic parameter in this item's generic parameters + //~| ERROR: the name `B` is already used for a generic parameter in this item's generic parameters + //~| ERROR: the name `C` is already used for a generic parameter in this item's generic parameters + //~| ERROR: the name `N` is already used for a generic parameter in this item's generic parameters + } +} + +reuse Trait::foo; + +fn main() { + +} diff --git a/tests/ui/delegation/generics/generic-params-same-names.stderr b/tests/ui/delegation/generics/generic-params-same-names.stderr new file mode 100644 index 0000000000000..71ac05fcada01 --- /dev/null +++ b/tests/ui/delegation/generics/generic-params-same-names.stderr @@ -0,0 +1,60 @@ +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/generic-params-same-names.rs:5:12 + | +LL | trait Trait<'a, 'b, 'c, A, B, C, const N: usize> { + | -- first declared here +LL | fn foo<'a, 'b, 'c, A, B, C, const N: usize>(&self) { + | ^^ lifetime `'a` already in scope + +error[E0496]: lifetime name `'b` shadows a lifetime name that is already in scope + --> $DIR/generic-params-same-names.rs:5:16 + | +LL | trait Trait<'a, 'b, 'c, A, B, C, const N: usize> { + | -- first declared here +LL | fn foo<'a, 'b, 'c, A, B, C, const N: usize>(&self) { + | ^^ lifetime `'b` already in scope + +error[E0496]: lifetime name `'c` shadows a lifetime name that is already in scope + --> $DIR/generic-params-same-names.rs:5:20 + | +LL | trait Trait<'a, 'b, 'c, A, B, C, const N: usize> { + | -- first declared here +LL | fn foo<'a, 'b, 'c, A, B, C, const N: usize>(&self) { + | ^^ lifetime `'c` already in scope + +error[E0403]: the name `A` is already used for a generic parameter in this item's generic parameters + --> $DIR/generic-params-same-names.rs:5:24 + | +LL | trait Trait<'a, 'b, 'c, A, B, C, const N: usize> { + | - first use of `A` +LL | fn foo<'a, 'b, 'c, A, B, C, const N: usize>(&self) { + | ^ already used + +error[E0403]: the name `B` is already used for a generic parameter in this item's generic parameters + --> $DIR/generic-params-same-names.rs:5:27 + | +LL | trait Trait<'a, 'b, 'c, A, B, C, const N: usize> { + | - first use of `B` +LL | fn foo<'a, 'b, 'c, A, B, C, const N: usize>(&self) { + | ^ already used + +error[E0403]: the name `C` is already used for a generic parameter in this item's generic parameters + --> $DIR/generic-params-same-names.rs:5:30 + | +LL | trait Trait<'a, 'b, 'c, A, B, C, const N: usize> { + | - first use of `C` +LL | fn foo<'a, 'b, 'c, A, B, C, const N: usize>(&self) { + | ^ already used + +error[E0403]: the name `N` is already used for a generic parameter in this item's generic parameters + --> $DIR/generic-params-same-names.rs:5:39 + | +LL | trait Trait<'a, 'b, 'c, A, B, C, const N: usize> { + | - first use of `N` +LL | fn foo<'a, 'b, 'c, A, B, C, const N: usize>(&self) { + | ^ already used + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0403, E0496. +For more information about an error, try `rustc --explain E0403`. diff --git a/tests/ui/delegation/generics/generics-aux-pass.rs b/tests/ui/delegation/generics/generics-aux-pass.rs new file mode 100644 index 0000000000000..a2cfe91dc4033 --- /dev/null +++ b/tests/ui/delegation/generics/generics-aux-pass.rs @@ -0,0 +1,63 @@ +//@ aux-crate:generics=generics.rs +//@ run-pass + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +reuse generics::foo as bar; +reuse generics::Trait::foo as trait_foo; + +reuse generics::foo::<'static, 'static, i32, i32, 1> as bar1; +reuse generics::Trait::<'static, i32, 1>::foo::<'static, i32, false> as trait_foo1; + +#[derive(Clone, Copy)] +struct X; + +impl generics::Trait<'static, i32, 1> for X {} + +impl X { + reuse generics::foo as bar; + reuse generics::Trait::foo as trait_foo; + + reuse generics::foo::<'static, 'static, i32, i32, 1> as bar1; + reuse generics::Trait::<'static, i32, 1>::foo::<'static, i32, false> as trait_foo1; +} + +trait LocalTrait { + fn get() -> u8 { 123 } + fn get_self(&self) -> u8 { 123 } + + reuse generics::foo as bar; + reuse generics::foo::<'static, 'static, i32, i32, 1> as bar1; + + reuse generics::Trait::foo as trait_foo { Self::get() } + reuse generics::Trait::<'static, i32, 1>::foo::<'static, i32, false> as trait_foo1 { + Self::get_self(&self) + } +} + +impl LocalTrait for usize {} + +fn main() { + bar::(); + bar::<'static, 'static, i32, i32, 1>(); + trait_foo::<'static, 'static, u8, i32, 1, String, true>(123); + + bar1(); + trait_foo1::(123); + + let x = X{}; + + X::bar::(); + X::bar::<'static, 'static, i32, i32, 1>(); + X::bar1(); + x.trait_foo::<'static, 'static, i32, 1, String, true>(); + x.trait_foo1(); + + ::bar::(); + ::bar::<'static, 'static, i32, i32, 1>(); + ::bar1(); + + 1usize.trait_foo::<'static, 'static, i32, 1, String, true>(); + 1usize.trait_foo1(); +} diff --git a/tests/ui/delegation/generics/generics-gen-args-errors.rs b/tests/ui/delegation/generics/generics-gen-args-errors.rs new file mode 100644 index 0000000000000..3edcc70420145 --- /dev/null +++ b/tests/ui/delegation/generics/generics-gen-args-errors.rs @@ -0,0 +1,118 @@ +//@ compile-flags: -Z deduplicate-diagnostics=yes + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod test_1 { + fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + reuse foo as bar; + + fn check() { + bar::<1, 2, 3, 4, 5, 6>(); + //~^ ERROR: function takes 3 generic arguments but 6 generic arguments were supplied + + bar::(); + //~^ ERROR: expected value, found struct `String` [E0423] + + bar::<'static, 'static, 'static, 'static, 'static>(); + //~^ ERROR: function takes 2 lifetime arguments but 5 lifetime arguments were supplied + + bar::(); + //~^ ERROR: constant provided when a type was expected + + bar(); + + bar::<_, _, _, _, _>(); + //~^ ERROR: function takes 3 generic arguments but 5 generic arguments were supplied + + bar::(); + //~^ ERROR: cannot find type `asd` in this scope + //~| ERROR: cannot find type `asd` in this scope + //~| ERROR: cannot find type `asd` in this scope + //~| ERROR: unresolved item provided when a constant was expected + + reuse foo:: as xd; + //~^ ERROR can't use generic parameters from outer item + //~| ERROR can't use generic parameters from outer item + //~| ERROR can't use generic parameters from outer item + //~| ERROR: unresolved item provided when a constant was expected + } +} + +mod test_2 { + fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + + reuse foo::<> as bar1; + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions + + reuse foo:: as bar2; + //~^ ERROR: function takes 3 generic arguments but 2 generic arguments were supplied + + reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; + //~^ ERROR: use of undeclared lifetime name `'asdasd` + //~| ERROR: function takes 2 lifetime arguments but 5 lifetime arguments were supplied + //~| ERROR: function takes 3 generic arguments but 2 generic arguments were supplied + reuse foo:: as bar4; + //~^ ERROR: cannot find type `asdasd` in this scope + //~| ERROR: function takes 2 lifetime arguments but 1 lifetime argument was supplied + + reuse foo::<1, 2, _, 4, 5, _> as bar5; + //~^ ERROR: function takes 3 generic arguments but 6 generic arguments were supplied + + reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6; + //~^ ERROR: cannot find type `asd` in this scope + //~| ERROR: function takes 3 generic arguments but 5 generic arguments were supplied + + reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7; + //~^ ERROR: use of undeclared lifetime name `'a` + //~| ERROR: cannot find type `asd` in this scope + //~| ERROR: constant provided when a type was expected + + reuse foo::<{}, {}, {}> as bar8; + //~^ ERROR: constant provided when a type was expected +} + +mod test_3 { + trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + fn foo<'d: 'd, U, const M: bool>(self) {} + } + + reuse Trait::::foo as bar1; + //~^ ERROR: cannot find type `asd` in this scope + //~| ERROR: cannot find type `asd` in this scope + //~| ERROR: cannot find type `asd` in this scope + //~| ERROR: cannot find type `asd` in this scope + //~| ERROR: cannot find type `asd` in this scope + //~| ERROR: cannot find type `asdasa` in this scope + //~| ERROR: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied + //~| ERROR: trait takes 2 generic arguments but 6 generic arguments were supplied + + reuse Trait::<'static, 'static>::foo as bar2; + //~^ ERROR: trait takes 3 lifetime arguments but 2 lifetime arguments were supplied + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for functions + reuse Trait::<1, 2, 3, 4, 5>::foo as bar3; + //~^ ERROR: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied + //~| ERROR: trait takes 2 generic arguments but 5 generic arguments were supplied + + reuse Trait::<1, 2, true>::foo as bar4; + //~^ ERROR: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied + //~| ERROR: trait takes 2 generic arguments but 3 generic arguments were supplied + + reuse Trait::<'static>::foo as bar5; + //~^ ERROR: trait takes 3 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for functions + + reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; + //~^ ERROR: cannot find type `DDDD` in this scope [E0425] + //~| ERROR: trait takes 3 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR: trait takes 2 generic arguments but 3 generic arguments were supplied + //~| ERROR: method takes 2 generic arguments but 6 generic arguments were supplied + + reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; + //~^ ERROR: missing lifetime specifiers [E0106] + //~| ERROR: trait takes 3 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR: trait takes 2 generic arguments but 5 generic arguments were supplied + //~| ERROR: method takes 2 generic arguments but 5 generic arguments were supplied +} + +fn main() {} diff --git a/tests/ui/delegation/generics/generics-gen-args-errors.stderr b/tests/ui/delegation/generics/generics-gen-args-errors.stderr new file mode 100644 index 0000000000000..78aefbc6604cc --- /dev/null +++ b/tests/ui/delegation/generics/generics-gen-args-errors.stderr @@ -0,0 +1,597 @@ +error[E0401]: can't use generic parameters from outer item + --> $DIR/generics-gen-args-errors.rs:34:21 + | +LL | fn check() { + | - type parameter from outer item +... +LL | reuse foo:: as xd; + | ^ -- generic parameter used in this inner delegated function + | | + | use of generic parameter from outer item + | + = note: nested items are independent from their parent item for everything except for privacy and name resolution + +error[E0401]: can't use generic parameters from outer item + --> $DIR/generics-gen-args-errors.rs:34:24 + | +LL | fn check() { + | - type parameter from outer item +... +LL | reuse foo:: as xd; + | ^ -- generic parameter used in this inner delegated function + | | + | use of generic parameter from outer item + | + = note: nested items are independent from their parent item for everything except for privacy and name resolution + +error[E0401]: can't use generic parameters from outer item + --> $DIR/generics-gen-args-errors.rs:34:27 + | +LL | fn check() { + | - type parameter from outer item +... +LL | reuse foo:: as xd; + | ^ -- generic parameter used in this inner delegated function + | | + | use of generic parameter from outer item + | + = note: nested items are independent from their parent item for everything except for privacy and name resolution + +error[E0261]: use of undeclared lifetime name `'asdasd` + --> $DIR/generics-gen-args-errors.rs:51:29 + | +LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; + | ^^^^^^^ undeclared lifetime + | +help: consider introducing lifetime `'asdasd` here + | +LL | reuse foo'asdasd, ::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; + | ++++++++ + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/generics-gen-args-errors.rs:66:50 + | +LL | reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7; + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +LL | reuse foo'a, ::<"asdasd", asd, "askdn", 'static, 'a> as bar7; + | +++ + +error[E0106]: missing lifetime specifiers + --> $DIR/generics-gen-args-errors.rs:111:19 + | +LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; + | ^^^^^ expected 3 lifetime parameters + | +help: consider introducing a named lifetime parameter + | +LL | reuse Trait::, Clone, _, 'static, dyn Send, _>::foo'a, ::<1, 2, 3, _, 6> as bar7; + | ++++++++++++ +++ + +error[E0423]: expected value, found struct `String` + --> $DIR/generics-gen-args-errors.rs:14:33 + | +LL | bar::(); + | ^^^^^^ + | + --> $SRC_DIR/alloc/src/string.rs:LL:COL + | + = note: `String` defined here + +error[E0425]: cannot find type `asd` in this scope + --> $DIR/generics-gen-args-errors.rs:28:15 + | +LL | bar::(); + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn check() { + | +++++ + +error[E0425]: cannot find type `asd` in this scope + --> $DIR/generics-gen-args-errors.rs:28:20 + | +LL | bar::(); + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn check() { + | +++++ + +error[E0425]: cannot find type `asd` in this scope + --> $DIR/generics-gen-args-errors.rs:28:25 + | +LL | bar::(); + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn check() { + | +++++ + +error[E0425]: cannot find type `asdasd` in this scope + --> $DIR/generics-gen-args-errors.rs:55:39 + | +LL | reuse foo:: as bar4; + | ^^^^^^ not found in this scope + +error[E0425]: cannot find type `asd` in this scope + --> $DIR/generics-gen-args-errors.rs:62:22 + | +LL | reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6; + | ^^^ not found in this scope + +error[E0425]: cannot find type `asd` in this scope + --> $DIR/generics-gen-args-errors.rs:66:27 + | +LL | reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7; + | ^^^ not found in this scope + +error[E0425]: cannot find type `asd` in this scope + --> $DIR/generics-gen-args-errors.rs:80:19 + | +LL | reuse Trait::::foo as bar1; + | ^^^ not found in this scope + +error[E0425]: cannot find type `asd` in this scope + --> $DIR/generics-gen-args-errors.rs:80:24 + | +LL | reuse Trait::::foo as bar1; + | ^^^ not found in this scope + +error[E0425]: cannot find type `asd` in this scope + --> $DIR/generics-gen-args-errors.rs:80:29 + | +LL | reuse Trait::::foo as bar1; + | ^^^ not found in this scope + +error[E0425]: cannot find type `asd` in this scope + --> $DIR/generics-gen-args-errors.rs:80:34 + | +LL | reuse Trait::::foo as bar1; + | ^^^ not found in this scope + +error[E0425]: cannot find type `asd` in this scope + --> $DIR/generics-gen-args-errors.rs:80:39 + | +LL | reuse Trait::::foo as bar1; + | ^^^ not found in this scope + +error[E0425]: cannot find type `asdasa` in this scope + --> $DIR/generics-gen-args-errors.rs:80:44 + | +LL | reuse Trait::::foo as bar1; + | ^^^^^^ not found in this scope + +error[E0425]: cannot find type `DDDD` in this scope + --> $DIR/generics-gen-args-errors.rs:105:34 + | +LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; + | ^^^^ not found in this scope + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/generics-gen-args-errors.rs:34:27 + | +LL | reuse foo:: as xd; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | reuse foo:: as xd; + | + + + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/generics-gen-args-errors.rs:45:11 + | +LL | reuse foo::<> as bar1; + | ^^^ not allowed in type signatures + +error[E0107]: function takes 3 generic arguments but 2 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:48:11 + | +LL | reuse foo:: as bar2; + | ^^^ ------ ------ supplied 2 generic arguments + | | + | expected 3 generic arguments + | +note: function defined here, with 3 generic parameters: `T`, `U`, `N` + --> $DIR/generics-gen-args-errors.rs:43:8 + | +LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + | ^^^ - - -------------- +help: add missing generic argument + | +LL | reuse foo:: as bar2; + | +++ + +error[E0107]: function takes 2 lifetime arguments but 5 lifetime arguments were supplied + --> $DIR/generics-gen-args-errors.rs:51:11 + | +LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; + | ^^^ --------------------------- help: remove the lifetime arguments + | | + | expected 2 lifetime arguments + | +note: function defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/generics-gen-args-errors.rs:43:8 + | +LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + | ^^^ -- -- + +error[E0107]: function takes 3 generic arguments but 2 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:51:11 + | +LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; + | ^^^ expected 3 generic arguments ------- - supplied 2 generic arguments + | +note: function defined here, with 3 generic parameters: `T`, `U`, `N` + --> $DIR/generics-gen-args-errors.rs:43:8 + | +LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + | ^^^ - - -------------- +help: add missing generic argument + | +LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _, N> as bar3; + | +++ + +error[E0107]: function takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/generics-gen-args-errors.rs:55:11 + | +LL | reuse foo:: as bar4; + | ^^^ ------ supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: function defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/generics-gen-args-errors.rs:43:8 + | +LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + | ^^^ -- -- +help: add missing lifetime argument + | +LL | reuse foo:: as bar4; + | +++++++++ + +error[E0107]: function takes 3 generic arguments but 6 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:59:11 + | +LL | reuse foo::<1, 2, _, 4, 5, _> as bar5; + | ^^^ --------- help: remove the unnecessary generic arguments + | | + | expected 3 generic arguments + | +note: function defined here, with 3 generic parameters: `T`, `U`, `N` + --> $DIR/generics-gen-args-errors.rs:43:8 + | +LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + | ^^^ - - -------------- + +error[E0107]: function takes 3 generic arguments but 5 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:62:11 + | +LL | reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6; + | ^^^ ----------------------- help: remove the unnecessary generic arguments + | | + | expected 3 generic arguments + | +note: function defined here, with 3 generic parameters: `T`, `U`, `N` + --> $DIR/generics-gen-args-errors.rs:43:8 + | +LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + | ^^^ - - -------------- + +error[E0747]: constant provided when a type was expected + --> $DIR/generics-gen-args-errors.rs:66:17 + | +LL | reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7; + | ^^^^^^^^ + +error[E0747]: constant provided when a type was expected + --> $DIR/generics-gen-args-errors.rs:71:17 + | +LL | reuse foo::<{}, {}, {}> as bar8; + | ^^ + +error[E0107]: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied + --> $DIR/generics-gen-args-errors.rs:80:11 + | +LL | reuse Trait::::foo as bar1; + | ^^^^^ expected 3 lifetime arguments + | +note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` + --> $DIR/generics-gen-args-errors.rs:76:11 + | +LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + | ^^^^^ -- -- -- +help: add missing lifetime arguments + | +LL | reuse Trait::<'b, 'c, 'a, asd, asd, asd, asd, asd, asdasa>::foo as bar1; + | +++++++++++ + +error[E0107]: trait takes 2 generic arguments but 6 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:80:11 + | +LL | reuse Trait::::foo as bar1; + | ^^^^^ ----------------------- help: remove the unnecessary generic arguments + | | + | expected 2 generic arguments + | +note: trait defined here, with 2 generic parameters: `T`, `N` + --> $DIR/generics-gen-args-errors.rs:76:11 + | +LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + | ^^^^^ - -------------- + +error[E0107]: trait takes 3 lifetime arguments but 2 lifetime arguments were supplied + --> $DIR/generics-gen-args-errors.rs:90:11 + | +LL | reuse Trait::<'static, 'static>::foo as bar2; + | ^^^^^ ------- ------- supplied 2 lifetime arguments + | | + | expected 3 lifetime arguments + | +note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` + --> $DIR/generics-gen-args-errors.rs:76:11 + | +LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + | ^^^^^ -- -- -- +help: add missing lifetime argument + | +LL | reuse Trait::<'static, 'static, 'static>::foo as bar2; + | +++++++++ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/generics-gen-args-errors.rs:90:11 + | +LL | reuse Trait::<'static, 'static>::foo as bar2; + | ^^^^^ not allowed in type signatures + +error[E0107]: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied + --> $DIR/generics-gen-args-errors.rs:93:11 + | +LL | reuse Trait::<1, 2, 3, 4, 5>::foo as bar3; + | ^^^^^ expected 3 lifetime arguments + | +note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` + --> $DIR/generics-gen-args-errors.rs:76:11 + | +LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + | ^^^^^ -- -- -- +help: add missing lifetime arguments + | +LL | reuse Trait::<'b, 'c, 'a, 1, 2, 3, 4, 5>::foo as bar3; + | +++++++++++ + +error[E0107]: trait takes 2 generic arguments but 5 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:93:11 + | +LL | reuse Trait::<1, 2, 3, 4, 5>::foo as bar3; + | ^^^^^ --------- help: remove the unnecessary generic arguments + | | + | expected 2 generic arguments + | +note: trait defined here, with 2 generic parameters: `T`, `N` + --> $DIR/generics-gen-args-errors.rs:76:11 + | +LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + | ^^^^^ - -------------- + +error[E0107]: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied + --> $DIR/generics-gen-args-errors.rs:97:11 + | +LL | reuse Trait::<1, 2, true>::foo as bar4; + | ^^^^^ expected 3 lifetime arguments + | +note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` + --> $DIR/generics-gen-args-errors.rs:76:11 + | +LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + | ^^^^^ -- -- -- +help: add missing lifetime arguments + | +LL | reuse Trait::<'b, 'c, 'a, 1, 2, true>::foo as bar4; + | +++++++++++ + +error[E0107]: trait takes 2 generic arguments but 3 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:97:11 + | +LL | reuse Trait::<1, 2, true>::foo as bar4; + | ^^^^^ ------ help: remove the unnecessary generic argument + | | + | expected 2 generic arguments + | +note: trait defined here, with 2 generic parameters: `T`, `N` + --> $DIR/generics-gen-args-errors.rs:76:11 + | +LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + | ^^^^^ - -------------- + +error[E0107]: trait takes 3 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/generics-gen-args-errors.rs:101:11 + | +LL | reuse Trait::<'static>::foo as bar5; + | ^^^^^ ------- supplied 1 lifetime argument + | | + | expected 3 lifetime arguments + | +note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` + --> $DIR/generics-gen-args-errors.rs:76:11 + | +LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + | ^^^^^ -- -- -- +help: add missing lifetime arguments + | +LL | reuse Trait::<'static, 'static, 'static>::foo as bar5; + | ++++++++++++++++++ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/generics-gen-args-errors.rs:101:11 + | +LL | reuse Trait::<'static>::foo as bar5; + | ^^^^^ not allowed in type signatures + +error[E0107]: trait takes 3 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/generics-gen-args-errors.rs:105:11 + | +LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; + | ^^^^^ - supplied 1 lifetime argument + | | + | expected 3 lifetime arguments + | +note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` + --> $DIR/generics-gen-args-errors.rs:76:11 + | +LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + | ^^^^^ -- -- -- +help: add missing lifetime arguments + | +LL | reuse Trait::<1, 'static, 'static, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; + | ++++++++++++++++++ + +error[E0107]: trait takes 2 generic arguments but 3 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:105:11 + | +LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; + | ^^^^^ --------------- help: remove the unnecessary generic argument + | | + | expected 2 generic arguments + | +note: trait defined here, with 2 generic parameters: `T`, `N` + --> $DIR/generics-gen-args-errors.rs:76:11 + | +LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + | ^^^^^ - -------------- + +error[E0107]: method takes 2 generic arguments but 6 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:105:41 + | +LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; + | ^^^ ------------ help: remove the unnecessary generic arguments + | | + | expected 2 generic arguments + | +note: method defined here, with 2 generic parameters: `U`, `M` + --> $DIR/generics-gen-args-errors.rs:77:12 + | +LL | fn foo<'d: 'd, U, const M: bool>(self) {} + | ^^^ - ------------- + +error[E0107]: trait takes 3 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/generics-gen-args-errors.rs:111:11 + | +LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; + | ^^^^^ ----- supplied 1 lifetime argument + | | + | expected 3 lifetime arguments + | +note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` + --> $DIR/generics-gen-args-errors.rs:76:11 + | +LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + | ^^^^^ -- -- -- +help: add missing lifetime arguments + | +LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; + | ++++++++++++++++++ + +error[E0107]: trait takes 2 generic arguments but 5 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:111:11 + | +LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; + | ^^^^^ --- help: remove the unnecessary generic argument + | | + | expected 2 generic arguments + | +note: trait defined here, with 2 generic parameters: `T`, `N` + --> $DIR/generics-gen-args-errors.rs:76:11 + | +LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { + | ^^^^^ - -------------- + +error[E0107]: method takes 2 generic arguments but 5 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:111:59 + | +LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; + | ^^^ --------- help: remove the unnecessary generic arguments + | | + | expected 2 generic arguments + | +note: method defined here, with 2 generic parameters: `U`, `M` + --> $DIR/generics-gen-args-errors.rs:77:12 + | +LL | fn foo<'d: 'd, U, const M: bool>(self) {} + | ^^^ - ------------- + +error[E0107]: function takes 3 generic arguments but 6 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:11:9 + | +LL | bar::<1, 2, 3, 4, 5, 6>(); + | ^^^ --------- help: remove the unnecessary generic arguments + | | + | expected 3 generic arguments + | +note: function defined here, with 3 generic parameters: `T`, `U`, `N` + --> $DIR/generics-gen-args-errors.rs:8:18 + | +LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + | - - -------------- +LL | reuse foo as bar; + | ^^^ + +error[E0107]: function takes 2 lifetime arguments but 5 lifetime arguments were supplied + --> $DIR/generics-gen-args-errors.rs:17:9 + | +LL | bar::<'static, 'static, 'static, 'static, 'static>(); + | ^^^ --------------------------- help: remove the lifetime arguments + | | + | expected 2 lifetime arguments + | +note: function defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/generics-gen-args-errors.rs:8:18 + | +LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + | -- -- +LL | reuse foo as bar; + | ^^^ + +error[E0747]: constant provided when a type was expected + --> $DIR/generics-gen-args-errors.rs:20:23 + | +LL | bar::(); + | ^ + +error[E0107]: function takes 3 generic arguments but 5 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:25:9 + | +LL | bar::<_, _, _, _, _>(); + | ^^^ ------ help: remove the unnecessary generic arguments + | | + | expected 3 generic arguments + | +note: function defined here, with 3 generic parameters: `T`, `U`, `N` + --> $DIR/generics-gen-args-errors.rs:8:18 + | +LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + | - - -------------- +LL | reuse foo as bar; + | ^^^ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/generics-gen-args-errors.rs:28:25 + | +LL | bar::(); + | ^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | bar::(); + | + + + +error: aborting due to 51 previous errors + +Some errors have detailed explanations: E0106, E0107, E0121, E0261, E0401, E0423, E0425, E0747. +For more information about an error, try `rustc --explain E0106`.