tamer: asg::graph::object::ident::definition{=>_narrow} and new `definition`
This renames the previous operation to `definition_narrow` and creates a new `definition` that does not attempt to narrow. This is important for distinguishing between a missing defintion and a definition of a given type, and will be important now that we're beginning to reason about identifiers that were resolved during parsing. DEV-13163main
parent
1c06605188
commit
087ef45153
|
@ -1105,7 +1105,7 @@ impl AirAggregateCtx {
|
||||||
Ident: ObjectRelTo<O>,
|
Ident: ObjectRelTo<O>,
|
||||||
{
|
{
|
||||||
self.env_scope_lookup::<Ident>(env, name)
|
self.env_scope_lookup::<Ident>(env, name)
|
||||||
.and_then(|oi| oi.definition(self.asg_ref()))
|
.and_then(|oi| oi.definition_narrow(self.asg_ref()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempt to retrieve an identifier from the graph by name relative to
|
/// Attempt to retrieve an identifier from the graph by name relative to
|
||||||
|
|
|
@ -298,7 +298,7 @@ fn assert_concat_list<'a, IT, IE: 'a>(
|
||||||
.edges(asg)
|
.edges(asg)
|
||||||
.filter_map(|rel| match rel {
|
.filter_map(|rel| match rel {
|
||||||
MetaRel::Meta(oi) => Some(oi),
|
MetaRel::Meta(oi) => Some(oi),
|
||||||
MetaRel::Ident(oi) => oi.definition::<Meta>(asg),
|
MetaRel::Ident(oi) => oi.definition_narrow::<Meta>(asg),
|
||||||
MetaRel::Doc(_) => None,
|
MetaRel::Doc(_) => None,
|
||||||
})
|
})
|
||||||
.map(ObjectIndex::cresolve(asg))
|
.map(ObjectIndex::cresolve(asg))
|
||||||
|
@ -362,7 +362,7 @@ where
|
||||||
"could not locate stub template (did you call \
|
"could not locate stub template (did you call \
|
||||||
air_ctx_from_tpl_body_toks without parse_as_tpl_body?)",
|
air_ctx_from_tpl_body_toks without parse_as_tpl_body?)",
|
||||||
)
|
)
|
||||||
.definition(ctx.asg_ref())
|
.definition_narrow(ctx.asg_ref())
|
||||||
.expect("missing stub template definition (test setup bug?)");
|
.expect("missing stub template definition (test setup bug?)");
|
||||||
|
|
||||||
(ctx, oi_tpl)
|
(ctx, oi_tpl)
|
||||||
|
|
|
@ -592,7 +592,7 @@ fn tpl_nested() {
|
||||||
let oi_tpl_inner_ident =
|
let oi_tpl_inner_ident =
|
||||||
oi_tpl_outer.lookup_local_linear(&asg, id_tpl_inner);
|
oi_tpl_outer.lookup_local_linear(&asg, id_tpl_inner);
|
||||||
let tpl_inner = oi_tpl_inner_ident
|
let tpl_inner = oi_tpl_inner_ident
|
||||||
.and_then(|oi| oi.definition::<Tpl>(&asg))
|
.and_then(|oi| oi.definition_narrow::<Tpl>(&asg))
|
||||||
.map(ObjectIndex::cresolve(&asg));
|
.map(ObjectIndex::cresolve(&asg));
|
||||||
|
|
||||||
assert_eq!(S3.merge(S5), tpl_inner.map(Tpl::span));
|
assert_eq!(S3.merge(S5), tpl_inner.map(Tpl::span));
|
||||||
|
@ -699,7 +699,7 @@ fn metavars_within_exprs_hoisted_to_parent_tpl() {
|
||||||
let span_outer = ctx
|
let span_outer = ctx
|
||||||
.env_scope_lookup::<Ident>(oi_outer, id_param_outer)
|
.env_scope_lookup::<Ident>(oi_outer, id_param_outer)
|
||||||
.expect("missing id_param_outer Ident")
|
.expect("missing id_param_outer Ident")
|
||||||
.definition::<Meta>(asg)
|
.definition_narrow::<Meta>(asg)
|
||||||
.expect("missing id_param_outer definition")
|
.expect("missing id_param_outer definition")
|
||||||
.resolve(asg)
|
.resolve(asg)
|
||||||
.span();
|
.span();
|
||||||
|
@ -709,13 +709,13 @@ fn metavars_within_exprs_hoisted_to_parent_tpl() {
|
||||||
let oi_inner = ctx
|
let oi_inner = ctx
|
||||||
.env_scope_lookup::<Ident>(oi_outer, id_tpl_inner)
|
.env_scope_lookup::<Ident>(oi_outer, id_tpl_inner)
|
||||||
.expect("could not locate inner Tpl's Ident")
|
.expect("could not locate inner Tpl's Ident")
|
||||||
.definition::<Tpl>(asg)
|
.definition_narrow::<Tpl>(asg)
|
||||||
.expect("missing inner Tpl");
|
.expect("missing inner Tpl");
|
||||||
|
|
||||||
let span_inner = ctx
|
let span_inner = ctx
|
||||||
.env_scope_lookup::<Ident>(oi_inner, id_param_inner)
|
.env_scope_lookup::<Ident>(oi_inner, id_param_inner)
|
||||||
.expect("missing id_param_inner Ident")
|
.expect("missing id_param_inner Ident")
|
||||||
.definition::<Meta>(asg)
|
.definition_narrow::<Meta>(asg)
|
||||||
.expect("missing id_param_inner definition")
|
.expect("missing id_param_inner definition")
|
||||||
.resolve(asg)
|
.resolve(asg)
|
||||||
.span();
|
.span();
|
||||||
|
@ -780,7 +780,7 @@ fn expr_abstract_bind_produces_cross_edge_from_ident_to_meta() {
|
||||||
|
|
||||||
// The identifier should be bound to the expression.
|
// The identifier should be bound to the expression.
|
||||||
let oi_expr = oi_ident
|
let oi_expr = oi_ident
|
||||||
.definition::<Expr>(asg)
|
.definition_narrow::<Expr>(asg)
|
||||||
.expect("abstract identifier did not bind to Expr");
|
.expect("abstract identifier did not bind to Expr");
|
||||||
|
|
||||||
assert_eq!(S3.merge(S5).unwrap(), oi_expr.resolve(asg).span());
|
assert_eq!(S3.merge(S5).unwrap(), oi_expr.resolve(asg).span());
|
||||||
|
|
|
@ -185,7 +185,7 @@ fn tpl_apply_nested_missing() {
|
||||||
let oi_tpl_inner = oi_tpl_outer
|
let oi_tpl_inner = oi_tpl_outer
|
||||||
.lookup_local_linear(&asg, id_tpl_inner)
|
.lookup_local_linear(&asg, id_tpl_inner)
|
||||||
.expect("could not locate inner template as a local")
|
.expect("could not locate inner template as a local")
|
||||||
.definition::<Tpl>(&asg)
|
.definition_narrow::<Tpl>(&asg)
|
||||||
.expect("could not resolve inner template ref to Tpl");
|
.expect("could not resolve inner template ref to Tpl");
|
||||||
|
|
||||||
// We should have two inner template applications.
|
// We should have two inner template applications.
|
||||||
|
@ -206,7 +206,7 @@ fn tpl_apply_nested_missing() {
|
||||||
inners
|
inners
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|oi| oi.edges_filtered::<Ident>(&asg))
|
.flat_map(|oi| oi.edges_filtered::<Ident>(&asg))
|
||||||
.filter_map(|oi| oi.definition(&asg))
|
.filter_map(|oi| oi.definition_narrow(&asg))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1282,8 +1282,35 @@ impl ObjectIndex<Ident> {
|
||||||
/// Look up the definition that this identifier binds to,
|
/// Look up the definition that this identifier binds to,
|
||||||
/// if any.
|
/// if any.
|
||||||
///
|
///
|
||||||
/// See [`Self::bind_definition`].
|
/// _It is assumed that an identifier has only a single definition_.
|
||||||
pub fn definition<O: ObjectRelFrom<Ident> + ObjectRelatable>(
|
/// If this invariant is not upheld,
|
||||||
|
/// then the definition that is returned is undefined.
|
||||||
|
///
|
||||||
|
/// See also [`Self::bind_definition`] and [`Self::definition_narrow`].
|
||||||
|
pub fn definition(
|
||||||
|
&self,
|
||||||
|
asg: &Asg,
|
||||||
|
) -> Option<<Ident as ObjectRelatable>::Rel> {
|
||||||
|
self.edges(asg).next()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Look up the definition that this identifier binds to,
|
||||||
|
/// if any,
|
||||||
|
/// and attempt to narrow its type.
|
||||||
|
///
|
||||||
|
/// This can be read as "attempt to find a definition of this
|
||||||
|
/// [`ObjectKind`]".
|
||||||
|
/// It cannot distinguish between the absence of a definition,
|
||||||
|
/// and one that does not meet the provided criterion.
|
||||||
|
/// If this distinction is important,
|
||||||
|
/// see [`Self::definition`].
|
||||||
|
///
|
||||||
|
/// _It is assumed that an identifier has only a single definition_.
|
||||||
|
/// If this invariant is not upheld,
|
||||||
|
/// then the definition that is returned is undefined.
|
||||||
|
///
|
||||||
|
/// See also [`Self::bind_definition`].
|
||||||
|
pub fn definition_narrow<O: ObjectRelFrom<Ident> + ObjectRelatable>(
|
||||||
&self,
|
&self,
|
||||||
asg: &Asg,
|
asg: &Asg,
|
||||||
) -> Option<ObjectIndex<O>> {
|
) -> Option<ObjectIndex<O>> {
|
||||||
|
|
|
@ -492,7 +492,9 @@ mod order {
|
||||||
Ident(oi_ident) => {
|
Ident(oi_ident) => {
|
||||||
// This is the (comparatively) expensive lookup,
|
// This is the (comparatively) expensive lookup,
|
||||||
// requiring a small graph traversal.
|
// requiring a small graph traversal.
|
||||||
match oi_ident.definition::<object::Meta>(asg) {
|
match oi_ident
|
||||||
|
.definition_narrow::<object::Meta>(asg)
|
||||||
|
{
|
||||||
Some(_) => TplOrder::Param,
|
Some(_) => TplOrder::Param,
|
||||||
None => TplOrder::Body,
|
None => TplOrder::Body,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue