Try structurally resolve
This commit is contained in:
parent
55cf09d761
commit
5ab6dca6d3
@ -134,6 +134,8 @@ pub trait TypeInformationCtxt<'tcx> {
|
|||||||
|
|
||||||
fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T;
|
fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T;
|
||||||
|
|
||||||
|
fn try_structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
|
||||||
|
|
||||||
fn tainted_by_errors(&self) -> Option<ErrorGuaranteed>;
|
fn tainted_by_errors(&self) -> Option<ErrorGuaranteed>;
|
||||||
|
|
||||||
fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool;
|
fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool;
|
||||||
@ -156,6 +158,10 @@ fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
|
|||||||
self.infcx.resolve_vars_if_possible(t)
|
self.infcx.resolve_vars_if_possible(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
|
(**self).try_structurally_resolve_type(sp, ty)
|
||||||
|
}
|
||||||
|
|
||||||
fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
|
fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
|
||||||
if let Some(guar) = self.infcx.tainted_by_errors() { Err(guar) } else { Ok(()) }
|
if let Some(guar) = self.infcx.tainted_by_errors() { Err(guar) } else { Ok(()) }
|
||||||
}
|
}
|
||||||
@ -182,6 +188,11 @@ fn typeck_results(&self) -> Self::TypeckResults<'_> {
|
|||||||
self.0.maybe_typeck_results().expect("expected typeck results")
|
self.0.maybe_typeck_results().expect("expected typeck results")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_structurally_resolve_type(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
|
// FIXME: Maybe need to normalize here.
|
||||||
|
ty
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
|
fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
|
||||||
t
|
t
|
||||||
}
|
}
|
||||||
@ -543,7 +554,8 @@ fn maybe_read_scrutinee<'t>(
|
|||||||
_ => {
|
_ => {
|
||||||
// Otherwise, this is a struct/enum variant, and so it's
|
// Otherwise, this is a struct/enum variant, and so it's
|
||||||
// only a read if we need to read the discriminant.
|
// only a read if we need to read the discriminant.
|
||||||
needs_to_be_read |= is_multivariant_adt(place.place.ty());
|
needs_to_be_read |=
|
||||||
|
self.is_multivariant_adt(place.place.ty(), pat.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -555,7 +567,7 @@ fn maybe_read_scrutinee<'t>(
|
|||||||
// perform some reads).
|
// perform some reads).
|
||||||
|
|
||||||
let place_ty = place.place.ty();
|
let place_ty = place.place.ty();
|
||||||
needs_to_be_read |= is_multivariant_adt(place_ty);
|
needs_to_be_read |= self.is_multivariant_adt(place_ty, pat.span);
|
||||||
}
|
}
|
||||||
PatKind::Lit(_) | PatKind::Range(..) => {
|
PatKind::Lit(_) | PatKind::Range(..) => {
|
||||||
// If the PatKind is a Lit or a Range then we want
|
// If the PatKind is a Lit or a Range then we want
|
||||||
@ -676,7 +688,7 @@ fn walk_struct_expr<'hir>(
|
|||||||
|
|
||||||
// Select just those fields of the `with`
|
// Select just those fields of the `with`
|
||||||
// expression that will actually be used
|
// expression that will actually be used
|
||||||
match with_place.place.ty().kind() {
|
match self.cx.try_structurally_resolve_type(with_expr.span, with_place.place.ty()).kind() {
|
||||||
ty::Adt(adt, args) if adt.is_struct() => {
|
ty::Adt(adt, args) if adt.is_struct() => {
|
||||||
// Consume those fields of the with expression that are needed.
|
// Consume those fields of the with expression that are needed.
|
||||||
for (f_index, with_field) in adt.non_enum_variant().fields.iter_enumerated() {
|
for (f_index, with_field) in adt.non_enum_variant().fields.iter_enumerated() {
|
||||||
@ -1099,8 +1111,12 @@ fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
|
|||||||
// a bind-by-ref means that the base_ty will be the type of the ident itself,
|
// a bind-by-ref means that the base_ty will be the type of the ident itself,
|
||||||
// but what we want here is the type of the underlying value being borrowed.
|
// but what we want here is the type of the underlying value being borrowed.
|
||||||
// So peel off one-level, turning the &T into T.
|
// So peel off one-level, turning the &T into T.
|
||||||
match base_ty.builtin_deref(false) {
|
match self
|
||||||
Some(t) => Ok(t.ty),
|
.cx
|
||||||
|
.try_structurally_resolve_type(pat.span, base_ty)
|
||||||
|
.builtin_deref(false)
|
||||||
|
{
|
||||||
|
Some(ty) => Ok(ty),
|
||||||
None => {
|
None => {
|
||||||
debug!("By-ref binding of non-derefable type");
|
debug!("By-ref binding of non-derefable type");
|
||||||
Err(self
|
Err(self
|
||||||
@ -1333,7 +1349,15 @@ fn cat_projection(
|
|||||||
// Opaque types can't have field projections, but we can instead convert
|
// Opaque types can't have field projections, but we can instead convert
|
||||||
// the current place in-place (heh) to the hidden type, and then apply all
|
// the current place in-place (heh) to the hidden type, and then apply all
|
||||||
// follow up projections on that.
|
// follow up projections on that.
|
||||||
if node_ty != place_ty && matches!(place_ty.kind(), ty::Alias(ty::Opaque, ..)) {
|
if node_ty != place_ty
|
||||||
|
&& self
|
||||||
|
.cx
|
||||||
|
.try_structurally_resolve_type(
|
||||||
|
self.cx.tcx().hir().span(base_place.hir_id),
|
||||||
|
place_ty,
|
||||||
|
)
|
||||||
|
.is_impl_trait()
|
||||||
|
{
|
||||||
projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
|
projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
|
||||||
}
|
}
|
||||||
projections.push(Projection { kind, ty });
|
projections.push(Projection { kind, ty });
|
||||||
@ -1351,7 +1375,9 @@ fn cat_overloaded_place(
|
|||||||
let place_ty = self.expr_ty(expr)?;
|
let place_ty = self.expr_ty(expr)?;
|
||||||
let base_ty = self.expr_ty_adjusted(base)?;
|
let base_ty = self.expr_ty_adjusted(base)?;
|
||||||
|
|
||||||
let ty::Ref(region, _, mutbl) = *base_ty.kind() else {
|
let ty::Ref(region, _, mutbl) =
|
||||||
|
*self.cx.try_structurally_resolve_type(base.span, base_ty).kind()
|
||||||
|
else {
|
||||||
span_bug!(expr.span, "cat_overloaded_place: base is not a reference");
|
span_bug!(expr.span, "cat_overloaded_place: base is not a reference");
|
||||||
};
|
};
|
||||||
let ref_ty = Ty::new_ref(self.cx.tcx(), region, place_ty, mutbl);
|
let ref_ty = Ty::new_ref(self.cx.tcx(), region, place_ty, mutbl);
|
||||||
@ -1366,8 +1392,15 @@ fn cat_deref(
|
|||||||
base_place: PlaceWithHirId<'tcx>,
|
base_place: PlaceWithHirId<'tcx>,
|
||||||
) -> McResult<PlaceWithHirId<'tcx>> {
|
) -> McResult<PlaceWithHirId<'tcx>> {
|
||||||
let base_curr_ty = base_place.place.ty();
|
let base_curr_ty = base_place.place.ty();
|
||||||
let deref_ty = match base_curr_ty.builtin_deref(true) {
|
let deref_ty = match self
|
||||||
Some(mt) => mt.ty,
|
.cx
|
||||||
|
.try_structurally_resolve_type(
|
||||||
|
self.cx.tcx().hir().span(base_place.hir_id),
|
||||||
|
base_curr_ty,
|
||||||
|
)
|
||||||
|
.builtin_deref(true)
|
||||||
|
{
|
||||||
|
Some(ty) => ty,
|
||||||
None => {
|
None => {
|
||||||
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
|
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
|
||||||
return Err(self.cx.tcx().dcx().span_delayed_bug(
|
return Err(self.cx.tcx().dcx().span_delayed_bug(
|
||||||
@ -1404,7 +1437,7 @@ fn variant_index_for_adt(
|
|||||||
) -> McResult<VariantIdx> {
|
) -> McResult<VariantIdx> {
|
||||||
let res = self.cx.typeck_results().qpath_res(qpath, pat_hir_id);
|
let res = self.cx.typeck_results().qpath_res(qpath, pat_hir_id);
|
||||||
let ty = self.cx.typeck_results().node_type(pat_hir_id);
|
let ty = self.cx.typeck_results().node_type(pat_hir_id);
|
||||||
let ty::Adt(adt_def, _) = ty.kind() else {
|
let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else {
|
||||||
return Err(self
|
return Err(self
|
||||||
.cx
|
.cx
|
||||||
.tcx()
|
.tcx()
|
||||||
@ -1438,7 +1471,7 @@ fn total_fields_in_adt_variant(
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> McResult<usize> {
|
) -> McResult<usize> {
|
||||||
let ty = self.cx.typeck_results().node_type(pat_hir_id);
|
let ty = self.cx.typeck_results().node_type(pat_hir_id);
|
||||||
match ty.kind() {
|
match self.cx.try_structurally_resolve_type(span, ty).kind() {
|
||||||
ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()),
|
ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()),
|
||||||
_ => {
|
_ => {
|
||||||
self.cx
|
self.cx
|
||||||
@ -1453,7 +1486,7 @@ fn total_fields_in_adt_variant(
|
|||||||
/// Here `pat_hir_id` is the HirId of the pattern itself.
|
/// Here `pat_hir_id` is the HirId of the pattern itself.
|
||||||
fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> McResult<usize> {
|
fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> McResult<usize> {
|
||||||
let ty = self.cx.typeck_results().node_type(pat_hir_id);
|
let ty = self.cx.typeck_results().node_type(pat_hir_id);
|
||||||
match ty.kind() {
|
match self.cx.try_structurally_resolve_type(span, ty).kind() {
|
||||||
ty::Tuple(args) => Ok(args.len()),
|
ty::Tuple(args) => Ok(args.len()),
|
||||||
_ => Err(self
|
_ => Err(self
|
||||||
.cx
|
.cx
|
||||||
@ -1668,10 +1701,9 @@ fn cat_pattern_<F>(
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn is_multivariant_adt(ty: Ty<'_>) -> bool {
|
fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
||||||
if let ty::Adt(def, _) = ty.kind() {
|
if let ty::Adt(def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() {
|
||||||
// Note that if a non-exhaustive SingleVariant is defined in another crate, we need
|
// Note that if a non-exhaustive SingleVariant is defined in another crate, we need
|
||||||
// to assume that more cases will be added to the variant in the future. This mean
|
// to assume that more cases will be added to the variant in the future. This mean
|
||||||
// that we should handle non-exhaustive SingleVariant the same way we would handle
|
// that we should handle non-exhaustive SingleVariant the same way we would handle
|
||||||
@ -1687,4 +1719,5 @@ fn is_multivariant_adt(ty: Ty<'_>) -> bool {
|
|||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
//@ compile-flags: -Znext-solver
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
struct Struct {
|
||||||
|
field: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hello(f: impl Fn() -> &'static Box<[i32]>, f2: impl Fn() -> &'static Struct) {
|
||||||
|
let cl = || {
|
||||||
|
let x = &f()[0];
|
||||||
|
let y = &f2().field;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in New Issue
Block a user