1
Fork 0

reduce indentaton

This commit is contained in:
Ellen 2022-01-14 00:18:11 +00:00
parent 73945fd620
commit b3d71d9001

View file

@ -26,85 +26,56 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
use hir::*;
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
if let Node::AnonConst(_) = tcx.hir().get(hir_id) {
let parent_node_id = tcx.hir().get_parent_node(hir_id);
let parent_node = tcx.hir().get(parent_node_id);
match tcx.hir().get(hir_id) {
Node::AnonConst(_) => (),
_ => return None,
};
let (generics, arg_idx) = match parent_node {
// This match arm is for when the def_id appears in a GAT whose
// path can't be resolved without typechecking e.g.
//
// trait Foo {
// type Assoc<const N: usize>;
// fn foo() -> Self::Assoc<3>;
// }
//
// In the above code we would call this query with the def_id of 3 and
// the parent_node we match on would be the hir node for Self::Assoc<3>
//
// `Self::Assoc<3>` cant be resolved without typchecking here as we
// didnt write <Self as Foo>::Assoc<3>. If we did then another match
// arm would handle this.
//
// I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
Node::Ty(hir_ty @ Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
// Find the Item containing the associated type so we can create an ItemCtxt.
// Using the ItemCtxt convert the HIR for the unresolved assoc type into a
// ty which is a fully resolved projection.
// For the code example above, this would mean converting Self::Assoc<3>
// into a ty::Projection(<Self as Foo>::Assoc<3>)
let item_hir_id = tcx
.hir()
.parent_iter(hir_id)
.filter(|(_, node)| matches!(node, Node::Item(_)))
.map(|(id, _)| id)
.next()
.unwrap();
let item_did = tcx.hir().local_def_id(item_hir_id).to_def_id();
let item_ctxt = &ItemCtxt::new(tcx, item_did) as &dyn crate::astconv::AstConv<'_>;
let ty = item_ctxt.ast_ty_to_ty(hir_ty);
let parent_node_id = tcx.hir().get_parent_node(hir_id);
let parent_node = tcx.hir().get(parent_node_id);
// Iterate through the generics of the projection to find the one that corresponds to
// the def_id that this query was called with. We filter to only const args here as a
// precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
// but it can't hurt to be safe ^^
if let ty::Projection(projection) = ty.kind() {
let generics = tcx.generics_of(projection.item_def_id);
let (generics, arg_idx) = match parent_node {
// This match arm is for when the def_id appears in a GAT whose
// path can't be resolved without typechecking e.g.
//
// trait Foo {
// type Assoc<const N: usize>;
// fn foo() -> Self::Assoc<3>;
// }
//
// In the above code we would call this query with the def_id of 3 and
// the parent_node we match on would be the hir node for Self::Assoc<3>
//
// `Self::Assoc<3>` cant be resolved without typchecking here as we
// didnt write <Self as Foo>::Assoc<3>. If we did then another match
// arm would handle this.
//
// I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
Node::Ty(hir_ty @ Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
// Find the Item containing the associated type so we can create an ItemCtxt.
// Using the ItemCtxt convert the HIR for the unresolved assoc type into a
// ty which is a fully resolved projection.
// For the code example above, this would mean converting Self::Assoc<3>
// into a ty::Projection(<Self as Foo>::Assoc<3>)
let item_hir_id = tcx
.hir()
.parent_iter(hir_id)
.filter(|(_, node)| matches!(node, Node::Item(_)))
.map(|(id, _)| id)
.next()
.unwrap();
let item_did = tcx.hir().local_def_id(item_hir_id).to_def_id();
let item_ctxt = &ItemCtxt::new(tcx, item_did) as &dyn crate::astconv::AstConv<'_>;
let ty = item_ctxt.ast_ty_to_ty(hir_ty);
let arg_index = segment
.args
.and_then(|args| {
args.args
.iter()
.filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
.position(|arg| arg.id() == hir_id)
})
.unwrap_or_else(|| {
bug!("no arg matching AnonConst in segment");
});
// Iterate through the generics of the projection to find the one that corresponds to
// the def_id that this query was called with. We filter to only const args here as a
// precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
// but it can't hurt to be safe ^^
if let ty::Projection(projection) = ty.kind() {
let generics = tcx.generics_of(projection.item_def_id);
(generics, arg_index)
} else {
// I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
"unexpected non-GAT usage of an anon const",
);
return None;
}
}
Node::Expr(&Expr {
kind:
ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
..
}) => {
let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
let tables = tcx.typeck(body_owner);
// This may fail in case the method/path does not actually exist.
// As there is no relevant param for `def_id`, we simply return
// `None` here.
let type_dependent_def = tables.type_dependent_def_id(parent_node_id)?;
let idx = segment
let arg_index = segment
.args
.and_then(|args| {
args.args
@ -116,145 +87,168 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
bug!("no arg matching AnonConst in segment");
});
(tcx.generics_of(type_dependent_def), idx)
}
Node::Ty(&Ty { kind: TyKind::Path(_), .. })
| Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
| Node::TraitRef(..)
| Node::Pat(_) => {
let path = match parent_node {
Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
| Node::TraitRef(&TraitRef { path, .. }) => &*path,
Node::Expr(&Expr {
kind:
ExprKind::Path(QPath::Resolved(_, path))
| ExprKind::Struct(&QPath::Resolved(_, path), ..),
..
}) => {
let body_owner =
tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
let _tables = tcx.typeck(body_owner);
&*path
}
Node::Pat(pat) => {
if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
path
} else {
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
&format!(
"unable to find const parent for {} in pat {:?}",
hir_id, pat
),
);
return None;
}
}
_ => {
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
&format!("unexpected const parent path {:?}", parent_node),
);
return None;
}
};
// We've encountered an `AnonConst` in some path, so we need to
// figure out which generic parameter it corresponds to and return
// the relevant type.
let filtered = path
.segments
.iter()
.filter_map(|seg| seg.args.map(|args| (args.args, seg)))
.find_map(|(args, seg)| {
args.iter()
.filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
.position(|arg| arg.id() == hir_id)
.map(|index| (index, seg))
});
let (arg_index, segment) = match filtered {
None => {
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
"no arg matching AnonConst in path",
);
return None;
}
Some(inner) => inner,
};
// Try to use the segment resolution if it is valid, otherwise we
// default to the path resolution.
let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
use def::CtorOf;
let generics = match res {
Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx.generics_of(
tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap(),
),
Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => {
tcx.generics_of(tcx.parent(def_id).unwrap())
}
// Other `DefKind`s don't have generics and would ICE when calling
// `generics_of`.
Res::Def(
DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::Trait
| DefKind::OpaqueTy
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::TraitAlias
| DefKind::AssocTy
| DefKind::Fn
| DefKind::AssocFn
| DefKind::AssocConst
| DefKind::Impl,
def_id,
) => tcx.generics_of(def_id),
Res::Err => {
tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err");
return None;
}
_ => {
// If the user tries to specify generics on a type that does not take them,
// e.g. `usize<T>`, we may hit this branch, in which case we treat it as if
// no arguments have been passed. An error should already have been emitted.
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
&format!("unexpected anon const res {:?} in path: {:?}", res, path),
);
return None;
}
};
(generics, arg_index)
} else {
// I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
"unexpected non-GAT usage of an anon const",
);
return None;
}
_ => return None,
};
}
Node::Expr(&Expr {
kind:
ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
..
}) => {
let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
let tables = tcx.typeck(body_owner);
// This may fail in case the method/path does not actually exist.
// As there is no relevant param for `def_id`, we simply return
// `None` here.
let type_dependent_def = tables.type_dependent_def_id(parent_node_id)?;
let idx = segment
.args
.and_then(|args| {
args.args
.iter()
.filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
.position(|arg| arg.id() == hir_id)
})
.unwrap_or_else(|| {
bug!("no arg matching AnonConst in segment");
});
debug!(?parent_node);
debug!(?generics);
debug!(?arg_idx);
generics
.params
.iter()
.filter(|param| !matches!(param.kind, ty::GenericParamDefKind::Lifetime { .. }))
.nth(match generics.has_self && generics.parent.is_none() {
true => arg_idx + 1,
false => arg_idx,
})
.and_then(|param| match param.kind {
ty::GenericParamDefKind::Const { .. } => {
debug!(?param);
Some(param.def_id)
(tcx.generics_of(type_dependent_def), idx)
}
Node::Ty(&Ty { kind: TyKind::Path(_), .. })
| Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
| Node::TraitRef(..)
| Node::Pat(_) => {
let path = match parent_node {
Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
| Node::TraitRef(&TraitRef { path, .. }) => &*path,
Node::Expr(&Expr {
kind:
ExprKind::Path(QPath::Resolved(_, path))
| ExprKind::Struct(&QPath::Resolved(_, path), ..),
..
}) => {
let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
let _tables = tcx.typeck(body_owner);
&*path
}
_ => None,
})
} else {
None
}
Node::Pat(pat) => {
if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
path
} else {
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
&format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
);
return None;
}
}
_ => {
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
&format!("unexpected const parent path {:?}", parent_node),
);
return None;
}
};
// We've encountered an `AnonConst` in some path, so we need to
// figure out which generic parameter it corresponds to and return
// the relevant type.
let filtered = path
.segments
.iter()
.filter_map(|seg| seg.args.map(|args| (args.args, seg)))
.find_map(|(args, seg)| {
args.iter()
.filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
.position(|arg| arg.id() == hir_id)
.map(|index| (index, seg))
});
let (arg_index, segment) = match filtered {
None => {
tcx.sess
.delay_span_bug(tcx.def_span(def_id), "no arg matching AnonConst in path");
return None;
}
Some(inner) => inner,
};
// Try to use the segment resolution if it is valid, otherwise we
// default to the path resolution.
let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
use def::CtorOf;
let generics = match res {
Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx
.generics_of(tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap()),
Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => {
tcx.generics_of(tcx.parent(def_id).unwrap())
}
// Other `DefKind`s don't have generics and would ICE when calling
// `generics_of`.
Res::Def(
DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::Trait
| DefKind::OpaqueTy
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::TraitAlias
| DefKind::AssocTy
| DefKind::Fn
| DefKind::AssocFn
| DefKind::AssocConst
| DefKind::Impl,
def_id,
) => tcx.generics_of(def_id),
Res::Err => {
tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err");
return None;
}
_ => {
// If the user tries to specify generics on a type that does not take them,
// e.g. `usize<T>`, we may hit this branch, in which case we treat it as if
// no arguments have been passed. An error should already have been emitted.
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
&format!("unexpected anon const res {:?} in path: {:?}", res, path),
);
return None;
}
};
(generics, arg_index)
}
_ => return None,
};
debug!(?parent_node);
debug!(?generics);
debug!(?arg_idx);
generics
.params
.iter()
.filter(|param| !matches!(param.kind, ty::GenericParamDefKind::Lifetime { .. }))
.nth(match generics.has_self && generics.parent.is_none() {
true => arg_idx + 1,
false => arg_idx,
})
.and_then(|param| match param.kind {
ty::GenericParamDefKind::Const { .. } => {
debug!(?param);
Some(param.def_id)
}
_ => None,
})
}
fn get_path_containing_arg_in_pat<'hir>(