From 507dec4dc321c868ad876c0b7302c66088b7cc7c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 30 Jul 2025 14:21:00 +1000 Subject: Make const bound handling more like types/regions. Currently there is `Ty` and `BoundTy`, and `Region` and `BoundRegion`, and `Const` and... `BoundVar`. An annoying inconsistency. This commit repurposes the existing `BoundConst`, which was barely used, so it's the partner to `Const`. Unlike `BoundTy`/`BoundRegion` it lacks a `kind` field but it's still nice to have because it makes the const code more similar to the ty/region code everywhere. The commit also removes `impl From for BoundTy`, which has a single use and doesn't seem worth it. These changes fix the "FIXME: We really should have a separate `BoundConst` for consts". --- compiler/rustc_trait_selection/src/traits/coherence.rs | 5 ++++- compiler/rustc_trait_selection/src/traits/mod.rs | 5 ++++- compiler/rustc_trait_selection/src/traits/util.rs | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'compiler/rustc_trait_selection/src/traits') diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 07e78da37b3..d8aedf5c2bf 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -535,7 +535,10 @@ fn plug_infer_with_placeholders<'tcx>( ct, ty::Const::new_placeholder( self.infcx.tcx, - ty::Placeholder { universe: self.universe, bound: self.next_var() }, + ty::Placeholder { + universe: self.universe, + bound: ty::BoundConst { var: self.next_var() }, + }, ), ) else { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 9b5e59ce0fd..08315dbd21f 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -706,7 +706,10 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( self.idx += 1; ty::Const::new_placeholder( self.tcx, - ty::PlaceholderConst { universe: ty::UniverseIndex::ROOT, bound: idx }, + ty::PlaceholderConst { + universe: ty::UniverseIndex::ROOT, + bound: ty::BoundConst { var: idx }, + }, ) } else { c.super_fold_with(self) diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index c3d60ec45c4..83c0969762f 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -222,7 +222,7 @@ pub struct PlaceholderReplacer<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, mapped_regions: FxIndexMap, mapped_types: FxIndexMap, - mapped_consts: FxIndexMap, + mapped_consts: FxIndexMap, universe_indices: &'a [Option], current_index: ty::DebruijnIndex, } @@ -232,7 +232,7 @@ impl<'a, 'tcx> PlaceholderReplacer<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, mapped_regions: FxIndexMap, mapped_types: FxIndexMap, - mapped_consts: FxIndexMap, + mapped_consts: FxIndexMap, universe_indices: &'a [Option], value: T, ) -> T { -- cgit 1.4.1-3-g733a5 From 066a973312066b792c5de4b41b92dcb437f22bac Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 25 Jul 2025 20:34:36 +1000 Subject: Overhaul `Constraint`. This commit changes it to store a `Region` instead of a `RegionVid` for the `Var` cases: - We avoid having to call `Region::new_var` to re-create `Region`s from `RegionVid`s in a few places, avoiding the interning process, giving a small perf win. (At the cost of the type allowing some invalid combinations of values.) - All the cases now store two `Region`s, so the commit also separates the `ConstraintKind` (a new type) from the `sub` and `sup` arguments in `Constraint`. --- .../src/diagnostics/bound_region_errors.rs | 39 ++-- .../src/infer/canonical/query_response.rs | 25 +-- .../src/infer/lexical_region_resolve/mod.rs | 234 +++++++++++---------- compiler/rustc_infer/src/infer/outlives/mod.rs | 8 +- .../src/infer/region_constraints/leak_check.rs | 29 +-- .../src/infer/region_constraints/mod.rs | 46 ++-- .../rustc_trait_selection/src/solve/delegate.rs | 1 - .../rustc_trait_selection/src/traits/auto_trait.rs | 44 ++-- .../src/traits/query/type_op/custom.rs | 1 - compiler/rustc_traits/src/coroutine_witnesses.rs | 1 - src/librustdoc/clean/auto_trait.rs | 40 ++-- 11 files changed, 227 insertions(+), 241 deletions(-) (limited to 'compiler/rustc_trait_selection/src/traits') diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 0de4bd67f0c..6ccded01e88 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use rustc_errors::Diag; use rustc_hir::def_id::LocalDefId; -use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; +use rustc_infer::infer::region_constraints::{Constraint, ConstraintKind, RegionConstraintData}; use rustc_infer::infer::{ InferCtxt, RegionResolutionError, RegionVariableOrigin, SubregionOrigin, TyCtxtInferExt as _, }; @@ -454,25 +454,24 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>( (RePlaceholder(a_p), RePlaceholder(b_p)) => a_p.bound == b_p.bound, _ => a_region == b_region, }; - let mut check = - |constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match *constraint { - Constraint::RegSubReg(sub, sup) - if ((exact && sup == placeholder_region) - || (!exact && regions_the_same(sup, placeholder_region))) - && sup != sub => - { - Some((sub, cause.clone())) - } - Constraint::VarSubReg(vid, sup) - if (exact - && sup == placeholder_region - && !universe_of_region(vid).can_name(placeholder_universe)) - || (!exact && regions_the_same(sup, placeholder_region)) => - { - Some((ty::Region::new_var(infcx.tcx, vid), cause.clone())) - } - _ => None, - }; + let mut check = |c: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match c.kind { + ConstraintKind::RegSubReg + if ((exact && c.sup == placeholder_region) + || (!exact && regions_the_same(c.sup, placeholder_region))) + && c.sup != c.sub => + { + Some((c.sub, cause.clone())) + } + ConstraintKind::VarSubReg + if (exact + && c.sup == placeholder_region + && !universe_of_region(c.sub.as_var()).can_name(placeholder_universe)) + || (!exact && regions_the_same(c.sup, placeholder_region)) => + { + Some((c.sub, cause.clone())) + } + _ => None, + }; let mut find_culprit = |exact_match: bool| { region_constraints diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 6be53c948c8..d92f4c2444b 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -21,7 +21,7 @@ use crate::infer::canonical::{ Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues, QueryRegionConstraints, QueryResponse, }; -use crate::infer::region_constraints::{Constraint, RegionConstraintData}; +use crate::infer::region_constraints::RegionConstraintData; use crate::infer::{ DefineOpaqueTypes, InferCtxt, InferOk, InferResult, SubregionOrigin, TypeOutlivesConstraint, }; @@ -105,8 +105,6 @@ impl<'tcx> InferCtxt<'tcx> { where T: Debug + TypeFoldable>, { - let tcx = self.tcx; - // Select everything, returning errors. let errors = fulfill_cx.select_all_or_error(self); @@ -120,7 +118,6 @@ impl<'tcx> InferCtxt<'tcx> { debug!(?region_obligations); let region_constraints = self.with_region_constraints(|region_constraints| { make_query_region_constraints( - tcx, region_obligations, region_constraints, region_assumptions, @@ -587,7 +584,6 @@ impl<'tcx> InferCtxt<'tcx> { /// Given the region obligations and constraints scraped from the infcx, /// creates query region constraints. pub fn make_query_region_constraints<'tcx>( - tcx: TyCtxt<'tcx>, outlives_obligations: Vec>, region_constraints: &RegionConstraintData<'tcx>, assumptions: Vec>, @@ -600,22 +596,9 @@ pub fn make_query_region_constraints<'tcx>( let outlives: Vec<_> = constraints .iter() - .map(|(k, origin)| { - let constraint = match *k { - // Swap regions because we are going from sub (<=) to outlives - // (>=). - Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate( - ty::Region::new_var(tcx, v2).into(), - ty::Region::new_var(tcx, v1), - ), - Constraint::VarSubReg(v1, r2) => { - ty::OutlivesPredicate(r2.into(), ty::Region::new_var(tcx, v1)) - } - Constraint::RegSubVar(r1, v2) => { - ty::OutlivesPredicate(ty::Region::new_var(tcx, v2).into(), r1) - } - Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1), - }; + .map(|(c, origin)| { + // Swap regions because we are going from sub (<=) to outlives (>=). + let constraint = ty::OutlivesPredicate(c.sup.into(), c.sub); (constraint, origin.to_constraint_category()) }) .chain(outlives_obligations.into_iter().map(|obl| { diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 2185886901e..3adcfb42727 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -19,7 +19,7 @@ use tracing::{debug, instrument}; use super::outlives::test_type_match; use crate::infer::region_constraints::{ - Constraint, GenericKind, RegionConstraintData, VarInfos, VerifyBound, + Constraint, ConstraintKind, GenericKind, RegionConstraintData, VarInfos, VerifyBound, }; use crate::infer::{RegionRelations, RegionVariableOrigin, SubregionOrigin}; @@ -187,91 +187,96 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { let mut constraints = IndexVec::from_elem(Vec::new(), &var_values.values); // Tracks the changed region vids. let mut changes = Vec::new(); - for (constraint, _) in &self.data.constraints { - match *constraint { - Constraint::RegSubVar(a_region, b_vid) => { - let b_data = var_values.value_mut(b_vid); - - if self.expand_node(a_region, b_vid, b_data) { - changes.push(b_vid); + for (c, _) in &self.data.constraints { + match c.kind { + ConstraintKind::RegSubVar => { + let sup_vid = c.sup.as_var(); + let sup_data = var_values.value_mut(sup_vid); + + if self.expand_node(c.sub, sup_vid, sup_data) { + changes.push(sup_vid); } } - Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) { - VarValue::ErrorValue => continue, - VarValue::Empty(a_universe) => { - let b_data = var_values.value_mut(b_vid); - - let changed = match *b_data { - VarValue::Empty(b_universe) => { - // Empty regions are ordered according to the universe - // they are associated with. - let ui = a_universe.min(b_universe); - - debug!( - "Expanding value of {:?} \ + ConstraintKind::VarSubVar => { + let sub_vid = c.sub.as_var(); + let sup_vid = c.sup.as_var(); + match *var_values.value(sub_vid) { + VarValue::ErrorValue => continue, + VarValue::Empty(sub_universe) => { + let sup_data = var_values.value_mut(sup_vid); + + let changed = match *sup_data { + VarValue::Empty(sup_universe) => { + // Empty regions are ordered according to the universe + // they are associated with. + let ui = sub_universe.min(sup_universe); + + debug!( + "Expanding value of {:?} \ from empty lifetime with universe {:?} \ to empty lifetime with universe {:?}", - b_vid, b_universe, ui - ); + sup_vid, sup_universe, ui + ); - *b_data = VarValue::Empty(ui); - true - } - VarValue::Value(cur_region) => { - match cur_region.kind() { - // If this empty region is from a universe that can name the - // placeholder universe, then the LUB is the Placeholder region - // (which is the cur_region). Otherwise, the LUB is the Static - // lifetime. - RePlaceholder(placeholder) - if !a_universe.can_name(placeholder.universe) => - { - let lub = self.tcx().lifetimes.re_static; - debug!( - "Expanding value of {:?} from {:?} to {:?}", - b_vid, cur_region, lub - ); - - *b_data = VarValue::Value(lub); - true + *sup_data = VarValue::Empty(ui); + true + } + VarValue::Value(cur_region) => { + match cur_region.kind() { + // If this empty region is from a universe that can name + // the placeholder universe, then the LUB is the + // Placeholder region (which is the cur_region). Otherwise, + // the LUB is the Static lifetime. + RePlaceholder(placeholder) + if !sub_universe.can_name(placeholder.universe) => + { + let lub = self.tcx().lifetimes.re_static; + debug!( + "Expanding value of {:?} from {:?} to {:?}", + sup_vid, cur_region, lub + ); + + *sup_data = VarValue::Value(lub); + true + } + + _ => false, } - - _ => false, } - } - VarValue::ErrorValue => false, - }; + VarValue::ErrorValue => false, + }; - if changed { - changes.push(b_vid); - } - match b_data { - VarValue::Value(Region(Interned(ReStatic, _))) - | VarValue::ErrorValue => (), - _ => { - constraints[a_vid].push((a_vid, b_vid)); - constraints[b_vid].push((a_vid, b_vid)); + if changed { + changes.push(sup_vid); + } + match sup_data { + VarValue::Value(Region(Interned(ReStatic, _))) + | VarValue::ErrorValue => (), + _ => { + constraints[sub_vid].push((sub_vid, sup_vid)); + constraints[sup_vid].push((sub_vid, sup_vid)); + } } } - } - VarValue::Value(a_region) => { - let b_data = var_values.value_mut(b_vid); + VarValue::Value(sub_region) => { + let sup_data = var_values.value_mut(sup_vid); - if self.expand_node(a_region, b_vid, b_data) { - changes.push(b_vid); - } - match b_data { - VarValue::Value(Region(Interned(ReStatic, _))) - | VarValue::ErrorValue => (), - _ => { - constraints[a_vid].push((a_vid, b_vid)); - constraints[b_vid].push((a_vid, b_vid)); + if self.expand_node(sub_region, sup_vid, sup_data) { + changes.push(sup_vid); + } + match sup_data { + VarValue::Value(Region(Interned(ReStatic, _))) + | VarValue::ErrorValue => (), + _ => { + constraints[sub_vid].push((sub_vid, sup_vid)); + constraints[sup_vid].push((sub_vid, sup_vid)); + } } } } - }, - Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => { + } + ConstraintKind::RegSubReg | ConstraintKind::VarSubReg => { // These constraints are checked after expansion // is done, in `collect_errors`. continue; @@ -528,49 +533,48 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { var_data: &mut LexicalRegionResolutions<'tcx>, errors: &mut Vec>, ) { - for (constraint, origin) in &self.data.constraints { - debug!(?constraint, ?origin); - match *constraint { - Constraint::RegSubVar(..) | Constraint::VarSubVar(..) => { + for (c, origin) in &self.data.constraints { + debug!(?c, ?origin); + match c.kind { + ConstraintKind::RegSubVar | ConstraintKind::VarSubVar => { // Expansion will ensure that these constraints hold. Ignore. } - Constraint::RegSubReg(sub, sup) => { - if self.sub_concrete_regions(sub, sup) { + ConstraintKind::RegSubReg => { + if self.sub_concrete_regions(c.sub, c.sup) { continue; } debug!( - "region error at {:?}: \ - cannot verify that {:?} <= {:?}", - origin, sub, sup + "region error at {:?}: cannot verify that {:?} <= {:?}", + origin, c.sub, c.sup ); errors.push(RegionResolutionError::ConcreteFailure( (*origin).clone(), - sub, - sup, + c.sub, + c.sup, )); } - Constraint::VarSubReg(a_vid, b_region) => { - let a_data = var_data.value_mut(a_vid); - debug!("contraction: {:?} == {:?}, {:?}", a_vid, a_data, b_region); + ConstraintKind::VarSubReg => { + let sub_vid = c.sub.as_var(); + let sub_data = var_data.value_mut(sub_vid); + debug!("contraction: {:?} == {:?}, {:?}", sub_vid, sub_data, c.sup); - let VarValue::Value(a_region) = *a_data else { + let VarValue::Value(sub_region) = *sub_data else { continue; }; // Do not report these errors immediately: // instead, set the variable value to error and // collect them later. - if !self.sub_concrete_regions(a_region, b_region) { + if !self.sub_concrete_regions(sub_region, c.sup) { debug!( - "region error at {:?}: \ - cannot verify that {:?}={:?} <= {:?}", - origin, a_vid, a_region, b_region + "region error at {:?}: cannot verify that {:?}={:?} <= {:?}", + origin, sub_vid, sub_region, c.sup ); - *a_data = VarValue::ErrorValue; + *sub_data = VarValue::ErrorValue; } } } @@ -682,18 +686,20 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { let dummy_source = graph.add_node(()); let dummy_sink = graph.add_node(()); - for (constraint, _) in &self.data.constraints { - match *constraint { - Constraint::VarSubVar(a_id, b_id) => { - graph.add_edge(NodeIndex(a_id.index()), NodeIndex(b_id.index()), *constraint); + for (c, _) in &self.data.constraints { + match c.kind { + ConstraintKind::VarSubVar => { + let sub_vid = c.sub.as_var(); + let sup_vid = c.sup.as_var(); + graph.add_edge(NodeIndex(sub_vid.index()), NodeIndex(sup_vid.index()), *c); } - Constraint::RegSubVar(_, b_id) => { - graph.add_edge(dummy_source, NodeIndex(b_id.index()), *constraint); + ConstraintKind::RegSubVar => { + graph.add_edge(dummy_source, NodeIndex(c.sup.as_var().index()), *c); } - Constraint::VarSubReg(a_id, _) => { - graph.add_edge(NodeIndex(a_id.index()), dummy_sink, *constraint); + ConstraintKind::VarSubReg => { + graph.add_edge(NodeIndex(c.sub.as_var().index()), dummy_sink, *c); } - Constraint::RegSubReg(..) => { + ConstraintKind::RegSubReg => { // this would be an edge from `dummy_source` to // `dummy_sink`; just ignore it. } @@ -878,26 +884,30 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { let source_node_index = NodeIndex(source_vid.index()); for (_, edge) in graph.adjacent_edges(source_node_index, dir) { - match edge.data { - Constraint::VarSubVar(from_vid, to_vid) => { + let get_origin = + || this.constraints.iter().find(|(c, _)| *c == edge.data).unwrap().1.clone(); + + match edge.data.kind { + ConstraintKind::VarSubVar => { + let from_vid = edge.data.sub.as_var(); + let to_vid = edge.data.sup.as_var(); let opp_vid = if from_vid == source_vid { to_vid } else { from_vid }; if state.set.insert(opp_vid) { state.stack.push(opp_vid); } } - Constraint::RegSubVar(region, _) | Constraint::VarSubReg(_, region) => { - let origin = this - .constraints - .iter() - .find(|(c, _)| *c == edge.data) - .unwrap() - .1 - .clone(); - state.result.push(RegionAndOrigin { region, origin }); + ConstraintKind::RegSubVar => { + let origin = get_origin(); + state.result.push(RegionAndOrigin { region: edge.data.sub, origin }); + } + + ConstraintKind::VarSubReg => { + let origin = get_origin(); + state.result.push(RegionAndOrigin { region: edge.data.sup, origin }); } - Constraint::RegSubReg(..) => panic!( + ConstraintKind::RegSubReg => panic!( "cannot reach reg-sub-reg edge in region inference \ post-processing" ), diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 19911bfbd48..c992cda8aae 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -10,7 +10,7 @@ use super::region_constraints::{RegionConstraintData, UndoLog}; use super::{InferCtxt, RegionResolutionError, SubregionOrigin}; use crate::infer::free_regions::RegionRelations; use crate::infer::lexical_region_resolve; -use crate::infer::region_constraints::Constraint; +use crate::infer::region_constraints::ConstraintKind; pub mod env; pub mod for_liveness; @@ -70,10 +70,10 @@ impl<'tcx> InferCtxt<'tcx> { // Filter out any region-region outlives assumptions that are implied by // coroutine well-formedness. if self.tcx.sess.opts.unstable_opts.higher_ranked_assumptions { - storage.data.constraints.retain(|(constraint, _)| match *constraint { - Constraint::RegSubReg(r1, r2) => !outlives_env + storage.data.constraints.retain(|(c, _)| match c.kind { + ConstraintKind::RegSubReg => !outlives_env .higher_ranked_assumptions() - .contains(&ty::OutlivesPredicate(r2.into(), r1)), + .contains(&ty::OutlivesPredicate(c.sup.into(), c.sub)), _ => true, }); } diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index e332b6d0447..4d76bc2e17a 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -83,7 +83,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { return Ok(()); } - let mini_graph = MiniGraph::new(tcx, &self, only_consider_snapshot); + let mini_graph = MiniGraph::new(&self, only_consider_snapshot); let mut leak_check = LeakCheck::new(tcx, outer_universe, max_universe, mini_graph, self); leak_check.assign_placeholder_values()?; @@ -359,7 +359,6 @@ struct MiniGraph<'tcx> { impl<'tcx> MiniGraph<'tcx> { fn new( - tcx: TyCtxt<'tcx>, region_constraints: &RegionConstraintCollector<'_, 'tcx>, only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>, ) -> Self { @@ -368,7 +367,6 @@ impl<'tcx> MiniGraph<'tcx> { // Note that if `R2: R1`, we get a callback `r1, r2`, so `target` is first parameter. Self::iterate_region_constraints( - tcx, region_constraints, only_consider_snapshot, |target, source| { @@ -384,33 +382,18 @@ impl<'tcx> MiniGraph<'tcx> { /// Invokes `each_edge(R1, R2)` for each edge where `R2: R1` fn iterate_region_constraints( - tcx: TyCtxt<'tcx>, region_constraints: &RegionConstraintCollector<'_, 'tcx>, only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>, mut each_edge: impl FnMut(ty::Region<'tcx>, ty::Region<'tcx>), ) { - let mut each_constraint = |constraint| match constraint { - &Constraint::VarSubVar(a, b) => { - each_edge(ty::Region::new_var(tcx, a), ty::Region::new_var(tcx, b)); - } - &Constraint::RegSubVar(a, b) => { - each_edge(a, ty::Region::new_var(tcx, b)); - } - &Constraint::VarSubReg(a, b) => { - each_edge(ty::Region::new_var(tcx, a), b); - } - &Constraint::RegSubReg(a, b) => { - each_edge(a, b); - } - }; - if let Some(snapshot) = only_consider_snapshot { for undo_entry in region_constraints.undo_log.region_constraints_in_snapshot(&snapshot.undo_snapshot) { match undo_entry { &AddConstraint(i) => { - each_constraint(®ion_constraints.data().constraints[i].0); + let c = region_constraints.data().constraints[i].0; + each_edge(c.sub, c.sup); } &AddVerify(i) => span_bug!( region_constraints.data().verifys[i].origin.span(), @@ -420,11 +403,7 @@ impl<'tcx> MiniGraph<'tcx> { } } } else { - region_constraints - .data() - .constraints - .iter() - .for_each(|(constraint, _)| each_constraint(constraint)); + region_constraints.data().constraints.iter().for_each(|(c, _)| each_edge(c.sub, c.sup)) } } diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 4747c203c80..85f5e55a8e1 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -80,31 +80,37 @@ pub struct RegionConstraintData<'tcx> { /// Represents a constraint that influences the inference process. #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] -pub enum Constraint<'tcx> { +pub enum ConstraintKind { /// A region variable is a subregion of another. - VarSubVar(RegionVid, RegionVid), + VarSubVar, /// A concrete region is a subregion of region variable. - RegSubVar(Region<'tcx>, RegionVid), + RegSubVar, /// A region variable is a subregion of a concrete region. This does not /// directly affect inference, but instead is checked after /// inference is complete. - VarSubReg(RegionVid, Region<'tcx>), + VarSubReg, /// A constraint where neither side is a variable. This does not /// directly affect inference, but instead is checked after /// inference is complete. - RegSubReg(Region<'tcx>, Region<'tcx>), + RegSubReg, +} + +/// Represents a constraint that influences the inference process. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub struct Constraint<'tcx> { + pub kind: ConstraintKind, + // If `kind` is `VarSubVar` or `VarSubReg`, this must be a `ReVar`. + pub sub: Region<'tcx>, + // If `kind` is `VarSubVar` or `RegSubVar`, this must be a `ReVar`. + pub sup: Region<'tcx>, } impl Constraint<'_> { pub fn involves_placeholders(&self) -> bool { - match self { - Constraint::VarSubVar(_, _) => false, - Constraint::VarSubReg(_, r) | Constraint::RegSubVar(r, _) => r.is_placeholder(), - Constraint::RegSubReg(r, s) => r.is_placeholder() || s.is_placeholder(), - } + self.sub.is_placeholder() || self.sup.is_placeholder() } } @@ -472,18 +478,22 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } (ReVar(sub_id), ReVar(sup_id)) => { if sub_id != sup_id { - self.add_constraint(Constraint::VarSubVar(sub_id, sup_id), origin); + self.add_constraint( + Constraint { kind: ConstraintKind::VarSubVar, sub, sup }, + origin, + ); } } - (_, ReVar(sup_id)) => { - self.add_constraint(Constraint::RegSubVar(sub, sup_id), origin); - } - (ReVar(sub_id), _) => { - self.add_constraint(Constraint::VarSubReg(sub_id, sup), origin); - } + (_, ReVar(_)) => self + .add_constraint(Constraint { kind: ConstraintKind::RegSubVar, sub, sup }, origin), + (ReVar(_), _) => self + .add_constraint(Constraint { kind: ConstraintKind::VarSubReg, sub, sup }, origin), _ => { if sub != sup { - self.add_constraint(Constraint::RegSubReg(sub, sup), origin); + self.add_constraint( + Constraint { kind: ConstraintKind::RegSubReg, sub, sup }, + origin, + ) } } } diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 7426504e139..96c6e589373 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -205,7 +205,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< let region_assumptions = self.0.inner.borrow().region_assumptions().to_owned(); let region_constraints = self.0.with_region_constraints(|region_constraints| { make_query_region_constraints( - self.tcx, region_obligations, region_constraints, region_assumptions, diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 759db1d18c0..c63cc0e17ab 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -13,7 +13,7 @@ use tracing::debug; use super::*; use crate::errors::UnableToConstructConstantValue; -use crate::infer::region_constraints::{Constraint, RegionConstraintData}; +use crate::infer::region_constraints::{ConstraintKind, RegionConstraintData}; use crate::regions::OutlivesEnvironmentBuildExt; use crate::traits::project::ProjectAndUnifyResult; @@ -452,37 +452,41 @@ impl<'tcx> AutoTraitFinder<'tcx> { let mut vid_map = FxIndexMap::, RegionDeps<'cx>>::default(); let mut finished_map = FxIndexMap::default(); - for (constraint, _) in ®ions.constraints { - match constraint { - &Constraint::VarSubVar(r1, r2) => { + for (c, _) in ®ions.constraints { + match c.kind { + ConstraintKind::VarSubVar => { + let sub_vid = c.sub.as_var(); + let sup_vid = c.sup.as_var(); { - let deps1 = vid_map.entry(RegionTarget::RegionVid(r1)).or_default(); - deps1.larger.insert(RegionTarget::RegionVid(r2)); + let deps1 = vid_map.entry(RegionTarget::RegionVid(sub_vid)).or_default(); + deps1.larger.insert(RegionTarget::RegionVid(sup_vid)); } - let deps2 = vid_map.entry(RegionTarget::RegionVid(r2)).or_default(); - deps2.smaller.insert(RegionTarget::RegionVid(r1)); + let deps2 = vid_map.entry(RegionTarget::RegionVid(sup_vid)).or_default(); + deps2.smaller.insert(RegionTarget::RegionVid(sub_vid)); } - &Constraint::RegSubVar(region, vid) => { + ConstraintKind::RegSubVar => { + let sup_vid = c.sup.as_var(); { - let deps1 = vid_map.entry(RegionTarget::Region(region)).or_default(); - deps1.larger.insert(RegionTarget::RegionVid(vid)); + let deps1 = vid_map.entry(RegionTarget::Region(c.sub)).or_default(); + deps1.larger.insert(RegionTarget::RegionVid(sup_vid)); } - let deps2 = vid_map.entry(RegionTarget::RegionVid(vid)).or_default(); - deps2.smaller.insert(RegionTarget::Region(region)); + let deps2 = vid_map.entry(RegionTarget::RegionVid(sup_vid)).or_default(); + deps2.smaller.insert(RegionTarget::Region(c.sub)); } - &Constraint::VarSubReg(vid, region) => { - finished_map.insert(vid, region); + ConstraintKind::VarSubReg => { + let sub_vid = c.sub.as_var(); + finished_map.insert(sub_vid, c.sup); } - &Constraint::RegSubReg(r1, r2) => { + ConstraintKind::RegSubReg => { { - let deps1 = vid_map.entry(RegionTarget::Region(r1)).or_default(); - deps1.larger.insert(RegionTarget::Region(r2)); + let deps1 = vid_map.entry(RegionTarget::Region(c.sub)).or_default(); + deps1.larger.insert(RegionTarget::Region(c.sup)); } - let deps2 = vid_map.entry(RegionTarget::Region(r2)).or_default(); - deps2.smaller.insert(RegionTarget::Region(r1)); + let deps2 = vid_map.entry(RegionTarget::Region(c.sup)).or_default(); + deps2.smaller.insert(RegionTarget::Region(c.sub)); } } } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs index f027ba1c5cb..0ca2d216228 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs @@ -108,7 +108,6 @@ where let region_assumptions = infcx.take_registered_region_assumptions(); let region_constraint_data = infcx.take_and_reset_region_constraints(); let region_constraints = query_response::make_query_region_constraints( - infcx.tcx, region_obligations, ®ion_constraint_data, region_assumptions, diff --git a/compiler/rustc_traits/src/coroutine_witnesses.rs b/compiler/rustc_traits/src/coroutine_witnesses.rs index 87d17f3e131..8a2a0832ddb 100644 --- a/compiler/rustc_traits/src/coroutine_witnesses.rs +++ b/compiler/rustc_traits/src/coroutine_witnesses.rs @@ -70,7 +70,6 @@ fn compute_assumptions<'tcx>( let region_constraints = infcx.take_and_reset_region_constraints(); let outlives = make_query_region_constraints( - tcx, region_obligations, ®ion_constraints, region_assumptions, diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index a91ea55bcae..e6ac0270f78 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -1,6 +1,6 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry}; use rustc_hir as hir; -use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; +use rustc_infer::infer::region_constraints::{ConstraintKind, RegionConstraintData}; use rustc_middle::bug; use rustc_middle::ty::{self, Region, Ty, fold_regions}; use rustc_span::def_id::DefId; @@ -233,31 +233,35 @@ fn clean_region_outlives_constraints<'tcx>( // Each `RegionTarget` (a `RegionVid` or a `Region`) maps to its smaller and larger regions. // Note that "larger" regions correspond to sub regions in the surface language. // E.g., in `'a: 'b`, `'a` is the larger region. - for (constraint, _) in ®ions.constraints { - match *constraint { - Constraint::VarSubVar(vid1, vid2) => { - let deps1 = map.entry(RegionTarget::RegionVid(vid1)).or_default(); - deps1.larger.insert(RegionTarget::RegionVid(vid2)); + for (c, _) in ®ions.constraints { + match c.kind { + ConstraintKind::VarSubVar => { + let sub_vid = c.sub.as_var(); + let sup_vid = c.sup.as_var(); + let deps1 = map.entry(RegionTarget::RegionVid(sub_vid)).or_default(); + deps1.larger.insert(RegionTarget::RegionVid(sup_vid)); - let deps2 = map.entry(RegionTarget::RegionVid(vid2)).or_default(); - deps2.smaller.insert(RegionTarget::RegionVid(vid1)); + let deps2 = map.entry(RegionTarget::RegionVid(sup_vid)).or_default(); + deps2.smaller.insert(RegionTarget::RegionVid(sub_vid)); } - Constraint::RegSubVar(region, vid) => { - let deps = map.entry(RegionTarget::RegionVid(vid)).or_default(); - deps.smaller.insert(RegionTarget::Region(region)); + ConstraintKind::RegSubVar => { + let sup_vid = c.sup.as_var(); + let deps = map.entry(RegionTarget::RegionVid(sup_vid)).or_default(); + deps.smaller.insert(RegionTarget::Region(c.sub)); } - Constraint::VarSubReg(vid, region) => { - let deps = map.entry(RegionTarget::RegionVid(vid)).or_default(); - deps.larger.insert(RegionTarget::Region(region)); + ConstraintKind::VarSubReg => { + let sub_vid = c.sub.as_var(); + let deps = map.entry(RegionTarget::RegionVid(sub_vid)).or_default(); + deps.larger.insert(RegionTarget::Region(c.sup)); } - Constraint::RegSubReg(r1, r2) => { + ConstraintKind::RegSubReg => { // The constraint is already in the form that we want, so we're done with it // The desired order is [larger, smaller], so flip them. - if early_bound_region_name(r1) != early_bound_region_name(r2) { + if early_bound_region_name(c.sub) != early_bound_region_name(c.sup) { outlives_predicates - .entry(early_bound_region_name(r2).expect("no region_name found")) + .entry(early_bound_region_name(c.sup).expect("no region_name found")) .or_default() - .push(r1); + .push(c.sub); } } } -- cgit 1.4.1-3-g733a5 From d525e79157e32abc510714dd32628c9c155f2997 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 18 Jul 2025 18:17:15 +0000 Subject: Stall coroutines based off of ty::Coroutine, not ty::CoroutineWitness --- .../src/solve/trait_goals.rs | 11 +- .../rustc_trait_selection/src/solve/fulfill.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 60 +++++----- .../rustc_trait_selection/src/traits/select/mod.rs | 2 +- compiler/rustc_type_ir/src/flags.rs | 11 +- tests/ui/async-await/issue-70818.rs | 1 + tests/ui/async-await/issue-70818.stderr | 23 +++- tests/ui/async-await/issue-86507.stderr | 2 +- tests/ui/coroutine/clone-impl-async.rs | 6 +- tests/ui/coroutine/clone-impl-async.stderr | 132 ++++++++++----------- tests/ui/coroutine/clone-impl-static.stderr | 12 +- tests/ui/coroutine/clone-impl.rs | 1 + tests/ui/coroutine/clone-impl.stderr | 88 +++++++------- tests/ui/coroutine/ref-upvar-not-send.stderr | 14 +-- tests/ui/impl-trait/issues/issue-55872-3.stderr | 15 +-- 15 files changed, 194 insertions(+), 186 deletions(-) (limited to 'compiler/rustc_trait_selection/src/traits') diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 650b85d99d2..31991565b0d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -229,7 +229,7 @@ where } // We need to make sure to stall any coroutines we are inferring to avoid query cycles. - if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) { + if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) { return cand; } @@ -294,7 +294,7 @@ where } // We need to make sure to stall any coroutines we are inferring to avoid query cycles. - if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) { + if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) { return cand; } @@ -1432,11 +1432,8 @@ where self.merge_trait_candidates(candidates) } - fn try_stall_coroutine_witness( - &mut self, - self_ty: I::Ty, - ) -> Option, NoSolution>> { - if let ty::CoroutineWitness(def_id, _) = self_ty.kind() { + fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option, NoSolution>> { + if let ty::Coroutine(def_id, _) = self_ty.kind() { match self.typing_mode() { TypingMode::Analysis { defining_opaque_types_and_generators: stalled_generators, diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 01bdae7435d..3f628d80662 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -355,7 +355,7 @@ impl<'tcx> TypeVisitor> for StalledOnCoroutines<'tcx> { return ControlFlow::Continue(()); } - if let ty::CoroutineWitness(def_id, _) = *ty.kind() + if let ty::Coroutine(def_id, _) = *ty.kind() && def_id.as_local().is_some_and(|def_id| self.stalled_coroutines.contains(&def_id)) { ControlFlow::Break(()) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 2c7089507a8..af6dafb3062 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -794,18 +794,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // The auto impl might apply; we don't know. candidates.ambiguous = true; } - ty::Coroutine(coroutine_def_id, _) - if self.tcx().is_lang_item(def_id, LangItem::Unpin) => - { - match self.tcx().coroutine_movability(coroutine_def_id) { - hir::Movability::Static => { - // Immovable coroutines are never `Unpin`, so - // suppress the normal auto-impl candidate for it. + ty::Coroutine(coroutine_def_id, _) => { + if self.tcx().is_lang_item(def_id, LangItem::Unpin) { + match self.tcx().coroutine_movability(coroutine_def_id) { + hir::Movability::Static => { + // Immovable coroutines are never `Unpin`, so + // suppress the normal auto-impl candidate for it. + } + hir::Movability::Movable => { + // Movable coroutines are always `Unpin`, so add an + // unconditional builtin candidate with no sub-obligations. + candidates.vec.push(BuiltinCandidate); + } } - hir::Movability::Movable => { - // Movable coroutines are always `Unpin`, so add an - // unconditional builtin candidate. - candidates.vec.push(BuiltinCandidate); + } else { + if self.should_stall_coroutine(coroutine_def_id) { + candidates.ambiguous = true; + } else { + // Coroutines implement all other auto traits normally. + candidates.vec.push(AutoImplCandidate); } } } @@ -842,12 +849,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::CoroutineWitness(def_id, _) => { - if self.should_stall_coroutine_witness(def_id) { - candidates.ambiguous = true; - } else { - candidates.vec.push(AutoImplCandidate); - } + ty::CoroutineWitness(..) => { + candidates.vec.push(AutoImplCandidate); } ty::Bool @@ -866,7 +869,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::FnPtr(..) | ty::Closure(..) | ty::CoroutineClosure(..) - | ty::Coroutine(..) | ty::Never | ty::Tuple(_) | ty::UnsafeBinder(_) => { @@ -1153,6 +1155,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Ref(_, _, hir::Mutability::Mut) => {} ty::Coroutine(coroutine_def_id, args) => { + if self.should_stall_coroutine(coroutine_def_id) { + candidates.ambiguous = true; + return; + } + match self.tcx().coroutine_movability(coroutine_def_id) { hir::Movability::Static => {} hir::Movability::Movable => { @@ -1194,12 +1201,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::CoroutineWitness(coroutine_def_id, _) => { - if self.should_stall_coroutine_witness(coroutine_def_id) { - candidates.ambiguous = true; - } else { - candidates.vec.push(SizedCandidate); - } + ty::CoroutineWitness(..) => { + candidates.vec.push(SizedCandidate); } // Fallback to whatever user-defined impls or param-env clauses exist in this case. @@ -1238,7 +1241,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::RawPtr(..) | ty::Char | ty::Ref(..) - | ty::Coroutine(..) | ty::Array(..) | ty::Closure(..) | ty::CoroutineClosure(..) @@ -1247,14 +1249,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates.vec.push(SizedCandidate); } - ty::CoroutineWitness(coroutine_def_id, _) => { - if self.should_stall_coroutine_witness(coroutine_def_id) { + ty::Coroutine(coroutine_def_id, _) => { + if self.should_stall_coroutine(coroutine_def_id) { candidates.ambiguous = true; } else { candidates.vec.push(SizedCandidate); } } + ty::CoroutineWitness(..) => { + candidates.vec.push(SizedCandidate); + } + // Conditionally `Sized`. ty::Tuple(..) | ty::Pat(..) | ty::Adt(..) | ty::UnsafeBinder(_) => { candidates.vec.push(SizedCandidate); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index d7c3543cb3f..e893add81c8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2841,7 +2841,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { obligations } - fn should_stall_coroutine_witness(&self, def_id: DefId) -> bool { + fn should_stall_coroutine(&self, def_id: DefId) -> bool { match self.infcx.typing_mode() { TypingMode::Analysis { defining_opaque_types_and_generators: stalled_generators } => { def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id)) diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index d7b9e0ca340..23b7f55fbbe 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -131,10 +131,7 @@ bitflags::bitflags! { /// Does this have any binders with bound vars (e.g. that need to be anonymized)? const HAS_BINDER_VARS = 1 << 23; - /// Does this type have any coroutine witnesses in it? - // FIXME: This should probably be changed to track whether the type has any - // *coroutines* in it, though this will happen if we remove coroutine witnesses - // altogether. + /// Does this type have any coroutines in it? const HAS_TY_CORO = 1 << 24; } } @@ -246,11 +243,13 @@ impl FlagComputation { self.add_flags(TypeFlags::HAS_TY_PARAM); } - ty::Closure(_, args) | ty::Coroutine(_, args) | ty::CoroutineClosure(_, args) => { + ty::Closure(_, args) + | ty::CoroutineClosure(_, args) + | ty::CoroutineWitness(_, args) => { self.add_args(args.as_slice()); } - ty::CoroutineWitness(_, args) => { + ty::Coroutine(_, args) => { self.add_flags(TypeFlags::HAS_TY_CORO); self.add_args(args.as_slice()); } diff --git a/tests/ui/async-await/issue-70818.rs b/tests/ui/async-await/issue-70818.rs index bc181de8d92..c11332fe7d8 100644 --- a/tests/ui/async-await/issue-70818.rs +++ b/tests/ui/async-await/issue-70818.rs @@ -4,6 +4,7 @@ use std::future::Future; fn foo(ty: T, ty1: U) -> impl Future + Send { //~^ ERROR future cannot be sent between threads safely async { (ty, ty1) } + //~^ ERROR future cannot be sent between threads safely } fn main() {} diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr index 8de6a825042..07fd20cdd77 100644 --- a/tests/ui/async-await/issue-70818.stderr +++ b/tests/ui/async-await/issue-70818.stderr @@ -1,3 +1,24 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-70818.rs:6:5 + | +LL | async { (ty, ty1) } + | ^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` + | +note: captured value is not `Send` + --> $DIR/issue-70818.rs:6:18 + | +LL | async { (ty, ty1) } + | ^^^ has type `U` which is not `Send` +note: required by a bound in an opaque type + --> $DIR/issue-70818.rs:4:69 + | +LL | fn foo(ty: T, ty1: U) -> impl Future + Send { + | ^^^^ +help: consider restricting type parameter `U` with trait `Send` + | +LL | fn foo(ty: T, ty1: U) -> impl Future + Send { + | +++++++++++++++++++ + error: future cannot be sent between threads safely --> $DIR/issue-70818.rs:4:38 | @@ -14,5 +35,5 @@ help: consider restricting type parameter `U` with trait `Send` LL | fn foo(ty: T, ty1: U) -> impl Future + Send { | +++++++++++++++++++ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/issue-86507.stderr b/tests/ui/async-await/issue-86507.stderr index 6385a8c975e..c71801dcfc8 100644 --- a/tests/ui/async-await/issue-86507.stderr +++ b/tests/ui/async-await/issue-86507.stderr @@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless | LL | let x = x; | ^ has type `&T` which is not `Send`, because `T` is not `Sync` - = note: required for the cast from `Pin>` to `Pin + Send + 'async_trait)>>` + = note: required for the cast from `Pin>` to `Pin + Send>>` help: consider further restricting type parameter `T` with trait `Sync` | LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T) diff --git a/tests/ui/coroutine/clone-impl-async.rs b/tests/ui/coroutine/clone-impl-async.rs index 2794b167aa2..4e2b26d0295 100644 --- a/tests/ui/coroutine/clone-impl-async.rs +++ b/tests/ui/coroutine/clone-impl-async.rs @@ -9,7 +9,7 @@ use std::future::ready; struct NonClone; -fn main() { +fn local() { let inner_non_clone = async { let non_clone = NonClone; let () = ready(()).await; @@ -34,7 +34,9 @@ fn main() { //~^ ERROR : Copy` is not satisfied check_clone(&maybe_copy_clone); //~^ ERROR : Clone` is not satisfied +} +fn non_local() { let inner_non_clone_fn = the_inner_non_clone_fn(); check_copy(&inner_non_clone_fn); //~^ ERROR : Copy` is not satisfied @@ -69,3 +71,5 @@ async fn the_maybe_copy_clone_fn() {} fn check_copy(_x: &T) {} fn check_clone(_x: &T) {} + +fn main() {} diff --git a/tests/ui/coroutine/clone-impl-async.stderr b/tests/ui/coroutine/clone-impl-async.stderr index 62bcce2fbcb..319a5ed3d8d 100644 --- a/tests/ui/coroutine/clone-impl-async.stderr +++ b/tests/ui/coroutine/clone-impl-async.stderr @@ -1,167 +1,155 @@ -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:18:16 +error[E0277]: the trait bound `impl Future: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:41:16 | -LL | check_copy(&inner_non_clone); - | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` +LL | check_copy(&inner_non_clone_fn); + | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:20:17 +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:43:17 | -LL | check_clone(&inner_non_clone); - | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` +LL | check_clone(&inner_non_clone_fn); + | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:27:16 +error[E0277]: the trait bound `impl Future: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:47:16 | -LL | check_copy(&outer_non_clone); - | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` +LL | check_copy(&outer_non_clone_fn); + | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:29:17 +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:49:17 | -LL | check_clone(&outer_non_clone); - | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` +LL | check_clone(&outer_non_clone_fn); + | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:33:16 +error[E0277]: the trait bound `impl Future: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:53:16 | -LL | check_copy(&maybe_copy_clone); - | ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` +LL | check_copy(&maybe_copy_clone_fn); + | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:35:17 +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:55:17 | -LL | check_clone(&maybe_copy_clone); - | ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` +LL | check_clone(&maybe_copy_clone_fn); + | ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `impl Future: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:39:16 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:18:5 | -LL | check_copy(&inner_non_clone_fn); - | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` - | | - | required by a bound introduced by this call +LL | check_copy(&inner_non_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `impl Future: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:41:17 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:20:5 | -LL | check_clone(&inner_non_clone_fn); - | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` - | | - | required by a bound introduced by this call +LL | check_clone(&inner_non_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `impl Future: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:45:16 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:27:5 | -LL | check_copy(&outer_non_clone_fn); - | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` - | | - | required by a bound introduced by this call +LL | check_copy(&outer_non_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `impl Future: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:47:17 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:29:5 | -LL | check_clone(&outer_non_clone_fn); - | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` - | | - | required by a bound introduced by this call +LL | check_clone(&outer_non_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `impl Future: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:51:16 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:33:5 | -LL | check_copy(&maybe_copy_clone_fn); - | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` - | | - | required by a bound introduced by this call +LL | check_copy(&maybe_copy_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `impl Future: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:53:17 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:35:5 | -LL | check_clone(&maybe_copy_clone_fn); - | ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` - | | - | required by a bound introduced by this call +LL | check_clone(&maybe_copy_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` diff --git a/tests/ui/coroutine/clone-impl-static.stderr b/tests/ui/coroutine/clone-impl-static.stderr index 9fb71fd5fd0..4df6b9759c3 100644 --- a/tests/ui/coroutine/clone-impl-static.stderr +++ b/tests/ui/coroutine/clone-impl-static.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Copy` is not satisfied - --> $DIR/clone-impl-static.rs:14:16 + --> $DIR/clone-impl-static.rs:14:5 | LL | check_copy(&generator); - | ---------- ^^^^^^^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` - | | - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` | note: required by a bound in `check_copy` --> $DIR/clone-impl-static.rs:20:18 @@ -13,12 +11,10 @@ LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Clone` is not satisfied - --> $DIR/clone-impl-static.rs:16:17 + --> $DIR/clone-impl-static.rs:16:5 | LL | check_clone(&generator); - | ----------- ^^^^^^^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` - | | - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` | note: required by a bound in `check_clone` --> $DIR/clone-impl-static.rs:21:19 diff --git a/tests/ui/coroutine/clone-impl.rs b/tests/ui/coroutine/clone-impl.rs index e528f031d52..9e04e256fc1 100644 --- a/tests/ui/coroutine/clone-impl.rs +++ b/tests/ui/coroutine/clone-impl.rs @@ -42,6 +42,7 @@ fn test3_upvars() { let clonable_0: Vec = Vec::new(); let gen_clone_0 = #[coroutine] move || { + yield; drop(clonable_0); }; check_copy(&gen_clone_0); diff --git a/tests/ui/coroutine/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr index 714e5aa3d9e..f316902a42d 100644 --- a/tests/ui/coroutine/clone-impl.stderr +++ b/tests/ui/coroutine/clone-impl.stderr @@ -1,59 +1,81 @@ error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}` - --> $DIR/clone-impl.rs:47:16 + --> $DIR/clone-impl.rs:48:5 | LL | move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}` ... LL | check_copy(&gen_clone_0); - | ^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`, the trait `Copy` is not implemented for `Vec` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:45:14 + --> $DIR/clone-impl.rs:46:14 | LL | drop(clonable_0); | ^^^^^^^^^^ has type `Vec` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:91:18 + --> $DIR/clone-impl.rs:92:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:67:5: 67:12}` - --> $DIR/clone-impl.rs:73:16 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:55:5: 55:12}` + --> $DIR/clone-impl.rs:60:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:67:5: 67:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:55:5: 55:12}` ... LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:67:5: 67:12}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:55:5: 55:12}`, the trait `Copy` is not implemented for `Vec` + | +note: coroutine does not implement `Copy` as this value is used across a yield + --> $DIR/clone-impl.rs:57:9 + | +LL | let v = vec!['a']; + | - has type `Vec` which does not implement `Copy` +LL | yield; + | ^^^^^ yield occurs here, with `v` maybe used later +note: required by a bound in `check_copy` + --> $DIR/clone-impl.rs:92:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:68:5: 68:12}` + --> $DIR/clone-impl.rs:74:5 + | +LL | move || { + | ------- within this `{coroutine@$DIR/clone-impl.rs:68:5: 68:12}` +... +LL | check_copy(&gen_clone_1); + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:68:5: 68:12}`, the trait `Copy` is not implemented for `Vec` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:71:14 + --> $DIR/clone-impl.rs:72:14 | LL | drop(clonable_1); | ^^^^^^^^^^ has type `Vec` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:91:18 + --> $DIR/clone-impl.rs:92:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}` - --> $DIR/clone-impl.rs:85:16 +error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}` + --> $DIR/clone-impl.rs:86:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}` ... LL | check_copy(&gen_non_clone); - | ^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}`, the trait `Copy` is not implemented for `NonClone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}`, the trait `Copy` is not implemented for `NonClone` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:83:14 + --> $DIR/clone-impl.rs:84:14 | LL | drop(non_clonable); | ^^^^^^^^^^^^ has type `NonClone` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:91:18 + --> $DIR/clone-impl.rs:92:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` @@ -63,22 +85,22 @@ LL + #[derive(Copy)] LL | struct NonClone; | -error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}` - --> $DIR/clone-impl.rs:87:17 +error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}` + --> $DIR/clone-impl.rs:88:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}` ... LL | check_clone(&gen_non_clone); - | ^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}`, the trait `Clone` is not implemented for `NonClone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}`, the trait `Clone` is not implemented for `NonClone` | note: captured value does not implement `Clone` - --> $DIR/clone-impl.rs:83:14 + --> $DIR/clone-impl.rs:84:14 | LL | drop(non_clonable); | ^^^^^^^^^^^^ has type `NonClone` which does not implement `Clone` note: required by a bound in `check_clone` - --> $DIR/clone-impl.rs:92:19 + --> $DIR/clone-impl.rs:93:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` @@ -88,28 +110,6 @@ LL + #[derive(Clone)] LL | struct NonClone; | -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:5: 54:12}` - --> $DIR/clone-impl.rs:59:5 - | -LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:54:5: 54:12}` -... -LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:5: 54:12}`, the trait `Copy` is not implemented for `Vec` - | -note: coroutine does not implement `Copy` as this value is used across a yield - --> $DIR/clone-impl.rs:56:9 - | -LL | let v = vec!['a']; - | - has type `Vec` which does not implement `Copy` -LL | yield; - | ^^^^^ yield occurs here, with `v` maybe used later -note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:91:18 - | -LL | fn check_copy(_x: &T) {} - | ^^^^ required by this bound in `check_copy` - error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/ref-upvar-not-send.stderr b/tests/ui/coroutine/ref-upvar-not-send.stderr index 892b5d261c2..3a5e8ec4dab 100644 --- a/tests/ui/coroutine/ref-upvar-not-send.stderr +++ b/tests/ui/coroutine/ref-upvar-not-send.stderr @@ -1,14 +1,13 @@ error: coroutine cannot be sent between threads safely - --> $DIR/ref-upvar-not-send.rs:15:30 + --> $DIR/ref-upvar-not-send.rs:15:5 | -LL | assert_send(#[coroutine] move || { - | ______________________________^ +LL | / assert_send(#[coroutine] move || { LL | | LL | | LL | | yield; LL | | let _x = x; LL | | }); - | |_____^ coroutine is not `Send` + | |______^ coroutine is not `Send` | = help: the trait `Sync` is not implemented for `*mut ()` note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` @@ -23,16 +22,15 @@ LL | fn assert_send(_: T) {} | ^^^^ required by this bound in `assert_send` error: coroutine cannot be sent between threads safely - --> $DIR/ref-upvar-not-send.rs:23:30 + --> $DIR/ref-upvar-not-send.rs:23:5 | -LL | assert_send(#[coroutine] move || { - | ______________________________^ +LL | / assert_send(#[coroutine] move || { LL | | LL | | LL | | yield; LL | | let _y = y; LL | | }); - | |_____^ coroutine is not `Send` + | |______^ coroutine is not `Send` | = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:30: 23:37}`, the trait `Send` is not implemented for `*mut ()` note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send` diff --git a/tests/ui/impl-trait/issues/issue-55872-3.stderr b/tests/ui/impl-trait/issues/issue-55872-3.stderr index ce2dd7f02b4..b7711e47468 100644 --- a/tests/ui/impl-trait/issues/issue-55872-3.stderr +++ b/tests/ui/impl-trait/issues/issue-55872-3.stderr @@ -1,12 +1,3 @@ -error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}: Copy` is not satisfied - --> $DIR/issue-55872-3.rs:14:20 - | -LL | fn foo() -> Self::E { - | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}` -... -LL | async {} - | -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}` here - error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias --> $DIR/issue-55872-3.rs:14:20 | @@ -21,6 +12,12 @@ LL | fn foo() -> Self::E { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}: Copy` is not satisfied + --> $DIR/issue-55872-3.rs:14:20 + | +LL | fn foo() -> Self::E { + | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}` + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. -- cgit 1.4.1-3-g733a5 From d05bb98d6bb448a221ed479842acda5923fb5eb1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 18 Jul 2025 19:47:08 +0000 Subject: Extract borrowck coroutine drop-liveness hack --- .../src/traits/query/dropck_outlives.rs | 7 +++- compiler/rustc_ty_utils/src/needs_drop.rs | 43 +++++++++++++--------- 2 files changed, 31 insertions(+), 19 deletions(-) (limited to 'compiler/rustc_trait_selection/src/traits') diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 38cfdcdc22d..b1b331d1b61 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -318,7 +318,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( }) } - ty::Coroutine(_, args) => { + ty::Coroutine(def_id, args) => { // rust-lang/rust#49918: types can be constructed, stored // in the interior, and sit idle when coroutine yields // (and is subsequently dropped). @@ -346,7 +346,10 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( // While we conservatively assume that all coroutines require drop // to avoid query cycles during MIR building, we can check the actual // witness during borrowck to avoid unnecessary liveness constraints. - if args.witness().needs_drop(tcx, tcx.erase_regions(typing_env)) { + let typing_env = tcx.erase_regions(typing_env); + if tcx.mir_coroutine_witnesses(def_id).is_some_and(|witness| { + witness.field_tys.iter().any(|field| field.ty.needs_drop(tcx, typing_env)) + }) { constraints.outlives.extend(args.upvar_tys().iter().map(ty::GenericArg::from)); constraints.outlives.push(args.resume_ty().into()); } diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index c3b04c20f4b..13d56889bd1 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -101,9 +101,6 @@ fn has_significant_drop_raw<'tcx>( struct NeedsDropTypes<'tcx, F> { tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - /// Whether to reveal coroutine witnesses, this is set - /// to `false` unless we compute `needs_drop` for a coroutine witness. - reveal_coroutine_witnesses: bool, query_ty: Ty<'tcx>, seen_tys: FxHashSet>, /// A stack of types left to process, and the recursion depth when we @@ -115,6 +112,15 @@ struct NeedsDropTypes<'tcx, F> { adt_components: F, /// Set this to true if an exhaustive list of types involved in /// drop obligation is requested. + // FIXME: Calling this bool `exhaustive` is confusing and possibly a footgun, + // since it does two things: It makes the iterator yield *all* of the types + // that need drop, and it also affects the computation of the drop components + // on `Coroutine`s. The latter is somewhat confusing, and probably should be + // a function of `typing_env`. See the HACK comment below for why this is + // necessary. If this isn't possible, then we probably should turn this into + // a `NeedsDropMode` so that we can have a variant like `CollectAllSignificantDrops`, + // which will more accurately indicate that we want *all* of the *significant* + // drops, which are the two important behavioral changes toggled by this bool. exhaustive: bool, } @@ -131,7 +137,6 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> { Self { tcx, typing_env, - reveal_coroutine_witnesses: exhaustive, seen_tys, query_ty: ty, unchecked_tys: vec![(ty, 0)], @@ -195,23 +200,27 @@ where // for the coroutine witness and check whether any of the contained types // need to be dropped, and only require the captured types to be live // if they do. - ty::Coroutine(_, args) => { - if self.reveal_coroutine_witnesses { - queue_type(self, args.as_coroutine().witness()); + ty::Coroutine(def_id, args) => { + // FIXME: See FIXME on `exhaustive` field above. + if self.exhaustive { + for upvar in args.as_coroutine().upvar_tys() { + queue_type(self, upvar); + } + queue_type(self, args.as_coroutine().resume_ty()); + if let Some(witness) = tcx.mir_coroutine_witnesses(def_id) { + for field_ty in &witness.field_tys { + queue_type( + self, + EarlyBinder::bind(field_ty.ty).instantiate(tcx, args), + ); + } + } } else { return Some(self.always_drop_component(ty)); } } - ty::CoroutineWitness(def_id, args) => { - if let Some(witness) = tcx.mir_coroutine_witnesses(def_id) { - self.reveal_coroutine_witnesses = true; - for field_ty in &witness.field_tys { - queue_type( - self, - EarlyBinder::bind(field_ty.ty).instantiate(tcx, args), - ); - } - } + ty::CoroutineWitness(..) => { + unreachable!("witness should be handled in parent"); } ty::UnsafeBinder(bound_ty) => { -- cgit 1.4.1-3-g733a5 From e9765781b2857da90161157a3fc523f9e1d58848 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 25 Jul 2025 16:46:11 +0000 Subject: Remove the witness type from coroutine args --- .../rustc_borrowck/src/type_check/input_output.rs | 1 - .../rustc_hir_analysis/src/collect/generics_of.rs | 12 +++------ compiler/rustc_hir_typeck/src/closure.rs | 5 ---- compiler/rustc_middle/src/ty/generic_args.rs | 29 ++++++++-------------- compiler/rustc_middle/src/ty/print/pretty.rs | 8 ++---- .../src/solve/assembly/structural_traits.rs | 20 ++++++++++++--- .../src/traits/select/candidate_assembly.rs | 4 +-- .../rustc_trait_selection/src/traits/select/mod.rs | 14 ++++++++--- compiler/rustc_type_ir/src/ty_kind/closure.rs | 27 -------------------- ...sync_await.b-{closure#0}.coroutine_resume.0.mir | 8 ------ .../ui/async-await/async-closures/def-path.stderr | 4 +-- ...igher-ranked-auto-trait-6.no_assumptions.stderr | 26 +------------------ .../print/coroutine-print-verbose-2.stderr | 4 +-- .../print/coroutine-print-verbose-3.stderr | 2 +- tests/ui/impl-trait/issues/issue-55872-2.rs | 1 - tests/ui/impl-trait/issues/issue-55872-2.stderr | 10 +------- tests/ui/impl-trait/issues/issue-55872-3.rs | 1 - tests/ui/impl-trait/issues/issue-55872-3.stderr | 14 +++-------- 18 files changed, 54 insertions(+), 136 deletions(-) (limited to 'compiler/rustc_trait_selection/src/traits') diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 99392ea1915..eb31b5de05d 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -86,7 +86,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // them with fresh ty vars. resume_ty: next_ty_var(), yield_ty: next_ty_var(), - witness: next_ty_var(), }, ) .args, diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 31e9c3b80fb..e2462c2d465 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -379,20 +379,14 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // for info on the usage of each of these fields. let dummy_args = match kind { ClosureKind::Closure => &["", "", ""][..], - ClosureKind::Coroutine(_) => &[ - "", - "", - "", - "", - "", - "", - ][..], + ClosureKind::Coroutine(_) => { + &["", "", "", "", ""][..] + } ClosureKind::CoroutineClosure(_) => &[ "", "", "", "", - "", ][..], }; diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index a413f805873..82b7c578a1f 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -161,8 +161,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Resume type defaults to `()` if the coroutine has no argument. let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit); - let interior = Ty::new_coroutine_witness(tcx, expr_def_id.to_def_id(), parent_args); - // Coroutines that come from coroutine closures have not yet determined // their kind ty, so make a fresh infer var which will be constrained // later during upvar analysis. Regular coroutines always have the kind @@ -182,7 +180,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { resume_ty, yield_ty, return_ty: liberated_sig.output(), - witness: interior, tupled_upvars_ty, }, ); @@ -210,7 +207,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Compute all of the variables that will be used to populate the coroutine. let resume_ty = self.next_ty_var(expr_span); - let interior = self.next_ty_var(expr_span); let closure_kind_ty = match expected_kind { Some(kind) => Ty::from_closure_kind(tcx, kind), @@ -243,7 +239,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), tupled_upvars_ty, coroutine_captures_by_ref_ty, - coroutine_witness_ty: interior, }, ); diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 7d34d8df3f3..b02abb5ab43 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -96,14 +96,12 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs> for ty::GenericArg signature_parts_ty, tupled_upvars_ty, coroutine_captures_by_ref_ty, - coroutine_witness_ty, ] => ty::CoroutineClosureArgsParts { parent_args, closure_kind_ty: closure_kind_ty.expect_ty(), signature_parts_ty: signature_parts_ty.expect_ty(), tupled_upvars_ty: tupled_upvars_ty.expect_ty(), coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(), - coroutine_witness_ty: coroutine_witness_ty.expect_ty(), }, _ => bug!("closure args missing synthetics"), } @@ -111,23 +109,16 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs> for ty::GenericArg fn split_coroutine_args(self) -> ty::CoroutineArgsParts> { match self[..] { - [ - ref parent_args @ .., - kind_ty, - resume_ty, - yield_ty, - return_ty, - witness, - tupled_upvars_ty, - ] => ty::CoroutineArgsParts { - parent_args, - kind_ty: kind_ty.expect_ty(), - resume_ty: resume_ty.expect_ty(), - yield_ty: yield_ty.expect_ty(), - return_ty: return_ty.expect_ty(), - witness: witness.expect_ty(), - tupled_upvars_ty: tupled_upvars_ty.expect_ty(), - }, + [ref parent_args @ .., kind_ty, resume_ty, yield_ty, return_ty, tupled_upvars_ty] => { + ty::CoroutineArgsParts { + parent_args, + kind_ty: kind_ty.expect_ty(), + resume_ty: resume_ty.expect_ty(), + yield_ty: yield_ty.expect_ty(), + return_ty: return_ty.expect_ty(), + tupled_upvars_ty: tupled_upvars_ty.expect_ty(), + } + } _ => bug!("coroutine args missing synthetics"), } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 5c44b10ba71..71eac294f15 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -913,9 +913,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { " yield_ty=", print(args.as_coroutine().yield_ty()), " return_ty=", - print(args.as_coroutine().return_ty()), - " witness=", - print(args.as_coroutine().witness()) + print(args.as_coroutine().return_ty()) ); } @@ -1035,9 +1033,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { " upvar_tys=", print(args.as_coroutine_closure().tupled_upvars_ty()), " coroutine_captures_by_ref_ty=", - print(args.as_coroutine_closure().coroutine_captures_by_ref_ty()), - " coroutine_witness_ty=", - print(args.as_coroutine_closure().coroutine_witness_ty()) + print(args.as_coroutine_closure().coroutine_captures_by_ref_ty()) ); } p!("}}"); diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index c0bebdf6fb6..faa86734d08 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -75,9 +75,16 @@ where Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()])) } - ty::Coroutine(_, args) => { + ty::Coroutine(def_id, args) => { let coroutine_args = args.as_coroutine(); - Ok(ty::Binder::dummy(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()])) + Ok(ty::Binder::dummy(vec![ + coroutine_args.tupled_upvars_ty(), + Ty::new_coroutine_witness( + ecx.cx(), + def_id, + ecx.cx().mk_args(coroutine_args.parent_args().as_slice()), + ), + ])) } ty::CoroutineWitness(def_id, args) => Ok(ecx @@ -245,7 +252,14 @@ where Movability::Movable => { if ecx.cx().features().coroutine_clone() { let coroutine = args.as_coroutine(); - Ok(ty::Binder::dummy(vec![coroutine.tupled_upvars_ty(), coroutine.witness()])) + Ok(ty::Binder::dummy(vec![ + coroutine.tupled_upvars_ty(), + Ty::new_coroutine_witness( + ecx.cx(), + def_id, + ecx.cx().mk_args(coroutine.parent_args().as_slice()), + ), + ])) } else { Err(NoSolution) } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index af6dafb3062..62795c8a3a6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -1166,9 +1166,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if self.tcx().features().coroutine_clone() { let resolved_upvars = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty()); - let resolved_witness = - self.infcx.shallow_resolve(args.as_coroutine().witness()); - if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() { + if resolved_upvars.is_ty_var() { // Not yet resolved. candidates.ambiguous = true; } else { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e893add81c8..7ea1548f8f2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2196,7 +2196,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { args.as_coroutine() .upvar_tys() .iter() - .chain([args.as_coroutine().witness()]) + .chain([Ty::new_coroutine_witness( + self.tcx(), + coroutine_def_id, + self.tcx().mk_args(args.as_coroutine().parent_args()), + )]) .collect::>(), ) } else { @@ -2327,9 +2331,13 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ty::Binder::dummy(AutoImplConstituents { types: vec![ty], assumptions: vec![] }) } - ty::Coroutine(_, args) => { + ty::Coroutine(def_id, args) => { let ty = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty()); - let witness = args.as_coroutine().witness(); + let witness = Ty::new_coroutine_witness( + self.tcx(), + def_id, + self.tcx().mk_args(args.as_coroutine().parent_args()), + ); ty::Binder::dummy(AutoImplConstituents { types: [ty].into_iter().chain(iter::once(witness)).collect(), assumptions: vec![], diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index d1ca9bdb7fb..c32f8339d0b 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -101,7 +101,6 @@ use crate::{self as ty, Interner}; /// `yield` inside the coroutine. /// * `GR`: The "return type", which is the type of value returned upon /// completion of the coroutine. -/// * `GW`: The "coroutine witness". #[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] pub struct ClosureArgs { @@ -239,8 +238,6 @@ pub struct CoroutineClosureArgsParts { /// while the `tupled_upvars_ty`, representing the by-move version of the same /// captures, will be `(String,)`. pub coroutine_captures_by_ref_ty: I::Ty, - /// Witness type returned by the generator produced by this coroutine-closure. - pub coroutine_witness_ty: I::Ty, } impl CoroutineClosureArgs { @@ -251,7 +248,6 @@ impl CoroutineClosureArgs { parts.signature_parts_ty.into(), parts.tupled_upvars_ty.into(), parts.coroutine_captures_by_ref_ty.into(), - parts.coroutine_witness_ty.into(), ])), } } @@ -292,7 +288,6 @@ impl CoroutineClosureArgs { } pub fn coroutine_closure_sig(self) -> ty::Binder> { - let interior = self.coroutine_witness_ty(); let ty::FnPtr(sig_tys, hdr) = self.signature_parts_ty().kind() else { panic!() }; sig_tys.map_bound(|sig_tys| { let [resume_ty, tupled_inputs_ty] = *sig_tys.inputs().as_slice() else { @@ -302,7 +297,6 @@ impl CoroutineClosureArgs { panic!() }; CoroutineClosureSignature { - interior, tupled_inputs_ty, resume_ty, yield_ty, @@ -318,10 +312,6 @@ impl CoroutineClosureArgs { self.split().coroutine_captures_by_ref_ty } - pub fn coroutine_witness_ty(self) -> I::Ty { - self.split().coroutine_witness_ty - } - pub fn has_self_borrows(&self) -> bool { match self.coroutine_captures_by_ref_ty().kind() { ty::FnPtr(sig_tys, _) => sig_tys @@ -361,7 +351,6 @@ impl TypeVisitor for HasRegionsBoundAt { #[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] pub struct CoroutineClosureSignature { - pub interior: I::Ty, pub tupled_inputs_ty: I::Ty, pub resume_ty: I::Ty, pub yield_ty: I::Ty, @@ -407,7 +396,6 @@ impl CoroutineClosureSignature { resume_ty: self.resume_ty, yield_ty: self.yield_ty, return_ty: self.return_ty, - witness: self.interior, tupled_upvars_ty, }, ); @@ -587,11 +575,6 @@ pub struct CoroutineArgsParts { pub yield_ty: I::Ty, pub return_ty: I::Ty, - /// The interior type of the coroutine. - /// Represents all types that are stored in locals - /// in the coroutine's body. - pub witness: I::Ty, - /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. pub tupled_upvars_ty: I::Ty, @@ -607,7 +590,6 @@ impl CoroutineArgs { parts.resume_ty.into(), parts.yield_ty.into(), parts.return_ty.into(), - parts.witness.into(), parts.tupled_upvars_ty.into(), ])), } @@ -629,15 +611,6 @@ impl CoroutineArgs { self.split().kind_ty } - /// This describes the types that can be contained in a coroutine. - /// It will be a type variable initially and unified in the last stages of typeck of a body. - /// It contains a tuple of all the types that could end up on a coroutine frame. - /// The state transformation MIR pass may only produce layouts which mention types - /// in this tuple. Upvars are not counted here. - pub fn witness(self) -> I::Ty { - self.split().witness - } - /// Returns an iterator over the list of types of captured paths by the coroutine. /// In case there was a type error in figuring out the types of the captured path, an /// empty iterator is returned. diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 109a41d1ef9..9bff257e063 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -9,10 +9,6 @@ std::future::ResumeTy, (), (), - CoroutineWitness( - DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), - [], - ), (), ], ), @@ -30,10 +26,6 @@ std::future::ResumeTy, (), (), - CoroutineWitness( - DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), - [], - ), (), ], ), diff --git a/tests/ui/async-await/async-closures/def-path.stderr b/tests/ui/async-await/async-closures/def-path.stderr index 58a5b0b79c4..a507fa69760 100644 --- a/tests/ui/async-await/async-closures/def-path.stderr +++ b/tests/ui/async-await/async-closures/def-path.stderr @@ -5,11 +5,11 @@ LL | let x = async || {}; | -- the expected `async` closure body LL | LL | let () = x(); - | ^^ --- this expression has type `{static main::{closure#0}::{closure#0} upvar_tys=?15t resume_ty=ResumeTy yield_ty=() return_ty=() witness={main::{closure#0}::{closure#0}}}` + | ^^ --- this expression has type `{static main::{closure#0}::{closure#0} upvar_tys=?14t resume_ty=ResumeTy yield_ty=() return_ty=()}` | | | expected `async` closure body, found `()` | - = note: expected `async` closure body `{static main::{closure#0}::{closure#0} upvar_tys=?15t resume_ty=ResumeTy yield_ty=() return_ty=() witness={main::{closure#0}::{closure#0}}}` + = note: expected `async` closure body `{static main::{closure#0}::{closure#0} upvar_tys=?14t resume_ty=ResumeTy yield_ty=() return_ty=()}` found unit type `()` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr index d1f2d9a0753..d1c88101618 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr @@ -21,30 +21,6 @@ LL | Box::new(async { new(|| async { f().await }).await }) = help: consider pinning your async block and casting it to a trait object = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0308]: mismatched types - --> $DIR/higher-ranked-auto-trait-6.rs:16:5 - | -LL | Box::new(async { new(|| async { f().await }).await }) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` - found `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` - = note: no two async blocks, even if identical, have the same type - = help: consider pinning your async block and casting it to a trait object - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0308]: mismatched types - --> $DIR/higher-ranked-auto-trait-6.rs:16:5 - | -LL | Box::new(async { new(|| async { f().await }).await }) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` - found `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` - = note: no two async blocks, even if identical, have the same type - = help: consider pinning your async block and casting it to a trait object - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr index 8877d45ddda..11b78e3bcf8 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr @@ -9,7 +9,7 @@ LL | | drop(a); LL | | }); | |______^ coroutine is not `Sync` | - = help: within `{main::{closure#0} upvar_tys=() resume_ty=() yield_ty=() return_ty=() witness={main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync` + = help: within `{main::{closure#0} upvar_tys=() resume_ty=() yield_ty=() return_ty=()}`, the trait `Sync` is not implemented for `NotSync` note: coroutine is not `Sync` as this value is used across a yield --> $DIR/coroutine-print-verbose-2.rs:20:9 | @@ -34,7 +34,7 @@ LL | | drop(a); LL | | }); | |______^ coroutine is not `Send` | - = help: within `{main::{closure#1} upvar_tys=() resume_ty=() yield_ty=() return_ty=() witness={main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend` + = help: within `{main::{closure#1} upvar_tys=() resume_ty=() yield_ty=() return_ty=()}`, the trait `Send` is not implemented for `NotSend` note: coroutine is not `Send` as this value is used across a yield --> $DIR/coroutine-print-verbose-2.rs:27:9 | diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr index 4a1e5b078a8..135e8175793 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr @@ -11,7 +11,7 @@ LL | | }; | |_____^ expected `()`, found coroutine | = note: expected unit type `()` - found coroutine `{main::{closure#0} upvar_tys=?4t resume_ty=() yield_ty=i32 return_ty=&'?1 str witness={main::{closure#0}}}` + found coroutine `{main::{closure#0} upvar_tys=?4t resume_ty=() yield_ty=i32 return_ty=&'?1 str}` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-55872-2.rs b/tests/ui/impl-trait/issues/issue-55872-2.rs index a3b2225126a..aea00dd9e3d 100644 --- a/tests/ui/impl-trait/issues/issue-55872-2.rs +++ b/tests/ui/impl-trait/issues/issue-55872-2.rs @@ -12,7 +12,6 @@ impl Bar for S { type E = impl std::marker::Send; fn foo() -> Self::E { //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - //~| ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias async {} } } diff --git a/tests/ui/impl-trait/issues/issue-55872-2.stderr b/tests/ui/impl-trait/issues/issue-55872-2.stderr index 51a7dd00ade..91c2ecdc8a4 100644 --- a/tests/ui/impl-trait/issues/issue-55872-2.stderr +++ b/tests/ui/impl-trait/issues/issue-55872-2.stderr @@ -4,13 +4,5 @@ error: type parameter `T` is part of concrete type but not used in parameter lis LL | fn foo() -> Self::E { | ^^^^^^^ -error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:13:20 - | -LL | fn foo() -> Self::E { - | ^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-55872-3.rs b/tests/ui/impl-trait/issues/issue-55872-3.rs index 763b4b9fd32..698e7f36234 100644 --- a/tests/ui/impl-trait/issues/issue-55872-3.rs +++ b/tests/ui/impl-trait/issues/issue-55872-3.rs @@ -14,7 +14,6 @@ impl Bar for S { fn foo() -> Self::E { //~^ ERROR : Copy` is not satisfied [E0277] //~| ERROR type parameter `T` is part of concrete type - //~| ERROR type parameter `T` is part of concrete type async {} } } diff --git a/tests/ui/impl-trait/issues/issue-55872-3.stderr b/tests/ui/impl-trait/issues/issue-55872-3.stderr index b7711e47468..5124c46baeb 100644 --- a/tests/ui/impl-trait/issues/issue-55872-3.stderr +++ b/tests/ui/impl-trait/issues/issue-55872-3.stderr @@ -4,20 +4,12 @@ error: type parameter `T` is part of concrete type but not used in parameter lis LL | fn foo() -> Self::E { | ^^^^^^^ -error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-3.rs:14:20 - | -LL | fn foo() -> Self::E { - | ^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}: Copy` is not satisfied +error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}: Copy` is not satisfied --> $DIR/issue-55872-3.rs:14:20 | LL | fn foo() -> Self::E { - | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}` + | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. -- cgit 1.4.1-3-g733a5