1
Fork 0

Rollup merge of #114079 - compiler-errors:closure-upvars, r=oli-obk

Use `upvar_tys` in more places, make it return a list

Just a cleanup that fell out of a PR that I was gonna write, but that PR kinda got stuck.
This commit is contained in:
Nilstrieb 2023-08-02 13:46:54 +02:00 committed by GitHub
commit 46f6b05eb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 66 additions and 78 deletions

View file

@ -886,6 +886,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
.universal_regions() .universal_regions()
.defining_ty .defining_ty
.upvar_tys() .upvar_tys()
.iter()
.position(|ty| self.any_param_predicate_mentions(&predicates, ty, region)) .position(|ty| self.any_param_predicate_mentions(&predicates, ty, region))
{ {
let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region( let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(

View file

@ -43,7 +43,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fr: RegionVid, fr: RegionVid,
) -> Option<usize> { ) -> Option<usize> {
let upvar_index = let upvar_index =
self.universal_regions().defining_ty.upvar_tys().position(|upvar_ty| { self.universal_regions().defining_ty.upvar_tys().iter().position(|upvar_ty| {
debug!("get_upvar_index_for_region: upvar_ty={upvar_ty:?}"); debug!("get_upvar_index_for_region: upvar_ty={upvar_ty:?}");
tcx.any_free_region_meets(&upvar_ty, |r| { tcx.any_free_region_meets(&upvar_ty, |r| {
let r = r.as_var(); let r = r.as_var();
@ -52,7 +52,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}) })
})?; })?;
let upvar_ty = self.universal_regions().defining_ty.upvar_tys().nth(upvar_index); let upvar_ty = self.universal_regions().defining_ty.upvar_tys().get(upvar_index);
debug!( debug!(
"get_upvar_index_for_region: found {fr:?} in upvar {upvar_index} which has type {upvar_ty:?}", "get_upvar_index_for_region: found {fr:?} in upvar {upvar_index} which has type {upvar_ty:?}",

View file

@ -791,25 +791,20 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
(adt_def.variant(FIRST_VARIANT), args) (adt_def.variant(FIRST_VARIANT), args)
} }
ty::Closure(_, args) => { ty::Closure(_, args) => {
return match args return match args.as_closure().upvar_tys().get(field.index()) {
.as_closure()
.tupled_upvars_ty()
.tuple_fields()
.get(field.index())
{
Some(&ty) => Ok(ty), Some(&ty) => Ok(ty),
None => Err(FieldAccessError::OutOfRange { None => Err(FieldAccessError::OutOfRange {
field_count: args.as_closure().upvar_tys().count(), field_count: args.as_closure().upvar_tys().len(),
}), }),
}; };
} }
ty::Generator(_, args, _) => { ty::Generator(_, args, _) => {
// Only prefix fields (upvars and current state) are // Only prefix fields (upvars and current state) are
// accessible without a variant index. // accessible without a variant index.
return match args.as_generator().prefix_tys().nth(field.index()) { return match args.as_generator().prefix_tys().get(field.index()) {
Some(ty) => Ok(ty), Some(ty) => Ok(*ty),
None => Err(FieldAccessError::OutOfRange { None => Err(FieldAccessError::OutOfRange {
field_count: args.as_generator().prefix_tys().count(), field_count: args.as_generator().prefix_tys().len(),
}), }),
}; };
} }
@ -1772,10 +1767,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
AggregateKind::Closure(_, args) => { AggregateKind::Closure(_, args) => {
match args.as_closure().upvar_tys().nth(field_index.as_usize()) { match args.as_closure().upvar_tys().get(field_index.as_usize()) {
Some(ty) => Ok(ty), Some(ty) => Ok(*ty),
None => Err(FieldAccessError::OutOfRange { None => Err(FieldAccessError::OutOfRange {
field_count: args.as_closure().upvar_tys().count(), field_count: args.as_closure().upvar_tys().len(),
}), }),
} }
} }
@ -1783,10 +1778,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// It doesn't make sense to look at a field beyond the prefix; // It doesn't make sense to look at a field beyond the prefix;
// these require a variant index, and are not initialized in // these require a variant index, and are not initialized in
// aggregate rvalues. // aggregate rvalues.
match args.as_generator().prefix_tys().nth(field_index.as_usize()) { match args.as_generator().prefix_tys().get(field_index.as_usize()) {
Some(ty) => Ok(ty), Some(ty) => Ok(*ty),
None => Err(FieldAccessError::OutOfRange { None => Err(FieldAccessError::OutOfRange {
field_count: args.as_generator().prefix_tys().count(), field_count: args.as_generator().prefix_tys().len(),
}), }),
} }
} }

View file

@ -12,7 +12,6 @@
//! The code in this file doesn't *do anything* with those results; it //! The code in this file doesn't *do anything* with those results; it
//! just returns them for other code to use. //! just returns them for other code to use.
use either::Either;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Diagnostic; use rustc_errors::Diagnostic;
use rustc_hir as hir; use rustc_hir as hir;
@ -115,14 +114,12 @@ impl<'tcx> DefiningTy<'tcx> {
/// not a closure or generator, there are no upvars, and hence it /// not a closure or generator, there are no upvars, and hence it
/// will be an empty list. The order of types in this list will /// will be an empty list. The order of types in this list will
/// match up with the upvar order in the HIR, typesystem, and MIR. /// match up with the upvar order in the HIR, typesystem, and MIR.
pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx { pub fn upvar_tys(self) -> &'tcx ty::List<Ty<'tcx>> {
match self { match self {
DefiningTy::Closure(_, args) => Either::Left(args.as_closure().upvar_tys()), DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(),
DefiningTy::Generator(_, args, _) => { DefiningTy::Generator(_, args, _) => args.as_generator().upvar_tys(),
Either::Right(Either::Left(args.as_generator().upvar_tys()))
}
DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => { DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => {
Either::Right(Either::Right(iter::empty())) ty::List::empty()
} }
} }
} }

View file

@ -990,14 +990,8 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
closure_or_generator_di_node: &'ll DIType, closure_or_generator_di_node: &'ll DIType,
) -> SmallVec<&'ll DIType> { ) -> SmallVec<&'ll DIType> {
let (&def_id, up_var_tys) = match closure_or_generator_ty.kind() { let (&def_id, up_var_tys) = match closure_or_generator_ty.kind() {
ty::Generator(def_id, args, _) => { ty::Generator(def_id, args, _) => (def_id, args.as_generator().prefix_tys()),
let upvar_tys: SmallVec<_> = args.as_generator().prefix_tys().collect(); ty::Closure(def_id, args) => (def_id, args.as_closure().upvar_tys()),
(def_id, upvar_tys)
}
ty::Closure(def_id, args) => {
let upvar_tys: SmallVec<_> = args.as_closure().upvar_tys().collect();
(def_id, upvar_tys)
}
_ => { _ => {
bug!( bug!(
"build_upvar_field_di_nodes() called with non-closure-or-generator-type: {:?}", "build_upvar_field_di_nodes() called with non-closure-or-generator-type: {:?}",
@ -1007,9 +1001,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
}; };
debug_assert!( debug_assert!(
up_var_tys up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
.iter()
.all(|&t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
); );
let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id); let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);

View file

@ -379,6 +379,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
// Fields that are common to all states // Fields that are common to all states
let common_fields: SmallVec<_> = generator_args let common_fields: SmallVec<_> = generator_args
.prefix_tys() .prefix_tys()
.iter()
.zip(common_upvar_names) .zip(common_upvar_names)
.enumerate() .enumerate()
.map(|(index, (upvar_ty, upvar_name))| { .map(|(index, (upvar_ty, upvar_name))| {

View file

@ -630,7 +630,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
} }
ty::Closure(_, args) => { ty::Closure(_, args) => {
let args = args.as_closure(); let args = args.as_closure();
let Some(f_ty) = args.upvar_tys().nth(f.as_usize()) else { let Some(&f_ty) = args.upvar_tys().get(f.as_usize()) else {
fail_out_of_bounds(self, location); fail_out_of_bounds(self, location);
return; return;
}; };
@ -667,7 +667,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
f_ty.ty f_ty.ty
} else { } else {
let Some(f_ty) = args.as_generator().prefix_tys().nth(f.index()) else { let Some(&f_ty) = args.as_generator().prefix_tys().get(f.index())
else {
fail_out_of_bounds(self, location); fail_out_of_bounds(self, location);
return; return;
}; };

View file

@ -448,7 +448,9 @@ where
ty::Closure(_, ref args) => { ty::Closure(_, ref args) => {
// Skip lifetime parameters of the enclosing item(s) // Skip lifetime parameters of the enclosing item(s)
args.as_closure().tupled_upvars_ty().visit_with(self); for upvar in args.as_closure().upvar_tys() {
upvar.visit_with(self);
}
args.as_closure().sig_as_fn_ptr_ty().visit_with(self); args.as_closure().sig_as_fn_ptr_ty().visit_with(self);
} }
@ -456,7 +458,9 @@ where
// Skip lifetime parameters of the enclosing item(s) // Skip lifetime parameters of the enclosing item(s)
// Also skip the witness type, because that has no free regions. // Also skip the witness type, because that has no free regions.
args.as_generator().tupled_upvars_ty().visit_with(self); for upvar in args.as_generator().upvar_tys() {
upvar.visit_with(self);
}
args.as_generator().return_ty().visit_with(self); args.as_generator().return_ty().visit_with(self);
args.as_generator().yield_ty().visit_with(self); args.as_generator().yield_ty().visit_with(self);
args.as_generator().resume_ty().visit_with(self); args.as_generator().resume_ty().visit_with(self);

View file

@ -911,7 +911,7 @@ where
if i == tag_field { if i == tag_field {
return TyMaybeWithLayout::TyAndLayout(tag_layout(tag)); return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
} }
TyMaybeWithLayout::Ty(args.as_generator().prefix_tys().nth(i).unwrap()) TyMaybeWithLayout::Ty(args.as_generator().prefix_tys()[i])
} }
}, },

View file

@ -827,7 +827,7 @@ pub trait PrettyPrinter<'tcx>:
if !args.as_generator().is_valid() { if !args.as_generator().is_valid() {
p!("unavailable"); p!("unavailable");
} else { } else {
self = self.comma_sep(args.as_generator().upvar_tys())?; self = self.comma_sep(args.as_generator().upvar_tys().iter())?;
} }
p!(")"); p!(")");
@ -900,7 +900,7 @@ pub trait PrettyPrinter<'tcx>:
print(args.as_closure().sig_as_fn_ptr_ty()) print(args.as_closure().sig_as_fn_ptr_ty())
); );
p!(" upvar_tys=("); p!(" upvar_tys=(");
self = self.comma_sep(args.as_closure().upvar_tys())?; self = self.comma_sep(args.as_closure().upvar_tys().iter())?;
p!(")"); p!(")");
} }
} }

View file

@ -296,15 +296,13 @@ impl<'tcx> ClosureArgs<'tcx> {
/// In case there was a type error in figuring out the types of the captured path, an /// In case there was a type error in figuring out the types of the captured path, an
/// empty iterator is returned. /// empty iterator is returned.
#[inline] #[inline]
pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx { pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
match self.tupled_upvars_ty().kind() { match self.tupled_upvars_ty().kind() {
TyKind::Error(_) => None, TyKind::Error(_) => ty::List::empty(),
TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(),
TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
} }
.into_iter()
.flatten()
} }
/// Returns the tuple type representing the upvars for this closure. /// Returns the tuple type representing the upvars for this closure.
@ -436,15 +434,13 @@ impl<'tcx> GeneratorArgs<'tcx> {
/// In case there was a type error in figuring out the types of the captured path, an /// In case there was a type error in figuring out the types of the captured path, an
/// empty iterator is returned. /// empty iterator is returned.
#[inline] #[inline]
pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx { pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
match self.tupled_upvars_ty().kind() { match self.tupled_upvars_ty().kind() {
TyKind::Error(_) => None, TyKind::Error(_) => ty::List::empty(),
TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(),
TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
} }
.into_iter()
.flatten()
} }
/// Returns the tuple type representing the upvars for this generator. /// Returns the tuple type representing the upvars for this generator.
@ -576,7 +572,7 @@ impl<'tcx> GeneratorArgs<'tcx> {
/// This is the types of the fields of a generator which are not stored in a /// This is the types of the fields of a generator which are not stored in a
/// variant. /// variant.
#[inline] #[inline]
pub fn prefix_tys(self) -> impl Iterator<Item = Ty<'tcx>> { pub fn prefix_tys(self) -> &'tcx List<Ty<'tcx>> {
self.upvar_tys() self.upvar_tys()
} }
} }
@ -592,20 +588,18 @@ impl<'tcx> UpvarArgs<'tcx> {
/// In case there was a type error in figuring out the types of the captured path, an /// In case there was a type error in figuring out the types of the captured path, an
/// empty iterator is returned. /// empty iterator is returned.
#[inline] #[inline]
pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx { pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
let tupled_tys = match self { let tupled_tys = match self {
UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(), UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(),
UpvarArgs::Generator(args) => args.as_generator().tupled_upvars_ty(), UpvarArgs::Generator(args) => args.as_generator().tupled_upvars_ty(),
}; };
match tupled_tys.kind() { match tupled_tys.kind() {
TyKind::Error(_) => None, TyKind::Error(_) => ty::List::empty(),
TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(),
TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
} }
.into_iter()
.flatten()
} }
#[inline] #[inline]

View file

@ -860,20 +860,14 @@ where
fn open_drop(&mut self) -> BasicBlock { fn open_drop(&mut self) -> BasicBlock {
let ty = self.place_ty(self.place); let ty = self.place_ty(self.place);
match ty.kind() { match ty.kind() {
ty::Closure(_, args) => { ty::Closure(_, args) => self.open_drop_for_tuple(&args.as_closure().upvar_tys()),
let tys: Vec<_> = args.as_closure().upvar_tys().collect();
self.open_drop_for_tuple(&tys)
}
// Note that `elaborate_drops` only drops the upvars of a generator, // Note that `elaborate_drops` only drops the upvars of a generator,
// and this is ok because `open_drop` here can only be reached // and this is ok because `open_drop` here can only be reached
// within that own generator's resume function. // within that own generator's resume function.
// This should only happen for the self argument on the resume function. // This should only happen for the self argument on the resume function.
// It effectively only contains upvars until the generator transformation runs. // It effectively only contains upvars until the generator transformation runs.
// See librustc_body/transform/generator.rs for more details. // See librustc_body/transform/generator.rs for more details.
ty::Generator(_, args, _) => { ty::Generator(_, args, _) => self.open_drop_for_tuple(&args.as_generator().upvar_tys()),
let tys: Vec<_> = args.as_generator().upvar_tys().collect();
self.open_drop_for_tuple(&tys)
}
ty::Tuple(fields) => self.open_drop_for_tuple(fields), ty::Tuple(fields) => self.open_drop_for_tuple(fields),
ty::Adt(def, args) => self.open_drop_for_adt(*def, args), ty::Adt(def, args) => self.open_drop_for_adt(*def, args),
ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind), ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind),

View file

@ -856,7 +856,7 @@ fn sanitize_witness<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
witness: Ty<'tcx>, witness: Ty<'tcx>,
upvars: Vec<Ty<'tcx>>, upvars: &'tcx ty::List<Ty<'tcx>>,
layout: &GeneratorLayout<'tcx>, layout: &GeneratorLayout<'tcx>,
) { ) {
let did = body.source.def_id(); let did = body.source.def_id();
@ -1471,7 +1471,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
let args = args.as_generator(); let args = args.as_generator();
( (
args.discr_ty(tcx), args.discr_ty(tcx),
args.upvar_tys().collect::<Vec<_>>(), args.upvar_tys(),
args.witness(), args.witness(),
movability == hir::Movability::Movable, movability == hir::Movability::Movable,
) )

View file

@ -291,9 +291,9 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
return Err(NoSolution); return Err(NoSolution);
} }
constraints.outlives.extend( constraints
args.as_generator().upvar_tys().map(|t| -> ty::GenericArg<'tcx> { t.into() }), .outlives
); .extend(args.as_generator().upvar_tys().iter().map(ty::GenericArg::from));
constraints.outlives.push(args.as_generator().resume_ty().into()); constraints.outlives.push(args.as_generator().resume_ty().into());
} }

View file

@ -2169,7 +2169,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
let all = args let all = args
.as_generator() .as_generator()
.upvar_tys() .upvar_tys()
.chain(iter::once(args.as_generator().witness())) .iter()
.chain([args.as_generator().witness()])
.collect::<Vec<_>>(); .collect::<Vec<_>>();
Where(obligation.predicate.rebind(all)) Where(obligation.predicate.rebind(all))
} }
@ -2210,7 +2211,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
// Not yet resolved. // Not yet resolved.
Ambiguous Ambiguous
} else { } else {
Where(obligation.predicate.rebind(args.as_closure().upvar_tys().collect())) Where(obligation.predicate.rebind(args.as_closure().upvar_tys().to_vec()))
} }
} }

View file

@ -317,7 +317,9 @@ fn layout_of_uncached<'tcx>(
ty::Closure(_, ref args) => { ty::Closure(_, ref args) => {
let tys = args.as_closure().upvar_tys(); let tys = args.as_closure().upvar_tys();
univariant( univariant(
&tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).try_collect::<IndexVec<_, _>>()?, &tys.iter()
.map(|ty| Ok(cx.layout_of(ty)?.layout))
.try_collect::<IndexVec<_, _>>()?,
&ReprOptions::default(), &ReprOptions::default(),
StructKind::AlwaysSized, StructKind::AlwaysSized,
)? )?
@ -729,7 +731,7 @@ fn generator_layout<'tcx>(
// Build a prefix layout, including "promoting" all ineligible // Build a prefix layout, including "promoting" all ineligible
// locals as part of the prefix. We compute the layout of all of // locals as part of the prefix. We compute the layout of all of
// these fields at once to get optimal packing. // these fields at once to get optimal packing.
let tag_index = args.as_generator().prefix_tys().count(); let tag_index = args.as_generator().prefix_tys().len();
// `info.variant_fields` already accounts for the reserved variants, so no need to add them. // `info.variant_fields` already accounts for the reserved variants, so no need to add them.
let max_discr = (info.variant_fields.len() - 1) as u128; let max_discr = (info.variant_fields.len() - 1) as u128;
@ -748,6 +750,7 @@ fn generator_layout<'tcx>(
let prefix_layouts = args let prefix_layouts = args
.as_generator() .as_generator()
.prefix_tys() .prefix_tys()
.iter()
.map(|ty| Ok(cx.layout_of(ty)?.layout)) .map(|ty| Ok(cx.layout_of(ty)?.layout))
.chain(iter::once(Ok(tag_layout))) .chain(iter::once(Ok(tag_layout)))
.chain(promoted_layouts) .chain(promoted_layouts)
@ -1062,6 +1065,7 @@ fn variant_info_for_generator<'tcx>(
let upvar_fields: Vec<_> = args let upvar_fields: Vec<_> = args
.as_generator() .as_generator()
.upvar_tys() .upvar_tys()
.iter()
.zip(upvar_names) .zip(upvar_names)
.enumerate() .enumerate()
.map(|(field_idx, (_, name))| { .map(|(field_idx, (_, name))| {

View file

@ -120,12 +120,16 @@ where
_ if component.is_copy_modulo_regions(tcx, self.param_env) => (), _ if component.is_copy_modulo_regions(tcx, self.param_env) => (),
ty::Closure(_, args) => { ty::Closure(_, args) => {
queue_type(self, args.as_closure().tupled_upvars_ty()); for upvar in args.as_closure().upvar_tys() {
queue_type(self, upvar);
}
} }
ty::Generator(def_id, args, _) => { ty::Generator(def_id, args, _) => {
let args = args.as_generator(); let args = args.as_generator();
queue_type(self, args.tupled_upvars_ty()); for upvar in args.upvar_tys() {
queue_type(self, upvar);
}
let witness = args.witness(); let witness = args.witness();
let interior_tys = match witness.kind() { let interior_tys = match witness.kind() {