Unwrap the results of type folders
Co-authored-by: Alan Egerton <eggyal@gmail.com>
This commit is contained in:
parent
6dc3dae46f
commit
30bf20a692
34 changed files with 191 additions and 167 deletions
|
@ -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
|
||||
|
@ -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()))
|
||||
|
@ -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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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`
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
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: \
|
||||
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")]
|
||||
|
@ -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() {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue