rustc: produce AST instead of HIR from hir::lowering::Resolver
methods.
This commit is contained in:
parent
53ae6d2eb5
commit
e6ee8a0d44
3 changed files with 46 additions and 46 deletions
|
@ -148,11 +148,11 @@ pub struct LoweringContext<'a> {
|
|||
|
||||
pub trait Resolver {
|
||||
/// Resolve a path generated by the lowerer when expanding `for`, `if let`, etc.
|
||||
fn resolve_hir_path(
|
||||
fn resolve_ast_path(
|
||||
&mut self,
|
||||
path: &ast::Path,
|
||||
is_value: bool,
|
||||
) -> hir::Path;
|
||||
) -> Res<NodeId>;
|
||||
|
||||
/// Obtain resolution for a `NodeId` with a single resolution.
|
||||
fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes>;
|
||||
|
@ -167,7 +167,7 @@ pub trait Resolver {
|
|||
/// This should only return `None` during testing.
|
||||
fn definitions(&mut self) -> &mut Definitions;
|
||||
|
||||
/// Given suffix `["b", "c", "d"]`, creates a HIR path for `[::crate_root]::b::c::d` and
|
||||
/// Given suffix `["b", "c", "d"]`, creates an AST path for `[::crate_root]::b::c::d` and
|
||||
/// resolves it based on `is_value`.
|
||||
fn resolve_str_path(
|
||||
&mut self,
|
||||
|
@ -175,7 +175,7 @@ pub trait Resolver {
|
|||
crate_root: Option<Symbol>,
|
||||
components: &[Symbol],
|
||||
is_value: bool,
|
||||
) -> hir::Path;
|
||||
) -> (ast::Path, Res<NodeId>);
|
||||
}
|
||||
|
||||
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
|
||||
|
@ -5546,16 +5546,26 @@ impl<'a> LoweringContext<'a> {
|
|||
params: Option<P<hir::GenericArgs>>,
|
||||
is_value: bool,
|
||||
) -> hir::Path {
|
||||
let mut path = self.resolver
|
||||
let (path, res) = self.resolver
|
||||
.resolve_str_path(span, self.crate_root, components, is_value);
|
||||
path.segments.last_mut().unwrap().args = params;
|
||||
|
||||
for seg in path.segments.iter_mut() {
|
||||
if seg.hir_id.is_some() {
|
||||
seg.hir_id = Some(self.next_id());
|
||||
let mut segments: Vec<_> = path.segments.iter().map(|segment| {
|
||||
let res = self.expect_full_res(segment.id);
|
||||
hir::PathSegment {
|
||||
ident: segment.ident,
|
||||
hir_id: Some(self.lower_node_id(segment.id)),
|
||||
res: Some(self.lower_res(res)),
|
||||
infer_args: true,
|
||||
args: None,
|
||||
}
|
||||
}).collect();
|
||||
segments.last_mut().unwrap().args = params;
|
||||
|
||||
hir::Path {
|
||||
span,
|
||||
res: res.map_id(|_| panic!("unexpected node_id")),
|
||||
segments: segments.into(),
|
||||
}
|
||||
path
|
||||
}
|
||||
|
||||
fn ty_path(&mut self, mut hir_id: hir::HirId, span: Span, qpath: hir::QPath) -> hir::Ty {
|
||||
|
|
|
@ -1744,12 +1744,12 @@ impl<'a, 'b> ty::DefIdTree for &'a Resolver<'b> {
|
|||
/// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that
|
||||
/// the resolver is no longer needed as all the relevant information is inline.
|
||||
impl<'a> hir::lowering::Resolver for Resolver<'a> {
|
||||
fn resolve_hir_path(
|
||||
fn resolve_ast_path(
|
||||
&mut self,
|
||||
path: &ast::Path,
|
||||
is_value: bool,
|
||||
) -> hir::Path {
|
||||
self.resolve_hir_path_cb(path, is_value,
|
||||
) -> Res {
|
||||
self.resolve_ast_path_cb(path, is_value,
|
||||
|resolver, span, error| resolve_error(resolver, span, error))
|
||||
}
|
||||
|
||||
|
@ -1759,7 +1759,7 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
|
|||
crate_root: Option<Symbol>,
|
||||
components: &[Symbol],
|
||||
is_value: bool
|
||||
) -> hir::Path {
|
||||
) -> (ast::Path, Res) {
|
||||
let root = if crate_root.is_some() {
|
||||
kw::PathRoot
|
||||
} else {
|
||||
|
@ -1777,7 +1777,8 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
|
|||
segments,
|
||||
};
|
||||
|
||||
self.resolve_hir_path(&path, is_value)
|
||||
let res = self.resolve_ast_path(&path, is_value);
|
||||
(path, res)
|
||||
}
|
||||
|
||||
fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes> {
|
||||
|
@ -1803,7 +1804,7 @@ impl<'a> Resolver<'a> {
|
|||
/// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
|
||||
/// just that an error occurred.
|
||||
pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: bool)
|
||||
-> Result<hir::Path, ()> {
|
||||
-> Result<(ast::Path, Res), ()> {
|
||||
let mut errored = false;
|
||||
|
||||
let path = if path_str.starts_with("::") {
|
||||
|
@ -1826,29 +1827,29 @@ impl<'a> Resolver<'a> {
|
|||
.collect(),
|
||||
}
|
||||
};
|
||||
let path = self.resolve_hir_path_cb(&path, is_value, |_, _, _| errored = true);
|
||||
if errored || path.res == def::Res::Err {
|
||||
let res = self.resolve_ast_path_cb(&path, is_value, |_, _, _| errored = true);
|
||||
if errored || res == def::Res::Err {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(path)
|
||||
Ok((path, res))
|
||||
}
|
||||
}
|
||||
|
||||
/// Like `resolve_hir_path`, but takes a callback in case there was an error.
|
||||
fn resolve_hir_path_cb<F>(
|
||||
/// Like `resolve_ast_path`, but takes a callback in case there was an error.
|
||||
// FIXME(eddyb) use `Result` or something instead of callbacks.
|
||||
fn resolve_ast_path_cb<F>(
|
||||
&mut self,
|
||||
path: &ast::Path,
|
||||
is_value: bool,
|
||||
error_callback: F,
|
||||
) -> hir::Path
|
||||
) -> Res
|
||||
where F: for<'c, 'b> FnOnce(&'c mut Resolver<'_>, Span, ResolutionError<'b>)
|
||||
{
|
||||
let namespace = if is_value { ValueNS } else { TypeNS };
|
||||
let span = path.span;
|
||||
let segments = &path.segments;
|
||||
let path = Segment::from_path(&path);
|
||||
// FIXME(Manishearth): intra-doc links won't get warned of epoch changes.
|
||||
let res = match self.resolve_path_without_parent_scope(&path, Some(namespace), true,
|
||||
match self.resolve_path_without_parent_scope(&path, Some(namespace), true,
|
||||
span, CrateLint::No) {
|
||||
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
|
||||
module.res().unwrap(),
|
||||
|
@ -1869,19 +1870,6 @@ impl<'a> Resolver<'a> {
|
|||
});
|
||||
Res::Err
|
||||
}
|
||||
};
|
||||
|
||||
let segments: Vec<_> = segments.iter().map(|seg| {
|
||||
let mut hir_seg = hir::PathSegment::from_ident(seg.ident);
|
||||
hir_seg.res = Some(self.partial_res_map.get(&seg.id).map_or(def::Res::Err, |p| {
|
||||
p.base_res().map_id(|_| panic!("unexpected node_id"))
|
||||
}));
|
||||
hir_seg
|
||||
}).collect();
|
||||
hir::Path {
|
||||
span,
|
||||
res: res.map_id(|_| panic!("unexpected node_id")),
|
||||
segments: segments.into(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,15 +71,16 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
})
|
||||
});
|
||||
|
||||
if let Ok(result) = result {
|
||||
if let Ok((_, res)) = result {
|
||||
let res = res.map_id(|_| panic!("unexpected node_id"));
|
||||
// In case this is a trait item, skip the
|
||||
// early return and try looking for the trait.
|
||||
let value = match result.res {
|
||||
let value = match res {
|
||||
Res::Def(DefKind::Method, _) | Res::Def(DefKind::AssocConst, _) => true,
|
||||
Res::Def(DefKind::AssocTy, _) => false,
|
||||
Res::Def(DefKind::Variant, _) => return handle_variant(cx, result.res),
|
||||
Res::Def(DefKind::Variant, _) => return handle_variant(cx, res),
|
||||
// Not a trait item; just return what we found.
|
||||
_ => return Ok((result.res, None))
|
||||
_ => return Ok((res, None))
|
||||
};
|
||||
|
||||
if value != (ns == ValueNS) {
|
||||
|
@ -129,10 +130,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
|
||||
// FIXME: `with_scope` requires the `NodeId` of a module.
|
||||
let node_id = cx.tcx.hir().hir_to_node_id(id);
|
||||
let ty = cx.enter_resolver(|resolver| resolver.with_scope(node_id, |resolver| {
|
||||
let (_, ty_res) = cx.enter_resolver(|resolver| resolver.with_scope(node_id, |resolver| {
|
||||
resolver.resolve_str_path_error(DUMMY_SP, &path, false)
|
||||
}))?;
|
||||
match ty.res {
|
||||
let ty_res = ty_res.map_id(|_| panic!("unexpected node_id"));
|
||||
match ty_res {
|
||||
Res::Def(DefKind::Struct, did)
|
||||
| Res::Def(DefKind::Union, did)
|
||||
| Res::Def(DefKind::Enum, did)
|
||||
|
@ -147,7 +149,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
ty::AssocKind::Const if ns == ValueNS => "associatedconstant",
|
||||
_ => return Err(())
|
||||
};
|
||||
Ok((ty.res, Some(format!("{}.{}", out, item_name))))
|
||||
Ok((ty_res, Some(format!("{}.{}", out, item_name))))
|
||||
} else {
|
||||
match cx.tcx.type_of(did).sty {
|
||||
ty::Adt(def, _) => {
|
||||
|
@ -159,7 +161,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
.iter()
|
||||
.find(|item| item.ident.name == item_name)
|
||||
} {
|
||||
Ok((ty.res,
|
||||
Ok((ty_res,
|
||||
Some(format!("{}.{}",
|
||||
if def.is_enum() {
|
||||
"variant"
|
||||
|
@ -193,7 +195,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
_ => return Err(())
|
||||
};
|
||||
|
||||
Ok((ty.res, Some(format!("{}.{}", kind, item_name))))
|
||||
Ok((ty_res, Some(format!("{}.{}", kind, item_name))))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue