Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix async closures in CTFE #120950

Merged
merged 2 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3161,7 +3161,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
// Define a fallback for when we can't match a closure.
let fallback = || {
let is_closure = self.infcx.tcx.is_closure_or_coroutine(self.mir_def_id().to_def_id());
let is_closure = self.infcx.tcx.is_closure_like(self.mir_def_id().to_def_id());
if is_closure {
None
} else {
Expand Down Expand Up @@ -3372,7 +3372,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
sig: ty::PolyFnSig<'tcx>,
) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig);
let is_closure = self.infcx.tcx.is_closure_or_coroutine(did.to_def_id());
let is_closure = self.infcx.tcx.is_closure_like(did.to_def_id());
let fn_hir_id = self.infcx.tcx.local_def_id_to_hir_id(did);
let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?;

Expand Down
11 changes: 5 additions & 6 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
local,
projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
} => {
debug_assert!(is_closure_or_coroutine(
debug_assert!(is_closure_like(
Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty
));

Expand Down Expand Up @@ -126,9 +126,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
{
item_msg = access_place_desc;
debug_assert!(self.body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty.is_ref());
debug_assert!(is_closure_or_coroutine(
the_place_err.ty(self.body, self.infcx.tcx).ty
));
debug_assert!(is_closure_like(the_place_err.ty(self.body, self.infcx.tcx).ty));

reason = if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
", as it is a captured variable in a `Fn` closure".to_string()
Expand Down Expand Up @@ -389,7 +387,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
local,
projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
} => {
debug_assert!(is_closure_or_coroutine(
debug_assert!(is_closure_like(
Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty
));

Expand Down Expand Up @@ -1474,7 +1472,8 @@ fn suggest_ampmut<'tcx>(
}
}

fn is_closure_or_coroutine(ty: Ty<'_>) -> bool {
/// If the type is a `Coroutine`, `Closure`, or `CoroutineClosure`
fn is_closure_like(ty: Ty<'_>) -> bool {
ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure()
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/type_check/input_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) {
let mir_def_id = body.source.def_id().expect_local();

if !self.tcx().is_closure_or_coroutine(mir_def_id.to_def_id()) {
if !self.tcx().is_closure_like(mir_def_id.to_def_id()) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
// `+multivalue` feature because the purpose of the wasm abi is to match
// the WebAssembly specification, which has this feature. This won't be
// needed when LLVM enables this `multivalue` feature by default.
if !cx.tcx.is_closure_or_coroutine(instance.def_id()) {
if !cx.tcx.is_closure_like(instance.def_id()) {
let abi = cx.tcx.fn_sig(instance.def_id()).skip_binder().abi();
if abi == Abi::Wasm {
function_features.push("+multivalue".to_string());
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
}
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
sym::track_caller => {
let is_closure = tcx.is_closure_or_coroutine(did.to_def_id());
let is_closure = tcx.is_closure_like(did.to_def_id());

if !is_closure
&& let Some(fn_sig) = fn_sig()
Expand Down Expand Up @@ -274,7 +274,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
}
}
sym::target_feature => {
if !tcx.is_closure_or_coroutine(did.to_def_id())
if !tcx.is_closure_like(did.to_def_id())
&& let Some(fn_sig) = fn_sig()
&& fn_sig.skip_binder().unsafety() == hir::Unsafety::Normal
{
Expand Down Expand Up @@ -529,7 +529,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
// would result in this closure being compiled without the inherited target features, but this
// is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute.
if tcx.features().target_feature_11
&& tcx.is_closure_or_coroutine(did.to_def_id())
&& tcx.is_closure_like(did.to_def_id())
&& codegen_fn_attrs.inline != InlineAttr::Always
{
let owner_id = tcx.parent(did.to_def_id());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {

pub fn fn_sig(&self) -> PolyFnSig<'tcx> {
let did = self.def_id().to_def_id();
if self.tcx.is_closure_or_coroutine(did) {
if self.tcx.is_closure_like(did) {
let ty = self.tcx.type_of(did).instantiate_identity();
let ty::Closure(_, args) = ty.kind() else { bug!("type_of closure not ty::Closure") };
args.as_closure().sig()
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_hir/src/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ pub enum DefKind {
Impl {
of_trait: bool,
},
/// A closure, coroutine, or coroutine-closure.
///
/// These are all represented with the same `ExprKind::Closure` in the AST and HIR,
/// which makes it difficult to distinguish these during def collection. Therefore,
/// we treat them all the same, and code which needs to distinguish them can match
/// or `hir::ClosureKind` or `type_of`.
Closure,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should also become ClosureLike then?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's probably gonna touch a lot of code, let's do that separately

}

Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_hir_typeck/src/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ pub(super) fn check_fn<'a, 'tcx>(
// ty.span == binding_span iff this is a closure parameter with no type ascription,
// or if it's an implicit `self` parameter
traits::SizedArgumentType(
if ty_span == Some(param.span) && tcx.is_closure_or_coroutine(fn_def_id.into())
{
if ty_span == Some(param.span) && tcx.is_closure_like(fn_def_id.into()) {
None
} else {
ty.map(|ty| ty.hir_id)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/gather_locals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
// ascription, or if it's an implicit `self` parameter
traits::SizedArgumentType(
if ty_span == ident.span
&& self.fcx.tcx.is_closure_or_coroutine(self.fcx.body_id.into())
&& self.fcx.tcx.is_closure_like(self.fcx.body_id.into())
{
None
} else {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io:
let kind = tcx.def_kind(def_id);
let is_function = match kind {
DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true,
_ => tcx.is_closure_or_coroutine(def_id),
_ => tcx.is_closure_like(def_id),
};
match (kind, body.source.promoted) {
(_, Some(i)) => write!(w, "{i:?} in ")?,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ pub struct ClosureTypeInfo<'tcx> {
}

fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo<'tcx> {
debug_assert!(tcx.is_closure_or_coroutine(def.to_def_id()));
debug_assert!(tcx.is_closure_like(def.to_def_id()));
let typeck_results = tcx.typeck(def);
let user_provided_sig = typeck_results.user_provided_sigs[&def];
let captures = typeck_results.closure_min_captures_flattened(def);
Expand All @@ -217,7 +217,7 @@ impl<'tcx> TyCtxt<'tcx> {
}

pub fn closure_captures(self, def_id: LocalDefId) -> &'tcx [&'tcx ty::CapturedPlace<'tcx>] {
if !self.is_closure_or_coroutine(def_id.to_def_id()) {
if !self.is_closure_like(def_id.to_def_id()) {
return &[];
};
self.closure_typeinfo(def_id).captures
Expand Down
7 changes: 2 additions & 5 deletions compiler/rustc_middle/src/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,10 +465,7 @@ impl<'tcx> Instance<'tcx> {
) -> Option<Instance<'tcx>> {
debug!("resolve(def_id={:?}, args={:?})", def_id, args);
// Use either `resolve_closure` or `resolve_for_vtable`
assert!(
!tcx.is_closure_or_coroutine(def_id),
"Called `resolve_for_fn_ptr` on closure: {def_id:?}"
);
assert!(!tcx.is_closure_like(def_id), "Called `resolve_for_fn_ptr` on closure: {def_id:?}");
Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| {
match resolved.def {
InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => {
Expand Down Expand Up @@ -530,7 +527,7 @@ impl<'tcx> Instance<'tcx> {
})
)
{
if tcx.is_closure_or_coroutine(def) {
if tcx.is_closure_like(def) {
debug!(" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}",
def, def_id, args);

Expand Down
16 changes: 9 additions & 7 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,13 +541,15 @@ impl<'tcx> TyCtxt<'tcx> {
Ok(())
}

/// Returns `true` if `def_id` refers to a closure (e.g., `|x| x * 2`). Note
/// that closures have a `DefId`, but the closure *expression* also
/// has a `HirId` that is located within the context where the
/// closure appears (and, sadly, a corresponding `NodeId`, since
/// those are not yet phased out). The parent of the closure's
/// `DefId` will also be the context where it appears.
pub fn is_closure_or_coroutine(self, def_id: DefId) -> bool {
/// Returns `true` if `def_id` refers to a closure, coroutine, or coroutine-closure
/// (i.e. an async closure). These are all represented by `hir::Closure`, and all
/// have the same `DefKind`.
///
/// Note that closures have a `DefId`, but the closure *expression* also has a
// `HirId` that is located within the context where the closure appears (and, sadly,
// a corresponding `NodeId`, since those are not yet phased out). The parent of
// the closure's `DefId` will also be the context where it appears.
pub fn is_closure_like(self, def_id: DefId) -> bool {
matches!(self.def_kind(def_id), DefKind::Closure)
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
let (span, visible_macro) =
unexpand_into_body_span_with_visible_macro(expn_span, body_span)?;

Some(SpanFromMir::new(span, visible_macro, bcb, is_closure_or_coroutine(statement)))
Some(SpanFromMir::new(span, visible_macro, bcb, is_closure_like(statement)))
});

let terminator_span = Some(data.terminator()).into_iter().filter_map(move |terminator| {
Expand All @@ -153,7 +153,7 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
})
}

fn is_closure_or_coroutine(statement: &Statement<'_>) -> bool {
fn is_closure_like(statement: &Statement<'_>) -> bool {
match statement.kind {
StatementKind::Assign(box (_, Rvalue::Aggregate(box ref agg_kind, _))) => match agg_kind {
AggregateKind::Closure(_, _)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,7 @@ fn create_fn_mono_item<'tcx>(
let def_id = instance.def_id();
if tcx.sess.opts.unstable_opts.profile_closures
&& def_id.is_local()
&& tcx.is_closure_or_coroutine(def_id)
&& tcx.is_closure_like(def_id)
{
crate::util::dump_closure_profile(tcx, instance);
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_passes/src/upvars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use rustc_span::Span;

pub fn provide(providers: &mut Providers) {
providers.upvars_mentioned = |tcx, def_id| {
if !tcx.is_closure_or_coroutine(def_id) {
if !tcx.is_closure_like(def_id) {
return None;
}

Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/redundant_locals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals {
fn is_by_value_closure_capture(cx: &LateContext<'_>, redefinition: HirId, root_variable: HirId) -> bool {
let closure_def_id = cx.tcx.hir().enclosing_body_owner(redefinition);

cx.tcx.is_closure_or_coroutine(closure_def_id.to_def_id())
cx.tcx.is_closure_like(closure_def_id.to_def_id())
&& cx.tcx.closure_captures(closure_def_id).iter().any(|c| {
matches!(c.info.capture_kind, UpvarCapture::ByValue)
&& matches!(c.place.base, PlaceBase::Upvar(upvar) if upvar.var_path.hir_id == root_variable)
Expand Down