Skip to content

Commit

Permalink
Unwrap the results of type folders
Browse files Browse the repository at this point in the history
Co-authored-by: Alan Egerton <eggyal@gmail.com>
  • Loading branch information
LeSeulArtichaut and eggyal committed Nov 26, 2021
1 parent 6dc3dae commit 30bf20a
Show file tree
Hide file tree
Showing 34 changed files with 192 additions and 168 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/lib.rs
Expand Up @@ -23,6 +23,7 @@ Rust MIR: a lowered representation of Rust.
#![feature(trusted_len)]
#![feature(trusted_step)]
#![feature(try_blocks)]
#![feature(unwrap_infallible)]
#![recursion_limit = "256"]

#[macro_use]
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_const_eval/src/transform/validate.rs
Expand Up @@ -95,7 +95,8 @@ pub fn equal_up_to_regions(
// Leave consts and types unchanged.
ct_op: |ct| ct,
ty_op: |ty| ty,
}),
})
.into_ok(),
)
};
tcx.infer_ctxt().enter(|infcx| infcx.can_eq(param_env, normalize(src), normalize(dest)).is_ok())
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
Expand Up @@ -503,7 +503,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
indices: FxHashMap::default(),
binder_index: ty::INNERMOST,
};
let out_value = value.fold_with(&mut canonicalizer);
let out_value = value.fold_with(&mut canonicalizer).into_ok();

// Once we have canonicalized `out_value`, it should not
// contain anything that ties it to this inference context
Expand Down Expand Up @@ -621,7 +621,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
let infcx = self.infcx;
let bound_to = infcx.shallow_resolve(ty_var);
if bound_to != ty_var {
self.fold_ty(bound_to)
self.fold_ty(bound_to).into_ok()
} else {
let var = self.canonical_var(info, ty_var.into());
self.tcx().mk_ty(ty::Bound(self.binder_index, var.into()))
Expand All @@ -640,12 +640,12 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
let infcx = self.infcx;
let bound_to = infcx.shallow_resolve(const_var);
if bound_to != const_var {
self.fold_const(bound_to)
self.fold_const(bound_to).into_ok()
} else {
let var = self.canonical_var(info, const_var.into());
self.tcx().mk_const(ty::Const {
val: ty::ConstKind::Bound(self.binder_index, var),
ty: self.fold_ty(const_var.ty),
ty: self.fold_ty(const_var.ty).into_ok(),
})
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_infer/src/infer/freshen.rs
Expand Up @@ -72,7 +72,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
F: FnOnce(u32) -> ty::InferTy,
{
if let Some(ty) = opt_ty {
return ty.fold_with(self);
return ty.fold_with(self).into_ok();
}

match self.ty_freshen_map.entry(key) {
Expand All @@ -98,7 +98,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
F: FnOnce(u32) -> ty::InferConst<'tcx>,
{
if let Some(ct) = opt_ct {
return ct.fold_with(self);
return ct.fold_with(self).into_ok();
}

match self.const_freshen_map.entry(key) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/fudge.rs
Expand Up @@ -161,7 +161,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
{
Ok(value)
} else {
Ok(value.fold_with(&mut fudger))
Ok(value.fold_with(&mut fudger).into_ok())
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_infer/src/infer/mod.rs
Expand Up @@ -681,7 +681,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}

pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T {
t.fold_with(&mut self.freshener())
t.fold_with(&mut self.freshener()).into_ok()
}

/// Returns the origin of the type variable identified by `vid`, or `None`
Expand Down Expand Up @@ -1381,7 +1381,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
where
T: TypeFoldable<'tcx>,
{
value.fold_with(&mut ShallowResolver { infcx: self })
value.fold_with(&mut ShallowResolver { infcx: self }).into_ok()
}

pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
Expand All @@ -1402,7 +1402,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
return value; // Avoid duplicated subst-folding.
}
let mut r = resolve::OpportunisticVarResolver::new(self);
value.fold_with(&mut r)
value.fold_with(&mut r).into_ok()
}

/// Returns the first unresolved variable contained in `T`. In the
Expand Down
196 changes: 100 additions & 96 deletions compiler/rustc_infer/src/infer/opaque_types.rs
Expand Up @@ -418,92 +418,94 @@ struct Instantiator<'a, 'tcx> {
impl<'a, 'tcx> Instantiator<'a, 'tcx> {
fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
let tcx = self.infcx.tcx;
value.fold_with(&mut BottomUpFolder {
tcx,
ty_op: |ty| {
if ty.references_error() {
return tcx.ty_error();
} else if let ty::Opaque(def_id, substs) = ty.kind() {
// Check that this is `impl Trait` type is
// declared by `parent_def_id` -- i.e., one whose
// value we are inferring. At present, this is
// always true during the first phase of
// type-check, but not always true later on during
// NLL. Once we support named opaque types more fully,
// this same scenario will be able to arise during all phases.
//
// Here is an example using type alias `impl Trait`
// that indicates the distinction we are checking for:
//
// ```rust
// mod a {
// pub type Foo = impl Iterator;
// pub fn make_foo() -> Foo { .. }
// }
//
// mod b {
// fn foo() -> a::Foo { a::make_foo() }
// }
// ```
//
// Here, the return type of `foo` references an
// `Opaque` indeed, but not one whose value is
// presently being inferred. You can get into a
// similar situation with closure return types
// today:
//
// ```rust
// fn foo() -> impl Iterator { .. }
// fn bar() {
// let x = || foo(); // returns the Opaque assoc with `foo`
// }
// ```
if let Some(def_id) = def_id.as_local() {
let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let parent_def_id = self.infcx.defining_use_anchor;
let def_scope_default = || {
let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
};
let (in_definition_scope, origin) =
match tcx.hir().expect_item(opaque_hir_id).kind {
// Anonymous `impl Trait`
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
impl_trait_fn: Some(parent),
origin,
..
}) => (parent == parent_def_id.to_def_id(), origin),
// Named `type Foo = impl Bar;`
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
impl_trait_fn: None,
origin,
..
}) => (
may_define_opaque_type(tcx, parent_def_id, opaque_hir_id),
origin,
),
_ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias),
value
.fold_with(&mut BottomUpFolder {
tcx,
ty_op: |ty| {
if ty.references_error() {
return tcx.ty_error();
} else if let ty::Opaque(def_id, substs) = ty.kind() {
// Check that this is `impl Trait` type is
// declared by `parent_def_id` -- i.e., one whose
// value we are inferring. At present, this is
// always true during the first phase of
// type-check, but not always true later on during
// NLL. Once we support named opaque types more fully,
// this same scenario will be able to arise during all phases.
//
// Here is an example using type alias `impl Trait`
// that indicates the distinction we are checking for:
//
// ```rust
// mod a {
// pub type Foo = impl Iterator;
// pub fn make_foo() -> Foo { .. }
// }
//
// mod b {
// fn foo() -> a::Foo { a::make_foo() }
// }
// ```
//
// Here, the return type of `foo` references an
// `Opaque` indeed, but not one whose value is
// presently being inferred. You can get into a
// similar situation with closure return types
// today:
//
// ```rust
// fn foo() -> impl Iterator { .. }
// fn bar() {
// let x = || foo(); // returns the Opaque assoc with `foo`
// }
// ```
if let Some(def_id) = def_id.as_local() {
let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let parent_def_id = self.infcx.defining_use_anchor;
let def_scope_default = || {
let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
};
if in_definition_scope {
let opaque_type_key =
OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
return self.fold_opaque_ty(ty, opaque_type_key, origin);
}

debug!(
"instantiate_opaque_types_in_map: \
let (in_definition_scope, origin) =
match tcx.hir().expect_item(opaque_hir_id).kind {
// Anonymous `impl Trait`
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
impl_trait_fn: Some(parent),
origin,
..
}) => (parent == parent_def_id.to_def_id(), origin),
// Named `type Foo = impl Bar;`
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
impl_trait_fn: None,
origin,
..
}) => (
may_define_opaque_type(tcx, parent_def_id, opaque_hir_id),
origin,
),
_ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias),
};
if in_definition_scope {
let opaque_type_key =
OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
return self.fold_opaque_ty(ty, opaque_type_key, origin);
}

debug!(
"instantiate_opaque_types_in_map: \
encountered opaque outside its definition scope \
def_id={:?}",
def_id,
);
def_id,
);
}
}
}

ty
},
lt_op: |lt| lt,
ct_op: |ct| ct,
})
ty
},
lt_op: |lt| lt,
ct_op: |ct| ct,
})
.into_ok()
}

#[instrument(skip(self), level = "debug")]
Expand Down Expand Up @@ -556,21 +558,23 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
debug!(?predicate);

// We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them.
let predicate = predicate.fold_with(&mut BottomUpFolder {
tcx,
ty_op: |ty| match ty.kind() {
ty::Projection(projection_ty) => infcx.infer_projection(
self.param_env,
*projection_ty,
traits::ObligationCause::misc(self.value_span, self.body_id),
0,
&mut self.obligations,
),
_ => ty,
},
lt_op: |lt| lt,
ct_op: |ct| ct,
});
let predicate = predicate
.fold_with(&mut BottomUpFolder {
tcx,
ty_op: |ty| match ty.kind() {
ty::Projection(projection_ty) => infcx.infer_projection(
self.param_env,
*projection_ty,
traits::ObligationCause::misc(self.value_span, self.body_id),
0,
&mut self.obligations,
),
_ => ty,
},
lt_op: |lt| lt,
ct_op: |ct| ct,
})
.into_ok();
debug!(?predicate);

if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/resolve.rs
Expand Up @@ -182,7 +182,7 @@ where
T: TypeFoldable<'tcx>,
{
let mut full_resolver = FullTypeResolver { infcx, err: None };
let result = value.fold_with(&mut full_resolver);
let result = value.fold_with(&mut full_resolver).into_ok();
match full_resolver.err {
None => Ok(result),
Some(e) => Err(e),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_infer/src/lib.rs
Expand Up @@ -24,6 +24,7 @@
#![feature(control_flow_enum)]
#![feature(min_specialization)]
#![feature(label_break_value)]
#![feature(unwrap_infallible)]
#![recursion_limit = "512"] // For rustdoc

#[macro_use]
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/lib.rs
Expand Up @@ -56,6 +56,7 @@
#![feature(try_blocks)]
#![feature(try_reserve_kind)]
#![feature(nonzero_ops)]
#![feature(unwrap_infallible)]
#![recursion_limit = "512"]

#[macro_use]
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/erase_regions.rs
Expand Up @@ -9,7 +9,7 @@ pub(super) fn provide(providers: &mut ty::query::Providers) {
fn erase_regions_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
// N.B., use `super_fold_with` here. If we used `fold_with`, it
// could invoke the `erase_regions_ty` query recursively.
ty.super_fold_with(&mut RegionEraserVisitor { tcx })
ty.super_fold_with(&mut RegionEraserVisitor { tcx }).into_ok()
}

impl<'tcx> TyCtxt<'tcx> {
Expand All @@ -27,7 +27,7 @@ impl<'tcx> TyCtxt<'tcx> {
return value;
}
debug!("erase_regions({:?})", value);
let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self });
let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self }).into_ok();
debug!("erase_regions = {:?}", value1);
value1
}
Expand Down

0 comments on commit 30bf20a

Please sign in to comment.