Skip to content

Commit d991d6e

Browse files
arora-amanroxelo
andcommitted
Ensure no type errors when calling Closure/Generator upvars_ty
Fixes #77993 Co-authored-by: Roxane Fruytier <[email protected]>
1 parent 89fdb30 commit d991d6e

File tree

17 files changed

+194
-51
lines changed

17 files changed

+194
-51
lines changed

compiler/rustc_middle/src/ty/flags.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ impl FlagComputation {
104104
self.add_ty(substs.return_ty());
105105
self.add_ty(substs.witness());
106106
self.add_ty(substs.yield_ty());
107-
self.add_ty(substs.tupled_upvars_ty());
107+
if let Ok(tupled_ty) = substs.tupled_upvars_ty() {
108+
self.add_ty(tupled_ty);
109+
}
108110
}
109111

110112
&ty::GeneratorWitness(ts) => {
@@ -122,7 +124,9 @@ impl FlagComputation {
122124

123125
self.add_ty(substs.sig_as_fn_ptr_ty());
124126
self.add_ty(substs.kind_ty());
125-
self.add_ty(substs.tupled_upvars_ty());
127+
if let Ok(tupled_ty) = substs.tupled_upvars_ty() {
128+
self.add_ty(tupled_ty);
129+
}
126130
}
127131

128132
&ty::Bound(debruijn, _) => {

compiler/rustc_middle/src/ty/instance.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -506,9 +506,9 @@ fn polymorphize<'tcx>(
506506
// the unpolymorphized upvar closure would result in a polymorphized closure producing
507507
// multiple mono items (and eventually symbol clashes).
508508
let upvars_ty = if tcx.is_closure(def_id) {
509-
Some(substs.as_closure().tupled_upvars_ty())
509+
substs.as_closure().tupled_upvars_ty().ok()
510510
} else if tcx.type_of(def_id).is_generator() {
511-
Some(substs.as_generator().tupled_upvars_ty())
511+
substs.as_generator().tupled_upvars_ty().ok()
512512
} else {
513513
None
514514
};

compiler/rustc_middle/src/ty/layout.rs

+21-8
Original file line numberDiff line numberDiff line change
@@ -609,12 +609,23 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
609609
ty::Generator(def_id, substs, _) => self.generator_layout(ty, def_id, substs)?,
610610

611611
ty::Closure(_, ref substs) => {
612-
let tys = substs.as_closure().upvar_tys();
613-
univariant(
614-
&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
615-
&ReprOptions::default(),
616-
StructKind::AlwaysSized,
617-
)?
612+
let substs = substs.as_closure();
613+
if substs.tupled_upvars_ty().is_ok() {
614+
let tys = substs.upvar_tys();
615+
univariant(
616+
&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
617+
&ReprOptions::default(),
618+
StructKind::AlwaysSized,
619+
)?
620+
} else {
621+
univariant(
622+
&std::iter::empty()
623+
.map(|ty| self.layout_of(ty))
624+
.collect::<Result<Vec<_>, _>>()?,
625+
&ReprOptions::default(),
626+
StructKind::AlwaysSized,
627+
)?
628+
}
618629
}
619630

620631
ty::Tuple(tys) => {
@@ -1396,10 +1407,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
13961407
let info = tcx.generator_layout(def_id);
13971408
let (ineligible_locals, assignments) = self.generator_saved_local_eligibility(&info);
13981409

1410+
let substs = substs.as_generator();
1411+
13991412
// Build a prefix layout, including "promoting" all ineligible
14001413
// locals as part of the prefix. We compute the layout of all of
14011414
// these fields at once to get optimal packing.
1402-
let tag_index = substs.as_generator().prefix_tys().count();
1415+
let tag_index =
1416+
if substs.tupled_upvars_ty().is_ok() { substs.prefix_tys().count() } else { 0 };
14031417

14041418
// `info.variant_fields` already accounts for the reserved variants, so no need to add them.
14051419
let max_discr = (info.variant_fields.len() - 1) as u128;
@@ -1415,7 +1429,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
14151429
.map(|ty| tcx.mk_maybe_uninit(ty))
14161430
.map(|ty| self.layout_of(ty));
14171431
let prefix_layouts = substs
1418-
.as_generator()
14191432
.prefix_tys()
14201433
.map(|ty| self.layout_of(ty))
14211434
.chain(iter::once(Ok(tag_layout)))

compiler/rustc_middle/src/ty/outlives.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,16 @@ fn compute_components(
9696
}
9797

9898
ty::Closure(_, ref substs) => {
99-
let tupled_ty = substs.as_closure().tupled_upvars_ty();
100-
compute_components(tcx, tupled_ty, out, visited);
99+
if let Ok(tupled_ty) = substs.as_closure().tupled_upvars_ty() {
100+
compute_components(tcx, tupled_ty, out, visited);
101+
}
101102
}
102103

103104
ty::Generator(_, ref substs, _) => {
104105
// Same as the closure case
105-
let tupled_ty = substs.as_generator().tupled_upvars_ty();
106-
compute_components(tcx, tupled_ty, out, visited);
106+
if let Ok(tupled_ty) = substs.as_generator().tupled_upvars_ty() {
107+
compute_components(tcx, tupled_ty, out, visited);
108+
}
107109

108110
// We ignore regions in the generator interior as we don't
109111
// want these to affect region inference

compiler/rustc_middle/src/ty/print/pretty.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,11 @@ pub trait PrettyPrinter<'tcx>:
664664
p!(print_def_path(did, substs));
665665
p!(" upvar_tys=(");
666666
if !substs.as_generator().is_valid() {
667-
p!("unavailable");
667+
if substs.as_generator().tupled_upvars_ty().is_err() {
668+
p!("err");
669+
} else {
670+
p!("unavailable");
671+
}
668672
} else {
669673
self = self.comma_sep(substs.as_generator().upvar_tys())?;
670674
}
@@ -699,7 +703,13 @@ pub trait PrettyPrinter<'tcx>:
699703
} else {
700704
p!(print_def_path(did, substs));
701705
if !substs.as_closure().is_valid() {
702-
p!(" closure_substs=(unavailable)");
706+
p!(" closure_substs=(");
707+
if substs.as_closure().tupled_upvars_ty().is_err() {
708+
p!("err");
709+
} else {
710+
p!("unavailable");
711+
}
712+
p!(")");
703713
} else {
704714
p!(" closure_kind_ty=", print(substs.as_closure().kind_ty()));
705715
p!(

compiler/rustc_middle/src/ty/sty.rs

+34-9
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS};
1414
use polonius_engine::Atom;
1515
use rustc_ast as ast;
1616
use rustc_data_structures::captures::Captures;
17+
use rustc_errors::ErrorReported;
1718
use rustc_hir as hir;
1819
use rustc_hir::def_id::DefId;
1920
use rustc_index::vec::Idx;
@@ -388,15 +389,23 @@ impl<'tcx> ClosureSubsts<'tcx> {
388389
self.split().parent_substs
389390
}
390391

392+
/// Returns an iterator that iterates the types of paths captured by a closure.
393+
/// Note it's possible that there was a type error that prevented us from figuring out
394+
/// the types of the upvars captured by the closure.
395+
///
396+
/// This function can be safely called if `self.tupled_upvars_ty().is_ok()` is true.
391397
#[inline]
392398
pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
393-
self.tupled_upvars_ty().tuple_fields()
399+
self.split().tupled_upvars_ty.expect_ty().tuple_fields()
394400
}
395401

396-
/// Returns the tuple type representing the upvars for this closure.
402+
/// Returns a tuple type containing the types of paths captured by the closure.
403+
/// Returns Err(ErrorReported) if a type error prevented us from figuring out
404+
/// the types of the upvars for this closure.
397405
#[inline]
398-
pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
399-
self.split().tupled_upvars_ty.expect_ty()
406+
pub fn tupled_upvars_ty(self) -> Result<Ty<'tcx>, ErrorReported> {
407+
let tupled_ty = self.split().tupled_upvars_ty.expect_ty();
408+
if let TyKind::Error(_) = tupled_ty.kind() { Err(ErrorReported) } else { Ok(tupled_ty) }
400409
}
401410

402411
/// Returns the closure kind for this closure; may return a type
@@ -515,15 +524,23 @@ impl<'tcx> GeneratorSubsts<'tcx> {
515524
self.split().witness.expect_ty()
516525
}
517526

527+
/// Returns an iterator that iterates the types of paths captured by a generator.
528+
/// Note it's possible that there was a type error that prevented us from figuring out
529+
/// the types of the upvars captured by the generator.
530+
///
531+
/// This function can be safely called if `self.tupled_upvars_ty().is_ok()` is true.
518532
#[inline]
519533
pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
520-
self.tupled_upvars_ty().tuple_fields()
534+
self.split().tupled_upvars_ty.expect_ty().tuple_fields()
521535
}
522536

523-
/// Returns the tuple type representing the upvars for this generator.
537+
/// Returns a tuple type containing the types of paths captured by the generator.
538+
/// Returns Err(ErrorReported) if a type error prevented us from figuring out
539+
/// the types of the upvars for this generator.
524540
#[inline]
525-
pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
526-
self.split().tupled_upvars_ty.expect_ty()
541+
pub fn tupled_upvars_ty(self) -> Result<Ty<'tcx>, ErrorReported> {
542+
let tupled_ty = self.split().tupled_upvars_ty.expect_ty();
543+
if let TyKind::Error(_) = tupled_ty.kind() { Err(ErrorReported) } else { Ok(tupled_ty) }
527544
}
528545

529546
/// Returns the type representing the resume type of the generator.
@@ -660,6 +677,11 @@ pub enum UpvarSubsts<'tcx> {
660677
}
661678

662679
impl<'tcx> UpvarSubsts<'tcx> {
680+
/// Returns an iterator that iterates the types of paths captured by a closure/generator.
681+
/// Note it's possible that there was a type error that prevented us from figuring out
682+
/// the types of the upvars captured by the closure/generator.
683+
///
684+
/// This function can be safely called if `self.tupled_upvars_ty().is_ok()` is true.
663685
#[inline]
664686
pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
665687
let tupled_upvars_ty = match self {
@@ -669,8 +691,11 @@ impl<'tcx> UpvarSubsts<'tcx> {
669691
tupled_upvars_ty.expect_ty().tuple_fields()
670692
}
671693

694+
/// Returns a tuple type containing the types of paths captured by a closure/generator.
695+
/// Returns Err(ErrorReported) if a type error prevented us from figuring out
696+
/// the types of the upvars for this closure/generator.
672697
#[inline]
673-
pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
698+
pub fn tupled_upvars_ty(self) -> Result<Ty<'tcx>, ErrorReported> {
674699
match self {
675700
UpvarSubsts::Closure(substs) => substs.as_closure().tupled_upvars_ty(),
676701
UpvarSubsts::Generator(substs) => substs.as_generator().tupled_upvars_ty(),

compiler/rustc_mir/src/util/elaborate_drops.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,12 @@ where
850850
let ty = self.place_ty(self.place);
851851
match ty.kind() {
852852
ty::Closure(_, substs) => {
853-
let tys: Vec<_> = substs.as_closure().upvar_tys().collect();
853+
let substs = substs.as_closure();
854+
let tys: Vec<_> = if substs.tupled_upvars_ty().is_ok() {
855+
substs.upvar_tys().collect()
856+
} else {
857+
vec![]
858+
};
854859
self.open_drop_for_tuple(&tys)
855860
}
856861
// Note that `elaborate_drops` only drops the upvars of a generator,
@@ -860,7 +865,12 @@ where
860865
// It effetively only contains upvars until the generator transformation runs.
861866
// See librustc_body/transform/generator.rs for more details.
862867
ty::Generator(_, substs, _) => {
863-
let tys: Vec<_> = substs.as_generator().upvar_tys().collect();
868+
let substs = substs.as_generator();
869+
let tys: Vec<_> = if substs.tupled_upvars_ty().is_ok() {
870+
substs.upvar_tys().collect()
871+
} else {
872+
vec![]
873+
};
864874
self.open_drop_for_tuple(&tys)
865875
}
866876
ty::Tuple(..) => {

compiler/rustc_trait_selection/src/opaque_types.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -717,10 +717,12 @@ where
717717
ty::Closure(_, ref substs) => {
718718
// Skip lifetime parameters of the enclosing item(s)
719719

720-
substs.as_closure().tupled_upvars_ty().visit_with(self);
720+
if let Ok(tupled_ty) = substs.as_closure().tupled_upvars_ty() {
721+
tupled_ty.visit_with(self);
721722

722-
for upvar_ty in substs.as_closure().upvar_tys() {
723-
upvar_ty.visit_with(self);
723+
for upvar_ty in substs.as_closure().upvar_tys() {
724+
upvar_ty.visit_with(self);
725+
}
724726
}
725727

726728
substs.as_closure().sig_as_fn_ptr_ty().visit_with(self);
@@ -730,10 +732,12 @@ where
730732
// Skip lifetime parameters of the enclosing item(s)
731733
// Also skip the witness type, because that has no free regions.
732734

733-
substs.as_generator().tupled_upvars_ty().visit_with(self);
735+
if let Ok(tupled_ty) = substs.as_generator().tupled_upvars_ty() {
736+
tupled_ty.visit_with(self);
734737

735-
for upvar_ty in substs.as_generator().upvar_tys() {
736-
upvar_ty.visit_with(self);
738+
for upvar_ty in substs.as_closure().upvar_tys() {
739+
upvar_ty.visit_with(self);
740+
}
737741
}
738742

739743
substs.as_generator().return_ty().visit_with(self);

compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,12 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
110110
// check if *any* of those are trivial.
111111
ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())),
112112
ty::Closure(_, ref substs) => {
113-
trivial_dropck_outlives(tcx, substs.as_closure().tupled_upvars_ty())
113+
if let Ok(tupled_tys) = substs.as_closure().tupled_upvars_ty() {
114+
trivial_dropck_outlives(tcx, tupled_tys)
115+
} else {
116+
// Same as the error case above
117+
true
118+
}
114119
}
115120

116121
ty::Adt(def, _) => {

compiler/rustc_trait_selection/src/traits/select/mod.rs

+25-9
Original file line numberDiff line numberDiff line change
@@ -1601,12 +1601,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16011601

16021602
ty::Closure(_, substs) => {
16031603
// (*) binder moved here
1604-
let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty());
1605-
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
1606-
// Not yet resolved.
1607-
Ambiguous
1604+
1605+
if let Ok(tupled_tys) = substs.as_closure().tupled_upvars_ty() {
1606+
let ty = self.infcx.shallow_resolve(tupled_tys);
1607+
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
1608+
// Not yet resolved.
1609+
Ambiguous
1610+
} else {
1611+
Where(
1612+
obligation.predicate.rebind(substs.as_closure().upvar_tys().collect()),
1613+
)
1614+
}
16081615
} else {
1609-
Where(obligation.predicate.rebind(substs.as_closure().upvar_tys().collect()))
1616+
Where(ty::Binder::dummy(Vec::new()))
16101617
}
16111618
}
16121619

@@ -1677,14 +1684,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16771684
}
16781685

16791686
ty::Closure(_, ref substs) => {
1680-
let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty());
1681-
vec![ty]
1687+
if let Ok(tupled_tys) = substs.as_closure().tupled_upvars_ty() {
1688+
let ty = self.infcx.shallow_resolve(tupled_tys);
1689+
vec![ty]
1690+
} else {
1691+
vec![]
1692+
}
16821693
}
16831694

16841695
ty::Generator(_, ref substs, _) => {
1685-
let ty = self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty());
1696+
let tys_vec = if let Ok(tupled_tys) = substs.as_closure().tupled_upvars_ty() {
1697+
let ty = self.infcx.shallow_resolve(tupled_tys);
1698+
vec![ty]
1699+
} else {
1700+
vec![]
1701+
};
16861702
let witness = substs.as_generator().witness();
1687-
vec![ty].into_iter().chain(iter::once(witness)).collect()
1703+
tys_vec.into_iter().chain(iter::once(witness)).collect()
16881704
}
16891705

16901706
ty::GeneratorWitness(types) => {

compiler/rustc_trait_selection/src/traits/wf.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
593593
// only inspects the upvar types).
594594
walker.skip_current_subtree(); // subtree handled below
595595
// FIXME(eddyb) add the type to `walker` instead of recursing.
596-
self.compute(substs.as_closure().tupled_upvars_ty().into());
596+
if let Ok(tupled_tys) = substs.as_closure().tupled_upvars_ty() {
597+
self.compute(tupled_tys.into());
598+
}
597599
}
598600

599601
ty::FnPtr(_) => {

compiler/rustc_ty/src/needs_drop.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,20 @@ where
9494
_ if component.is_copy_modulo_regions(tcx.at(DUMMY_SP), self.param_env) => (),
9595

9696
ty::Closure(_, substs) => {
97-
for upvar_ty in substs.as_closure().upvar_tys() {
98-
queue_type(self, upvar_ty);
97+
let substs = substs.as_closure();
98+
if substs.tupled_upvars_ty().is_ok() {
99+
for upvar_ty in substs.upvar_tys() {
100+
queue_type(self, upvar_ty);
101+
}
99102
}
100103
}
101104

102105
ty::Generator(def_id, substs, _) => {
103106
let substs = substs.as_generator();
104-
for upvar_ty in substs.upvar_tys() {
105-
queue_type(self, upvar_ty);
107+
if substs.tupled_upvars_ty().is_ok() {
108+
for upvar_ty in substs.upvar_tys() {
109+
queue_type(self, upvar_ty);
110+
}
106111
}
107112

108113
let witness = substs.witness();

compiler/rustc_typeck/src/check/upvar.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
206206
// Build a tuple (U0..Un) of the final upvar types U0..Un
207207
// and unify the upvar tupe type in the closure with it:
208208
let final_tupled_upvars_type = self.tcx.mk_tup(final_upvar_tys.iter());
209-
self.demand_suptype(span, substs.tupled_upvars_ty(), final_tupled_upvars_type);
209+
if let Ok(tupled_upvars) = substs.tupled_upvars_ty() {
210+
self.demand_suptype(span, tupled_upvars, final_tupled_upvars_type);
211+
}
210212

211213
// If we are also inferred the closure kind here,
212214
// process any deferred resolutions.

0 commit comments

Comments
 (0)