//! Since the AST and HIR are fairly similar, this is mostly a simple procedure,
//! much like a fold. Where lowering involves a bit more work things get more
//! interesting and there are some invariants you should know about. These mostly
-//! concern spans and ids.
+//! concern spans and IDs.
//!
//! Spans are assigned to AST nodes during parsing and then are modified during
//! expansion to indicate the origin of a node and the process it went through
-//! being expanded. Ids are assigned to AST nodes just before lowering.
+//! being expanded. IDs are assigned to AST nodes just before lowering.
//!
-//! For the simpler lowering steps, ids and spans should be preserved. Unlike
+//! For the simpler lowering steps, IDs and spans should be preserved. Unlike
//! expansion we do not preserve the process of lowering in the spans, so spans
//! should not be modified here. When creating a new node (as opposed to
-//! 'folding' an existing one), then you create a new id using `next_id()`.
+//! 'folding' an existing one), then you create a new ID using `next_id()`.
//!
-//! You must ensure that ids are unique. That means that you should only use the
-//! id from an AST node in a single HIR node (you can assume that AST node ids
-//! are unique). Every new node must have a unique id. Avoid cloning HIR nodes.
-//! If you do, you must then set the new node's id to a fresh one.
+//! You must ensure that IDs are unique. That means that you should only use the
+//! ID from an AST node in a single HIR node (you can assume that AST node IDs
+//! are unique). Every new node must have a unique ID. Avoid cloning HIR nodes.
+//! If you do, you must then set the new node's ID to a fresh one.
//!
//! Spans are used for error messages and for tools to map semantics back to
-//! source code. It is therefore not as important with spans as ids to be strict
+//! source code. It is therefore not as important with spans as IDs to be strict
//! about use (you can't break the compiler by screwing up a span). Obviously, a
//! HIR node can only have a single span. But multiple nodes can have the same
//! span and spans don't need to be kept in order, etc. Where code is preserved
//! in the HIR, especially for multiple identifiers.
use crate::dep_graph::DepGraph;
-use crate::errors::Applicability;
use crate::hir::{self, ParamName};
use crate::hir::HirVec;
use crate::hir::map::{DefKey, DefPathData, Definitions};
use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
ELIDED_LIFETIMES_IN_PATHS};
use crate::middle::cstore::CrateStore;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_data_structures::thin_vec::ThinVec;
use crate::session::Session;
use crate::session::config::nightly_options;
use crate::util::common::FN_OUTPUT_NAME;
use crate::util::nodemap::{DefIdMap, NodeMap};
+use errors::Applicability;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::thin_vec::ThinVec;
+use rustc_data_structures::sync::Lrc;
use std::collections::{BTreeSet, BTreeMap};
use std::fmt::Debug;
is_value: bool,
) -> hir::Path;
- /// Obtain the resolution for a node-id.
+ /// Obtain the resolution for a `NodeId`.
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution>;
/// Obtain the possible resolutions for the given `use` statement.
}
/// What to do when we encounter an **anonymous** lifetime
-/// reference. Anonymous lifetime references come in two flavors. You
+/// reference. Anonymous lifetime references come in two flavors. You
/// have implicit, or fully elided, references to lifetimes, like the
/// one in `&T` or `Ref<T>`, and you have `'_` lifetimes, like `&'_ T`
-/// or `Ref<'_, T>`. These often behave the same, but not always:
+/// or `Ref<'_, T>`. These often behave the same, but not always:
///
/// - certain usages of implicit references are deprecated, like
/// `Ref<T>`, and we sometimes just give hard errors in those cases
Ident::with_empty_ctxt(Symbol::gensym(s))
}
- fn allow_internal_unstable(&self, reason: CompilerDesugaringKind, span: Span) -> Span {
+ /// Reuses the span but adds information like the kind of the desugaring and features that are
+ /// allowed inside this span.
+ fn mark_span_with_reason(
+ &self,
+ reason: CompilerDesugaringKind,
+ span: Span,
+ allow_internal_unstable: Option<Lrc<[Symbol]>>,
+ ) -> Span {
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(source_map::ExpnInfo {
call_site: span,
def_site: Some(span),
format: source_map::CompilerDesugaring(reason),
- allow_internal_unstable: true,
+ allow_internal_unstable,
allow_internal_unsafe: false,
local_inner_macros: false,
edition: source_map::hygiene::default_edition(),
attrs: ThinVec::new(),
};
- let unstable_span = self.allow_internal_unstable(CompilerDesugaringKind::Async, span);
+ let unstable_span = self.mark_span_with_reason(
+ CompilerDesugaringKind::Async,
+ span,
+ Some(vec![
+ Symbol::intern("gen_future"),
+ ].into()),
+ );
let gen_future = self.expr_std_path(
unstable_span, &["future", "from_generator"], None, ThinVec::new());
hir::ExprKind::Call(P(gen_future), hir_vec![generator])
match arg {
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)),
ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty_direct(&ty, itctx)),
+ ast::GenericArg::Const(ct) => {
+ // FIXME(const_generics): const generics are not yet defined in the HIR.
+ self.sess.struct_span_err(
+ ct.value.span,
+ "const generics in any position are currently unsupported",
+ ).emit();
+ self.sess.abort_if_errors();
+ bug!();
+ }
}
}
// desugaring that explicitly states that we don't want to track that.
// Not tracking it makes lints in rustc and clippy very fragile as
// frequently opened issues show.
- let exist_ty_span = self.allow_internal_unstable(
+ let exist_ty_span = self.mark_span_with_reason(
CompilerDesugaringKind::ExistentialReturnType,
span,
+ None,
);
let exist_ty_def_index = self
|this| this.lower_param_bounds(¶m.bounds, itctx.reborrow()),
);
- match param.kind {
+ let (name, kind) = match param.kind {
GenericParamKind::Lifetime => {
let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
self.is_collecting_in_band_lifetimes = false;
| hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()),
hir::LifetimeName::Error => ParamName::Error,
};
- let param = hir::GenericParam {
- id: lt.id,
- hir_id: lt.hir_id,
- name: param_name,
- span: lt.span,
- pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"),
- attrs: self.lower_attrs(¶m.attrs),
- bounds,
- kind: hir::GenericParamKind::Lifetime {
- kind: hir::LifetimeParamKind::Explicit,
- }
+
+ let kind = hir::GenericParamKind::Lifetime {
+ kind: hir::LifetimeParamKind::Explicit
};
self.is_collecting_in_band_lifetimes = was_collecting_in_band;
- param
+ (param_name, kind)
}
GenericParamKind::Type { ref default, .. } => {
// Don't expose `Self` (recovered "keyword used as ident" parse error).
.chain(params)
.collect();
}
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(param.id);
- hir::GenericParam {
- id: node_id,
- hir_id,
- name: hir::ParamName::Plain(ident),
- pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"),
- attrs: self.lower_attrs(¶m.attrs),
- bounds,
- span: ident.span,
- kind: hir::GenericParamKind::Type {
- default: default.as_ref().map(|x| {
- self.lower_ty(x, ImplTraitContext::disallowed())
- }),
- synthetic: param.attrs.iter()
- .filter(|attr| attr.check_name("rustc_synthetic"))
- .map(|_| hir::SyntheticTyParamKind::ImplTrait)
- .next(),
- }
- }
+ let kind = hir::GenericParamKind::Type {
+ default: default.as_ref().map(|x| {
+ self.lower_ty(x, ImplTraitContext::disallowed())
+ }),
+ synthetic: param.attrs.iter()
+ .filter(|attr| attr.check_name("rustc_synthetic"))
+ .map(|_| hir::SyntheticTyParamKind::ImplTrait)
+ .next(),
+ };
+
+ (hir::ParamName::Plain(ident), kind)
+ }
+ GenericParamKind::Const { .. } => {
+ // FIXME(const_generics): const generics are not yet defined in the HIR.
+ self.sess.struct_span_err(
+ param.ident.span,
+ "const generics in any position are currently unsupported",
+ ).emit();
+ self.sess.abort_if_errors();
+ bug!();
}
+ };
+
+ let LoweredNodeId { node_id, hir_id } = self.lower_node_id(param.id);
+
+ hir::GenericParam {
+ id: node_id,
+ hir_id,
+ name,
+ span: param.ident.span,
+ pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"),
+ attrs: self.lower_attrs(¶m.attrs),
+ bounds,
+ kind,
}
}
/// Paths like the visibility path in `pub(super) use foo::{bar, baz}` are repeated
/// many times in the HIR tree; for each occurrence, we need to assign distinct
- /// node-ids. (See e.g., #56128.)
+ /// `NodeId`s. (See, e.g., #56128.)
fn renumber_segment_ids(&mut self, path: &P<hir::Path>) -> P<hir::Path> {
debug!("renumber_segment_ids(path = {:?})", path);
let mut path = path.clone();
}),
ExprKind::TryBlock(ref body) => {
self.with_catch_scope(body.id, |this| {
- let unstable_span =
- this.allow_internal_unstable(CompilerDesugaringKind::TryBlock, body.span);
+ let unstable_span = this.mark_span_with_reason(
+ CompilerDesugaringKind::TryBlock,
+ body.span,
+ Some(vec![
+ Symbol::intern("try_trait"),
+ ].into()),
+ );
let mut block = this.lower_block(body, true).into_inner();
let tail = block.expr.take().map_or_else(
|| {
// expand <head>
let head = self.lower_expr(head);
let head_sp = head.span;
- let desugared_span = self.allow_internal_unstable(
+ let desugared_span = self.mark_span_with_reason(
CompilerDesugaringKind::ForLoop,
head_sp,
+ None,
);
let iter = self.str_to_ident("iter");
// return Try::from_error(From::from(err)),
// }
- let unstable_span =
- self.allow_internal_unstable(CompilerDesugaringKind::QuestionMark, e.span);
+ let unstable_span = self.mark_span_with_reason(
+ CompilerDesugaringKind::QuestionMark,
+ e.span,
+ Some(vec![
+ Symbol::intern("try_trait")
+ ].into()),
+ );
// `Try::into_result(<expr>)`
let discr = {