delegation: Support async, const, extern "ABI" and C-variadic functions
Also allow `impl Trait` in delegated functions. The delegation item will refer to the original opaque type from the callee, fresh opaque type won't be created.
This commit is contained in:
parent
99b635eafa
commit
7b7c26f09b
@ -49,7 +49,7 @@
|
|||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::span_bug;
|
use rustc_middle::span_bug;
|
||||||
use rustc_middle::ty::ResolverAstLowering;
|
use rustc_middle::ty::{Asyncness, ResolverAstLowering};
|
||||||
use rustc_span::{symbol::Ident, Span};
|
use rustc_span::{symbol::Ident, Span};
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
@ -67,7 +67,7 @@ pub(crate) fn delegation_has_self(&self, item_id: NodeId, path_id: NodeId, span:
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
if let Some(local_sig_id) = sig_id.as_local() {
|
if let Some(local_sig_id) = sig_id.as_local() {
|
||||||
self.resolver.has_self.contains(&local_sig_id)
|
self.resolver.delegation_fn_sigs[&local_sig_id].has_self
|
||||||
} else {
|
} else {
|
||||||
match self.tcx.def_kind(sig_id) {
|
match self.tcx.def_kind(sig_id) {
|
||||||
DefKind::Fn => false,
|
DefKind::Fn => false,
|
||||||
@ -82,13 +82,14 @@ pub(crate) fn lower_delegation(
|
|||||||
delegation: &Delegation,
|
delegation: &Delegation,
|
||||||
item_id: NodeId,
|
item_id: NodeId,
|
||||||
) -> DelegationResults<'hir> {
|
) -> DelegationResults<'hir> {
|
||||||
let span = delegation.path.segments.last().unwrap().ident.span;
|
let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span);
|
||||||
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span);
|
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span);
|
||||||
match sig_id {
|
match sig_id {
|
||||||
Ok(sig_id) => {
|
Ok(sig_id) => {
|
||||||
let decl = self.lower_delegation_decl(sig_id, span);
|
let (param_count, c_variadic) = self.param_count(sig_id);
|
||||||
let sig = self.lower_delegation_sig(span, decl);
|
let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span);
|
||||||
let body_id = self.lower_delegation_body(sig.decl, delegation);
|
let sig = self.lower_delegation_sig(sig_id, decl, span);
|
||||||
|
let body_id = self.lower_delegation_body(delegation, param_count, span);
|
||||||
|
|
||||||
let generics = self.lower_delegation_generics(span);
|
let generics = self.lower_delegation_generics(span);
|
||||||
DelegationResults { body_id, sig, generics }
|
DelegationResults { body_id, sig, generics }
|
||||||
@ -123,34 +124,47 @@ fn lower_delegation_generics(&mut self, span: Span) -> &'hir hir::Generics<'hir>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function parameter count, including C variadic `...` if present.
|
||||||
|
fn param_count(&self, sig_id: DefId) -> (usize, bool /*c_variadic*/) {
|
||||||
|
if let Some(local_sig_id) = sig_id.as_local() {
|
||||||
|
// Map may be filled incorrectly due to recursive delegation.
|
||||||
|
// Error will be emmited later during HIR ty lowering.
|
||||||
|
match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
|
||||||
|
Some(sig) => (sig.param_count, sig.c_variadic),
|
||||||
|
None => (0, false),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder();
|
||||||
|
(sig.inputs().len() + usize::from(sig.c_variadic), sig.c_variadic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn lower_delegation_decl(
|
fn lower_delegation_decl(
|
||||||
&mut self,
|
&mut self,
|
||||||
sig_id: DefId,
|
sig_id: DefId,
|
||||||
param_span: Span,
|
param_count: usize,
|
||||||
|
c_variadic: bool,
|
||||||
|
span: Span,
|
||||||
) -> &'hir hir::FnDecl<'hir> {
|
) -> &'hir hir::FnDecl<'hir> {
|
||||||
let args_count = if let Some(local_sig_id) = sig_id.as_local() {
|
// The last parameter in C variadic functions is skipped in the signature,
|
||||||
// Map may be filled incorrectly due to recursive delegation.
|
// like during regular lowering.
|
||||||
// Error will be emitted later during HIR ty lowering.
|
let decl_param_count = param_count - c_variadic as usize;
|
||||||
self.resolver.fn_parameter_counts.get(&local_sig_id).cloned().unwrap_or_default()
|
let inputs = self.arena.alloc_from_iter((0..decl_param_count).map(|arg| hir::Ty {
|
||||||
} else {
|
|
||||||
self.tcx.fn_arg_names(sig_id).len()
|
|
||||||
};
|
|
||||||
let inputs = self.arena.alloc_from_iter((0..args_count).map(|arg| hir::Ty {
|
|
||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Input(arg)),
|
kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Input(arg)),
|
||||||
span: self.lower_span(param_span),
|
span,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let output = self.arena.alloc(hir::Ty {
|
let output = self.arena.alloc(hir::Ty {
|
||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output),
|
kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output),
|
||||||
span: self.lower_span(param_span),
|
span,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.arena.alloc(hir::FnDecl {
|
self.arena.alloc(hir::FnDecl {
|
||||||
inputs,
|
inputs,
|
||||||
output: hir::FnRetTy::Return(output),
|
output: hir::FnRetTy::Return(output),
|
||||||
c_variadic: false,
|
c_variadic,
|
||||||
lifetime_elision_allowed: true,
|
lifetime_elision_allowed: true,
|
||||||
implicit_self: hir::ImplicitSelfKind::None,
|
implicit_self: hir::ImplicitSelfKind::None,
|
||||||
})
|
})
|
||||||
@ -158,35 +172,45 @@ fn lower_delegation_decl(
|
|||||||
|
|
||||||
fn lower_delegation_sig(
|
fn lower_delegation_sig(
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
sig_id: DefId,
|
||||||
decl: &'hir hir::FnDecl<'hir>,
|
decl: &'hir hir::FnDecl<'hir>,
|
||||||
|
span: Span,
|
||||||
) -> hir::FnSig<'hir> {
|
) -> hir::FnSig<'hir> {
|
||||||
hir::FnSig {
|
let header = if let Some(local_sig_id) = sig_id.as_local() {
|
||||||
decl,
|
match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
|
||||||
header: hir::FnHeader {
|
Some(sig) => self.lower_fn_header(sig.header),
|
||||||
unsafety: hir::Unsafety::Normal,
|
None => self.generate_header_error(),
|
||||||
constness: hir::Constness::NotConst,
|
}
|
||||||
asyncness: hir::IsAsync::NotAsync,
|
} else {
|
||||||
abi: abi::Abi::Rust,
|
let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder();
|
||||||
},
|
let asyncness = match self.tcx.asyncness(sig_id) {
|
||||||
span: self.lower_span(span),
|
Asyncness::Yes => hir::IsAsync::Async(span),
|
||||||
}
|
Asyncness::No => hir::IsAsync::NotAsync,
|
||||||
|
};
|
||||||
|
hir::FnHeader {
|
||||||
|
unsafety: sig.unsafety,
|
||||||
|
constness: self.tcx.constness(sig_id),
|
||||||
|
asyncness,
|
||||||
|
abi: sig.abi,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
hir::FnSig { decl, header, span }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_param(&mut self, ty: &'hir hir::Ty<'hir>) -> (hir::Param<'hir>, NodeId) {
|
fn generate_param(&mut self, span: Span) -> (hir::Param<'hir>, NodeId) {
|
||||||
let pat_node_id = self.next_node_id();
|
let pat_node_id = self.next_node_id();
|
||||||
let pat_id = self.lower_node_id(pat_node_id);
|
let pat_id = self.lower_node_id(pat_node_id);
|
||||||
let pat = self.arena.alloc(hir::Pat {
|
let pat = self.arena.alloc(hir::Pat {
|
||||||
hir_id: pat_id,
|
hir_id: pat_id,
|
||||||
kind: hir::PatKind::Binding(hir::BindingMode::NONE, pat_id, Ident::empty(), None),
|
kind: hir::PatKind::Binding(hir::BindingMode::NONE, pat_id, Ident::empty(), None),
|
||||||
span: ty.span,
|
span,
|
||||||
default_binding_modes: false,
|
default_binding_modes: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
(hir::Param { hir_id: self.next_id(), pat, ty_span: ty.span, span: ty.span }, pat_node_id)
|
(hir::Param { hir_id: self.next_id(), pat, ty_span: span, span }, pat_node_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_arg(&mut self, ty: &'hir hir::Ty<'hir>, param_id: HirId) -> hir::Expr<'hir> {
|
fn generate_arg(&mut self, param_id: HirId, span: Span) -> hir::Expr<'hir> {
|
||||||
let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment {
|
let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment {
|
||||||
ident: Ident::empty(),
|
ident: Ident::empty(),
|
||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
@ -195,20 +219,20 @@ fn generate_arg(&mut self, ty: &'hir hir::Ty<'hir>, param_id: HirId) -> hir::Exp
|
|||||||
infer_args: false,
|
infer_args: false,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let path =
|
let path = self.arena.alloc(hir::Path { span, res: Res::Local(param_id), segments });
|
||||||
self.arena.alloc(hir::Path { span: ty.span, res: Res::Local(param_id), segments });
|
|
||||||
|
|
||||||
hir::Expr {
|
hir::Expr {
|
||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
|
kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
|
||||||
span: ty.span,
|
span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_delegation_body(
|
fn lower_delegation_body(
|
||||||
&mut self,
|
&mut self,
|
||||||
decl: &'hir hir::FnDecl<'hir>,
|
|
||||||
delegation: &Delegation,
|
delegation: &Delegation,
|
||||||
|
param_count: usize,
|
||||||
|
span: Span,
|
||||||
) -> BodyId {
|
) -> BodyId {
|
||||||
let path = self.lower_qpath(
|
let path = self.lower_qpath(
|
||||||
delegation.id,
|
delegation.id,
|
||||||
@ -224,8 +248,8 @@ fn lower_delegation_body(
|
|||||||
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
|
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
|
||||||
let mut args: Vec<hir::Expr<'hir>> = Vec::new();
|
let mut args: Vec<hir::Expr<'hir>> = Vec::new();
|
||||||
|
|
||||||
for (idx, param_ty) in decl.inputs.iter().enumerate() {
|
for idx in 0..param_count {
|
||||||
let (param, pat_node_id) = this.generate_param(param_ty);
|
let (param, pat_node_id) = this.generate_param(span);
|
||||||
parameters.push(param);
|
parameters.push(param);
|
||||||
|
|
||||||
let arg = if let Some(block) = block
|
let arg = if let Some(block) = block
|
||||||
@ -245,7 +269,7 @@ fn lower_delegation_body(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let pat_hir_id = this.lower_node_id(pat_node_id);
|
let pat_hir_id = this.lower_node_id(pat_node_id);
|
||||||
this.generate_arg(param_ty, pat_hir_id)
|
this.generate_arg(pat_hir_id, span)
|
||||||
};
|
};
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
}
|
}
|
||||||
@ -304,7 +328,9 @@ fn generate_delegation_error(
|
|||||||
implicit_self: hir::ImplicitSelfKind::None,
|
implicit_self: hir::ImplicitSelfKind::None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let sig = self.lower_delegation_sig(span, decl);
|
let header = self.generate_header_error();
|
||||||
|
let sig = hir::FnSig { decl, header, span };
|
||||||
|
|
||||||
let body_id = self.lower_body(|this| {
|
let body_id = self.lower_body(|this| {
|
||||||
let expr =
|
let expr =
|
||||||
hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span };
|
hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span };
|
||||||
@ -312,6 +338,15 @@ fn generate_delegation_error(
|
|||||||
});
|
});
|
||||||
DelegationResults { generics, body_id, sig }
|
DelegationResults { generics, body_id, sig }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_header_error(&self) -> hir::FnHeader {
|
||||||
|
hir::FnHeader {
|
||||||
|
unsafety: hir::Unsafety::Normal,
|
||||||
|
constness: hir::Constness::NotConst,
|
||||||
|
asyncness: hir::IsAsync::NotAsync,
|
||||||
|
abi: abi::Abi::Rust,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SelfResolver<'a> {
|
struct SelfResolver<'a> {
|
||||||
|
@ -1344,7 +1344,7 @@ fn lower_method_sig(
|
|||||||
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
|
pub(super) fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
|
||||||
let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind {
|
let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind {
|
||||||
hir::IsAsync::Async(span)
|
hir::IsAsync::Async(span)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1964,11 +1964,6 @@ fn check_delegation_constraints(&self, sig_id: DefId, span: Span, emit: bool) ->
|
|||||||
try_emit("recursive delegation");
|
try_emit("recursive delegation");
|
||||||
}
|
}
|
||||||
|
|
||||||
let sig = self.tcx().fn_sig(sig_id).instantiate_identity();
|
|
||||||
if sig.output().has_opaque_types() {
|
|
||||||
try_emit("delegation to a function with opaque type");
|
|
||||||
}
|
|
||||||
|
|
||||||
let sig_generics = self.tcx().generics_of(sig_id);
|
let sig_generics = self.tcx().generics_of(sig_id);
|
||||||
let parent = self.tcx().parent(self.item_def_id());
|
let parent = self.tcx().parent(self.item_def_id());
|
||||||
let parent_generics = self.tcx().generics_of(parent);
|
let parent_generics = self.tcx().generics_of(parent);
|
||||||
@ -1991,29 +1986,6 @@ fn check_delegation_constraints(&self, sig_id: DefId, span: Span, emit: bool) ->
|
|||||||
try_emit("delegation to a trait method from a free function");
|
try_emit("delegation to a trait method from a free function");
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.tcx().asyncness(sig_id) == ty::Asyncness::Yes {
|
|
||||||
try_emit("delegation to async functions");
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.tcx().constness(sig_id) == hir::Constness::Const {
|
|
||||||
try_emit("delegation to const functions");
|
|
||||||
}
|
|
||||||
|
|
||||||
if sig.c_variadic() {
|
|
||||||
try_emit("delegation to variadic functions");
|
|
||||||
// variadic functions are also `unsafe` and `extern "C"`.
|
|
||||||
// Do not emit same error multiple times.
|
|
||||||
return error_occured;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let hir::Unsafety::Unsafe = sig.unsafety() {
|
|
||||||
try_emit("delegation to unsafe functions");
|
|
||||||
}
|
|
||||||
|
|
||||||
if abi::Abi::Rust != sig.abi() {
|
|
||||||
try_emit("delegation to non Rust ABI functions");
|
|
||||||
}
|
|
||||||
|
|
||||||
error_occured
|
error_occured
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
|
use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
|
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet};
|
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_query_system::ich::StableHashingContext;
|
use rustc_query_system::ich::StableHashingContext;
|
||||||
@ -224,8 +224,15 @@ pub struct ResolverAstLowering {
|
|||||||
pub lint_buffer: Steal<LintBuffer>,
|
pub lint_buffer: Steal<LintBuffer>,
|
||||||
|
|
||||||
/// Information about functions signatures for delegation items expansion
|
/// Information about functions signatures for delegation items expansion
|
||||||
pub has_self: LocalDefIdSet,
|
pub delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
|
||||||
pub fn_parameter_counts: LocalDefIdMap<usize>,
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DelegationFnSig {
|
||||||
|
pub header: ast::FnHeader,
|
||||||
|
pub param_count: usize,
|
||||||
|
pub has_self: bool,
|
||||||
|
pub c_variadic: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||||
use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
|
use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
|
||||||
use rustc_middle::middle::resolve_bound_vars::Set1;
|
use rustc_middle::middle::resolve_bound_vars::Set1;
|
||||||
|
use rustc_middle::ty::DelegationFnSig;
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_session::config::{CrateType, ResolveDocLinks};
|
use rustc_session::config::{CrateType, ResolveDocLinks};
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
@ -4749,12 +4750,13 @@ struct ItemInfoCollector<'a, 'b, 'tcx> {
|
|||||||
|
|
||||||
impl ItemInfoCollector<'_, '_, '_> {
|
impl ItemInfoCollector<'_, '_, '_> {
|
||||||
fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) {
|
fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) {
|
||||||
let def_id = self.r.local_def_id(id);
|
let sig = DelegationFnSig {
|
||||||
self.r.fn_parameter_counts.insert(def_id, sig.decl.inputs.len());
|
header: sig.header,
|
||||||
|
param_count: sig.decl.inputs.len(),
|
||||||
if sig.decl.has_self() {
|
has_self: sig.decl.has_self(),
|
||||||
self.r.has_self.insert(def_id);
|
c_variadic: sig.decl.c_variadic(),
|
||||||
}
|
};
|
||||||
|
self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2039,7 +2039,8 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
|
|||||||
ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called },
|
ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called },
|
||||||
ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType,
|
ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType,
|
||||||
ast::AssocItemKind::Delegation(..)
|
ast::AssocItemKind::Delegation(..)
|
||||||
if self.r.has_self.contains(&self.r.local_def_id(assoc_item.id)) =>
|
if self.r.delegation_fn_sigs[&self.r.local_def_id(assoc_item.id)]
|
||||||
|
.has_self =>
|
||||||
{
|
{
|
||||||
AssocSuggestion::MethodWithSelf { called }
|
AssocSuggestion::MethodWithSelf { called }
|
||||||
}
|
}
|
||||||
@ -2062,7 +2063,9 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
|
|||||||
if filter_fn(res) {
|
if filter_fn(res) {
|
||||||
let def_id = res.def_id();
|
let def_id = res.def_id();
|
||||||
let has_self = match def_id.as_local() {
|
let has_self = match def_id.as_local() {
|
||||||
Some(def_id) => self.r.has_self.contains(&def_id),
|
Some(def_id) => {
|
||||||
|
self.r.delegation_fn_sigs.get(&def_id).map_or(false, |sig| sig.has_self)
|
||||||
|
}
|
||||||
None => self
|
None => self
|
||||||
.r
|
.r
|
||||||
.tcx
|
.tcx
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
use rustc_hir::def::Namespace::{self, *};
|
use rustc_hir::def::Namespace::{self, *};
|
||||||
use rustc_hir::def::NonMacroAttrKind;
|
use rustc_hir::def::NonMacroAttrKind;
|
||||||
use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS};
|
use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet};
|
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
|
||||||
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
|
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
|
||||||
use rustc_hir::{PrimTy, TraitCandidate};
|
use rustc_hir::{PrimTy, TraitCandidate};
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
@ -52,8 +52,8 @@
|
|||||||
use rustc_middle::middle::privacy::EffectiveVisibilities;
|
use rustc_middle::middle::privacy::EffectiveVisibilities;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::span_bug;
|
use rustc_middle::span_bug;
|
||||||
use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt, TyCtxtFeed};
|
use rustc_middle::ty::{self, DelegationFnSig, Feed, MainDefinition, RegisteredTools};
|
||||||
use rustc_middle::ty::{Feed, ResolverGlobalCtxt, ResolverOutputs};
|
use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, TyCtxt, TyCtxtFeed};
|
||||||
use rustc_query_system::ich::StableHashingContext;
|
use rustc_query_system::ich::StableHashingContext;
|
||||||
use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
|
use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
|
||||||
use rustc_session::lint::LintBuffer;
|
use rustc_session::lint::LintBuffer;
|
||||||
@ -992,7 +992,6 @@ pub struct Resolver<'a, 'tcx> {
|
|||||||
extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
|
extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
|
||||||
|
|
||||||
/// N.B., this is used only for better diagnostics, not name resolution itself.
|
/// N.B., this is used only for better diagnostics, not name resolution itself.
|
||||||
has_self: LocalDefIdSet,
|
|
||||||
field_def_ids: LocalDefIdMap<&'tcx [DefId]>,
|
field_def_ids: LocalDefIdMap<&'tcx [DefId]>,
|
||||||
|
|
||||||
/// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax.
|
/// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax.
|
||||||
@ -1149,8 +1148,7 @@ pub struct Resolver<'a, 'tcx> {
|
|||||||
legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,
|
legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,
|
||||||
/// Amount of lifetime parameters for each item in the crate.
|
/// Amount of lifetime parameters for each item in the crate.
|
||||||
item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>,
|
item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>,
|
||||||
/// Amount of parameters for each function in the crate.
|
delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
|
||||||
fn_parameter_counts: LocalDefIdMap<usize>,
|
|
||||||
|
|
||||||
main_def: Option<MainDefinition>,
|
main_def: Option<MainDefinition>,
|
||||||
trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
|
trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
|
||||||
@ -1399,7 +1397,6 @@ pub fn new(
|
|||||||
prelude: None,
|
prelude: None,
|
||||||
extern_prelude,
|
extern_prelude,
|
||||||
|
|
||||||
has_self: Default::default(),
|
|
||||||
field_def_ids: Default::default(),
|
field_def_ids: Default::default(),
|
||||||
field_visibility_spans: FxHashMap::default(),
|
field_visibility_spans: FxHashMap::default(),
|
||||||
|
|
||||||
@ -1508,7 +1505,7 @@ pub fn new(
|
|||||||
doc_link_resolutions: Default::default(),
|
doc_link_resolutions: Default::default(),
|
||||||
doc_link_traits_in_scope: Default::default(),
|
doc_link_traits_in_scope: Default::default(),
|
||||||
all_macro_rules: Default::default(),
|
all_macro_rules: Default::default(),
|
||||||
fn_parameter_counts: Default::default(),
|
delegation_fn_sigs: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let root_parent_scope = ParentScope::module(graph_root, &resolver);
|
let root_parent_scope = ParentScope::module(graph_root, &resolver);
|
||||||
@ -1621,8 +1618,7 @@ pub fn into_outputs(self) -> ResolverOutputs {
|
|||||||
trait_map: self.trait_map,
|
trait_map: self.trait_map,
|
||||||
lifetime_elision_allowed: self.lifetime_elision_allowed,
|
lifetime_elision_allowed: self.lifetime_elision_allowed,
|
||||||
lint_buffer: Steal::new(self.lint_buffer),
|
lint_buffer: Steal::new(self.lint_buffer),
|
||||||
has_self: self.has_self,
|
delegation_fn_sigs: self.delegation_fn_sigs,
|
||||||
fn_parameter_counts: self.fn_parameter_counts,
|
|
||||||
};
|
};
|
||||||
ResolverOutputs { global_ctxt, ast_lowering }
|
ResolverOutputs { global_ctxt, ast_lowering }
|
||||||
}
|
}
|
||||||
|
9
tests/ui/delegation/auxiliary/fn-header-aux.rs
Normal file
9
tests/ui/delegation/auxiliary/fn-header-aux.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
//@ edition:2018
|
||||||
|
|
||||||
|
#![feature(c_variadic)]
|
||||||
|
|
||||||
|
pub unsafe fn unsafe_fn_extern() {}
|
||||||
|
pub extern "C" fn extern_fn_extern() {}
|
||||||
|
pub unsafe extern "C" fn variadic_fn_extern(n: usize, mut args: ...) {}
|
||||||
|
pub const fn const_fn_extern() {}
|
||||||
|
pub async fn async_fn_extern() {}
|
57
tests/ui/delegation/fn-header.rs
Normal file
57
tests/ui/delegation/fn-header.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//@ check-pass
|
||||||
|
//@ edition:2018
|
||||||
|
//@ aux-crate:fn_header_aux=fn-header-aux.rs
|
||||||
|
|
||||||
|
#![feature(c_variadic)]
|
||||||
|
#![feature(fn_delegation)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
#![deny(unused_unsafe)]
|
||||||
|
|
||||||
|
mod to_reuse {
|
||||||
|
pub unsafe fn unsafe_fn() {}
|
||||||
|
pub extern "C" fn extern_fn() {}
|
||||||
|
pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
|
||||||
|
pub const fn const_fn() {}
|
||||||
|
pub async fn async_fn() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
reuse to_reuse::unsafe_fn;
|
||||||
|
reuse to_reuse::extern_fn;
|
||||||
|
reuse to_reuse::variadic_fn;
|
||||||
|
reuse to_reuse::const_fn;
|
||||||
|
reuse to_reuse::async_fn;
|
||||||
|
|
||||||
|
reuse fn_header_aux::unsafe_fn_extern;
|
||||||
|
reuse fn_header_aux::extern_fn_extern;
|
||||||
|
reuse fn_header_aux::variadic_fn_extern;
|
||||||
|
reuse fn_header_aux::const_fn_extern;
|
||||||
|
reuse fn_header_aux::async_fn_extern;
|
||||||
|
|
||||||
|
const fn const_check() {
|
||||||
|
const_fn();
|
||||||
|
const_fn_extern();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn async_check() {
|
||||||
|
async_fn().await;
|
||||||
|
async_fn_extern().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe {
|
||||||
|
unsafe_fn();
|
||||||
|
unsafe_fn_extern();
|
||||||
|
}
|
||||||
|
extern_fn();
|
||||||
|
extern_fn_extern();
|
||||||
|
let _: extern "C" fn() = extern_fn;
|
||||||
|
let _: extern "C" fn() = extern_fn_extern;
|
||||||
|
unsafe {
|
||||||
|
variadic_fn(0);
|
||||||
|
variadic_fn(0, 1);
|
||||||
|
variadic_fn_extern(0);
|
||||||
|
variadic_fn_extern(0, 1);
|
||||||
|
}
|
||||||
|
let _: unsafe extern "C" fn(usize, ...) = variadic_fn;
|
||||||
|
let _: unsafe extern "C" fn(usize, ...) = variadic_fn_extern;
|
||||||
|
}
|
27
tests/ui/delegation/impl-trait.rs
Normal file
27
tests/ui/delegation/impl-trait.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
#![feature(fn_delegation)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
mod to_reuse {
|
||||||
|
pub fn foo() -> impl Clone { 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
reuse to_reuse::foo;
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
fn bar() -> impl Clone { 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
impl Trait for S {}
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
reuse to_reuse::foo;
|
||||||
|
reuse <S as Trait>::bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
foo().clone();
|
||||||
|
<S>::bar().clone();
|
||||||
|
}
|
@ -14,9 +14,9 @@ fn foo2<T>(&self, x: T) -> T { x }
|
|||||||
fn foo3<'a: 'a>(_: &'a u32) {}
|
fn foo3<'a: 'a>(_: &'a u32) {}
|
||||||
|
|
||||||
reuse GenericTrait::bar;
|
reuse GenericTrait::bar;
|
||||||
//~^ delegation with early bound generics is not supported yet
|
//~^ ERROR delegation with early bound generics is not supported yet
|
||||||
reuse GenericTrait::bar1;
|
reuse GenericTrait::bar1;
|
||||||
//~^ delegation with early bound generics is not supported yet
|
//~^ ERROR delegation with early bound generics is not supported yet
|
||||||
}
|
}
|
||||||
|
|
||||||
struct F;
|
struct F;
|
||||||
@ -73,26 +73,18 @@ pub fn opaque_ret() -> impl Trait { unimplemented!() }
|
|||||||
}
|
}
|
||||||
reuse to_reuse::opaque_arg;
|
reuse to_reuse::opaque_arg;
|
||||||
//~^ ERROR delegation with early bound generics is not supported yet
|
//~^ ERROR delegation with early bound generics is not supported yet
|
||||||
reuse to_reuse::opaque_ret;
|
|
||||||
//~^ ERROR delegation to a function with opaque type is not supported yet
|
|
||||||
}
|
|
||||||
|
|
||||||
mod fn_header {
|
trait ToReuse {
|
||||||
mod to_reuse {
|
fn opaque_ret() -> impl Trait { unimplemented!() }
|
||||||
pub unsafe fn unsafe_fn() {}
|
|
||||||
pub extern "C" fn extern_fn() {}
|
|
||||||
pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
|
|
||||||
pub const fn const_fn() {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reuse to_reuse::unsafe_fn;
|
// FIXME: Inherited `impl Trait`s create query cycles when used inside trait impls.
|
||||||
//~^ ERROR delegation to unsafe functions is not supported yet
|
impl ToReuse for u8 {
|
||||||
reuse to_reuse::extern_fn;
|
reuse to_reuse::opaque_ret; //~ ERROR cycle detected when computing type
|
||||||
//~^ ERROR delegation to non Rust ABI functions is not supported yet
|
}
|
||||||
reuse to_reuse::variadic_fn;
|
impl ToReuse for u16 {
|
||||||
//~^ ERROR delegation to variadic functions is not supported yet
|
reuse ToReuse::opaque_ret; //~ ERROR cycle detected when computing type
|
||||||
reuse to_reuse::const_fn;
|
}
|
||||||
//~^ ERROR delegation to const functions is not supported yet
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod recursive {
|
mod recursive {
|
||||||
|
@ -115,53 +115,46 @@ LL | pub fn opaque_arg(_: impl Trait) -> i32 { 0 }
|
|||||||
LL | reuse to_reuse::opaque_arg;
|
LL | reuse to_reuse::opaque_arg;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: delegation to a function with opaque type is not supported yet
|
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:82:5: 82:24>::{synthetic#0}`
|
||||||
--> $DIR/not-supported.rs:76:21
|
--> $DIR/not-supported.rs:83:25
|
||||||
|
|
|
|
||||||
LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
|
LL | reuse to_reuse::opaque_ret;
|
||||||
| --------------------------------- callee defined here
|
| ^^^^^^^^^^
|
||||||
...
|
|
|
||||||
LL | reuse to_reuse::opaque_ret;
|
note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
|
||||||
| ^^^^^^^^^^
|
--> $DIR/not-supported.rs:83:25
|
||||||
|
|
|
||||||
|
LL | reuse to_reuse::opaque_ret;
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
= note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:82:5: 82:24>::{synthetic#0}`, completing the cycle
|
||||||
|
note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:82:5: 82:24>` is well-formed
|
||||||
|
--> $DIR/not-supported.rs:82:5
|
||||||
|
|
|
||||||
|
LL | impl ToReuse for u8 {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||||
|
|
||||||
error: delegation to unsafe functions is not supported yet
|
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:85:5: 85:25>::{synthetic#0}`
|
||||||
--> $DIR/not-supported.rs:88:21
|
--> $DIR/not-supported.rs:86:24
|
||||||
|
|
|
|
||||||
LL | pub unsafe fn unsafe_fn() {}
|
LL | reuse ToReuse::opaque_ret;
|
||||||
| ------------------------- callee defined here
|
| ^^^^^^^^^^
|
||||||
...
|
|
||||||
LL | reuse to_reuse::unsafe_fn;
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
||||||
error: delegation to non Rust ABI functions is not supported yet
|
|
||||||
--> $DIR/not-supported.rs:90:21
|
|
||||||
|
|
|
|
||||||
LL | pub extern "C" fn extern_fn() {}
|
note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
|
||||||
| ----------------------------- callee defined here
|
--> $DIR/not-supported.rs:86:24
|
||||||
...
|
|
||||||
LL | reuse to_reuse::extern_fn;
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
||||||
error: delegation to variadic functions is not supported yet
|
|
||||||
--> $DIR/not-supported.rs:92:21
|
|
||||||
|
|
|
|
||||||
LL | pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
|
LL | reuse ToReuse::opaque_ret;
|
||||||
| ------------------------------------------------------------- callee defined here
|
| ^^^^^^^^^^
|
||||||
...
|
= note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:85:5: 85:25>::{synthetic#0}`, completing the cycle
|
||||||
LL | reuse to_reuse::variadic_fn;
|
note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:85:5: 85:25>` is well-formed
|
||||||
| ^^^^^^^^^^^
|
--> $DIR/not-supported.rs:85:5
|
||||||
|
|
||||||
error: delegation to const functions is not supported yet
|
|
||||||
--> $DIR/not-supported.rs:94:21
|
|
||||||
|
|
|
|
||||||
LL | pub const fn const_fn() {}
|
LL | impl ToReuse for u16 {
|
||||||
| ----------------------- callee defined here
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
...
|
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||||
LL | reuse to_reuse::const_fn;
|
|
||||||
| ^^^^^^^^
|
|
||||||
|
|
||||||
error: recursive delegation is not supported yet
|
error: recursive delegation is not supported yet
|
||||||
--> $DIR/not-supported.rs:107:22
|
--> $DIR/not-supported.rs:99:22
|
||||||
|
|
|
|
||||||
LL | pub reuse to_reuse2::foo;
|
LL | pub reuse to_reuse2::foo;
|
||||||
| --- callee defined here
|
| --- callee defined here
|
||||||
@ -169,7 +162,7 @@ LL | pub reuse to_reuse2::foo;
|
|||||||
LL | reuse to_reuse1::foo;
|
LL | reuse to_reuse1::foo;
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: aborting due to 19 previous errors
|
error: aborting due to 16 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0049, E0195.
|
Some errors have detailed explanations: E0049, E0195, E0391.
|
||||||
For more information about an error, try `rustc --explain E0049`.
|
For more information about an error, try `rustc --explain E0049`.
|
||||||
|
Loading…
Reference in New Issue
Block a user