Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Replace tuple of infer vars for upvar_tys with single infer var #77873

Merged
merged 4 commits into from
Oct 15, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions compiler/rustc_middle/src/ty/outlives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,25 @@ fn compute_components(
}

ty::Closure(_, ref substs) => {
for upvar_ty in substs.as_closure().upvar_tys() {
compute_components(tcx, upvar_ty, out, visited);
if substs.as_closure().is_valid() {
roxelo marked this conversation as resolved.
Show resolved Hide resolved
for upvar_ty in substs.as_closure().upvar_tys() {
compute_components(tcx, upvar_ty, out, visited);
}
} else {
let tupled_ty = substs.as_closure().tupled_upvars_ty();
compute_components(tcx, tupled_ty, out, visited);
}
}

ty::Generator(_, ref substs, _) => {
// Same as the closure case
for upvar_ty in substs.as_generator().upvar_tys() {
compute_components(tcx, upvar_ty, out, visited);
if substs.as_generator().is_valid() {
roxelo marked this conversation as resolved.
Show resolved Hide resolved
for upvar_ty in substs.as_generator().upvar_tys() {
compute_components(tcx, upvar_ty, out, visited);
}
} else {
let tupled_ty = substs.as_generator().tupled_upvars_ty();
compute_components(tcx, tupled_ty, out, visited);
}

// We ignore regions in the generator interior as we don't
Expand Down
46 changes: 17 additions & 29 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,18 +663,13 @@ pub trait PrettyPrinter<'tcx>:
}
} else {
p!(print_def_path(did, substs));
if substs.as_generator().is_valid() {
// Search for the first inference variable
p!(" upvar_tys=(");
let mut uninferred_ty =
substs.as_generator().upvar_tys().filter(|ty| ty.is_ty_infer());
if uninferred_ty.next().is_some() {
p!(write("unavailable"));
} else {
self = self.comma_sep(substs.as_generator().upvar_tys())?;
}
p!(")");
p!(" upvar_tys=(");
if !substs.as_generator().is_valid() {
p!("unavailable");
} else {
self = self.comma_sep(substs.as_generator().upvar_tys())?;
}
p!(")");
roxelo marked this conversation as resolved.
Show resolved Hide resolved
}

if substs.as_generator().is_valid() {
Expand Down Expand Up @@ -704,24 +699,17 @@ pub trait PrettyPrinter<'tcx>:
}
} else {
p!(print_def_path(did, substs));
if substs.as_closure().is_valid() {
// Search for the first inference variable
let mut uninferred_ty =
substs.as_closure().upvar_tys().filter(|ty| ty.is_ty_infer());
if uninferred_ty.next().is_some() {
// If the upvar substs contain an inference variable we haven't
// finished capture analysis.
p!(" closure_substs=(unavailable)");
} else {
p!(" closure_kind_ty=", print(substs.as_closure().kind_ty()));
p!(
" closure_sig_as_fn_ptr_ty=",
print(substs.as_closure().sig_as_fn_ptr_ty())
);
p!(" upvar_tys=(");
self = self.comma_sep(substs.as_closure().upvar_tys())?;
p!(")");
}
if !substs.as_closure().is_valid() {
p!(" closure_substs=(unavailable)");
} else {
p!(" closure_kind_ty=", print(substs.as_closure().kind_ty()));
p!(
" closure_sig_as_fn_ptr_ty=",
print(substs.as_closure().sig_as_fn_ptr_ty())
);
p!(" upvar_tys=(");
self = self.comma_sep(substs.as_closure().upvar_tys())?;
p!(")");
}
}
p!("]");
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,14 @@ impl<'tcx> UpvarSubsts<'tcx> {
};
tupled_upvars_ty.expect_ty().tuple_fields()
}

#[inline]
pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
match self {
UpvarSubsts::Closure(substs) => substs.as_closure().tupled_upvars_ty(),
UpvarSubsts::Generator(substs) => substs.as_generator().tupled_upvars_ty(),
}
}
}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)]
Expand Down
40 changes: 28 additions & 12 deletions compiler/rustc_trait_selection/src/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {

for required_region in required_region_bounds {
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
infcx: self,
op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
});
}
Expand Down Expand Up @@ -509,6 +510,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
}
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
infcx: self,
op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
});
}
Expand Down Expand Up @@ -543,6 +545,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
);

concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
infcx: self,
op: |r| {
self.member_constraint(
opaque_type_def_id,
Expand Down Expand Up @@ -683,11 +686,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
//
// We ignore any type parameters because impl trait values are assumed to
// capture all the in-scope type parameters.
struct ConstrainOpaqueTypeRegionVisitor<OP> {
struct ConstrainOpaqueTypeRegionVisitor<'cx, 'tcx, OP> {
infcx: &'cx InferCtxt<'cx, 'tcx>,
op: OP,
}

impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<OP>
impl<'cx, 'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'cx, 'tcx, OP>
where
OP: FnMut(ty::Region<'tcx>),
{
Expand Down Expand Up @@ -717,24 +721,36 @@ where
ty::Closure(_, ref substs) => {
// Skip lifetime parameters of the enclosing item(s)

for upvar_ty in substs.as_closure().upvar_tys() {
upvar_ty.visit_with(self);
}
let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty());
roxelo marked this conversation as resolved.
Show resolved Hide resolved
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
// Not yet resolved.
ty.super_visit_with(self);
} else {
for upvar_ty in substs.as_closure().upvar_tys() {
upvar_ty.visit_with(self);
}

substs.as_closure().sig_as_fn_ptr_ty().visit_with(self);
substs.as_closure().sig_as_fn_ptr_ty().visit_with(self);
}
}

ty::Generator(_, ref substs, _) => {
// Skip lifetime parameters of the enclosing item(s)
// Also skip the witness type, because that has no free regions.

for upvar_ty in substs.as_generator().upvar_tys() {
upvar_ty.visit_with(self);
}
let ty = self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty());
roxelo marked this conversation as resolved.
Show resolved Hide resolved
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
// Not yet resolved.
ty.super_visit_with(self);
} else {
for upvar_ty in substs.as_generator().upvar_tys() {
upvar_ty.visit_with(self);
}

substs.as_generator().return_ty().visit_with(self);
substs.as_generator().yield_ty().visit_with(self);
substs.as_generator().resume_ty().visit_with(self);
substs.as_generator().return_ty().visit_with(self);
substs.as_generator().yield_ty().visit_with(self);
substs.as_generator().resume_ty().visit_with(self);
}
}
_ => {
ty.super_visit_with(self);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let mut generator = None;
let mut outer_generator = None;
let mut next_code = Some(&obligation.cause.code);

let mut seen_upvar_tys_infer_tuple = false;

while let Some(code) = next_code {
debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
match code {
Expand All @@ -1327,6 +1330,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
outer_generator = Some(did);
}
ty::GeneratorWitness(..) => {}
ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
// By introducing a tuple of upvar types into the chain of obligations
// of a generator, the first non-generator item is now the tuple itself,
// we shall ignore this.

seen_upvar_tys_infer_tuple = true;
}
_ if generator.is_none() => {
trait_ref = Some(derived_obligation.parent_trait_ref.skip_binder());
target_ty = Some(ty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
// check if *any* of those are trivial.
ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())),
ty::Closure(_, ref substs) => {
substs.as_closure().upvar_tys().all(|t| trivial_dropck_outlives(tcx, t))
trivial_dropck_outlives(tcx, substs.as_closure().tupled_upvars_ty())
}

ty::Adt(def, _) => {
Expand Down
34 changes: 30 additions & 4 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1631,7 +1631,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

ty::Closure(_, substs) => {
// (*) binder moved here
Where(ty::Binder::bind(substs.as_closure().upvar_tys().collect()))
let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty());
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
// Not yet resolved.
Ambiguous
} else {
Where(ty::Binder::bind(substs.as_closure().upvar_tys().collect()))
}
}

ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => {
Expand Down Expand Up @@ -1700,11 +1706,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
tys.iter().map(|k| k.expect_ty()).collect()
}

ty::Closure(_, ref substs) => substs.as_closure().upvar_tys().collect(),
ty::Closure(_, ref substs) => {
let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty());
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
roxelo marked this conversation as resolved.
Show resolved Hide resolved
// The inference variable will be replaced by a tuple once capture analysis
// completes. If the tuple meets a bound, so do all the elements within it.
vec![ty]
} else {
substs.as_closure().upvar_tys().collect()
}
}

ty::Generator(_, ref substs, _) => {
let witness = substs.as_generator().witness();
substs.as_generator().upvar_tys().chain(iter::once(witness)).collect()
let upvar_tys_resolved =
self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty());

if let ty::Infer(ty::TyVar(_)) = upvar_tys_resolved.kind() {
// The inference variable will be replaced by a tuple once capture analysis
// completes, if the tuple meets a bound, so do all the elements within it.
let witness_resolved =
self.infcx.shallow_resolve(substs.as_generator().witness());
vec![upvar_tys_resolved, witness_resolved]
roxelo marked this conversation as resolved.
Show resolved Hide resolved
} else {
let witness = substs.as_generator().witness();
substs.as_generator().upvar_tys().chain(iter::once(witness)).collect()
}
}

ty::GeneratorWitness(types) => {
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_trait_selection/src/traits/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,10 +592,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
// anyway, except via auto trait matching (which
// only inspects the upvar types).
walker.skip_current_subtree(); // subtree handled below
for upvar_ty in substs.as_closure().upvar_tys() {
// FIXME(eddyb) add the type to `walker` instead of recursing.
self.compute(upvar_ty.into());
}
// FIXME(eddyb) add the type to `walker` instead of recursing.
self.compute(substs.as_closure().tupled_upvars_ty().into());
}

ty::FnPtr(_) => {
Expand Down
24 changes: 19 additions & 5 deletions compiler/rustc_traits/src/dropck_outlives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,20 @@ fn dtorck_constraint_for_ty<'tcx>(
Ok::<_, NoSolution>(())
})?,

ty::Closure(_, substs) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
for ty in substs.as_closure().upvar_tys() {
dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?;
ty::Closure(_, substs) => {
if !substs.as_closure().is_valid() {
// By the time this code runs, all type variables ought to
// be fully resolved.
return Err(NoSolution);
roxelo marked this conversation as resolved.
Show resolved Hide resolved
}
Ok::<_, NoSolution>(())
})?,

rustc_data_structures::stack::ensure_sufficient_stack(|| {
for ty in substs.as_closure().upvar_tys() {
dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?;
}
Ok::<_, NoSolution>(())
})?
}

ty::Generator(_, substs, _movability) => {
// rust-lang/rust#49918: types can be constructed, stored
Expand All @@ -241,6 +249,12 @@ fn dtorck_constraint_for_ty<'tcx>(
// derived from lifetimes attached to the upvars and resume
// argument, and we *do* incorporate those here.

if !substs.as_generator().is_valid() {
// By the time this code runs, all type variables ought to
// be fully resolved.
return Err(NoSolution);
roxelo marked this conversation as resolved.
Show resolved Hide resolved
}

constraints.outlives.extend(
substs
.as_generator()
Expand Down
17 changes: 4 additions & 13 deletions compiler/rustc_typeck/src/check/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,19 +81,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.closure_base_def_id(expr_def_id.to_def_id()),
);

let tupled_upvars_ty =
self.tcx.mk_tup(self.tcx.upvars_mentioned(expr_def_id).iter().flat_map(|upvars| {
upvars.iter().map(|(&var_hir_id, _)| {
// Create type variables (for now) to represent the transformed
// types of upvars. These will be unified during the upvar
// inference phase (`upvar.rs`).
self.infcx.next_ty_var(TypeVariableOrigin {
// FIXME(eddyb) distinguish upvar inference variables from the rest.
kind: TypeVariableOriginKind::ClosureSynthetic,
span: self.tcx.hir().span(var_hir_id),
})
})
}));
let tupled_upvars_ty = self.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: self.tcx.hir().span(expr.hir_id),
});

if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types
{
Expand Down
Loading