});
}
- fn visit_fn(
- &mut self,
- fk: intravisit::FnKind<'hir>,
- fd: &'hir FnDecl<'hir>,
- b: BodyId,
- _: Span,
- id: HirId,
- ) {
- assert_eq!(self.owner, id.owner);
- assert_eq!(self.parent_node, id.local_id);
- intravisit::walk_fn(self, fk, fd, b, id);
- }
-
fn visit_block(&mut self, block: &'hir Block<'hir>) {
self.insert(block.span, block.hir_id, Node::Block(block));
self.with_parent(block.hir_id, |this| {
current_hir_id_owner: hir::CRATE_OWNER_ID,
item_local_id_counter: hir::ItemLocalId::new(0),
node_id_to_local_id: Default::default(),
- local_id_to_def_id: SortedMap::new(),
trait_map: Default::default(),
// Lowering state.
current_hir_id_owner: hir::OwnerId,
item_local_id_counter: hir::ItemLocalId,
- local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>,
trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>,
impl_trait_defs: Vec<hir::GenericParam<'hir>>,
let current_attrs = std::mem::take(&mut self.attrs);
let current_bodies = std::mem::take(&mut self.bodies);
let current_node_ids = std::mem::take(&mut self.node_id_to_local_id);
- let current_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id);
let current_trait_map = std::mem::take(&mut self.trait_map);
let current_owner =
std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id });
self.attrs = current_attrs;
self.bodies = current_bodies;
self.node_id_to_local_id = current_node_ids;
- self.local_id_to_def_id = current_id_to_def_id;
self.trait_map = current_trait_map;
self.current_hir_id_owner = current_owner;
self.item_local_id_counter = current_local_counter;
fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {
let attrs = std::mem::take(&mut self.attrs);
let mut bodies = std::mem::take(&mut self.bodies);
- let local_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id);
let trait_map = std::mem::take(&mut self.trait_map);
#[cfg(debug_assertions)]
let (hash_including_bodies, hash_without_bodies) = self.hash_owner(node, &bodies);
let (nodes, parenting) =
index::index_hir(self.tcx.sess, &*self.tcx.definitions_untracked(), node, &bodies);
- let nodes = hir::OwnerNodes {
- hash_including_bodies,
- hash_without_bodies,
- nodes,
- bodies,
- local_id_to_def_id,
- };
+ let nodes = hir::OwnerNodes { hash_including_bodies, hash_without_bodies, nodes, bodies };
let attrs = {
let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
let mut stable_hasher = StableHasher::new();
assert_ne!(local_id, hir::ItemLocalId::new(0));
if let Some(def_id) = self.opt_local_def_id(ast_node_id) {
self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
- self.local_id_to_def_id.insert(local_id, def_id);
}
if let Some(traits) = self.resolver.trait_map.remove(&ast_node_id) {
use crate::deriving::generic::ty::*;
use crate::deriving::generic::*;
use crate::deriving::{path_std, pathvec_std};
-use rustc_ast::MetaItem;
+use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
let attrs = thin_vec![cx.attr_word(sym::inline, span)];
+ // Order in which to perform matching
+ let tag_then_data = if let Annotatable::Item(item) = item
+ && let ItemKind::Enum(def, _) = &item.kind {
+ let dataful: Vec<bool> = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect();
+ match dataful.iter().filter(|&&b| b).count() {
+ // No data, placing the tag check first makes codegen simpler
+ 0 => true,
+ 1..=2 => false,
+ _ => {
+ (0..dataful.len()-1).any(|i| {
+ if dataful[i] && let Some(idx) = dataful[i+1..].iter().position(|v| *v) {
+ idx >= 2
+ } else {
+ false
+ }
+ })
+ }
+ }
+ } else {
+ true
+ };
let partial_cmp_def = MethodDef {
name: sym::partial_cmp,
generics: Bounds::empty(),
attributes: attrs,
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
- cs_partial_cmp(cx, span, substr)
+ cs_partial_cmp(cx, span, substr, tag_then_data)
})),
};
trait_def.expand(cx, mitem, item, push)
}
-pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
+fn cs_partial_cmp(
+ cx: &mut ExtCtxt<'_>,
+ span: Span,
+ substr: &Substructure<'_>,
+ tag_then_data: bool,
+) -> BlockOrExpr {
let test_id = Ident::new(sym::cmp, span);
let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
let args = vec![field.self_expr.clone(), other_expr.clone()];
cx.expr_call_global(field.span, partial_cmp_path.clone(), args)
}
- CsFold::Combine(span, expr1, expr2) => {
- let eq_arm =
- cx.arm(span, cx.pat_some(span, cx.pat_path(span, equal_path.clone())), expr1);
- let neq_arm =
- cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id));
- cx.expr_match(span, expr2, vec![eq_arm, neq_arm])
+ CsFold::Combine(span, mut expr1, expr2) => {
+ // When the item is an enum, this expands to
+ // ```
+ // match (expr2) {
+ // Some(Ordering::Equal) => expr1,
+ // cmp => cmp
+ // }
+ // ```
+ // where `expr2` is `partial_cmp(self_tag, other_tag)`, and `expr1` is a `match`
+ // against the enum variants. This means that we begin by comparing the enum tags,
+ // before either inspecting their contents (if they match), or returning
+ // the `cmp::Ordering` of comparing the enum tags.
+ // ```
+ // match partial_cmp(self_tag, other_tag) {
+ // Some(Ordering::Equal) => match (self, other) {
+ // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0),
+ // (Self::B(self_0), Self::B(other_0)) => partial_cmp(self_0, other_0),
+ // _ => Some(Ordering::Equal)
+ // }
+ // cmp => cmp
+ // }
+ // ```
+ // If we have any certain enum layouts, flipping this results in better codegen
+ // ```
+ // match (self, other) {
+ // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0),
+ // _ => partial_cmp(self_tag, other_tag)
+ // }
+ // ```
+ // Reference: https://github.com/rust-lang/rust/pull/103659#issuecomment-1328126354
+
+ if !tag_then_data
+ && let ExprKind::Match(_, arms) = &mut expr1.kind
+ && let Some(last) = arms.last_mut()
+ && let PatKind::Wild = last.pat.kind {
+ last.body = expr2;
+ expr1
+ } else {
+ let eq_arm =
+ cx.arm(span, cx.pat_some(span, cx.pat_path(span, equal_path.clone())), expr1);
+ let neq_arm =
+ cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id));
+ cx.expr_match(span, expr2, vec![eq_arm, neq_arm])
+ }
}
CsFold::Fieldless => cx.expr_some(span, cx.expr_path(equal_path.clone())),
},
// Arguments get assigned to by means of the function being called
for arg in mir.args_iter() {
- analyzer.assign(arg, mir::START_BLOCK.start_location());
+ analyzer.assign(arg, DefLocation::Argument);
}
// If there exists a local definition that dominates all uses of that local,
/// A scalar or a scalar pair local that is neither defined nor used.
Unused,
/// A scalar or a scalar pair local with a single definition that dominates all uses.
- SSA(mir::Location),
+ SSA(DefLocation),
+}
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+enum DefLocation {
+ Argument,
+ Body(Location),
+}
+
+impl DefLocation {
+ fn dominates(self, location: Location, dominators: &Dominators<mir::BasicBlock>) -> bool {
+ match self {
+ DefLocation::Argument => true,
+ DefLocation::Body(def) => def.successor_within_block().dominates(location, dominators),
+ }
+ }
}
struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
}
impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
- fn assign(&mut self, local: mir::Local, location: Location) {
+ fn assign(&mut self, local: mir::Local, location: DefLocation) {
let kind = &mut self.locals[local];
match *kind {
LocalKind::ZST => {}
LocalKind::Memory => {}
- LocalKind::Unused => {
- *kind = LocalKind::SSA(location);
- }
- LocalKind::SSA(_) => {
- *kind = LocalKind::Memory;
- }
+ LocalKind::Unused => *kind = LocalKind::SSA(location),
+ LocalKind::SSA(_) => *kind = LocalKind::Memory,
}
}
debug!("visit_assign(place={:?}, rvalue={:?})", place, rvalue);
if let Some(local) = place.as_local() {
- self.assign(local, location);
+ self.assign(local, DefLocation::Body(location));
if self.locals[local] != LocalKind::Memory {
let decl_span = self.fx.mir.local_decls[local].source_info.span;
if !self.fx.rvalue_creates_operand(rvalue, decl_span) {
match context {
PlaceContext::MutatingUse(MutatingUseContext::Call)
| PlaceContext::MutatingUse(MutatingUseContext::Yield) => {
- self.assign(local, location);
+ self.assign(local, DefLocation::Body(location));
}
PlaceContext::NonUse(_) | PlaceContext::MutatingUse(MutatingUseContext::Retag) => {}
invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}`
codegen_gcc_invalid_monomorphization_invalid_bitmask =
- invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
+ invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
codegen_gcc_invalid_monomorphization_simd_shuffle =
invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
-codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {error}
+codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
-codegen_ssa_read_file = failed to read file: {message}
+codegen_ssa_read_file = failed to read file: {$message}
codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
pub nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>,
/// Content of local bodies.
pub bodies: SortedMap<ItemLocalId, &'tcx Body<'tcx>>,
- /// Non-owning definitions contained in this owner.
- pub local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>,
}
impl<'tcx> OwnerNodes<'tcx> {
.collect::<Vec<_>>(),
)
.field("bodies", &self.bodies)
- .field("local_id_to_def_id", &self.local_id_to_def_id)
.field("hash_without_bodies", &self.hash_without_bodies)
.field("hash_including_bodies", &self.hash_including_bodies)
.finish()
use crate::hir::*;
use rustc_ast::walk_list;
use rustc_ast::{Attribute, Label};
+use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span;
fn visit_fn_decl(&mut self, fd: &'v FnDecl<'v>) {
walk_fn_decl(self, fd)
}
- fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl<'v>, b: BodyId, _: Span, id: HirId) {
+ fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl<'v>, b: BodyId, _: Span, id: LocalDefId) {
walk_fn(self, fk, fd, b, id)
}
fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) {
visitor.visit_ty(typ);
visitor.visit_nested_body(body);
}
- ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn(
- FnKind::ItemFn(item.ident, generics, sig.header),
- sig.decl,
- body_id,
- item.span,
- item.hir_id(),
- ),
+ ItemKind::Fn(ref sig, ref generics, body_id) => {
+ visitor.visit_id(item.hir_id());
+ visitor.visit_fn(
+ FnKind::ItemFn(item.ident, generics, sig.header),
+ sig.decl,
+ body_id,
+ item.span,
+ item.owner_id.def_id,
+ )
+ }
ItemKind::Macro(..) => {
visitor.visit_id(item.hir_id());
}
walk_list!(visitor, visit_arm, arms);
}
ExprKind::Closure(&Closure {
- def_id: _,
+ def_id,
binder: _,
bound_generic_params,
fn_decl,
constness: _,
}) => {
walk_list!(visitor, visit_generic_param, bound_generic_params);
- visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id)
+ visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, def_id)
}
ExprKind::Block(ref block, ref opt_label) => {
walk_list!(visitor, visit_label, opt_label);
function_kind: FnKind<'v>,
function_declaration: &'v FnDecl<'v>,
body_id: BodyId,
- id: HirId,
+ _: LocalDefId,
) {
- visitor.visit_id(id);
visitor.visit_fn_decl(function_declaration);
walk_fn_kind(visitor, function_kind);
visitor.visit_nested_body(body_id)
let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item;
let hir_id = trait_item.hir_id();
visitor.visit_ident(ident);
- visitor.visit_generics(generics);
- visitor.visit_defaultness(defaultness);
+ visitor.visit_generics(&generics);
+ visitor.visit_defaultness(&defaultness);
+ visitor.visit_id(hir_id);
match *kind {
TraitItemKind::Const(ref ty, default) => {
- visitor.visit_id(hir_id);
visitor.visit_ty(ty);
walk_list!(visitor, visit_nested_body, default);
}
TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
- visitor.visit_id(hir_id);
visitor.visit_fn_decl(sig.decl);
for ¶m_name in param_names {
visitor.visit_ident(param_name);
}
}
TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
- visitor.visit_fn(FnKind::Method(ident, sig), sig.decl, body_id, span, hir_id);
+ visitor.visit_fn(
+ FnKind::Method(ident, sig),
+ sig.decl,
+ body_id,
+ span,
+ trait_item.owner_id.def_id,
+ );
}
TraitItemKind::Type(bounds, ref default) => {
- visitor.visit_id(hir_id);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, default);
}
visitor.visit_ident(ident);
visitor.visit_generics(generics);
visitor.visit_defaultness(defaultness);
+ visitor.visit_id(impl_item.hir_id());
match *kind {
ImplItemKind::Const(ref ty, body) => {
- visitor.visit_id(impl_item.hir_id());
visitor.visit_ty(ty);
visitor.visit_nested_body(body);
}
sig.decl,
body_id,
impl_item.span,
- impl_item.hir_id(),
+ impl_item.owner_id.def_id,
);
}
ImplItemKind::Type(ref ty) => {
- visitor.visit_id(impl_item.hir_id());
visitor.visit_ty(ty);
}
}
// `local_id_to_def_id` is also ignored because is dependent on the body, then just hashing
// the body satisfies the condition of two nodes being different have different
// `hash_stable` results.
- let OwnerNodes {
- hash_including_bodies,
- hash_without_bodies: _,
- nodes: _,
- bodies: _,
- local_id_to_def_id: _,
- } = *self;
+ let OwnerNodes { hash_including_bodies, hash_without_bodies: _, nodes: _, bodies: _ } =
+ *self;
hash_including_bodies.hash_stable(hcx, hasher);
}
}
DefKind::GlobalAsm => {
let it = tcx.hir().item(id);
let hir::ItemKind::GlobalAsm(asm) = it.kind else { span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it) };
- InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, id.hir_id());
+ InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, id.owner_id.def_id);
}
_ => {}
}
use rustc_hir as hir;
use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitable, UintTy};
use rustc_session::lint;
+use rustc_span::def_id::LocalDefId;
use rustc_span::{Symbol, DUMMY_SP};
use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType};
Some(asm_ty)
}
- pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: hir::HirId) {
- let hir = self.tcx.hir();
- let enclosing_def_id = hir.local_def_id(enclosing_id).to_def_id();
- let target_features = self.tcx.asm_target_features(enclosing_def_id);
+ pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: LocalDefId) {
+ let target_features = self.tcx.asm_target_features(enclosing_id.to_def_id());
let Some(asm_arch) = self.tcx.sess.asm_arch else {
self.tcx.sess.delay_span_bug(DUMMY_SP, "target architecture does not support asm");
return;
gather_gat_bounds(
tcx,
param_env,
- item_def_id.def_id,
+ item_def_id,
sig.inputs_and_output,
// We also assume that all of the function signature's parameter types
// are well formed.
gather_gat_bounds(
tcx,
param_env,
- item_def_id.def_id,
+ item_def_id,
tcx.explicit_item_bounds(item_def_id).to_vec(),
&FxIndexSet::default(),
gat_def_id.def_id,
fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- item_def_id: LocalDefId,
+ item_def_id: hir::OwnerId,
to_check: T,
wf_tys: &FxIndexSet<Ty<'tcx>>,
gat_def_id: LocalDefId,
// reflected in a where clause on the GAT itself.
for (ty, ty_idx) in &types {
// In our example, requires that `Self: 'a`
- if ty_known_to_outlive(tcx, item_def_id, param_env, &wf_tys, *ty, *region_a) {
+ if ty_known_to_outlive(tcx, item_def_id.def_id, param_env, &wf_tys, *ty, *region_a) {
debug!(?ty_idx, ?region_a_idx);
debug!("required clause: {ty} must outlive {region_a}");
// Translate into the generic parameters of the GAT. In
if ty::ReStatic == **region_b || region_a == region_b {
continue;
}
- if region_known_to_outlive(tcx, item_def_id, param_env, &wf_tys, *region_a, *region_b) {
+ if region_known_to_outlive(
+ tcx,
+ item_def_id.def_id,
+ param_env,
+ &wf_tys,
+ *region_a,
+ *region_b,
+ ) {
debug!(?region_a_idx, ?region_b_idx);
debug!("required clause: {region_a} must outlive {region_b}");
// Translate into the generic parameters of the GAT.
fd: &'tcx hir::FnDecl<'tcx>,
body_id: hir::BodyId,
_: Span,
- _: hir::HirId,
+ _: LocalDefId,
) {
let output = match fd.output {
hir::FnRetTy::DefaultReturn(_) => None,
} else if let Some(body_id) = outermost_body {
let fn_id = self.tcx.hir().body_owner(body_id);
match self.tcx.hir().get(fn_id) {
- Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })
+ Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn(..), .. })
| Node::TraitItem(hir::TraitItem {
- kind: hir::TraitItemKind::Fn(..), ..
+ owner_id,
+ kind: hir::TraitItemKind::Fn(..),
+ ..
})
- | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. })
- | Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
- let scope = self.tcx.hir().local_def_id(fn_id);
- def = Region::Free(scope.to_def_id(), def.id().unwrap());
+ | Node::ImplItem(hir::ImplItem {
+ owner_id,
+ kind: hir::ImplItemKind::Fn(..),
+ ..
+ }) => {
+ def = Region::Free(owner_id.to_def_id(), def.id().unwrap());
+ }
+ Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => {
+ def = Region::Free(closure.def_id.to_def_id(), def.id().unwrap());
}
_ => {}
}
/// "Constrained" basically means that it appears in any type but
/// not amongst the inputs to a projection. In other words, `<&'a
/// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`.
-fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<LocalDefId>> {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let decl = tcx.hir().fn_decl_by_hir_id(hir_id)?;
- let generics = tcx.hir().get_generics(def_id)?;
+fn is_late_bound_map(
+ tcx: TyCtxt<'_>,
+ owner_id: hir::OwnerId,
+) -> Option<&FxIndexSet<hir::ItemLocalId>> {
+ let decl = tcx.hir().fn_decl_by_hir_id(owner_id.into())?;
+ let generics = tcx.hir().get_generics(owner_id.def_id)?;
let mut late_bound = FxIndexSet::default();
hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
}
- let param_def_id = tcx.hir().local_def_id(param.hir_id);
-
// appears in the where clauses? early-bound.
- if appears_in_where_clause.regions.contains(¶m_def_id) {
+ if appears_in_where_clause.regions.contains(¶m.def_id) {
continue;
}
// does not appear in the inputs, but appears in the return type? early-bound.
- if !constrained_by_input.regions.contains(¶m_def_id)
- && appears_in_output.regions.contains(¶m_def_id)
+ if !constrained_by_input.regions.contains(¶m.def_id)
+ && appears_in_output.regions.contains(¶m.def_id)
{
continue;
}
- debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.hir_id);
+ debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.def_id);
- let inserted = late_bound.insert(param_def_id);
- assert!(inserted, "visited lifetime {:?} twice", param.hir_id);
+ let inserted = late_bound.insert(param.hir_id.local_id);
+ assert!(inserted, "visited lifetime {:?} twice", param.def_id);
}
debug!(?late_bound);
}
let hir::GenericParamKind::Lifetime { .. } = duplicate.kind else { continue };
- let dup_def = tcx.hir().local_def_id(duplicate.hir_id).to_def_id();
+ let dup_def = duplicate.def_id.to_def_id();
let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() };
// ty which is a fully resolved projection.
// For the code example above, this would mean converting Self::Assoc<3>
// into a ty::Alias(ty::Projection, <Self as Foo>::Assoc<3>)
- let item_hir_id = tcx
+ let item_def_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<'_>;
+ .parent_owner_iter(hir_id)
+ .find(|(_, node)| matches!(node, OwnerNode::Item(_)))
+ .unwrap()
+ .0
+ .to_def_id();
+ let item_ctxt = &ItemCtxt::new(tcx, item_def_id) as &dyn crate::astconv::AstConv<'_>;
let ty = item_ctxt.ast_ty_to_ty(hir_ty);
// Iterate through the generics of the projection to find the one that corresponds to
prior_arm: Option<(Option<hir::HirId>, Ty<'tcx>, Span)>,
) {
let hir = self.tcx.hir();
+
// First, check that we're actually in the tail of a function.
let Some(body_id) = hir.maybe_body_owned_by(self.body_id) else { return; };
let body = hir.body(body_id);
let gen_ty = if let (Some(_), Some(gen_kind)) = (can_be_generator, body.generator_kind) {
let interior = fcx
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span });
- fcx.deferred_generator_interiors.borrow_mut().push((fn_id, body.id(), interior, gen_kind));
+ fcx.deferred_generator_interiors.borrow_mut().push((
+ fn_def_id,
+ body.id(),
+ interior,
+ gen_kind,
+ ));
let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap();
Some(GeneratorTypes {
// Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
if let Some(panic_impl_did) = tcx.lang_items().panic_impl()
- && panic_impl_did == hir.local_def_id(fn_id).to_def_id()
+ && panic_impl_did == fn_def_id.to_def_id()
{
check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty);
}
- if let Some(lang_start_defid) = tcx.lang_items().start_fn() && lang_start_defid == hir.local_def_id(fn_id).to_def_id() {
+ if let Some(lang_start_defid) = tcx.lang_items().start_fn() && lang_start_defid == fn_def_id.to_def_id() {
check_lang_start_fn(tcx, fn_sig, decl, fn_def_id);
}
let generators = std::mem::take(&mut *self.deferred_generator_interiors.borrow_mut());
debug!(?generators);
- for &(expr_hir_id, body_id, interior, _) in generators.iter() {
- let expr_def_id = self.tcx.hir().local_def_id(expr_hir_id);
+ for &(expr_def_id, body_id, interior, _) in generators.iter() {
debug!(?expr_def_id);
// Create the `GeneratorWitness` type that we will unify with `interior`.
}
};
InlineAsmCtxt::new_in_fn(self.tcx, self.param_env, get_operand_ty)
- .check_asm(asm, self.tcx.hir().local_def_id_to_hir_id(enclosing_id));
+ .check_asm(asm, enclosing_id);
}
}
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::ty::Ty;
use rustc_middle::ty::UserType;
+use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
use rustc_trait_selection::traits;
_: &'tcx hir::FnDecl<'tcx>,
_: hir::BodyId,
_: Span,
- _: hir::HirId,
+ _: LocalDefId,
) {
}
}
pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, hir::HirId)>>,
pub(super) deferred_generator_interiors:
- RefCell<Vec<(hir::HirId, hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
+ RefCell<Vec<(LocalDefId, hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
pub(super) body_id: Option<hir::BodyId>,
&self,
body: &'tcx hir::Body<'tcx>,
) -> &'tcx ty::TypeckResults<'tcx> {
- let item_id = self.tcx.hir().body_owner(body.id());
- let item_def_id = self.tcx.hir().local_def_id(item_id);
+ let item_def_id = self.tcx.hir().body_owner_def_id(body.id());
// This attribute causes us to dump some writeback information
// in the form of errors, which is used for unit tests.
// Type only exists for constants and statics, not functions.
match self.tcx.hir().body_owner_kind(item_def_id) {
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => {
- wbcx.visit_node_id(body.value.span, item_id);
+ let item_hir_id = self.tcx.hir().local_def_id_to_hir_id(item_def_id);
+ wbcx.visit_node_id(body.value.span, item_hir_id);
}
hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (),
}
use rustc_data_structures::graph::implementation::{Direction, NodeIndex, INCOMING, OUTGOING};
use rustc_graphviz as dot;
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::dep_graph::{
DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter,
let (if_this_changed, then_this_would_need) = {
let mut visitor =
IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] };
- visitor.process_attrs(hir::CRATE_HIR_ID);
+ visitor.process_attrs(CRATE_DEF_ID);
tcx.hir().visit_all_item_likes_in_crate(&mut visitor);
(visitor.if_this_changed, visitor.then_this_would_need)
};
value
}
- fn process_attrs(&mut self, hir_id: hir::HirId) {
- let def_id = self.tcx.hir().local_def_id(hir_id);
+ fn process_attrs(&mut self, def_id: LocalDefId) {
let def_path_hash = self.tcx.def_path_hash(def_id.to_def_id());
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let attrs = self.tcx.hir().attrs(hir_id);
for attr in attrs {
if attr.has_name(sym::rustc_if_this_changed) {
}
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- self.process_attrs(item.hir_id());
+ self.process_attrs(item.owner_id.def_id);
intravisit::walk_item(self, item);
}
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
- self.process_attrs(trait_item.hir_id());
+ self.process_attrs(trait_item.owner_id.def_id);
intravisit::walk_trait_item(self, trait_item);
}
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
- self.process_attrs(impl_item.hir_id());
+ self.process_attrs(impl_item.owner_id.def_id);
intravisit::walk_impl_item(self, impl_item);
}
fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) {
- self.process_attrs(s.hir_id);
+ self.process_attrs(s.def_id);
intravisit::walk_field_def(self, s);
}
}
use rustc_index::vec::IndexVec;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::GenericArg;
-use rustc_middle::ty::{self, BoundVar, List};
+use rustc_middle::ty::{self, List};
use rustc_span::source_map::Span;
pub use rustc_middle::infer::canonical::*;
variables: &List<CanonicalVarInfo<'tcx>>,
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
) -> CanonicalVarValues<'tcx> {
- let var_values: IndexVec<BoundVar, GenericArg<'tcx>> = variables
- .iter()
- .map(|info| self.instantiate_canonical_var(span, info, &universe_map))
- .collect();
-
- CanonicalVarValues { var_values }
+ CanonicalVarValues {
+ var_values: self.tcx.mk_substs(
+ variables
+ .iter()
+ .map(|info| self.instantiate_canonical_var(span, info, &universe_map)),
+ ),
+ }
}
/// Given the "info" about a canonical variable, creates a fresh
// given variable in the loop above, use that. Otherwise, use
// a fresh inference variable.
let result_subst = CanonicalVarValues {
- var_values: query_response
- .variables
- .iter()
- .enumerate()
- .map(|(index, info)| {
+ var_values: self.tcx.mk_substs(query_response.variables.iter().enumerate().map(
+ |(index, info)| {
if info.is_existential() {
match opt_values[BoundVar::new(index)] {
Some(k) => k,
universe_map[u.as_usize()]
})
}
- })
- .collect(),
+ },
+ )),
};
let mut obligations = vec![];
value
} else {
let delegate = FnMutDelegate {
- regions: &mut |br: ty::BoundRegion| match var_values.var_values[br.var].unpack() {
+ regions: &mut |br: ty::BoundRegion| match var_values[br.var].unpack() {
GenericArgKind::Lifetime(l) => l,
r => bug!("{:?} is a region but value is {:?}", br, r),
},
- types: &mut |bound_ty: ty::BoundTy| match var_values.var_values[bound_ty.var].unpack() {
+ types: &mut |bound_ty: ty::BoundTy| match var_values[bound_ty.var].unpack() {
GenericArgKind::Type(ty) => ty,
r => bug!("{:?} is a type but value is {:?}", bound_ty, r),
},
- consts: &mut |bound_ct: ty::BoundVar, _| match var_values.var_values[bound_ct].unpack()
- {
+ consts: &mut |bound_ct: ty::BoundVar, _| match var_values[bound_ct].unpack() {
GenericArgKind::Const(ct) => ct,
c => bug!("{:?} is a const but value is {:?}", bound_ct, c),
},
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{
+ self, FallibleTypeFolder, InferConst, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
+ TypeVisitable,
+};
use rustc_middle::ty::{IntType, UintType};
use rustc_span::{Span, DUMMY_SP};
let a = self.shallow_resolve(a);
let b = self.shallow_resolve(b);
- let a_is_expected = relation.a_is_expected();
-
match (a.kind(), b.kind()) {
(
ty::ConstKind::Infer(InferConst::Var(a_vid)),
}
(ty::ConstKind::Infer(InferConst::Var(vid)), _) => {
- return self.unify_const_variable(relation.param_env(), vid, b, a_is_expected);
+ return self.unify_const_variable(vid, b);
}
(_, ty::ConstKind::Infer(InferConst::Var(vid))) => {
- return self.unify_const_variable(relation.param_env(), vid, a, !a_is_expected);
+ return self.unify_const_variable(vid, a);
}
(ty::ConstKind::Unevaluated(..), _) if self.tcx.lazy_normalization() => {
// FIXME(#59490): Need to remove the leak check to accommodate
#[instrument(level = "debug", skip(self))]
fn unify_const_variable(
&self,
- param_env: ty::ParamEnv<'tcx>,
target_vid: ty::ConstVid<'tcx>,
ct: ty::Const<'tcx>,
- vid_is_expected: bool,
) -> RelateResult<'tcx, ty::Const<'tcx>> {
let (for_universe, span) = {
let mut inner = self.inner.borrow_mut();
ConstVariableValue::Unknown { universe } => (universe, var_value.origin.span),
}
};
- let value = ConstInferUnifier { infcx: self, span, param_env, for_universe, target_vid }
- .relate(ct, ct)?;
+ let value = ct.try_fold_with(&mut ConstInferUnifier {
+ infcx: self,
+ span,
+ for_universe,
+ target_vid,
+ })?;
self.inner.borrow_mut().const_unification_table().union_value(
target_vid,
span: Span,
- param_env: ty::ParamEnv<'tcx>,
-
for_universe: ty::UniverseIndex,
/// The vid of the const variable that is in the process of being
target_vid: ty::ConstVid<'tcx>,
}
-// We use `TypeRelation` here to propagate `RelateResult` upwards.
-//
-// Both inputs are expected to be the same.
-impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
- self.infcx.tcx
- }
-
- fn intercrate(&self) -> bool {
- assert!(!self.infcx.intercrate);
- false
- }
-
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.param_env
- }
-
- fn tag(&self) -> &'static str {
- "ConstInferUnifier"
- }
-
- fn a_is_expected(&self) -> bool {
- true
- }
-
- fn mark_ambiguous(&mut self) {
- bug!()
- }
-
- fn relate_with_variance<T: Relate<'tcx>>(
- &mut self,
- _variance: ty::Variance,
- _info: ty::VarianceDiagInfo<'tcx>,
- a: T,
- b: T,
- ) -> RelateResult<'tcx, T> {
- // We don't care about variance here.
- self.relate(a, b)
- }
+impl<'tcx> FallibleTypeFolder<'tcx> for ConstInferUnifier<'_, 'tcx> {
+ type Error = TypeError<'tcx>;
- fn binders<T>(
- &mut self,
- a: ty::Binder<'tcx, T>,
- b: ty::Binder<'tcx, T>,
- ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
- where
- T: Relate<'tcx>,
- {
- Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
+ fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+ self.infcx.tcx
}
#[instrument(level = "debug", skip(self), ret)]
- fn tys(&mut self, t: Ty<'tcx>, _t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
- debug_assert_eq!(t, _t);
-
+ fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, TypeError<'tcx>> {
match t.kind() {
&ty::Infer(ty::TyVar(vid)) => {
let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
match probe {
TypeVariableValue::Known { value: u } => {
debug!("ConstOccursChecker: known value {:?}", u);
- self.tys(u, u)
+ u.try_fold_with(self)
}
TypeVariableValue::Unknown { universe } => {
if self.for_universe.can_name(universe) {
}
}
ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => Ok(t),
- _ => relate::super_relate_tys(self, t, t),
+ _ => t.try_super_fold_with(self),
}
}
- fn regions(
+ #[instrument(level = "debug", skip(self), ret)]
+ fn try_fold_region(
&mut self,
r: ty::Region<'tcx>,
- _r: ty::Region<'tcx>,
- ) -> RelateResult<'tcx, ty::Region<'tcx>> {
- debug_assert_eq!(r, _r);
+ ) -> Result<ty::Region<'tcx>, TypeError<'tcx>> {
debug!("ConstInferUnifier: r={:?}", r);
match *r {
}
}
- #[instrument(level = "debug", skip(self))]
- fn consts(
- &mut self,
- c: ty::Const<'tcx>,
- _c: ty::Const<'tcx>,
- ) -> RelateResult<'tcx, ty::Const<'tcx>> {
- debug_assert_eq!(c, _c);
-
+ #[instrument(level = "debug", skip(self), ret)]
+ fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, TypeError<'tcx>> {
match c.kind() {
ty::ConstKind::Infer(InferConst::Var(vid)) => {
// Check if the current unification would end up
let var_value =
self.infcx.inner.borrow_mut().const_unification_table().probe_value(vid);
match var_value.val {
- ConstVariableValue::Known { value: u } => self.consts(u, u),
+ ConstVariableValue::Known { value: u } => u.try_fold_with(self),
ConstVariableValue::Unknown { universe } => {
if self.for_universe.can_name(universe) {
Ok(c)
}
}
}
- ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
- let substs = self.relate_with_variance(
- ty::Variance::Invariant,
- ty::VarianceDiagInfo::default(),
- substs,
- substs,
- )?;
-
- Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty()))
- }
- _ => relate::super_relate_consts(self, c, c),
+ _ => c.try_super_fold_with(self),
}
}
}
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
use rustc_hir::intravisit::FnKind as HirFnKind;
-use rustc_hir::{
- Body, FnDecl, ForeignItemKind, GenericParamKind, HirId, Node, PatKind, PredicateOrigin,
-};
+use rustc_hir::{Body, FnDecl, ForeignItemKind, GenericParamKind, Node, PatKind, PredicateOrigin};
use rustc_index::vec::Idx;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
// If the method is an impl for a trait, don't doc.
- if method_context(cx, impl_item.hir_id()) == MethodLateContext::TraitImpl {
+ let context = method_context(cx, impl_item.owner_id.def_id);
+ if context == MethodLateContext::TraitImpl {
return;
}
// If the method is an impl for an item with docs_hidden, don't doc.
- if method_context(cx, impl_item.hir_id()) == MethodLateContext::PlainImpl {
+ if context == MethodLateContext::PlainImpl {
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
let impl_ty = cx.tcx.type_of(parent);
let outerdef = match impl_ty.kind() {
_: &'tcx FnDecl<'_>,
_: &'tcx Body<'_>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
if fn_kind.asyncness() == IsAsync::Async
&& !cx.tcx.features().closure_track_caller
- && let attrs = cx.tcx.hir().attrs(hir_id)
// Now, check if the function has the `#[track_caller]` attribute
- && let Some(attr) = attrs.iter().find(|attr| attr.has_name(sym::track_caller))
- {
- cx.emit_spanned_lint(UNGATED_ASYNC_FN_TRACK_CALLER, attr.span, BuiltinUngatedAsyncFnTrackCaller {
- label: span,
- parse_sess: &cx.tcx.sess.parse_sess,
- });
- }
+ && let Some(attr) = cx.tcx.get_attr(def_id.to_def_id(), sym::track_caller)
+ {
+ cx.emit_spanned_lint(UNGATED_ASYNC_FN_TRACK_CALLER, attr.span, BuiltinUngatedAsyncFnTrackCaller {
+ label: span,
+ parse_sess: &cx.tcx.sess.parse_sess,
+ });
+ }
}
}
/// the symbol should be reported as a clashing declaration.
// FIXME: Technically, we could just store a &'tcx str here without issue; however, the
// `impl_lint_pass` macro doesn't currently support lints parametric over a lifetime.
- seen_decls: FxHashMap<Symbol, HirId>,
+ seen_decls: FxHashMap<Symbol, hir::OwnerId>,
}
/// Differentiate between whether the name for an extern decl came from the link_name attribute or
pub(crate) fn new() -> Self {
ClashingExternDeclarations { seen_decls: FxHashMap::default() }
}
+
/// Insert a new foreign item into the seen set. If a symbol with the same name already exists
/// for the item, return its HirId without updating the set.
- fn insert(&mut self, tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> Option<HirId> {
+ fn insert(&mut self, tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> Option<hir::OwnerId> {
let did = fi.owner_id.to_def_id();
let instance = Instance::new(did, ty::List::identity_for_item(tcx, did));
let name = Symbol::intern(tcx.symbol_name(instance).name);
- if let Some(&hir_id) = self.seen_decls.get(&name) {
+ if let Some(&existing_id) = self.seen_decls.get(&name) {
// Avoid updating the map with the new entry when we do find a collision. We want to
// make sure we're always pointing to the first definition as the previous declaration.
// This lets us avoid emitting "knock-on" diagnostics.
- Some(hir_id)
+ Some(existing_id)
} else {
- self.seen_decls.insert(name, fi.hir_id())
+ self.seen_decls.insert(name, fi.owner_id)
}
}
impl_lint_pass!(ClashingExternDeclarations => [CLASHING_EXTERN_DECLARATIONS]);
impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
+ #[instrument(level = "trace", skip(self, cx))]
fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, this_fi: &hir::ForeignItem<'_>) {
- trace!("ClashingExternDeclarations: check_foreign_item: {:?}", this_fi);
if let ForeignItemKind::Fn(..) = this_fi.kind {
let tcx = cx.tcx;
- if let Some(existing_hid) = self.insert(tcx, this_fi) {
- let existing_decl_ty = tcx.type_of(tcx.hir().local_def_id(existing_hid));
+ if let Some(existing_did) = self.insert(tcx, this_fi) {
+ let existing_decl_ty = tcx.type_of(existing_did);
let this_decl_ty = tcx.type_of(this_fi.owner_id);
debug!(
"ClashingExternDeclarations: Comparing existing {:?}: {:?} to this {:?}: {:?}",
- existing_hid, existing_decl_ty, this_fi.owner_id, this_decl_ty
+ existing_did, existing_decl_ty, this_fi.owner_id, this_decl_ty
);
// Check that the declarations match.
if !Self::structurally_same_type(
this_decl_ty,
CItemKind::Declaration,
) {
- let orig_fi = tcx.hir().expect_foreign_item(existing_hid.expect_owner());
+ let orig_fi = tcx.hir().expect_foreign_item(existing_did);
let orig = Self::name_of_extern_decl(tcx, orig_fi);
// We want to ensure that we use spans for both decls that include where the
self.context.last_node_with_lint_attrs = prev;
}
- fn with_param_env<F>(&mut self, id: hir::HirId, f: F)
+ fn with_param_env<F>(&mut self, id: hir::OwnerId, f: F)
where
F: FnOnce(&mut Self),
{
let old_param_env = self.context.param_env;
- self.context.param_env =
- self.context.tcx.param_env(self.context.tcx.hir().local_def_id(id));
+ self.context.param_env = self.context.tcx.param_env(id);
f(self);
self.context.param_env = old_param_env;
}
let old_cached_typeck_results = self.context.cached_typeck_results.take();
let old_enclosing_body = self.context.enclosing_body.take();
self.with_lint_attrs(it.hir_id(), |cx| {
- cx.with_param_env(it.hir_id(), |cx| {
+ cx.with_param_env(it.owner_id, |cx| {
lint_callback!(cx, check_item, it);
hir_visit::walk_item(cx, it);
lint_callback!(cx, check_item_post, it);
fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
self.with_lint_attrs(it.hir_id(), |cx| {
- cx.with_param_env(it.hir_id(), |cx| {
+ cx.with_param_env(it.owner_id, |cx| {
lint_callback!(cx, check_foreign_item, it);
hir_visit::walk_foreign_item(cx, it);
});
decl: &'tcx hir::FnDecl<'tcx>,
body_id: hir::BodyId,
span: Span,
- id: hir::HirId,
+ id: LocalDefId,
) {
// Wrap in typeck results here, not just in visit_nested_body,
// in order for `check_fn` to be able to use them.
let generics = self.context.generics.take();
self.context.generics = Some(&trait_item.generics);
self.with_lint_attrs(trait_item.hir_id(), |cx| {
- cx.with_param_env(trait_item.hir_id(), |cx| {
+ cx.with_param_env(trait_item.owner_id, |cx| {
lint_callback!(cx, check_trait_item, trait_item);
hir_visit::walk_trait_item(cx, trait_item);
});
let generics = self.context.generics.take();
self.context.generics = Some(&impl_item.generics);
self.with_lint_attrs(impl_item.hir_id(), |cx| {
- cx.with_param_env(impl_item.hir_id(), |cx| {
+ cx.with_param_env(impl_item.owner_id, |cx| {
lint_callback!(cx, check_impl_item, impl_item);
hir_visit::walk_impl_item(cx, impl_item);
lint_callback!(cx, check_impl_item_post, impl_item);
use rustc_hir::intravisit::FnKind;
use rustc_hir::{GenericParamKind, PatKind};
use rustc_middle::ty;
-use rustc_span::symbol::sym;
-use rustc_span::{symbol::Ident, BytePos, Span};
+use rustc_span::def_id::LocalDefId;
+use rustc_span::symbol::{sym, Ident};
+use rustc_span::{BytePos, Span};
use rustc_target::spec::abi::Abi;
#[derive(PartialEq)]
PlainImpl,
}
-pub fn method_context(cx: &LateContext<'_>, id: hir::HirId) -> MethodLateContext {
- let def_id = cx.tcx.hir().local_def_id(id);
- let item = cx.tcx.associated_item(def_id);
+pub fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext {
+ let item = cx.tcx.associated_item(id);
match item.container {
ty::TraitContainer => MethodLateContext::TraitAutoImpl,
ty::ImplContainer => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) {
_: &hir::FnDecl<'_>,
_: &hir::Body<'_>,
_: Span,
- id: hir::HirId,
+ id: LocalDefId,
) {
- let attrs = cx.tcx.hir().attrs(id);
match &fk {
FnKind::Method(ident, sig, ..) => match method_context(cx, id) {
MethodLateContext::PlainImpl => {
- if sig.header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle)
+ if sig.header.abi != Abi::Rust
+ && cx.tcx.has_attr(id.to_def_id(), sym::no_mangle)
{
return;
}
},
FnKind::ItemFn(ident, _, header) => {
// Skip foreign-ABI #[no_mangle] functions (Issue #31924)
- if header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle) {
+ if header.abi != Abi::Rust && cx.tcx.has_attr(id.to_def_id(), sym::no_mangle) {
return;
}
self.check_snake_case(cx, "function", ident);
use rustc_hir as hir;
use rustc_session::lint::builtin::HardwiredLints;
use rustc_session::lint::LintPass;
+use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::Ident;
use rustc_span::Span;
b: &'tcx hir::FnDecl<'tcx>,
c: &'tcx hir::Body<'tcx>,
d: Span,
- e: hir::HirId);
+ e: LocalDefId);
fn check_trait_item(a: &'tcx hir::TraitItem<'tcx>);
fn check_impl_item(a: &'tcx hir::ImplItem<'tcx>);
fn check_impl_item_post(a: &'tcx hir::ImplItem<'tcx>);
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
}
}
- fn check_foreign_fn(&mut self, id: hir::HirId, decl: &hir::FnDecl<'_>) {
- let def_id = self.cx.tcx.hir().local_def_id(id);
+ fn check_foreign_fn(&mut self, def_id: LocalDefId, decl: &hir::FnDecl<'_>) {
let sig = self.cx.tcx.fn_sig(def_id).subst_identity();
let sig = self.cx.tcx.erase_late_bound_regions(sig);
}
}
- fn check_foreign_static(&mut self, id: hir::HirId, span: Span) {
- let def_id = self.cx.tcx.hir().local_def_id(id);
- let ty = self.cx.tcx.type_of(def_id);
+ fn check_foreign_static(&mut self, id: hir::OwnerId, span: Span) {
+ let ty = self.cx.tcx.type_of(id);
self.check_type_for_ffi_and_report_errors(span, ty, true, false);
}
if !vis.is_internal_abi(abi) {
match it.kind {
hir::ForeignItemKind::Fn(ref decl, _, _) => {
- vis.check_foreign_fn(it.hir_id(), decl);
+ vis.check_foreign_fn(it.owner_id.def_id, decl);
}
hir::ForeignItemKind::Static(ref ty, _) => {
- vis.check_foreign_static(it.hir_id(), ty.span);
+ vis.check_foreign_static(it.owner_id, ty.span);
}
hir::ForeignItemKind::Type => (),
}
decl: &'tcx hir::FnDecl<'_>,
_: &'tcx hir::Body<'_>,
_: Span,
- hir_id: hir::HirId,
+ id: LocalDefId,
) {
use hir::intravisit::FnKind;
let mut vis = ImproperCTypesVisitor { cx, mode: CItemKind::Definition };
if !vis.is_internal_abi(abi) {
- vis.check_foreign_fn(hir_id, decl);
+ vis.check_foreign_fn(id, decl);
}
}
}
};
use fluent_bundle::{FluentBundle, FluentError, FluentResource};
use fluent_syntax::{
- ast::{Attribute, Entry, Identifier, Message},
+ ast::{
+ Attribute, Entry, Expression, Identifier, InlineExpression, Message, Pattern,
+ PatternElement,
+ },
parser::ParserError,
};
use proc_macro::{Diagnostic, Level, Span};
};
let mut constants = TokenStream::new();
+ let mut messagerefs = Vec::new();
for entry in resource.entries() {
let span = res.krate.span();
- if let Entry::Message(Message { id: Identifier { name }, attributes, .. }) = entry {
+ if let Entry::Message(Message { id: Identifier { name }, attributes, value, .. }) =
+ entry
+ {
let _ = previous_defns.entry(name.to_string()).or_insert(path_span);
if name.contains('-') {
.emit();
}
+ if let Some(Pattern { elements }) = value {
+ for elt in elements {
+ if let PatternElement::Placeable {
+ expression:
+ Expression::Inline(InlineExpression::MessageReference { id, .. }),
+ } = elt
+ {
+ messagerefs.push((id.name, *name));
+ }
+ }
+ }
+
// Require that the message name starts with the crate name
// `hir_typeck_foo_bar` (in `hir_typeck.ftl`)
// `const_eval_baz` (in `const_eval.ftl`)
}
}
+ for (mref, name) in messagerefs.into_iter() {
+ if !previous_defns.contains_key(mref) {
+ Diagnostic::spanned(
+ path_span,
+ Level::Error,
+ format!("referenced message `{mref}` does not exist (in message `{name}`)"),
+ )
+ .help(&format!("you may have meant to use a variable reference (`{{${mref}}}`)"))
+ .emit();
+ }
+ }
+
if let Err(errs) = bundle.add_resource(resource) {
for e in errs {
match e {
hir::ItemKind::Struct(ref vdata, _) => {
yield item_id.owner_id.def_id.local_def_index;
// Encode constructors which take a separate slot in value namespace.
- if let Some(ctor_hir_id) = vdata.ctor_hir_id() {
- yield tcx.hir().local_def_id(ctor_hir_id).local_def_index;
+ if let Some(ctor_def_id) = vdata.ctor_def_id() {
+ yield ctor_def_id.local_def_index;
}
}
_ if tcx.def_key(item_id.owner_id.to_def_id()).get_opt_name().is_some() => {
if encode_opt {
record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
- if let DefKind::Generator = self.tcx.def_kind(def_id) {
+ if let DefKind::Generator = self.tcx.def_kind(def_id) && tcx.sess.opts.unstable_opts.drop_tracking_mir {
record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- tcx.mir_generator_witnesses(def_id));
}
}
// (during lowering) and the `librustc_middle` arena (for decoding MIR)
[decode] asm_template: rustc_ast::InlineAsmTemplatePiece,
[decode] used_trait_imports: rustc_data_structures::unord::UnordSet<rustc_hir::def_id::LocalDefId>,
- [decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet<rustc_hir::def_id::LocalDefId>,
+ [decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet<rustc_hir::ItemLocalId>,
[decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>,
[] dep_kind: rustc_middle::dep_graph::DepKindStruct<'tcx>,
use rustc_target::spec::abi::Abi;
#[inline]
-pub fn associated_body(node: Node<'_>) -> Option<BodyId> {
+pub fn associated_body(node: Node<'_>) -> Option<(LocalDefId, BodyId)> {
match node {
Node::Item(Item {
+ owner_id,
kind: ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body),
..
})
| Node::TraitItem(TraitItem {
+ owner_id,
kind:
TraitItemKind::Const(_, Some(body)) | TraitItemKind::Fn(_, TraitFn::Provided(body)),
..
})
| Node::ImplItem(ImplItem {
+ owner_id,
kind: ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body),
..
- })
- | Node::Expr(Expr { kind: ExprKind::Closure(Closure { body, .. }), .. }) => Some(*body),
+ }) => Some((owner_id.def_id, *body)),
+
+ Node::Expr(Expr { kind: ExprKind::Closure(Closure { def_id, body, .. }), .. }) => {
+ Some((*def_id, *body))
+ }
- Node::AnonConst(constant) => Some(constant.body),
+ Node::AnonConst(constant) => Some((constant.def_id, constant.body)),
_ => None,
}
fn is_body_owner(node: Node<'_>, hir_id: HirId) -> bool {
match associated_body(node) {
- Some(b) => b.hir_id == hir_id,
+ Some((_, b)) => b.hir_id == hir_id,
None => false,
}
}
self.tcx.definitions_untracked().def_key(def_id)
}
- pub fn def_path_from_hir_id(self, id: HirId) -> Option<DefPath> {
- self.opt_local_def_id(id).map(|def_id| self.def_path(def_id))
- }
-
pub fn def_path(self, def_id: LocalDefId) -> DefPath {
// Accessing the DefPath is ok, since it is part of DefPathHash.
self.tcx.definitions_untracked().def_path(def_id)
self.tcx.definitions_untracked().def_path_hash(def_id)
}
- #[inline]
- #[track_caller]
- pub fn local_def_id(self, hir_id: HirId) -> LocalDefId {
- self.opt_local_def_id(hir_id).unwrap_or_else(|| {
- bug!(
- "local_def_id: no entry for `{:?}`, which has a map of `{:?}`",
- hir_id,
- self.find(hir_id)
- )
- })
- }
-
- #[inline]
- pub fn opt_local_def_id(self, hir_id: HirId) -> Option<LocalDefId> {
- if hir_id.local_id == ItemLocalId::new(0) {
- Some(hir_id.owner.def_id)
- } else {
- self.tcx
- .hir_owner_nodes(hir_id.owner)
- .as_owner()?
- .local_id_to_def_id
- .get(&hir_id.local_id)
- .copied()
- }
- }
-
#[inline]
pub fn local_def_id_to_hir_id(self, def_id: LocalDefId) -> HirId {
self.tcx.local_def_id_to_hir_id(def_id)
#[track_caller]
pub fn enclosing_body_owner(self, hir_id: HirId) -> LocalDefId {
for (_, node) in self.parent_iter(hir_id) {
- if let Some(body) = associated_body(node) {
- return self.body_owner_def_id(body);
+ if let Some((def_id, _)) = associated_body(node) {
+ return def_id;
}
}
parent
}
- pub fn body_owner_def_id(self, id: BodyId) -> LocalDefId {
- self.local_def_id(self.body_owner(id))
+ pub fn body_owner_def_id(self, BodyId { hir_id }: BodyId) -> LocalDefId {
+ let parent = self.parent_id(hir_id);
+ associated_body(self.get(parent)).unwrap().0
}
/// Given a `LocalDefId`, returns the `BodyId` associated with it,
/// if the node is a body owner, otherwise returns `None`.
pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option<BodyId> {
- self.find_by_def_id(id).and_then(associated_body)
+ let node = self.find_by_def_id(id)?;
+ let (_, body_id) = associated_body(node)?;
+ Some(body_id)
}
/// Given a body owner's id, returns the `BodyId` associated with it.
use crate::mir::ConstraintCategory;
use crate::ty::subst::GenericArg;
use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};
-use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
use smallvec::SmallVec;
-use std::iter;
use std::ops::Index;
/// A "canonicalized" type `V` is one where all free inference
/// vectors with the original values that were replaced by canonical
/// variables. You will need to supply it later to instantiate the
/// canonicalized query response.
-#[derive(Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct CanonicalVarValues<'tcx> {
- pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
+ pub var_values: ty::SubstsRef<'tcx>,
}
impl CanonicalVarValues<'_> {
pub fn is_identity(&self) -> bool {
- self.var_values.iter_enumerated().all(|(bv, arg)| match arg.unpack() {
+ self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() {
ty::GenericArgKind::Lifetime(r) => {
- matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var == bv)
+ matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var.as_usize() == bv)
}
ty::GenericArgKind::Type(ty) => {
- matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var == bv)
+ matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv)
}
ty::GenericArgKind::Const(ct) => {
- matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc == bv)
+ matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv)
}
})
}
}
impl<'tcx> CanonicalVarValues<'tcx> {
+ // Given a list of canonical variables, construct a set of values which are
+ // the identity response.
+ pub fn make_identity(
+ tcx: TyCtxt<'tcx>,
+ infos: CanonicalVarInfos<'tcx>,
+ ) -> CanonicalVarValues<'tcx> {
+ CanonicalVarValues {
+ var_values: tcx.mk_substs(infos.iter().enumerate().map(
+ |(i, info)| -> ty::GenericArg<'tcx> {
+ match info.kind {
+ CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => tcx
+ .mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into()))
+ .into(),
+ CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
+ let br = ty::BoundRegion {
+ var: ty::BoundVar::from_usize(i),
+ kind: ty::BrAnon(i as u32, None),
+ };
+ tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
+ }
+ CanonicalVarKind::Const(_, ty)
+ | CanonicalVarKind::PlaceholderConst(_, ty) => tcx
+ .mk_const(
+ ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)),
+ ty,
+ )
+ .into(),
+ }
+ },
+ )),
+ }
+ }
+
/// Creates dummy var values which should not be used in a
/// canonical response.
pub fn dummy() -> CanonicalVarValues<'tcx> {
- CanonicalVarValues { var_values: Default::default() }
+ CanonicalVarValues { var_values: ty::List::empty() }
}
#[inline]
pub fn len(&self) -> usize {
self.var_values.len()
}
-
- /// Makes an identity substitution from this one: each bound var
- /// is matched to the same bound var, preserving the original kinds.
- /// For example, if we have:
- /// `self.var_values == [Type(u32), Lifetime('a), Type(u64)]`
- /// we'll return a substitution `subst` with:
- /// `subst.var_values == [Type(^0), Lifetime(^1), Type(^2)]`.
- pub fn make_identity(&self, tcx: TyCtxt<'tcx>) -> Self {
- use crate::ty::subst::GenericArgKind;
-
- CanonicalVarValues {
- var_values: iter::zip(&self.var_values, 0..)
- .map(|(kind, i)| match kind.unpack() {
- GenericArgKind::Type(..) => {
- tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
- }
- GenericArgKind::Lifetime(..) => {
- let br = ty::BoundRegion {
- var: ty::BoundVar::from_u32(i),
- kind: ty::BrAnon(i, None),
- };
- tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
- }
- GenericArgKind::Const(ct) => tcx
- .mk_const(
- ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)),
- ct.ty(),
- )
- .into(),
- })
- .collect(),
- }
- }
}
impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> {
type Item = GenericArg<'tcx>;
- type IntoIter = ::std::iter::Cloned<::std::slice::Iter<'a, GenericArg<'tcx>>>;
+ type IntoIter = ::std::iter::Copied<::std::slice::Iter<'a, GenericArg<'tcx>>>;
fn into_iter(self) -> Self::IntoIter {
- self.var_values.iter().cloned()
+ self.var_values.iter()
}
}
type Output = GenericArg<'tcx>;
fn index(&self, value: BoundVar) -> &GenericArg<'tcx> {
- &self.var_values[value]
+ &self.var_values[value.as_usize()]
}
}
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id) {
- if let Some(parent_did) = tcx.hir().opt_local_def_id(parent_hir_id) {
+ if let Some(parent_did) = parent_hir_id.as_owner() {
InternalSubsts::identity_for_item(tcx, parent_did.to_def_id())
} else {
tcx.mk_substs(Vec::<GenericArg<'tcx>>::new().into_iter())
fn hir_body(tcx: TyCtxt<'_>, def_id: DefId) -> Option<&rustc_hir::Body<'_>> {
let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local");
- hir::map::associated_body(hir_node).map(|fn_body_id| tcx.hir().body(fn_body_id))
+ hir::map::associated_body(hir_node).map(|(_, fn_body_id)| tcx.hir().body(fn_body_id))
}
fn escape_html(s: &str) -> String {
Option<&'tcx FxHashMap<ItemLocalId, Region>> {
desc { "looking up a named region" }
}
- query is_late_bound_map(_: LocalDefId) -> Option<&'tcx FxIndexSet<LocalDefId>> {
+ query is_late_bound_map(_: hir::OwnerId) -> Option<&'tcx FxIndexSet<ItemLocalId>> {
desc { "testing if a region is late bound" }
}
/// For a given item's generic parameter, gets the default lifetimes to be used
}
pub fn is_late_bound(self, id: HirId) -> bool {
- self.is_late_bound_map(id.owner.def_id).map_or(false, |set| {
- let def_id = self.hir().local_def_id(id);
- set.contains(&def_id)
- })
+ self.is_late_bound_map(id.owner).map_or(false, |set| set.contains(&id.local_id))
}
pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
use rustc_ast as ast;
use rustc_ast::node_id::NodeMap;
use rustc_attr as attr;
-use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
#[rustc_pass_by_value]
pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
-impl<'tcx> TyCtxt<'tcx> {
- /// A "bool" type used in rustc_mir_transform unit tests when we
- /// have not spun up a TyCtxt.
- pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> =
- Ty(Interned::new_unchecked(&WithCachedTypeInfo {
- internee: ty::Bool,
- stable_hash: Fingerprint::ZERO,
- flags: TypeFlags::empty(),
- outer_exclusive_binder: DebruijnIndex::from_usize(0),
- }));
-}
-
impl ty::EarlyBoundRegion {
/// Does this early bound region have a name? Early bound regions normally
/// always have names except when using anonymous lifetimes (`'_`).
macro_rules! query_helper_param_ty {
(DefId) => { impl IntoQueryParam<DefId> };
+ (LocalDefId) => { impl IntoQueryParam<LocalDefId> };
($K:ty) => { $K };
}
}
}
+ impl IntoQueryParam<LocalDefId> for OwnerId {
+ #[inline(always)]
+ fn into_query_param(self) -> LocalDefId {
+ self.def_id
+ }
+ }
+
impl IntoQueryParam<DefId> for LocalDefId {
#[inline(always)]
fn into_query_param(self) -> DefId {
use rustc_middle::thir::{FieldPat, Pat, PatKind};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::lint;
-use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::Span;
use rustc_trait_selection::traits::predicate_for_trait_def;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
// using `PartialEq::eq` in this scenario in the past.)
let partial_eq_trait_id =
self.tcx().require_lang_item(hir::LangItem::PartialEq, Some(self.span));
- let def_id = self.tcx().hir().opt_local_def_id(self.id).unwrap_or(CRATE_DEF_ID);
let obligation: PredicateObligation<'_> = predicate_for_trait_def(
self.tcx(),
self.param_env,
- ObligationCause::misc(self.span, def_id),
+ ObligationCause::misc(self.span, self.id.owner.def_id),
partial_eq_trait_id,
0,
[ty, ty],
_fd: &'tcx hir::FnDecl<'tcx>,
b: hir::BodyId,
_s: rustc_span::Span,
- _id: HirId,
+ _id: LocalDefId,
) {
if matches!(fk, intravisit::FnKind::Closure) {
self.visit_body(self.tcx.hir().body(b))
// FIXME(#79625): Consider improving MIR to provide the information needed, to avoid going back
// to HIR for it.
let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local");
- let fn_body_id = hir::map::associated_body(hir_node).expect("HIR node is a function with body");
+ let (_, fn_body_id) =
+ hir::map::associated_body(hir_node).expect("HIR node is a function with body");
(hir_node.fn_sig(), tcx.hir().body(fn_body_id))
}
tcx: TyCtxt<'tcx>,
def_id: DefId,
) -> GeneratorLayout<'tcx> {
+ assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir);
let def_id = def_id.expect_local();
let (body, _) = tcx.mir_promoted(ty::WithOptConstParam::unknown(def_id));
let gen_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
// Get the interior types and substs which typeck computed
- let (upvars, interior, movable) = match *gen_ty.kind() {
- ty::Generator(_, substs, movability) => {
- let substs = substs.as_generator();
- (
- substs.upvar_tys().collect::<Vec<_>>(),
- substs.witness(),
- movability == hir::Movability::Movable,
- )
- }
+ let movable = match *gen_ty.kind() {
+ ty::Generator(_, _, movability) => movability == hir::Movability::Movable,
_ => span_bug!(body.span, "unexpected generator type {}", gen_ty),
};
// `storage_liveness` tells us which locals have live storage at suspension points
let (_, generator_layout, _) = compute_layout(tcx, liveness_info, body);
- if tcx.sess.opts.unstable_opts.drop_tracking_mir {
- check_suspend_tys(tcx, &generator_layout, &body);
- } else {
- sanitize_witness(tcx, body, interior, upvars, &generator_layout);
- }
+ check_suspend_tys(tcx, &generator_layout, &body);
generator_layout
}
let gen_ty = body.local_decls.raw[1].ty;
// Get the discriminant type and substs which typeck computed
- let (discr_ty, movable) = match *gen_ty.kind() {
+ let (discr_ty, upvars, interior, movable) = match *gen_ty.kind() {
ty::Generator(_, substs, movability) => {
let substs = substs.as_generator();
- (substs.discr_ty(tcx), movability == hir::Movability::Movable)
+ (
+ substs.discr_ty(tcx),
+ substs.upvar_tys().collect::<Vec<_>>(),
+ substs.witness(),
+ movability == hir::Movability::Movable,
+ )
}
_ => {
tcx.sess
// `storage_liveness` tells us which locals have live storage at suspension points
let (remap, layout, storage_liveness) = compute_layout(tcx, liveness_info, body);
+ if tcx.sess.opts.unstable_opts.validate_mir
+ && !tcx.sess.opts.unstable_opts.drop_tracking_mir
+ {
+ sanitize_witness(tcx, body, interior, upvars, &layout);
+ }
+
let can_return = can_return(tcx, body, tcx.param_env(body.source.def_id()));
// Run the transformation which converts Places from Local to generator struct
return tcx.mir_drops_elaborated_and_const_checked(def);
}
- if tcx.generator_kind(def.did).is_some() {
+ if tcx.generator_kind(def.did).is_some() && tcx.sess.opts.unstable_opts.drop_tracking_mir {
tcx.ensure().mir_generator_witnesses(def.did);
}
let mir_borrowck = tcx.mir_borrowck_opt_const_arg(def);
--- /dev/null
+use super::UnmatchedBrace;
+use rustc_ast::token::Delimiter;
+use rustc_errors::Diagnostic;
+use rustc_span::source_map::SourceMap;
+use rustc_span::Span;
+
+#[derive(Default)]
+pub struct TokenTreeDiagInfo {
+ /// Stack of open delimiters and their spans. Used for error message.
+ pub open_braces: Vec<(Delimiter, Span)>,
+ pub unmatched_braces: Vec<UnmatchedBrace>,
+
+ /// Used only for error recovery when arriving to EOF with mismatched braces.
+ pub last_unclosed_found_span: Option<Span>,
+
+ /// Collect empty block spans that might have been auto-inserted by editors.
+ pub empty_block_spans: Vec<Span>,
+
+ /// Collect the spans of braces (Open, Close). Used only
+ /// for detecting if blocks are empty and only braces.
+ pub matching_block_spans: Vec<(Span, Span)>,
+}
+
+pub fn same_identation_level(sm: &SourceMap, open_sp: Span, close_sp: Span) -> bool {
+ match (sm.span_to_margin(open_sp), sm.span_to_margin(close_sp)) {
+ (Some(open_padding), Some(close_padding)) => open_padding == close_padding,
+ _ => false,
+ }
+}
+
+// When we get a `)` or `]` for `{`, we should emit help message here
+// it's more friendly compared to report `unmatched error` in later phase
+pub fn report_missing_open_delim(
+ err: &mut Diagnostic,
+ unmatched_braces: &[UnmatchedBrace],
+) -> bool {
+ let mut reported_missing_open = false;
+ for unmatch_brace in unmatched_braces.iter() {
+ if let Some(delim) = unmatch_brace.found_delim
+ && matches!(delim, Delimiter::Parenthesis | Delimiter::Bracket)
+ {
+ let missed_open = match delim {
+ Delimiter::Parenthesis => "(",
+ Delimiter::Bracket => "[",
+ _ => unreachable!(),
+ };
+ err.span_label(
+ unmatch_brace.found_span.shrink_to_lo(),
+ format!("missing open `{}` for this delimiter", missed_open),
+ );
+ reported_missing_open = true;
+ }
+ }
+ reported_missing_open
+}
+
+pub fn report_suspicious_mismatch_block(
+ err: &mut Diagnostic,
+ diag_info: &TokenTreeDiagInfo,
+ sm: &SourceMap,
+ delim: Delimiter,
+) {
+ if report_missing_open_delim(err, &diag_info.unmatched_braces) {
+ return;
+ }
+
+ let mut matched_spans: Vec<(Span, bool)> = diag_info
+ .matching_block_spans
+ .iter()
+ .map(|&(open, close)| (open.with_hi(close.lo()), same_identation_level(sm, open, close)))
+ .collect();
+
+ // sort by `lo`, so the large block spans in the front
+ matched_spans.sort_by(|a, b| a.0.lo().cmp(&b.0.lo()));
+
+ // We use larger block whose identation is well to cover those inner mismatched blocks
+ // O(N^2) here, but we are on error reporting path, so it is fine
+ for i in 0..matched_spans.len() {
+ let (block_span, same_ident) = matched_spans[i];
+ if same_ident {
+ for j in i + 1..matched_spans.len() {
+ let (inner_block, inner_same_ident) = matched_spans[j];
+ if block_span.contains(inner_block) && !inner_same_ident {
+ matched_spans[j] = (inner_block, true);
+ }
+ }
+ }
+ }
+
+ // Find the inner-most span candidate for final report
+ let candidate_span =
+ matched_spans.into_iter().rev().find(|&(_, same_ident)| !same_ident).map(|(span, _)| span);
+
+ if let Some(block_span) = candidate_span {
+ err.span_label(block_span.shrink_to_lo(), "this delimiter might not be properly closed...");
+ err.span_label(
+ block_span.shrink_to_hi(),
+ "...as it matches this but it has different indentation",
+ );
+
+ // If there is a empty block in the mismatched span, note it
+ if delim == Delimiter::Brace {
+ for span in diag_info.empty_block_spans.iter() {
+ if block_span.contains(*span) {
+ err.span_label(*span, "block is empty, you might have not meant to close it");
+ break;
+ }
+ }
+ }
+ } else {
+ // If there is no suspicious span, give the last properly closed block may help
+ if let Some(parent) = diag_info.matching_block_spans.last()
+ && diag_info.open_braces.last().is_none()
+ && diag_info.empty_block_spans.iter().all(|&sp| sp != parent.0.to(parent.1)) {
+ err.span_label(parent.0, "this opening brace...");
+ err.span_label(parent.1, "...matches this closing brace");
+ }
+ }
+}
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{edition::Edition, BytePos, Pos, Span};
+mod diagnostics;
mod tokentrees;
mod unescape_error_reporting;
mod unicode_chars;
+use super::diagnostics::report_suspicious_mismatch_block;
+use super::diagnostics::same_identation_level;
+use super::diagnostics::TokenTreeDiagInfo;
use super::{StringReader, UnmatchedBrace};
use rustc_ast::token::{self, Delimiter, Token};
use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree};
use rustc_ast_pretty::pprust::token_to_string;
-use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{PErr, PResult};
-use rustc_span::Span;
pub(super) struct TokenTreesReader<'a> {
string_reader: StringReader<'a>,
/// The "next" token, which has been obtained from the `StringReader` but
/// not yet handled by the `TokenTreesReader`.
token: Token,
- /// Stack of open delimiters and their spans. Used for error message.
- open_braces: Vec<(Delimiter, Span)>,
- unmatched_braces: Vec<UnmatchedBrace>,
- /// The type and spans for all braces
- ///
- /// Used only for error recovery when arriving to EOF with mismatched braces.
- matching_delim_spans: Vec<(Delimiter, Span, Span)>,
- last_unclosed_found_span: Option<Span>,
- /// Collect empty block spans that might have been auto-inserted by editors.
- last_delim_empty_block_spans: FxHashMap<Delimiter, Span>,
- /// Collect the spans of braces (Open, Close). Used only
- /// for detecting if blocks are empty and only braces.
- matching_block_spans: Vec<(Span, Span)>,
+ diag_info: TokenTreeDiagInfo,
}
impl<'a> TokenTreesReader<'a> {
let mut tt_reader = TokenTreesReader {
string_reader,
token: Token::dummy(),
- open_braces: Vec::new(),
- unmatched_braces: Vec::new(),
- matching_delim_spans: Vec::new(),
- last_unclosed_found_span: None,
- last_delim_empty_block_spans: FxHashMap::default(),
- matching_block_spans: Vec::new(),
+ diag_info: TokenTreeDiagInfo::default(),
};
let res = tt_reader.parse_token_trees(/* is_delimited */ false);
- (res, tt_reader.unmatched_braces)
+ (res, tt_reader.diag_info.unmatched_braces)
}
// Parse a stream of tokens into a list of `TokenTree`s.
fn eof_err(&mut self) -> PErr<'a> {
let msg = "this file contains an unclosed delimiter";
let mut err = self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, msg);
- for &(_, sp) in &self.open_braces {
+ for &(_, sp) in &self.diag_info.open_braces {
err.span_label(sp, "unclosed delimiter");
- self.unmatched_braces.push(UnmatchedBrace {
+ self.diag_info.unmatched_braces.push(UnmatchedBrace {
expected_delim: Delimiter::Brace,
found_delim: None,
found_span: self.token.span,
});
}
- if let Some((delim, _)) = self.open_braces.last() {
- if let Some((_, open_sp, close_sp)) =
- self.matching_delim_spans.iter().find(|(d, open_sp, close_sp)| {
- let sm = self.string_reader.sess.source_map();
- if let Some(close_padding) = sm.span_to_margin(*close_sp) {
- if let Some(open_padding) = sm.span_to_margin(*open_sp) {
- return delim == d && close_padding != open_padding;
- }
- }
- false
- })
- // these are in reverse order as they get inserted on close, but
- {
- // we want the last open/first close
- err.span_label(*open_sp, "this delimiter might not be properly closed...");
- err.span_label(*close_sp, "...as it matches this but it has different indentation");
- }
+ if let Some((delim, _)) = self.diag_info.open_braces.last() {
+ report_suspicious_mismatch_block(
+ &mut err,
+ &self.diag_info,
+ &self.string_reader.sess.source_map(),
+ *delim,
+ )
}
err
}
// The span for beginning of the delimited section
let pre_span = self.token.span;
- self.open_braces.push((open_delim, self.token.span));
+ self.diag_info.open_braces.push((open_delim, self.token.span));
// Parse the token trees within the delimiters.
// We stop at any delimiter so we can try to recover if the user
// Expand to cover the entire delimited token tree
let delim_span = DelimSpan::from_pair(pre_span, self.token.span);
+ let sm = self.string_reader.sess.source_map();
match self.token.kind {
// Correct delimiter.
token::CloseDelim(close_delim) if close_delim == open_delim => {
- let (open_brace, open_brace_span) = self.open_braces.pop().unwrap();
+ let (open_brace, open_brace_span) = self.diag_info.open_braces.pop().unwrap();
let close_brace_span = self.token.span;
- if tts.is_empty() {
+ if tts.is_empty() && close_delim == Delimiter::Brace {
let empty_block_span = open_brace_span.to(close_brace_span);
- let sm = self.string_reader.sess.source_map();
if !sm.is_multiline(empty_block_span) {
// Only track if the block is in the form of `{}`, otherwise it is
// likely that it was written on purpose.
- self.last_delim_empty_block_spans.insert(open_delim, empty_block_span);
+ self.diag_info.empty_block_spans.push(empty_block_span);
}
}
- //only add braces
+ // only add braces
if let (Delimiter::Brace, Delimiter::Brace) = (open_brace, open_delim) {
- self.matching_block_spans.push((open_brace_span, close_brace_span));
+ // Add all the matching spans, we will sort by span later
+ self.diag_info.matching_block_spans.push((open_brace_span, close_brace_span));
}
- if self.open_braces.is_empty() {
- // Clear up these spans to avoid suggesting them as we've found
- // properly matched delimiters so far for an entire block.
- self.matching_delim_spans.clear();
- } else {
- self.matching_delim_spans.push((open_brace, open_brace_span, close_brace_span));
- }
// Move past the closing delimiter.
self.token = self.string_reader.next_token().0;
}
let mut unclosed_delimiter = None;
let mut candidate = None;
- if self.last_unclosed_found_span != Some(self.token.span) {
+ if self.diag_info.last_unclosed_found_span != Some(self.token.span) {
// do not complain about the same unclosed delimiter multiple times
- self.last_unclosed_found_span = Some(self.token.span);
+ self.diag_info.last_unclosed_found_span = Some(self.token.span);
// This is a conservative error: only report the last unclosed
// delimiter. The previous unclosed delimiters could actually be
// closed! The parser just hasn't gotten to them yet.
- if let Some(&(_, sp)) = self.open_braces.last() {
+ if let Some(&(_, sp)) = self.diag_info.open_braces.last() {
unclosed_delimiter = Some(sp);
};
- let sm = self.string_reader.sess.source_map();
- if let Some(current_padding) = sm.span_to_margin(self.token.span) {
- for (brace, brace_span) in &self.open_braces {
- if let Some(padding) = sm.span_to_margin(*brace_span) {
- // high likelihood of these two corresponding
- if current_padding == padding && brace == &close_delim {
- candidate = Some(*brace_span);
- }
- }
+ for (brace, brace_span) in &self.diag_info.open_braces {
+ if same_identation_level(&sm, self.token.span, *brace_span)
+ && brace == &close_delim
+ {
+ // high likelihood of these two corresponding
+ candidate = Some(*brace_span);
}
}
- let (tok, _) = self.open_braces.pop().unwrap();
- self.unmatched_braces.push(UnmatchedBrace {
+ let (tok, _) = self.diag_info.open_braces.pop().unwrap();
+ self.diag_info.unmatched_braces.push(UnmatchedBrace {
expected_delim: tok,
found_delim: Some(close_delim),
found_span: self.token.span,
candidate_span: candidate,
});
} else {
- self.open_braces.pop();
+ self.diag_info.open_braces.pop();
}
// If the incorrect delimiter matches an earlier opening
// fn foo() {
// bar(baz(
// } // Incorrect delimiter but matches the earlier `{`
- if !self.open_braces.iter().any(|&(b, _)| b == close_delim) {
+ if !self.diag_info.open_braces.iter().any(|&(b, _)| b == close_delim) {
self.token = self.string_reader.next_token().0;
}
}
let mut err =
self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, &msg);
- // Braces are added at the end, so the last element is the biggest block
- if let Some(parent) = self.matching_block_spans.last() {
- if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) {
- // Check if the (empty block) is in the last properly closed block
- if (parent.0.to(parent.1)).contains(span) {
- err.span_label(span, "block is empty, you might have not meant to close it");
- } else {
- err.span_label(parent.0, "this opening brace...");
- err.span_label(parent.1, "...matches this closing brace");
- }
- } else {
- err.span_label(parent.0, "this opening brace...");
- err.span_label(parent.1, "...matches this closing brace");
- }
- }
-
+ report_suspicious_mismatch_block(
+ &mut err,
+ &self.diag_info,
+ &self.string_reader.sess.source_map(),
+ delim,
+ );
err.span_label(self.token.span, "unexpected closing delimiter");
err
}
/// Debugging aid for `object_lifetime_default` query.
fn check_object_lifetime_default(&self, hir_id: HirId) {
let tcx = self.tcx;
- if let Some(generics) = tcx.hir().get_generics(tcx.hir().local_def_id(hir_id)) {
+ if let Some(owner_id) = hir_id.as_owner()
+ && let Some(generics) = tcx.hir().get_generics(owner_id.def_id)
+ {
for p in generics.params {
let hir::GenericParamKind::Type { .. } = p.kind else { continue };
let default = tcx.object_lifetime_default(p.def_id);
) -> bool {
match target {
Target::Fn | Target::Method(_)
- if self.tcx.is_const_fn_raw(self.tcx.hir().local_def_id(hir_id).to_def_id()) =>
+ if self.tcx.is_const_fn_raw(hir_id.expect_owner().to_def_id()) =>
{
true
}
// referenced by it should be considered as used.
let in_pat = mem::replace(&mut self.in_pat, false);
- self.live_symbols.insert(self.tcx.hir().local_def_id(c.hir_id));
+ self.live_symbols.insert(c.def_id);
intravisit::walk_anon_const(self, c);
self.in_pat = in_pat;
}
}
-fn has_allow_dead_code_or_lang_attr_helper(
- tcx: TyCtxt<'_>,
- id: hir::HirId,
- lint: &'static lint::Lint,
-) -> bool {
- let attrs = tcx.hir().attrs(id);
- if tcx.sess.contains_name(attrs, sym::lang) {
+fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+ if tcx.has_attr(def_id.to_def_id(), sym::lang) {
return true;
}
// Stable attribute for #[lang = "panic_impl"]
- if tcx.sess.contains_name(attrs, sym::panic_handler) {
+ if tcx.has_attr(def_id.to_def_id(), sym::panic_handler) {
return true;
}
- let def_id = tcx.hir().local_def_id(id);
if tcx.def_kind(def_id).has_codegen_attrs() {
let cg_attrs = tcx.codegen_fn_attrs(def_id);
}
}
- tcx.lint_level_at_node(lint, id).0 == lint::Allow
-}
-
-fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
- has_allow_dead_code_or_lang_attr_helper(tcx, id, lint::builtin::DEAD_CODE)
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0 == lint::Allow
}
// These check_* functions seeds items that
struct_constructors: &mut FxHashMap<LocalDefId, LocalDefId>,
id: hir::ItemId,
) {
- let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.hir_id());
+ let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id);
if allow_dead_code {
worklist.push(id.owner_id.def_id);
}
// And we access the Map here to get HirId from LocalDefId
for id in local_def_ids {
- if of_trait.is_some()
- || has_allow_dead_code_or_lang_attr(tcx, tcx.hir().local_def_id_to_hir_id(id))
- {
+ if of_trait.is_some() || has_allow_dead_code_or_lang_attr(tcx, id) {
worklist.push(id);
}
}
DefKind::Struct => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Struct(ref variant_data, _) = item.kind
- && let Some(ctor_hir_id) = variant_data.ctor_hir_id()
+ && let Some(ctor_def_id) = variant_data.ctor_def_id()
{
- struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.owner_id.def_id);
+ struct_constructors.insert(ctor_def_id, item.owner_id.def_id);
}
}
DefKind::GlobalAsm => {
if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) {
let trait_item = tcx.hir().trait_item(id);
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_)))
- && has_allow_dead_code_or_lang_attr(tcx, trait_item.hir_id())
+ && has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
{
worklist.push(trait_item.owner_id.def_id);
}
fn check_foreign_item(tcx: TyCtxt<'_>, worklist: &mut Vec<LocalDefId>, id: hir::ForeignItemId) {
if matches!(tcx.def_kind(id.owner_id), DefKind::Static(_) | DefKind::Fn)
- && has_allow_dead_code_or_lang_attr(tcx, id.hir_id())
+ && has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id)
{
worklist.push(id.owner_id.def_id);
}
if self.live_symbols.contains(&def_id) {
return;
}
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
- if has_allow_dead_code_or_lang_attr(self.tcx, hir_id) {
+ if has_allow_dead_code_or_lang_attr(self.tcx, def_id) {
return;
}
let Some(name) = self.tcx.opt_item_name(def_id.to_def_id()) else {
use rustc_middle::hir::map::Map;
use rustc_middle::ty::TyCtxt;
use rustc_middle::util::common::to_readable_str;
+use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
fd: &'v hir::FnDecl<'v>,
b: hir::BodyId,
_: Span,
- id: hir::HirId,
+ id: LocalDefId,
) {
self.record("FnDecl", Id::None, fd);
hir_visit::walk_fn(self, fk, fd, b, id)
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::{extract, GenericRequirement};
-use rustc_hir::{HirId, LangItem, LanguageItems, Target};
+use rustc_hir::{LangItem, LanguageItems, Target};
use rustc_middle::ty::TyCtxt;
use rustc_session::cstore::ExternCrate;
use rustc_span::{symbol::kw::Empty, Span};
LanguageItemCollector { tcx, items: LanguageItems::new() }
}
- fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId) {
- let attrs = self.tcx.hir().attrs(hir_id);
+ fn check_for_lang(&mut self, actual_target: Target, def_id: LocalDefId) {
+ let attrs = self.tcx.hir().attrs(self.tcx.hir().local_def_id_to_hir_id(def_id));
if let Some((name, span)) = extract(&attrs) {
match LangItem::from_name(name) {
// Known lang item with attribute on correct target.
Some(lang_item) if actual_target == lang_item.target() => {
- self.collect_item_extended(lang_item, hir_id, span);
+ self.collect_item_extended(lang_item, def_id, span);
}
// Known lang item with attribute on incorrect target.
Some(lang_item) => {
// Like collect_item() above, but also checks whether the lang item is declared
// with the right number of generic arguments.
- fn collect_item_extended(&mut self, lang_item: LangItem, hir_id: HirId, span: Span) {
- let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
+ fn collect_item_extended(&mut self, lang_item: LangItem, item_def_id: LocalDefId, span: Span) {
let name = lang_item.name();
// Now check whether the lang_item has the expected number of generic
// Some other types like Box and various functions like drop_in_place
// have minimum requirements.
- if let hir::Node::Item(hir::Item { kind, span: item_span, .. }) = self.tcx.hir().get(hir_id)
+ if let hir::Node::Item(hir::Item { kind, span: item_span, .. }) =
+ self.tcx.hir().get_by_def_id(item_def_id)
{
let (actual_num, generics_span) = match kind.generics() {
Some(generics) => (generics.params.len(), generics.span),
}
}
- self.collect_item(lang_item, item_def_id);
+ self.collect_item(lang_item, item_def_id.to_def_id());
}
}
let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
- collector.check_for_lang(Target::from_def_kind(tcx.def_kind(id.owner_id)), id.hir_id());
+ collector
+ .check_for_lang(Target::from_def_kind(tcx.def_kind(id.owner_id)), id.owner_id.def_id);
if matches!(tcx.def_kind(id.owner_id), DefKind::Enum) {
let item = tcx.hir().item(id);
if let hir::ItemKind::Enum(def, ..) = &item.kind {
for variant in def.variants {
- collector.check_for_lang(Target::Variant, variant.hir_id);
+ collector.check_for_lang(Target::Variant, variant.def_id);
}
}
}
// FIXME: avoid calling trait_item() when possible
for id in crate_items.trait_items() {
let item = tcx.hir().trait_item(id);
- collector.check_for_lang(Target::from_trait_item(item), item.hir_id())
+ collector.check_for_lang(Target::from_trait_item(item), item.owner_id.def_id)
}
// FIXME: avoid calling impl_item() when possible
for id in crate_items.impl_items() {
let item = tcx.hir().impl_item(id);
- collector.check_for_lang(target_from_impl_item(tcx, item), item.hir_id())
+ collector.check_for_lang(target_from_impl_item(tcx, item), item.owner_id.def_id)
}
// Extract out the found lang items.
/// See issue #94972 for details on why this is a special case
fn is_unstable_reexport(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
// Get the LocalDefId so we can lookup the item to check the kind.
- let Some(def_id) = tcx.hir().opt_local_def_id(id) else { return false; };
+ let Some(owner) = id.as_owner() else { return false; };
+ let def_id = owner.def_id;
let Some(stab) = tcx.stability().local_stability(def_id) else {
return false;
use rustc_data_structures::intern::Interned;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{AssocItemKind, HirIdSet, ItemId, Node, PatKind};
use rustc_middle::bug;
struct PrivateItemsInPublicInterfacesChecker<'tcx> {
tcx: TyCtxt<'tcx>,
- old_error_set_ancestry: LocalDefIdSet,
+ old_error_set_ancestry: HirIdSet,
}
impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
tcx: self.tcx,
item_def_id: def_id,
required_visibility,
- has_old_errors: self.old_error_set_ancestry.contains(&def_id),
+ has_old_errors: self
+ .old_error_set_ancestry
+ .contains(&self.tcx.hir().local_def_id_to_hir_id(def_id)),
in_assoc_ty: false,
}
}
}
// Check for private types and traits in public interfaces.
- let mut checker = PrivateItemsInPublicInterfacesChecker {
- tcx,
- // Only definition IDs are ever searched in `old_error_set_ancestry`,
- // so we can filter away all non-definition IDs at this point.
- old_error_set_ancestry: old_error_set_ancestry
- .into_iter()
- .filter_map(|hir_id| tcx.hir().opt_local_def_id(hir_id))
- .collect(),
- };
+ let mut checker = PrivateItemsInPublicInterfacesChecker { tcx, old_error_set_ancestry };
for id in tcx.hir().items() {
checker.check_item(id);
None => continue,
};
if !self.span.filter_generated(ident.span) {
- let id = id_from_hir_id(hir_id, &self.save_ctxt);
+ let id = id_from_hir_id(hir_id);
let span = self.span_from_span(ident.span);
self.dumper.dump_def(
&mut self,
sig: &'tcx hir::FnSig<'tcx>,
body: Option<hir::BodyId>,
- def_id: LocalDefId,
+ owner_id: hir::OwnerId,
ident: Ident,
generics: &'tcx hir::Generics<'tcx>,
span: Span,
) {
- debug!("process_method: {:?}:{}", def_id, ident);
+ debug!("process_method: {:?}:{}", owner_id, ident);
let map = self.tcx.hir();
- let hir_id = map.local_def_id_to_hir_id(def_id);
- self.nest_typeck_results(def_id, |v| {
- if let Some(mut method_data) = v.save_ctxt.get_method_data(hir_id, ident, span) {
+ let hir_id: hir::HirId = owner_id.into();
+ self.nest_typeck_results(owner_id.def_id, |v| {
+ if let Some(mut method_data) = v.save_ctxt.get_method_data(owner_id, ident, span) {
if let Some(body) = body {
v.process_formals(map.body(body).params, &method_data.qualname);
}
method_data.value =
fn_to_string(sig.decl, sig.header, Some(ident.name), generics, &[], None);
- method_data.sig = sig::method_signature(hir_id, ident, generics, sig, &v.save_ctxt);
+ method_data.sig =
+ sig::method_signature(owner_id, ident, generics, sig, &v.save_ctxt);
- v.dumper.dump_def(&access_from!(v.save_ctxt, def_id), method_data);
+ v.dumper.dump_def(&access_from!(v.save_ctxt, owner_id.def_id), method_data);
}
// walk arg and return types
fn process_struct_field_def(
&mut self,
field: &'tcx hir::FieldDef<'tcx>,
- parent_id: hir::HirId,
+ parent_id: LocalDefId,
) {
let field_data = self.save_ctxt.get_field_data(field, parent_id);
if let Some(field_data) = field_data {
- self.dumper.dump_def(
- &access_from!(self.save_ctxt, self.tcx.hir().local_def_id(field.hir_id)),
- field_data,
- );
+ self.dumper.dump_def(&access_from!(self.save_ctxt, field.def_id), field_data);
}
}
// Append $id to name to make sure each one is unique.
let qualname = format!("{}::{}${}", prefix, name, id);
if !self.span.filter_generated(param_ss) {
- let id = id_from_hir_id(param.hir_id, &self.save_ctxt);
+ let id = id_from_def_id(param.def_id.to_def_id());
let span = self.span_from_span(param_ss);
self.dumper.dump_def(
fn process_assoc_const(
&mut self,
- def_id: LocalDefId,
+ owner_id: hir::OwnerId,
ident: Ident,
typ: &'tcx hir::Ty<'tcx>,
expr: Option<&'tcx hir::Expr<'tcx>>,
parent_id: DefId,
attrs: &'tcx [ast::Attribute],
) {
- let qualname = format!("::{}", self.tcx.def_path_str(def_id.to_def_id()));
+ let qualname = format!("::{}", self.tcx.def_path_str(owner_id.to_def_id()));
if !self.span.filter_generated(ident.span) {
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
- let sig = sig::assoc_const_signature(hir_id, ident.name, typ, expr, &self.save_ctxt);
+ let sig = sig::assoc_const_signature(owner_id, ident.name, typ, expr, &self.save_ctxt);
let span = self.span_from_span(ident.span);
self.dumper.dump_def(
- &access_from!(self.save_ctxt, def_id),
+ &access_from!(self.save_ctxt, owner_id.def_id),
Def {
kind: DefKind::Const,
- id: id_from_hir_id(hir_id, &self.save_ctxt),
+ id: id_from_def_id(owner_id.to_def_id()),
span,
name: ident.name.to_string(),
qualname,
}
// walk type and init value
- self.nest_typeck_results(def_id, |v| {
+ self.nest_typeck_results(owner_id.def_id, |v| {
v.visit_ty(typ);
if let Some(expr) = expr {
v.visit_expr(expr);
if include_priv_fields {
return Some(f.ident.to_string());
}
- let def_id = self.save_ctxt.tcx.hir().local_def_id(f.hir_id);
- if self.save_ctxt.tcx.visibility(def_id).is_public() {
+ if self.save_ctxt.tcx.visibility(f.def_id).is_public() {
Some(f.ident.to_string())
} else {
None
.collect::<Vec<_>>()
.join(", ");
let value = format!("{} {{ {} }}", name, fields_str);
- (value, fields.iter().map(|f| id_from_hir_id(f.hir_id, &self.save_ctxt)).collect())
+ (value, fields.iter().map(|f| id_from_def_id(f.def_id.to_def_id())).collect())
}
_ => (String::new(), vec![]),
};
self.nest_typeck_results(item.owner_id.def_id, |v| {
for field in def.fields() {
- v.process_struct_field_def(field, item.hir_id());
+ v.process_struct_field_def(field, item.owner_id.def_id);
v.visit_ty(&field.ty);
}
let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
if !self.span.filter_generated(name_span) {
let span = self.span_from_span(name_span);
- let id = id_from_hir_id(variant.hir_id, &self.save_ctxt);
+ let id = id_from_def_id(variant.def_id.to_def_id());
let parent = Some(id_from_def_id(item.owner_id.to_def_id()));
let attrs = self.tcx.hir().attrs(variant.hir_id);
}
if !self.span.filter_generated(name_span) {
let span = self.span_from_span(name_span);
- let id = id_from_hir_id(variant.hir_id, &self.save_ctxt);
+ let id = id_from_def_id(variant.def_id.to_def_id());
let parent = Some(id_from_def_id(item.owner_id.to_def_id()));
let attrs = self.tcx.hir().attrs(variant.hir_id);
}
for field in variant.data.fields() {
- self.process_struct_field_def(field, variant.hir_id);
+ self.process_struct_field_def(field, variant.def_id);
self.visit_ty(field.ty);
}
}
// Rust uses the id of the pattern for var lookups, so we'll use it too.
if !self.span.filter_generated(ident.span) {
let qualname = format!("{}${}", ident, hir_id);
- let id = id_from_hir_id(hir_id, &self.save_ctxt);
+ let id = id_from_hir_id(hir_id);
let span = self.span_from_span(ident.span);
self.dumper.dump_def(
let body = body.map(|b| self.tcx.hir().body(b).value);
let attrs = self.tcx.hir().attrs(trait_item.hir_id());
self.process_assoc_const(
- trait_item.owner_id.def_id,
+ trait_item.owner_id,
trait_item.ident,
&ty,
body,
self.process_method(
sig,
body,
- trait_item.owner_id.def_id,
+ trait_item.owner_id,
trait_item.ident,
&trait_item.generics,
trait_item.span,
decl_id: None,
docs: self.save_ctxt.docs_for_attrs(attrs),
sig: sig::assoc_type_signature(
- trait_item.hir_id(),
+ trait_item.owner_id,
trait_item.ident,
Some(bounds),
default_ty.as_deref(),
let body = self.tcx.hir().body(body);
let attrs = self.tcx.hir().attrs(impl_item.hir_id());
self.process_assoc_const(
- impl_item.owner_id.def_id,
+ impl_item.owner_id,
impl_item.ident,
&ty,
Some(&body.value),
self.process_method(
sig,
Some(body),
- impl_item.owner_id.def_id,
+ impl_item.owner_id,
impl_item.ident,
&impl_item.generics,
impl_item.span,
}
pub(crate) fn process_crate(&mut self) {
- let id = hir::CRATE_HIR_ID;
- let qualname =
- format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id(id).to_def_id()));
+ let qualname = format!("::{}", self.tcx.def_path_str(CRATE_DEF_ID.to_def_id()));
let sm = self.tcx.sess.source_map();
let krate_mod = self.tcx.hir().root_module();
let filename = sm.span_to_filename(krate_mod.spans.inner_span);
- let data_id = id_from_hir_id(id, &self.save_ctxt);
+ let data_id = id_from_def_id(CRATE_DEF_ID.to_def_id());
let children =
krate_mod.item_ids.iter().map(|i| id_from_def_id(i.owner_id.to_def_id())).collect();
let span = self.span_from_span(krate_mod.spans.inner_span);
- let attrs = self.tcx.hir().attrs(id);
+ let attrs = self.tcx.hir().attrs(hir::CRATE_HIR_ID);
self.dumper.dump_def(
&Access { public: true, reachable: true },
// output the inferred type here? :shrug:
hir::ArrayLen::Infer(..) => {}
hir::ArrayLen::Body(anon_const) => self
- .nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
+ .nest_typeck_results(anon_const.def_id, |v| {
v.visit_expr(&map.body(anon_const.body).value)
}),
}
}
}
}
- hir::ExprKind::Closure(&hir::Closure { ref fn_decl, body, .. }) => {
+ hir::ExprKind::Closure(&hir::Closure { ref fn_decl, body, def_id, .. }) => {
let id = format!("${}", ex.hir_id);
// walk arg and return types
// walk the body
let map = self.tcx.hir();
- self.nest_typeck_results(self.tcx.hir().local_def_id(ex.hir_id), |v| {
+ self.nest_typeck_results(def_id, |v| {
let body = map.body(body);
v.process_formals(body.params, &id);
v.visit_expr(&body.value)
// output the inferred type here? :shrug:
hir::ArrayLen::Infer(..) => {}
hir::ArrayLen::Body(anon_const) => self
- .nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
+ .nest_typeck_results(anon_const.def_id, |v| {
v.visit_expr(&map.body(anon_const.body).value)
}),
}
use rustc_ast_pretty::pprust::attribute_to_string;
use rustc_hir as hir;
use rustc_hir::def::{DefKind as HirDefKind, Res};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::Node;
use rustc_hir_pretty::{enum_def_to_string, fn_to_string, ty_to_string};
qualname,
value,
parent: None,
- children: def.variants.iter().map(|v| id_from_hir_id(v.hir_id, self)).collect(),
+ children: def.variants.iter().map(|v| id_from_def_id(v.def_id.to_def_id())).collect(),
decl_id: None,
docs: self.docs_for_attrs(attrs),
sig: sig::item_signature(item, self),
}
}
- pub fn get_field_data(&self, field: &hir::FieldDef<'_>, scope: hir::HirId) -> Option<Def> {
+ pub fn get_field_data(&self, field: &hir::FieldDef<'_>, scope: LocalDefId) -> Option<Def> {
let name = field.ident.to_string();
- let scope_def_id = self.tcx.hir().local_def_id(scope).to_def_id();
- let qualname = format!("::{}::{}", self.tcx.def_path_str(scope_def_id), field.ident);
+ let qualname = format!("::{}::{}", self.tcx.def_path_str(scope.to_def_id()), field.ident);
filter!(self.span_utils, field.ident.span);
- let field_def_id = self.tcx.hir().local_def_id(field.hir_id).to_def_id();
+ let field_def_id = field.def_id.to_def_id();
let typ = self.tcx.type_of(field_def_id).to_string();
let id = id_from_def_id(field_def_id);
name,
qualname,
value: typ,
- parent: Some(id_from_def_id(scope_def_id)),
+ parent: Some(id_from_def_id(scope.to_def_id())),
children: vec![],
decl_id: None,
docs: self.docs_for_attrs(attrs),
// FIXME would be nice to take a MethodItem here, but the ast provides both
// trait and impl flavours, so the caller must do the disassembly.
- pub fn get_method_data(&self, hir_id: hir::HirId, ident: Ident, span: Span) -> Option<Def> {
+ pub fn get_method_data(&self, owner_id: hir::OwnerId, ident: Ident, span: Span) -> Option<Def> {
// The qualname for a method is the trait name or name of the struct in an impl in
// which the method is declared in, followed by the method's name.
- let def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
let (qualname, parent_scope, decl_id, docs, attributes) =
- match self.tcx.impl_of_method(def_id) {
+ match self.tcx.impl_of_method(owner_id.to_def_id()) {
Some(impl_id) => match self.tcx.hir().get_if_local(impl_id) {
Some(Node::Item(item)) => match item.kind {
hir::ItemKind::Impl(hir::Impl { ref self_ty, .. }) => {
let trait_id = self.tcx.trait_id_of_impl(impl_id);
let mut docs = String::new();
let mut attrs = vec![];
- if let Some(Node::ImplItem(_)) = hir.find(hir_id) {
- attrs = self.tcx.hir().attrs(hir_id).to_vec();
+ if let Some(Node::ImplItem(_)) = hir.find(owner_id.into()) {
+ attrs = self.tcx.hir().attrs(owner_id.into()).to_vec();
docs = self.docs_for_attrs(&attrs);
}
_ => {
span_bug!(
span,
- "Container {:?} for method {} not an impl?",
+ "Container {:?} for method {:?} not an impl?",
impl_id,
- hir_id
+ owner_id,
);
}
},
r => {
span_bug!(
span,
- "Container {:?} for method {} is not a node item {:?}",
+ "Container {:?} for method {:?} is not a node item {:?}",
impl_id,
- hir_id,
+ owner_id,
r
);
}
},
- None => match self.tcx.trait_of_item(def_id) {
+ None => match self.tcx.trait_of_item(owner_id.to_def_id()) {
Some(def_id) => {
let mut docs = String::new();
let mut attrs = vec![];
- if let Some(Node::TraitItem(_)) = self.tcx.hir().find(hir_id) {
- attrs = self.tcx.hir().attrs(hir_id).to_vec();
+ if let Some(Node::TraitItem(_)) = self.tcx.hir().find(owner_id.into()) {
+ attrs = self.tcx.hir().attrs(owner_id.into()).to_vec();
docs = self.docs_for_attrs(&attrs);
}
)
}
None => {
- debug!("could not find container for method {} at {:?}", hir_id, span);
+ debug!("could not find container for method {:?} at {:?}", owner_id, span);
// This is not necessarily a bug, if there was a compilation error,
// the typeck results we need might not exist.
return None;
Some(Def {
kind: DefKind::Method,
- id: id_from_def_id(def_id),
+ id: id_from_def_id(owner_id.to_def_id()),
span: self.span_from_span(ident.span),
name: ident.name.to_string(),
qualname,
match res {
Res::Local(id) => {
- Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_hir_id(id, self) })
+ Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_hir_id(id) })
}
Res::Def(HirDefKind::Trait, def_id) if fn_type(path_seg) => {
Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(def_id) })
rls_data::Id { krate: id.krate.as_u32(), index: id.index.as_u32() }
}
-fn id_from_hir_id(id: hir::HirId, scx: &SaveContext<'_>) -> rls_data::Id {
- let def_id = scx.tcx.hir().opt_local_def_id(id);
- def_id.map(|id| id_from_def_id(id.to_def_id())).unwrap_or_else(|| {
- // Create a *fake* `DefId` out of a `HirId` by combining the owner
- // `local_def_index` and the `local_id`.
- // This will work unless you have *billions* of definitions in a single
- // crate (very unlikely to actually happen).
- rls_data::Id {
- krate: LOCAL_CRATE.as_u32(),
- index: id.owner.def_id.local_def_index.as_u32() | id.local_id.as_u32().reverse_bits(),
- }
- })
+fn id_from_hir_id(id: hir::HirId) -> rls_data::Id {
+ // Create a *fake* `DefId` out of a `HirId` by combining the owner
+ // `local_def_index` and the `local_id`.
+ // This will work unless you have *billions* of definitions in a single
+ // crate (very unlikely to actually happen).
+ rls_data::Id {
+ krate: LOCAL_CRATE.as_u32(),
+ index: id.owner.def_id.local_def_index.as_u32() | id.local_id.as_u32().reverse_bits(),
+ }
}
fn null_id() -> rls_data::Id {
//
// FIXME where clauses need implementing, defs/refs in generics are mostly missing.
-use crate::{id_from_def_id, id_from_hir_id, SaveContext};
+use crate::{id_from_def_id, SaveContext};
use rls_data::{SigElement, Signature};
use rustc_hir::def::{DefKind, Res};
use rustc_hir_pretty::id_to_string;
use rustc_hir_pretty::{bounds_to_string, path_segment_to_string, path_to_string, ty_to_string};
+use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{Ident, Symbol};
pub fn item_signature(item: &hir::Item<'_>, scx: &SaveContext<'_>) -> Option<Signature> {
}
pub fn method_signature(
- id: hir::HirId,
+ id: hir::OwnerId,
ident: Ident,
generics: &hir::Generics<'_>,
m: &hir::FnSig<'_>,
}
pub fn assoc_const_signature(
- id: hir::HirId,
+ id: hir::OwnerId,
ident: Symbol,
ty: &hir::Ty<'_>,
default: Option<&hir::Expr<'_>>,
}
pub fn assoc_type_signature(
- id: hir::HirId,
+ id: hir::OwnerId,
ident: Ident,
bounds: Option<hir::GenericBounds<'_>>,
default: Option<&hir::Ty<'_>>,
type Result = std::result::Result<Signature, &'static str>;
trait Sig {
- fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result;
+ type Parent;
+ fn make(&self, offset: usize, id: Option<Self::Parent>, scx: &SaveContext<'_>) -> Result;
}
fn extend_sig(
}
impl<'hir> Sig for hir::Ty<'hir> {
+ type Parent = hir::HirId;
fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
let id = Some(self.hir_id);
match self.kind {
}
impl<'hir> Sig for hir::Item<'hir> {
+ type Parent = hir::HirId;
fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
let id = Some(self.hir_id());
text.push_str("fn ");
let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
+ name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
sig.text.push('(');
for i in decl.inputs {
hir::ItemKind::TyAlias(ref ty, ref generics) => {
let text = "type ".to_owned();
let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
+ name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
sig.text.push_str(" = ");
let ty = ty.make(offset + sig.text.len(), id, scx)?;
hir::ItemKind::Enum(_, ref generics) => {
let text = "enum ".to_owned();
let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
+ name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
sig.text.push_str(" {}");
Ok(sig)
}
hir::ItemKind::Struct(_, ref generics) => {
let text = "struct ".to_owned();
let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
+ name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
sig.text.push_str(" {}");
Ok(sig)
}
hir::ItemKind::Union(_, ref generics) => {
let text = "union ".to_owned();
let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
+ name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
sig.text.push_str(" {}");
Ok(sig)
}
}
text.push_str("trait ");
let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
+ name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
if !bounds.is_empty() {
sig.text.push_str(": ");
let mut text = String::new();
text.push_str("trait ");
let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
+ name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
if !bounds.is_empty() {
sig.text.push_str(" = ");
text.push_str(" const");
}
- let generics_sig = generics.make(offset + text.len(), id, scx)?;
+ let generics_sig =
+ generics.make(offset + text.len(), Some(self.owner_id.def_id), scx)?;
text.push_str(&generics_sig.text);
text.push(' ');
}
impl<'hir> Sig for hir::Path<'hir> {
+ type Parent = hir::HirId;
fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
// This does not cover the where clause, which must be processed separately.
impl<'hir> Sig for hir::Generics<'hir> {
- fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
+ type Parent = LocalDefId;
+ fn make(&self, offset: usize, _parent_id: Option<LocalDefId>, scx: &SaveContext<'_>) -> Result {
if self.params.is_empty() {
return Ok(text_sig(String::new()));
}
}
param_text.push_str(param.name.ident().as_str());
defs.push(SigElement {
- id: id_from_hir_id(param.hir_id, scx),
+ id: id_from_def_id(param.def_id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + param_text.as_str().len(),
});
}
impl<'hir> Sig for hir::FieldDef<'hir> {
- fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
+ type Parent = LocalDefId;
+ fn make(&self, offset: usize, _parent_id: Option<LocalDefId>, scx: &SaveContext<'_>) -> Result {
let mut text = String::new();
text.push_str(&self.ident.to_string());
let defs = Some(SigElement {
- id: id_from_hir_id(self.hir_id, scx),
+ id: id_from_def_id(self.def_id.to_def_id()),
start: offset,
end: offset + text.len(),
});
}
impl<'hir> Sig for hir::Variant<'hir> {
- fn make(&self, offset: usize, parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
+ type Parent = LocalDefId;
+ fn make(&self, offset: usize, parent_id: Option<LocalDefId>, scx: &SaveContext<'_>) -> Result {
let mut text = self.ident.to_string();
match self.data {
hir::VariantData::Struct(fields, r) => {
let id = parent_id.ok_or("Missing id for Variant's parent")?;
let name_def = SigElement {
- id: id_from_hir_id(id, scx),
+ id: id_from_def_id(id.to_def_id()),
start: offset,
end: offset + text.len(),
};
text.push('}');
Ok(Signature { text, defs, refs })
}
- hir::VariantData::Tuple(fields, id, _) => {
+ hir::VariantData::Tuple(fields, _, def_id) => {
let name_def = SigElement {
- id: id_from_hir_id(id, scx),
+ id: id_from_def_id(def_id.to_def_id()),
start: offset,
end: offset + text.len(),
};
let mut defs = vec![name_def];
let mut refs = vec![];
for f in fields {
- let field_sig = f.make(offset + text.len(), Some(id), scx)?;
+ let field_sig = f.make(offset + text.len(), Some(def_id), scx)?;
text.push_str(&field_sig.text);
text.push_str(", ");
defs.extend(field_sig.defs.into_iter());
text.push(')');
Ok(Signature { text, defs, refs })
}
- hir::VariantData::Unit(id, _) => {
+ hir::VariantData::Unit(_, def_id) => {
let name_def = SigElement {
- id: id_from_hir_id(id, scx),
+ id: id_from_def_id(def_id.to_def_id()),
start: offset,
end: offset + text.len(),
};
}
impl<'hir> Sig for hir::ForeignItem<'hir> {
+ type Parent = hir::HirId;
fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
let id = Some(self.hir_id());
match self.kind {
text.push_str("fn ");
let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
+ name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
sig.text.push('(');
for i in decl.inputs {
mut text: String,
offset: usize,
generics: &hir::Generics<'_>,
- id: hir::HirId,
+ id: hir::OwnerId,
name: Ident,
scx: &SaveContext<'_>,
) -> Result {
let name = name.to_string();
let def = SigElement {
- id: id_from_hir_id(id, scx),
+ id: id_from_def_id(id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + name.len(),
};
text.push_str(&name);
- let generics: Signature = generics.make(offset + text.len(), Some(id), scx)?;
+ let generics: Signature = generics.make(offset + text.len(), Some(id.def_id), scx)?;
// FIXME where clause
let text = format!("{}{}", text, generics.text);
Ok(extend_sig(generics, text, vec![def], vec![]))
}
fn make_assoc_type_signature(
- id: hir::HirId,
+ id: hir::OwnerId,
ident: Ident,
bounds: Option<hir::GenericBounds<'_>>,
default: Option<&hir::Ty<'_>>,
let mut text = "type ".to_owned();
let name = ident.to_string();
let mut defs = vec![SigElement {
- id: id_from_hir_id(id, scx),
+ id: id_from_def_id(id.to_def_id()),
start: text.len(),
end: text.len() + name.len(),
}];
}
if let Some(default) = default {
text.push_str(" = ");
- let ty_sig = default.make(text.len(), Some(id), scx)?;
+ let ty_sig = default.make(text.len(), Some(id.into()), scx)?;
text.push_str(&ty_sig.text);
defs.extend(ty_sig.defs.into_iter());
refs.extend(ty_sig.refs.into_iter());
}
fn make_assoc_const_signature(
- id: hir::HirId,
+ id: hir::OwnerId,
ident: Symbol,
ty: &hir::Ty<'_>,
default: Option<&hir::Expr<'_>>,
let mut text = "const ".to_owned();
let name = ident.to_string();
let mut defs = vec![SigElement {
- id: id_from_hir_id(id, scx),
+ id: id_from_def_id(id.to_def_id()),
start: text.len(),
end: text.len() + name.len(),
}];
text.push_str(&name);
text.push_str(": ");
- let ty_sig = ty.make(text.len(), Some(id), scx)?;
+ let ty_sig = ty.make(text.len(), Some(id.into()), scx)?;
text.push_str(&ty_sig.text);
defs.extend(ty_sig.defs.into_iter());
refs.extend(ty_sig.refs.into_iter());
}
fn make_method_signature(
- id: hir::HirId,
+ id: hir::OwnerId,
ident: Ident,
generics: &hir::Generics<'_>,
m: &hir::FnSig<'_>,
/// let _y = x.clone();
/// }
/// ```
- AliasBound(usize),
+ AliasBound,
}
pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq {
// NOTE: Alternatively we could call `evaluate_goal` here and only have a `Normalized` candidate.
// This doesn't work as long as we use `CandidateSource` in winnowing.
let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
- // FIXME: This is broken if we care about the `usize` of `AliasBound` because the self type
- // could be normalized to yet another projection with different item bounds.
let normalized_candidates = self.assemble_and_evaluate_candidates(goal);
for mut normalized_candidate in normalized_candidates {
normalized_candidate.result =
ty::Alias(_, alias_ty) => alias_ty,
};
- for (i, (assumption, _)) in self
+ for (assumption, _) in self
.tcx()
.bound_explicit_item_bounds(alias_ty.def_id)
.subst_iter_copied(self.tcx(), alias_ty.substs)
- .enumerate()
{
match G::consider_assumption(self, goal, assumption) {
Ok(result) => {
- candidates.push(Candidate { source: CandidateSource::AliasBound(i), result })
+ candidates.push(Candidate { source: CandidateSource::AliasBound, result })
}
Err(NoSolution) => (),
}
// preserves universes and creates a unique var (in the highest universe) for each
// appearance of a region.
-// FIXME: `CanonicalVarValues` should be interned and `Copy`.
-
// FIXME: uses of `infcx.at` need to enable deferred projection equality once that's implemented.
use std::mem;
use rustc_hir::def_id::DefId;
-use rustc_infer::infer::canonical::{Canonical, CanonicalVarKind, CanonicalVarValues};
+use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse};
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use rustc_infer::traits::query::NoSolution;
let external_constraints = take_external_constraints(self.infcx)?;
Ok(self.infcx.canonicalize_response(Response {
- var_values: self.var_values.clone(),
+ var_values: self.var_values,
external_constraints,
certainty,
}))
goal: Canonical<'tcx, impl Sized>,
certainty: Certainty,
) -> QueryResult<'tcx> {
- let var_values = goal
- .variables
- .iter()
- .enumerate()
- .map(|(i, info)| match info.kind {
- CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => {
- tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into())).into()
- }
- CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
- let br = ty::BoundRegion {
- var: ty::BoundVar::from_usize(i),
- kind: ty::BrAnon(i as u32, None),
- };
- tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
- }
- CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => tcx
- .mk_const(ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)), ty)
- .into(),
- })
- .collect();
-
Ok(Canonical {
max_universe: goal.max_universe,
variables: goal.variables,
value: Response {
- var_values: CanonicalVarValues { var_values },
+ var_values: CanonicalVarValues::make_identity(tcx, goal.variables),
external_constraints: Default::default(),
certainty,
},
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if t.needs_infer() {
if ty::Term::from(t) == self.term {
- ControlFlow::BREAK
+ ControlFlow::Break(())
} else {
t.super_visit_with(self)
}
} else {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if c.needs_infer() {
if ty::Term::from(c) == self.term {
- ControlFlow::BREAK
+ ControlFlow::Break(())
} else {
c.super_visit_with(self)
}
} else {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
}
(CandidateSource::Impl(_), _)
| (CandidateSource::ParamEnv(_), _)
| (CandidateSource::BuiltinImpl, _)
- | (CandidateSource::AliasBound(_), _) => unimplemented!(),
+ | (CandidateSource::AliasBound, _) => unimplemented!(),
}
}
}
}
pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> QueryResult<'tcx> {
+ // FIXME: Responses should probably be `Copy` as well
self.entries[entry_index].response.clone()
}
}
match (candidate.source, other.source) {
(CandidateSource::Impl(_), _)
| (CandidateSource::ParamEnv(_), _)
- | (CandidateSource::AliasBound(_), _)
+ | (CandidateSource::AliasBound, _)
| (CandidateSource::BuiltinImpl, _) => unimplemented!(),
}
}
/// param for cleaner code.
fn suggest_restriction<'tcx>(
tcx: TyCtxt<'tcx>,
- hir_id: HirId,
+ item_id: LocalDefId,
hir_generics: &hir::Generics<'tcx>,
msg: &str,
err: &mut Diagnostic,
{
return;
}
- let Some(item_id) = hir_id.as_owner() else { return; };
let generics = tcx.generics_of(item_id);
// Given `fn foo(t: impl Trait)` where `Trait` requires assoc type `A`...
if let Some((param, bound_str, fn_sig)) =
mut err: &mut Diagnostic,
trait_pred: ty::PolyTraitPredicate<'tcx>,
associated_ty: Option<(&'static str, Ty<'tcx>)>,
- body_id: LocalDefId,
+ mut body_id: LocalDefId,
) {
let trait_pred = self.resolve_numeric_literals_with_default(trait_pred);
// FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
// don't suggest `T: Sized + ?Sized`.
- let mut body_id = body_id;
while let Some(node) = self.tcx.hir().find_by_def_id(body_id) {
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(body_id);
match node {
hir::Node::Item(hir::Item {
ident,
// Restricting `Self` for a single method.
suggest_restriction(
self.tcx,
- hir_id,
+ body_id,
&generics,
"`Self`",
err,
assert!(param_ty);
// Restricting `Self` for a single method.
suggest_restriction(
- self.tcx, hir_id, &generics, "`Self`", err, None, projection, trait_pred,
+ self.tcx, body_id, &generics, "`Self`", err, None, projection, trait_pred,
None,
);
return;
// Missing restriction on associated type of type parameter (unmet projection).
suggest_restriction(
self.tcx,
- hir_id,
+ body_id,
&generics,
"the associated type",
err,
// Missing restriction on associated type of type parameter (unmet projection).
suggest_restriction(
self.tcx,
- hir_id,
+ body_id,
&generics,
"the associated type",
err,
use rustc_data_structures::fx::FxHashMap;
-use rustc_index::vec::IndexVec;
-
use rustc_middle::infer::canonical::{CanonicalTyVarKind, CanonicalVarKind};
use rustc_middle::traits::ChalkRustInterner;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::GenericArg;
-use rustc_middle::ty::{self, BoundVar, ParamTy, TyCtxt, TypeFoldable, TypeVisitable};
+use rustc_middle::ty::{self, ParamTy, TyCtxt, TypeFoldable, TypeVisitable};
use rustc_infer::infer::canonical::{
Canonical, CanonicalVarValues, Certainty, QueryRegionConstraints, QueryResponse,
binders: chalk_ir::CanonicalVarKinds<_>| {
use rustc_middle::infer::canonical::CanonicalVarInfo;
- let mut var_values: IndexVec<BoundVar, GenericArg<'tcx>> = IndexVec::new();
let mut reverse_param_substitutor = ReverseParamsSubstitutor::new(tcx, params);
- subst.as_slice(interner).iter().for_each(|p| {
- var_values.push(p.lower_into(interner).fold_with(&mut reverse_param_substitutor));
- });
+ let var_values = tcx.mk_substs(
+ subst
+ .as_slice(interner)
+ .iter()
+ .map(|p| p.lower_into(interner).fold_with(&mut reverse_param_substitutor)),
+ );
let variables: Vec<_> = binders
.iter(interner)
.map(|var| {
max_universe: ty::UniverseIndex::from_usize(0),
variables: obligation.variables,
value: QueryResponse {
- var_values: CanonicalVarValues { var_values: IndexVec::new() }
- .make_identity(tcx),
+ var_values: CanonicalVarValues::dummy(),
region_constraints: QueryRegionConstraints::default(),
certainty: Certainty::Ambiguous,
opaque_types: vec![],
) -> impl FnMut((), T) -> ControlFlow<B> + '_ {
move |(), x| match f(x) {
Some(x) => ControlFlow::Break(x),
- None => ControlFlow::CONTINUE,
+ None => ControlFlow::Continue(()),
}
}
#[rustc_inherit_overflow_checks]
fn advance<U: Iterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
match iter.advance_by(n) {
- Ok(()) => ControlFlow::BREAK,
+ Ok(()) => ControlFlow::Break(()),
Err(advanced) => ControlFlow::Continue(n - advanced),
}
}
#[rustc_inherit_overflow_checks]
fn advance<U: DoubleEndedIterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
match iter.advance_back_by(n) {
- Ok(()) => ControlFlow::BREAK,
+ Ok(()) => ControlFlow::Break(()),
Err(advanced) => ControlFlow::Continue(n - advanced),
}
}
#[inline]
fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow<T> {
move |(), x| {
- if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE }
+ if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
}
}
#[inline]
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> {
move |(), x| {
- if f(x) { ControlFlow::CONTINUE } else { ControlFlow::BREAK }
+ if f(x) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
}
}
- self.try_fold((), check(f)) == ControlFlow::CONTINUE
+ self.try_fold((), check(f)) == ControlFlow::Continue(())
}
/// Tests if any element of the iterator matches a predicate.
#[inline]
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> {
move |(), x| {
- if f(x) { ControlFlow::BREAK } else { ControlFlow::CONTINUE }
+ if f(x) { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
}
}
- self.try_fold((), check(f)) == ControlFlow::BREAK
+ self.try_fold((), check(f)) == ControlFlow::Break(())
}
/// Searches for an element of an iterator that satisfies a predicate.
#[inline]
fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow<T> {
move |(), x| {
- if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE }
+ if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
}
}
fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut((), T) -> ControlFlow<B> {
move |(), x| match f(x) {
Some(x) => ControlFlow::Break(x),
- None => ControlFlow::CONTINUE,
+ None => ControlFlow::Continue(()),
}
}
R: Residual<Option<I>>,
{
move |(), x| match f(&x).branch() {
- ControlFlow::Continue(false) => ControlFlow::CONTINUE,
+ ControlFlow::Continue(false) => ControlFlow::Continue(()),
ControlFlow::Continue(true) => ControlFlow::Break(Try::from_output(Some(x))),
ControlFlow::Break(r) => ControlFlow::Break(FromResidual::from_residual(r)),
}
F: FnMut(X, Y) -> Ordering,
{
move |x, y| match cmp(x, y) {
- Ordering::Equal => ControlFlow::CONTINUE,
+ Ordering::Equal => ControlFlow::Continue(()),
non_eq => ControlFlow::Break(non_eq),
}
}
F: FnMut(X, Y) -> Option<Ordering>,
{
move |x, y| match partial_cmp(x, y) {
- Some(Ordering::Equal) => ControlFlow::CONTINUE,
+ Some(Ordering::Equal) => ControlFlow::Continue(()),
non_eq => ControlFlow::Break(non_eq),
}
}
F: FnMut(X, Y) -> bool,
{
move |x, y| {
- if eq(x, y) { ControlFlow::CONTINUE } else { ControlFlow::BREAK }
+ if eq(x, y) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
}
}
/// Compares two iterators element-wise using the given function.
///
-/// If `ControlFlow::CONTINUE` is returned from the function, the comparison moves on to the next
+/// If `ControlFlow::Continue(())` is returned from the function, the comparison moves on to the next
/// elements of both iterators. Returning `ControlFlow::Break(x)` short-circuits the iteration and
/// returns `ControlFlow::Break(x)`. If one of the iterators runs out of elements,
/// `ControlFlow::Continue(ord)` is returned where `ord` is the result of comparing the lengths of
}
}
}
-
-impl<B> ControlFlow<B, ()> {
- /// It's frequently the case that there's no value needed with `Continue`,
- /// so this provides a way to avoid typing `(())`, if you prefer it.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(control_flow_enum)]
- /// use std::ops::ControlFlow;
- ///
- /// let mut partial_sum = 0;
- /// let last_used = (1..10).chain(20..25).try_for_each(|x| {
- /// partial_sum += x;
- /// if partial_sum > 100 { ControlFlow::Break(x) }
- /// else { ControlFlow::CONTINUE }
- /// });
- /// assert_eq!(last_used.break_value(), Some(22));
- /// ```
- #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
- pub const CONTINUE: Self = ControlFlow::Continue(());
-}
-
-impl<C> ControlFlow<(), C> {
- /// APIs like `try_for_each` don't need values with `Break`,
- /// so this provides a way to avoid typing `(())`, if you prefer it.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(control_flow_enum)]
- /// use std::ops::ControlFlow;
- ///
- /// let mut partial_sum = 0;
- /// (1..10).chain(20..25).try_for_each(|x| {
- /// if partial_sum > 100 { ControlFlow::BREAK }
- /// else { partial_sum += x; ControlFlow::CONTINUE }
- /// });
- /// assert_eq!(partial_sum, 108);
- /// ```
- #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
- pub const BREAK: Self = ControlFlow::Break(());
-}
use rand::RngCore;
+#[cfg(target_os = "macos")]
+use crate::ffi::{c_char, c_int};
#[cfg(unix)]
use crate::os::unix::fs::symlink as symlink_dir;
#[cfg(unix)]
use crate::sys::fs::symlink_junction;
#[cfg(target_os = "macos")]
use crate::sys::weak::weak;
-#[cfg(target_os = "macos")]
-use libc::{c_char, c_int};
macro_rules! check {
($e:expr) => {
#![feature(const_ip)]
#![feature(const_ipv4)]
#![feature(const_ipv6)]
-#![feature(const_socketaddr)]
#![feature(thread_local_internals)]
//
#![default_lib_allocator]
/// ```
#[stable(feature = "ip_addr", since = "1.7.0")]
#[must_use]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
pub const fn new(ip: IpAddr, port: u16) -> SocketAddr {
match ip {
IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)),
/// ```
#[must_use]
#[stable(feature = "ip_addr", since = "1.7.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
pub const fn ip(&self) -> IpAddr {
match *self {
SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()),
/// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
pub const fn port(&self) -> u16 {
match *self {
SocketAddr::V4(ref a) => a.port(),
/// ```
#[must_use]
#[stable(feature = "sockaddr_checker", since = "1.16.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
pub const fn is_ipv4(&self) -> bool {
matches!(*self, SocketAddr::V4(_))
}
/// ```
#[must_use]
#[stable(feature = "sockaddr_checker", since = "1.16.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
pub const fn is_ipv6(&self) -> bool {
matches!(*self, SocketAddr::V6(_))
}
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
SocketAddrV4 { ip, port }
}
/// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
pub const fn ip(&self) -> &Ipv4Addr {
&self.ip
}
/// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
pub const fn port(&self) -> u16 {
self.port
}
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 {
SocketAddrV6 { ip, port, flowinfo, scope_id }
}
/// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
pub const fn ip(&self) -> &Ipv6Addr {
&self.ip
}
/// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
pub const fn port(&self) -> u16 {
self.port
}
/// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
pub const fn flowinfo(&self) -> u32 {
self.flowinfo
}
/// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
pub const fn scope_id(&self) -> u32 {
self.scope_id
}
//! OS-specific networking functionality.
+// See cfg macros in `library/std/src/os/mod.rs` for why these platforms must
+// be special-cased during rustdoc generation.
+#[cfg(not(all(
+ doc,
+ any(
+ all(target_arch = "wasm32", not(target_os = "wasi")),
+ all(target_vendor = "fortanix", target_env = "sgx")
+ )
+)))]
#[cfg(any(target_os = "linux", target_os = "android", doc))]
pub(super) mod linux_ext;
//! On Emscripten Rust panics are wrapped in C++ exceptions, so we just forward
//! to `__gxx_personality_v0` which is provided by Emscripten.
-use libc::c_int;
+use crate::ffi::c_int;
use unwind as uw;
// This is required by the compiler to exist (e.g., it's a lang item), but it's
//! and the last personality routine transfers control to the catch block.
use super::dwarf::eh::{self, EHAction, EHContext};
-use libc::{c_int, uintptr_t};
+use crate::ffi::c_int;
+use libc::uintptr_t;
use unwind as uw;
// Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
#[cfg(any(
target_arch = "x86",
target_arch = "arm",
+ target_arch = "m68k",
target_arch = "mips",
target_arch = "powerpc",
target_arch = "powerpc64",
fn keyed_event_handle() -> c::HANDLE {
const INVALID: c::HANDLE = ptr::invalid_mut(!0);
- static HANDLE: AtomicPtr<libc::c_void> = AtomicPtr::new(INVALID);
+ static HANDLE: AtomicPtr<crate::ffi::c_void> = AtomicPtr::new(INVALID);
match HANDLE.load(Relaxed) {
INVALID => {
let mut handle = c::INVALID_HANDLE_VALUE;
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::Duration;
-use libc::{c_int, c_void};
+use crate::ffi::{c_int, c_void};
cfg_if::cfg_if! {
if #[cfg(any(
target_os = "dragonfly", target_os = "freebsd",
target_os = "openbsd", target_os = "netbsd",
target_os = "solaris", target_os = "illumos"))] {
- use libc::c_uchar;
+ use crate::ffi::c_uchar;
type IpV4MultiCastType = c_uchar;
} else {
type IpV4MultiCastType = c_int;
}
#[cfg(not(target_os = "android"))]
-fn to_ipv6mr_interface(value: u32) -> libc::c_uint {
- value as libc::c_uint
+fn to_ipv6mr_interface(value: u32) -> crate::ffi::c_uint {
+ value as crate::ffi::c_uint
}
////////////////////////////////////////////////////////////////////////////////
return Vec::new();
}
+ if !stamp.exists() {
+ eprintln!(
+ "Warning: Unable to find the stamp file, did you try to keep a nonexistent build stage?"
+ );
+ crate::detail_exit(1);
+ }
+
let mut paths = Vec::new();
let contents = t!(fs::read(stamp), &stamp);
// This is the method we use for extracting paths from the stamp file passed to us. See
fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
match term {
hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
- hir::Term::Const(c) => {
- let def_id = cx.tcx.hir().local_def_id(c.hir_id);
- Term::Constant(clean_middle_const(
- ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, def_id)),
- cx,
- ))
- }
+ hir::Term::Const(c) => Term::Constant(clean_middle_const(
+ ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, c.def_id)),
+ cx,
+ )),
}
}
generics: Option<&hir::Generics<'tcx>>,
param: &hir::GenericParam<'tcx>,
) -> GenericParamDef {
- let did = cx.tcx.hir().local_def_id(param.hir_id);
let (name, kind) = match param.kind {
hir::GenericParamKind::Lifetime { .. } => {
let outlives = if let Some(generics) = generics {
generics
- .outlives_for_param(did)
+ .outlives_for_param(param.def_id)
.filter(|bp| !bp.in_where_clause)
.flat_map(|bp| bp.bounds)
.map(|bound| match bound {
hir::GenericParamKind::Type { ref default, synthetic } => {
let bounds = if let Some(generics) = generics {
generics
- .bounds_for_param(did)
+ .bounds_for_param(param.def_id)
.filter(|bp| bp.origin != PredicateOrigin::WhereClause)
.flat_map(|bp| bp.bounds)
.filter_map(|x| clean_generic_bound(x, cx))
(
param.name.ident().name,
GenericParamDefKind::Type {
- did: did.to_def_id(),
+ did: param.def_id.to_def_id(),
bounds,
default: default.map(|t| clean_ty(t, cx)).map(Box::new),
synthetic,
hir::GenericParamKind::Const { ty, default } => (
param.name.ident().name,
GenericParamDefKind::Const {
- did: did.to_def_id(),
+ did: param.def_id.to_def_id(),
ty: Box::new(clean_ty(ty, cx)),
- default: default.map(|ct| {
- let def_id = cx.tcx.hir().local_def_id(ct.hir_id);
- Box::new(ty::Const::from_anon_const(cx.tcx, def_id).to_string())
- }),
+ default: default
+ .map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())),
},
),
};
_ => None,
});
if let Some(lt) = lifetime {
- let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let cleaned = if !lt.is_anonymous() {
clean_lifetime(lt, cx)
} else {
Lifetime::elided()
};
- substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned));
+ substs.insert(param.def_id.to_def_id(), SubstParam::Lifetime(cleaned));
}
indices.lifetimes += 1;
}
hir::GenericParamKind::Type { ref default, .. } => {
- let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let mut j = 0;
let type_ = generic_args.args.iter().find_map(|arg| match arg {
hir::GenericArg::Type(ty) => {
_ => None,
});
if let Some(ty) = type_ {
- substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(clean_ty(ty, cx)));
+ substs.insert(param.def_id.to_def_id(), SubstParam::Type(clean_ty(ty, cx)));
} else if let Some(default) = *default {
- substs.insert(
- ty_param_def_id.to_def_id(),
- SubstParam::Type(clean_ty(default, cx)),
- );
+ substs
+ .insert(param.def_id.to_def_id(), SubstParam::Type(clean_ty(default, cx)));
}
indices.types += 1;
}
hir::GenericParamKind::Const { .. } => {
- let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let mut j = 0;
let const_ = generic_args.args.iter().find_map(|arg| match arg {
hir::GenericArg::Const(ct) => {
});
if let Some(ct) = const_ {
substs.insert(
- const_param_def_id.to_def_id(),
+ param.def_id.to_def_id(),
SubstParam::Constant(clean_const(ct, cx)),
);
}
let length = match length {
hir::ArrayLen::Infer(_, _) => "_".to_string(),
hir::ArrayLen::Body(anon_const) => {
- let def_id = cx.tcx.hir().local_def_id(anon_const.hir_id);
// NOTE(min_const_generics): We can't use `const_eval_poly` for constants
// as we currently do not supply the parent generics to anonymous constants
// but do allow `ConstKind::Param`.
// `const_eval_poly` tries to first substitute generic parameters which
// results in an ICE while manually constructing the constant and using `eval`
// does nothing for `ConstKind::Param`.
- let ct = ty::Const::from_anon_const(cx.tcx, def_id);
- let param_env = cx.tcx.param_env(def_id);
+ let ct = ty::Const::from_anon_const(cx.tcx, anon_const.def_id);
+ let param_env = cx.tcx.param_env(anon_const.def_id);
print_const(cx, ct.eval(cx.tcx, param_env))
}
};
}
pub(crate) fn clean_field<'tcx>(field: &hir::FieldDef<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
- let def_id = cx.tcx.hir().local_def_id(field.hir_id).to_def_id();
- clean_field_with_def_id(def_id, field.ident.name, clean_ty(field.ty, cx), cx)
+ clean_field_with_def_id(field.def_id.to_def_id(), field.ident.name, clean_ty(field.ty, cx), cx)
}
pub(crate) fn clean_middle_field<'tcx>(field: &ty::FieldDef, cx: &mut DocContext<'tcx>) -> Item {
disr_expr: &Option<hir::AnonConst>,
cx: &mut DocContext<'tcx>,
) -> Variant {
- let discriminant = disr_expr.map(|disr| Discriminant {
- expr: Some(disr.body),
- value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(),
- });
+ let discriminant = disr_expr
+ .map(|disr| Discriminant { expr: Some(disr.body), value: disr.def_id.to_def_id() });
let kind = match variant {
hir::VariantData::Struct(..) => VariantKind::Struct(VariantStruct {
/// and returns [`ControlFlow::Break`].
pub(super) fn push(&mut self, text: &str) -> ControlFlow<(), ()> {
if self.len + text.len() > self.limit {
- return ControlFlow::BREAK;
+ return ControlFlow::Break(());
}
self.flush_queue();
write!(self.buf, "{}", Escape(text)).unwrap();
self.len += text.len();
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
/// Open an HTML tag.
buf.push("word#")?;
buf.push(&n.to_string())?;
buf.close_tag();
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
});
buf.close_tag();
assert_eq!(
Event::Start(tag) => match tag {
Tag::Emphasis => buf.open_tag("em"),
Tag::Strong => buf.open_tag("strong"),
- Tag::CodeBlock(..) => return ControlFlow::BREAK,
+ Tag::CodeBlock(..) => return ControlFlow::Break(()),
_ => {}
},
Event::End(tag) => match tag {
Tag::Emphasis | Tag::Strong => buf.close_tag(),
- Tag::Paragraph | Tag::Heading(..) => return ControlFlow::BREAK,
+ Tag::Paragraph | Tag::Heading(..) => return ControlFlow::Break(()),
_ => {}
},
Event::HardBreak | Event::SoftBreak => buf.push(" ")?,
_ => {}
};
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
});
(buf.finish(), stopped_early)
(function() {
let reset_button_timeout = null;
- window.copy_path = but => {
+ const but = document.getElementById("copy-path");
+ if (!but) {
+ return;
+ }
+ but.onclick = () => {
const parent = but.parentElement;
const path = [];
<a href="{{component.path|safe}}index.html">{{component.name}}</a>::<wbr>
{%- endfor -%}
<a class="{{item_type}}" href="#">{{name}}</a> {#- -#}
- <button id="copy-path" onclick="copy_path(this)" title="Copy item path to clipboard"> {#- -#}
+ <button id="copy-path" title="Copy item path to clipboard"> {#- -#}
<img src="{{static_root_path|safe}}{{clipboard_svg}}" {# -#}
width="19" height="18" {# -#}
alt="Copy item path"> {#- -#}
#![feature(array_methods)]
#![feature(assert_matches)]
#![feature(box_patterns)]
-#![feature(control_flow_enum)]
#![feature(drain_filter)]
#![feature(is_terminal)]
#![feature(let_chains)]
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
-use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, UnOp};
+use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::sym;
_: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
_: Span,
- _: HirId,
+ _: LocalDefId,
) {
NonminimalBoolVisitor { cx }.visit_body(body);
}
use core::ops::ControlFlow;
use rustc_ast::ast::Attribute;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId};
+use rustc_hir::{Body, Expr, ExprKind, FnDecl};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::{sym, BytePos};
decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
- let def_id = cx.tcx.hir().local_def_id(hir_id);
if !cx.tcx.has_attr(def_id.to_def_id(), sym::test) {
let expr = if is_async_fn(kind) {
match get_async_fn_body(cx.tcx, body) {
Node::Expr(parent) if parent.span.ctxt() == ctxt => match parent.kind {
ExprKind::Ret(_) => {
- let owner_id = cx.tcx.hir().body_owner(cx.enclosing_body.unwrap());
+ let owner_id = cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap());
Some(
if let Node::Expr(
closure_expr @ Expr {
kind: ExprKind::Closure(closure),
..
},
- ) = cx.tcx.hir().get(owner_id)
+ ) = cx.tcx.hir().get_by_def_id(owner_id)
{
closure_result_position(cx, closure, cx.typeck_results().expr_ty(closure_expr), precedence)
} else {
let output = cx
.tcx
- .erase_late_bound_regions(cx.tcx.fn_sig(cx.tcx.hir().local_def_id(owner_id)).subst_identity().output());
+ .erase_late_bound_regions(cx.tcx.fn_sig(owner_id).subst_identity().output());
ty_auto_deref_stability(cx, output, precedence).position_for_result(cx)
},
)
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor};
use rustc_hir::{
- self as hir, BlockCheckMode, BodyId, Constness, Expr, ExprKind, FnDecl, HirId, Impl, Item, ItemKind, UnsafeSource,
+ self as hir, BlockCheckMode, BodyId, Constness, Expr, ExprKind, FnDecl, Impl, Item, ItemKind, UnsafeSource,
Unsafety,
};
use rustc_lint::{LateContext, LateLintPass};
TraitPredicate, Ty, TyCtxt,
};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::sym;
impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
type NestedFilter = nested_filter::All;
- fn visit_fn(&mut self, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body_id: BodyId, _: Span, id: HirId) {
+ fn visit_fn(&mut self, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body_id: BodyId, _: Span, id: LocalDefId) {
if self.has_unsafe {
return;
}
use rustc_parse::parser::ForceCollect;
use rustc_session::parse::ParseSess;
use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::def_id::LocalDefId;
use rustc_span::edition::Edition;
use rustc_span::source_map::{BytePos, FilePathMapping, SourceMap, Span};
use rustc_span::{sym, FileName, Pos};
panic_span: None,
};
fpu.visit_expr(body.value);
- lint_for_missing_headers(cx, item.owner_id.def_id, sig, headers, Some(body_id), fpu.panic_span);
+ lint_for_missing_headers(cx, item.owner_id, sig, headers, Some(body_id), fpu.panic_span);
}
},
hir::ItemKind::Impl(impl_) => {
let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else { return };
if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
if !in_external_macro(cx.tcx.sess, item.span) {
- lint_for_missing_headers(cx, item.owner_id.def_id, sig, headers, None, None);
+ lint_for_missing_headers(cx, item.owner_id, sig, headers, None, None);
}
}
}
panic_span: None,
};
fpu.visit_expr(body.value);
- lint_for_missing_headers(cx, item.owner_id.def_id, sig, headers, Some(body_id), fpu.panic_span);
+ lint_for_missing_headers(cx, item.owner_id, sig, headers, Some(body_id), fpu.panic_span);
}
}
}
fn lint_for_missing_headers(
cx: &LateContext<'_>,
- def_id: LocalDefId,
+ owner_id: hir::OwnerId,
sig: &hir::FnSig<'_>,
headers: DocHeaders,
body_id: Option<hir::BodyId>,
panic_span: Option<Span>,
) {
- if !cx.effective_visibilities.is_exported(def_id) {
+ if !cx.effective_visibilities.is_exported(owner_id.def_id) {
return; // Private functions do not require doc comments
}
if cx
.tcx
.hir()
- .parent_iter(cx.tcx.hir().local_def_id_to_hir_id(def_id))
+ .parent_iter(owner_id.into())
.any(|(id, _node)| is_doc_hidden(cx.tcx.hir().attrs(id)))
{
return;
}
- let span = cx.tcx.def_span(def_id);
+ let span = cx.tcx.def_span(owner_id);
match (headers.safety, sig.header.unsafety) {
(false, hir::Unsafety::Unsafe) => span_lint(
cx,
);
}
if !headers.errors {
- let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
- if is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::Result) {
+ if is_type_diagnostic_item(cx, return_ty(cx, owner_id), sym::Result) {
span_lint(
cx,
MISSING_ERRORS_DOC,
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, TraitRef, Ty};
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::symbol::kw;
use rustc_target::spec::abi::Abi;
_: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
_: Span,
- hir_id: HirId,
+ fn_def_id: LocalDefId,
) {
if let Some(header) = fn_kind.header() {
if header.abi != Abi::Rust {
}
}
- let parent_id = cx.tcx.hir().get_parent_item(hir_id).def_id;
+ let parent_id = cx
+ .tcx
+ .hir()
+ .get_parent_item(cx.tcx.hir().local_def_id_to_hir_id(fn_def_id))
+ .def_id;
let parent_node = cx.tcx.hir().find_by_def_id(parent_id);
let mut trait_self_ty = None;
// find `self` ty for this trait if relevant
if let ItemKind::Trait(_, _, _, _, items) = item.kind {
for trait_item in items {
- if trait_item.id.hir_id() == hir_id {
+ if trait_item.id.owner_id.def_id == fn_def_id {
// be sure we have `self` parameter in this function
if trait_item.kind == (AssocItemKind::Fn { has_self: true }) {
trait_self_ty = Some(
too_large_for_stack: self.too_large_for_stack,
};
- let fn_def_id = cx.tcx.hir().local_def_id(hir_id);
let infcx = cx.tcx.infer_ctxt().build();
ExprUseVisitor::new(&mut v, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::{get_parent_as_impl, has_repr_attr, is_bool};
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, FnDecl, HirId, Item, ItemKind, TraitFn, TraitItem, TraitItemKind, Ty};
+use rustc_hir::{Body, FnDecl, Item, ItemKind, TraitFn, TraitItem, TraitItemKind, Ty};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
use rustc_target::spec::abi::Abi;
declare_clippy_lint! {
fn_decl: &'tcx FnDecl<'tcx>,
_: &'tcx Body<'tcx>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
if let Some(fn_header) = fn_kind.header()
&& fn_header.abi == Abi::Rust
&& get_parent_as_impl(cx.tcx, hir_id)
then {
let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind {
if v.fields().iter().any(|f| {
- let def_id = cx.tcx.hir().local_def_id(f.hir_id);
- !cx.tcx.visibility(def_id).is_public()
+ !cx.tcx.visibility(f.def_id).is_public()
}) {
// skip structs with private fields
return;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use rustc_errors::Applicability;
-use rustc_hir::{intravisit::FnKind, Body, ExprKind, FnDecl, HirId, ImplicitSelfKind, Unsafety};
+use rustc_hir::{intravisit::FnKind, Body, ExprKind, FnDecl, ImplicitSelfKind, Unsafety};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_span::Span;
decl: &FnDecl<'_>,
body: &Body<'_>,
span: Span,
- _hir_id: HirId,
) {
let FnKind::Method(ref ident, sig) = kind else {
return;
use rustc_hir::intravisit;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
declare_clippy_lint! {
decl: &'tcx hir::FnDecl<'_>,
body: &'tcx hir::Body<'_>,
span: Span,
- hir_id: hir::HirId,
+ def_id: LocalDefId,
) {
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
too_many_arguments::check_fn(cx, kind, decl, span, hir_id, self.too_many_arguments_threshold);
too_many_lines::check_fn(cx, kind, span, body, self.too_many_lines_threshold);
- not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, hir_id);
- misnamed_getters::check_fn(cx, kind, decl, body, span, hir_id);
+ not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, def_id);
+ misnamed_getters::check_fn(cx, kind, decl, body, span);
}
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
use rustc_ast::ast::Attribute;
use rustc_errors::Applicability;
-use rustc_hir::def_id::{DefIdSet, LocalDefId};
+use rustc_hir::def_id::DefIdSet;
use rustc_hir::{self as hir, def::Res, QPath};
use rustc_lint::{LateContext, LintContext};
use rustc_middle::{
let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
if let Some(attr) = attr {
- check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
+ check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
} else if is_public && !is_proc_macro(cx.sess(), attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) {
check_must_use_candidate(
cx,
sig.decl,
cx.tcx.hir().body(*body_id),
item.span,
- item.owner_id.def_id,
+ item.owner_id,
item.span.with_hi(sig.decl.output.span().hi()),
"this function could have a `#[must_use]` attribute",
);
let attrs = cx.tcx.hir().attrs(item.hir_id());
let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
if let Some(attr) = attr {
- check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
+ check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
} else if is_public
&& !is_proc_macro(cx.sess(), attrs)
&& trait_ref_of_method(cx, item.owner_id.def_id).is_none()
sig.decl,
cx.tcx.hir().body(*body_id),
item.span,
- item.owner_id.def_id,
+ item.owner_id,
item.span.with_hi(sig.decl.output.span().hi()),
"this method could have a `#[must_use]` attribute",
);
let attrs = cx.tcx.hir().attrs(item.hir_id());
let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
if let Some(attr) = attr {
- check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
+ check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
} else if let hir::TraitFn::Provided(eid) = *eid {
let body = cx.tcx.hir().body(eid);
if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) {
sig.decl,
body,
item.span,
- item.owner_id.def_id,
+ item.owner_id,
item.span.with_hi(sig.decl.output.span().hi()),
"this method could have a `#[must_use]` attribute",
);
fn check_needless_must_use(
cx: &LateContext<'_>,
decl: &hir::FnDecl<'_>,
- item_id: hir::HirId,
+ item_id: hir::OwnerId,
item_span: Span,
fn_header_span: Span,
attr: &Attribute,
decl: &'tcx hir::FnDecl<'_>,
body: &'tcx hir::Body<'_>,
item_span: Span,
- item_id: LocalDefId,
+ item_id: hir::OwnerId,
fn_span: Span,
msg: &str,
) {
|| mutates_static(cx, body)
|| in_external_macro(cx.sess(), item_span)
|| returns_unit(decl)
- || !cx.effective_visibilities.is_exported(item_id)
- || is_must_use_ty(cx, return_ty(cx, cx.tcx.hir().local_def_id_to_hir_id(item_id)))
+ || !cx.effective_visibilities.is_exported(item_id.def_id)
+ || is_must_use_ty(cx, return_ty(cx, item_id))
{
return;
}
kind: intravisit::FnKind<'tcx>,
decl: &'tcx hir::FnDecl<'tcx>,
body: &'tcx hir::Body<'tcx>,
- hir_id: hir::HirId,
+ def_id: LocalDefId,
) {
let unsafety = match kind {
intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }) => unsafety,
intravisit::FnKind::Closure => return,
};
- check_raw_ptr(cx, unsafety, decl, body, cx.tcx.hir().local_def_id(hir_id));
+ check_raw_ptr(cx, unsafety, decl, body, def_id)
}
pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::return_ty;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, FnDecl, HirId};
+use rustc_hir::{Body, FnDecl};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, AliasTy, Clause, EarlyBinder, PredicateKind};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span};
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
use rustc_trait_selection::traits::{self, FulfillmentError};
decl: &'tcx FnDecl<'tcx>,
_: &'tcx Body<'tcx>,
_: Span,
- hir_id: HirId,
+ fn_def_id: LocalDefId,
) {
if let FnKind::Closure = kind {
return;
}
- let ret_ty = return_ty(cx, hir_id);
+ let ret_ty = return_ty(cx, cx.tcx.hir().local_def_id_to_hir_id(fn_def_id).expect_owner());
if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() {
let preds = cx.tcx.explicit_item_bounds(def_id);
let mut is_future = false;
let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
let span = decl.output.span();
let infcx = cx.tcx.infer_ctxt().build();
- let def_id = cx.tcx.hir().local_def_id(hir_id);
- let cause = traits::ObligationCause::misc(span, def_id);
+ let cause = traits::ObligationCause::misc(span, fn_def_id);
let send_errors = traits::fully_solve_bound(&infcx, cause, cx.param_env, ret_ty, send_trait);
if !send_errors.is_empty() {
span_lint_and_then(
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::{Span, SyntaxContext};
declare_clippy_lint! {
decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
span: Span,
- _: HirId,
+ _: LocalDefId,
) {
if (!matches!(kind, FnKind::Closure) && matches!(decl.output, FnRetTy::DefaultReturn(_)))
|| span.ctxt() != body.value.span.ctxt()
if impl_item.generics.params.iter().all(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }));
// Check if return type is String
- if is_type_lang_item(cx, return_ty(cx, impl_item.hir_id()), LangItem::String);
+ if is_type_lang_item(cx, return_ty(cx, impl_item.owner_id), LangItem::String);
// Filters instances of to_string which are required by a trait
if trait_ref_of_method(cx, impl_item.owner_id.def_id).is_none();
#![feature(array_windows)]
#![feature(binary_heap_into_iter_sorted)]
#![feature(box_patterns)]
-#![feature(control_flow_enum)]
#![feature(drain_filter)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter as middle_nested_filter;
-use rustc_middle::ty::TyCtxt;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
.filter(|param| matches!(param.kind, GenericParamKind::Type { .. }));
for typ in types {
- for pred in generics.bounds_for_param(cx.tcx.hir().local_def_id(typ.hir_id)) {
+ for pred in generics.bounds_for_param(typ.def_id) {
if pred.origin == PredicateOrigin::WhereClause {
// has_where_lifetimes checked that this predicate contains no lifetime.
continue;
// level of the current item.
// check named LTs
- let allowed_lts = allowed_lts_from(cx.tcx, named_generics);
+ let allowed_lts = allowed_lts_from(named_generics);
// these will collect all the lifetimes for references in arg/return types
let mut input_visitor = RefVisitor::new(cx);
}
}
-fn allowed_lts_from(tcx: TyCtxt<'_>, named_generics: &[GenericParam<'_>]) -> FxHashSet<RefLt> {
+fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<RefLt> {
let mut allowed_lts = FxHashSet::default();
for par in named_generics.iter() {
if let GenericParamKind::Lifetime { .. } = par.kind {
- allowed_lts.insert(RefLt::Named(tcx.hir().local_def_id(par.hir_id)));
+ allowed_lts.insert(RefLt::Named(par.def_id));
}
}
allowed_lts.insert(RefLt::Unnamed);
return true;
}
// if the bounds define new lifetimes, they are fine to occur
- let allowed_lts = allowed_lts_from(cx.tcx, pred.bound_generic_params);
+ let allowed_lts = allowed_lts_from(pred.bound_generic_params);
// now walk the bounds
for bound in pred.bounds.iter() {
walk_param_bound(&mut visitor, bound);
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
AsyncGeneratorKind, Block, Body, Closure, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound,
- HirId, ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind,
+ ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span};
declare_clippy_lint! {
decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
span: Span,
- _: HirId,
+ _: LocalDefId,
) {
if_chain! {
if let Some(header) = kind.header();
&& def.variants.len() > 1
{
let mut iter = def.variants.iter().filter_map(|v| {
- let id = cx.tcx.hir().local_def_id(v.hir_id);
- (matches!(v.data, hir::VariantData::Unit(..))
+ (matches!(v.data, hir::VariantData::Unit(_, _))
&& v.ident.as_str().starts_with('_')
&& is_doc_hidden(cx.tcx.hir().attrs(v.hir_id)))
- .then_some((id, v.span))
+ .then_some((v.def_id, v.span))
});
if let Some((id, span)) = iter.next()
&& iter.next().is_none()
from_args.push_front(from);
ControlFlow::Continue(())
} else {
- ControlFlow::BREAK
+ ControlFlow::Break(())
}
} else {
ControlFlow::Continue(())
}
if let hir::ImplItemKind::Fn(_, _) = impl_item.kind {
- let ret_ty = return_ty(cx, impl_item.hir_id());
+ let ret_ty = return_ty(cx, impl_item.owner_id);
if contains_ty_adt_constructor_opaque(cx, ret_ty, self_ty) {
return;
if_chain! {
if item.ident.name == sym::new;
if let TraitItemKind::Fn(_, _) = item.kind;
- let ret_ty = return_ty(cx, item.hir_id());
+ let ret_ty = return_ty(cx, item.owner_id);
let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id())
.self_ty()
.skip_binder();
pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, count_recv: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) {
if_chain! {
if is_trait_method(cx, count_recv, sym::Iterator);
- let closure = expr_or_init(cx, map_arg);
- if let Some(def_id) = cx.tcx.hir().opt_local_def_id(closure.hir_id);
- if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(def_id);
- let closure_body = cx.tcx.hir().body(body_id);
+ if let hir::ExprKind::Closure(closure) = expr_or_init(cx, map_arg).kind;
+ let closure_body = cx.tcx.hir().body(closure.body);
if !cx.typeck_results().expr_ty(closure_body.value).is_unit();
then {
if let Some(map_mutated_vars) = mutated_variables(closure_body.value, cx) {
Node::Block(..) => continue,
Node::Item(item) => {
if let ItemKind::Fn(_, _, body_id) = &item.kind
- && let output_ty = return_ty(cx, item.hir_id())
- && let local_def_id = cx.tcx.hir().local_def_id(item.hir_id())
- && Inherited::build(cx.tcx, local_def_id).enter(|inherited| {
- let fn_ctxt = FnCtxt::new(inherited, cx.param_env, local_def_id);
+ && let output_ty = return_ty(cx, item.owner_id)
+ && Inherited::build(cx.tcx, item.owner_id.def_id).enter(|inherited| {
+ let fn_ctxt = FnCtxt::new(inherited, cx.param_env, item.owner_id.def_id);
fn_ctxt.can_coerce(ty, output_ty)
}) {
if has_lifetime(output_ty) && has_lifetime(ty) {
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
- self as hir, def, BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind,
- Stmt, StmtKind, TyKind,
+ self as hir, def, BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, Mutability, PatKind, Stmt,
+ StmtKind, TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::{ExpnKind, Span};
decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
span: Span,
- _: HirId,
+ _: LocalDefId,
) {
if let FnKind::Closure = k {
// Does not apply to closures
use rustc_hir as hir;
use rustc_hir::def_id::CRATE_DEF_ID;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId};
+use rustc_hir::{Body, Constness, FnDecl, GenericParamKind};
use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
declare_clippy_lint! {
_: &FnDecl<'_>,
body: &Body<'tcx>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
if !self.msrv.meets(msrvs::CONST_IF_MATCH) {
return;
}
- let def_id = cx.tcx.hir().local_def_id(hir_id);
-
if in_external_macro(cx.tcx.sess, span) || is_entrypoint_fn(cx, def_id.to_def_id()) {
return;
}
FnKind::Closure => return,
}
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
+
// Const fns are not allowed as methods in a trait.
{
let parent = cx.tcx.hir().get_parent_item(hir_id).def_id;
use rustc_middle::ty::TypeVisitable;
use rustc_middle::ty::{Adt, Array, Ref, Slice, Tuple, Ty};
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::symbol::sym;
use std::iter;
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
if let hir::ItemKind::Fn(ref sig, ..) = item.kind {
- self.check_sig(cx, item.hir_id(), sig.decl);
+ self.check_sig(cx, item.owner_id.def_id, sig.decl);
}
}
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) {
if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind {
if trait_ref_of_method(cx, item.owner_id.def_id).is_none() {
- self.check_sig(cx, item.hir_id(), sig.decl);
+ self.check_sig(cx, item.owner_id.def_id, sig.decl);
}
}
}
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'tcx>) {
if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
- self.check_sig(cx, item.hir_id(), sig.decl);
+ self.check_sig(cx, item.owner_id.def_id, sig.decl);
}
}
}
}
- fn check_sig(&self, cx: &LateContext<'_>, item_hir_id: hir::HirId, decl: &hir::FnDecl<'_>) {
- let fn_def_id = cx.tcx.hir().local_def_id(item_hir_id);
+ fn check_sig(&self, cx: &LateContext<'_>, fn_def_id: LocalDefId, decl: &hir::FnDecl<'_>) {
let fn_sig = cx.tcx.fn_sig(fn_def_id).subst_identity();
for (hir_ty, ty) in iter::zip(decl.inputs, fn_sig.inputs().skip_binder()) {
self.check_ty_(cx, hir_ty.span, *ty);
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::{self, TypeVisitable};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::kw;
use rustc_span::{sym, Span};
use rustc_target::spec::abi::Abi;
decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
span: Span,
- hir_id: HirId,
+ fn_def_id: LocalDefId,
) {
if span.from_expansion() {
return;
}
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
+
match kind {
FnKind::ItemFn(.., header) => {
let attrs = cx.tcx.hir().attrs(hir_id);
let sized_trait = need!(cx.tcx.lang_items().sized_trait());
- let fn_def_id = cx.tcx.hir().local_def_id(hir_id);
-
let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds().iter())
.filter(|p| !p.is_global())
.filter_map(|obligation| {
}
if let hir::ImplItemKind::Fn(ref sig, _) = impl_item.kind {
let name = impl_item.ident.name;
- let id = impl_item.hir_id();
+ let id = impl_item.owner_id;
if sig.header.constness == hir::Constness::Const {
// can't be implemented by default
return;
if sig.decl.inputs.is_empty();
if name == sym::new;
if cx.effective_visibilities.is_reachable(impl_item.owner_id.def_id);
- let self_def_id = cx.tcx.hir().get_parent_item(id);
+ let self_def_id = cx.tcx.hir().get_parent_item(id.into());
let self_ty = cx.tcx.type_of(self_def_id);
if self_ty == return_ty(cx, id);
if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default);
span_lint_hir_and_then(
cx,
NEW_WITHOUT_DEFAULT,
- id,
+ id.into(),
impl_item.span,
&format!(
"you should consider adding a `Default` implementation for `{self_type_snip}`"
fn check_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
let body_owner = cx.tcx.hir().body_owner(body.id());
- let body_owner_def_id = cx.tcx.hir().local_def_id(body_owner);
+ let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id());
+
let body_owner_kind = cx.tcx.hir().body_owner_kind(body_owner_def_id);
if let hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) = body_owner_kind {
let body_span = cx.tcx.hir().span_with_body(body_owner);
pub fn enter_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
let body_owner = cx.tcx.hir().body_owner(body.id());
- let body_owner_def_id = cx.tcx.hir().local_def_id(body_owner);
+ let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id());
match cx.tcx.hir().body_owner_kind(body_owner_def_id) {
hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const => {
use rustc_hir::intravisit::FnKind;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span};
declare_clippy_lint! {
_: &'tcx hir::FnDecl<'tcx>,
body: &'tcx hir::Body<'tcx>,
span: Span,
- hir_id: hir::HirId,
+ def_id: LocalDefId,
) {
- if !matches!(fn_kind, FnKind::Closure) && is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::Result) {
+ if matches!(fn_kind, FnKind::Closure) {
+ return;
+ }
+ let owner = cx.tcx.hir().local_def_id_to_hir_id(def_id).expect_owner();
+ if is_type_diagnostic_item(cx, return_ty(cx, owner), sym::Result) {
lint_impl_body(cx, span, body);
}
}
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{BindingAnnotation, Body, FnDecl, HirId, Impl, ItemKind, MutTy, Mutability, Node, PatKind};
+use rustc_hir::{BindingAnnotation, Body, FnDecl, Impl, ItemKind, MutTy, Mutability, Node, PatKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::adjustment::{Adjust, PointerCast};
use rustc_middle::ty::layout::LayoutOf;
decl: &'tcx FnDecl<'_>,
_body: &'tcx Body<'_>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
if span.from_expansion() {
return;
}
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
match kind {
FnKind::ItemFn(.., header) => {
if header.abi != Abi::Rust {
}
}
- self.check_poly_fn(cx, cx.tcx.hir().local_def_id(hir_id), decl, Some(span));
+ self.check_poly_fn(cx, def_id, decl, Some(span));
}
}
use clippy_utils::diagnostics::span_lint_and_help;
-use rustc_hir::{
- intravisit, Body, Expr, ExprKind, FnDecl, HirId, Let, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind,
-};
+use rustc_hir::{intravisit, Body, Expr, ExprKind, FnDecl, Let, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
declare_clippy_lint! {
_: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
_: Span,
- _: HirId,
+ _: LocalDefId,
) {
for param in body.params {
apply_lint(cx, param.pat, DerefPossible::Impossible);
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{def_id, Body, FnDecl, HirId, LangItem};
+use rustc_hir::{def_id, Body, FnDecl, LangItem};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::{BytePos, Span};
use rustc_span::sym;
cx: &LateContext<'tcx>,
_: FnKind<'tcx>,
_: &'tcx FnDecl<'_>,
- body: &'tcx Body<'_>,
+ _: &'tcx Body<'_>,
_: Span,
- _: HirId,
+ def_id: LocalDefId,
) {
- let def_id = cx.tcx.hir().body_owner_def_id(body.id());
-
// Building MIR for `fn`s with unsatisfiable preds results in ICE.
if fn_has_unsatisfiable_preds(cx, def_id.to_def_id()) {
return;
use clippy_utils::{nth_arg, return_ty};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, FnDecl, HirId, TraitItem, TraitItemKind};
+use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_lint_pass!(ReturnSelfNotMustUse => [RETURN_SELF_NOT_MUST_USE]);
-fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, span: Span, hir_id: HirId) {
+fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, span: Span, owner_id: OwnerId) {
if_chain! {
// If it comes from an external macro, better ignore it.
if !in_external_macro(cx.sess(), span);
// We only show this warning for public exported methods.
if cx.effective_visibilities.is_exported(fn_def);
// We don't want to emit this lint if the `#[must_use]` attribute is already there.
- if !cx.tcx.hir().attrs(hir_id).iter().any(|attr| attr.has_name(sym::must_use));
+ if !cx.tcx.hir().attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use));
if cx.tcx.visibility(fn_def.to_def_id()).is_public();
- let ret_ty = return_ty(cx, hir_id);
- let self_arg = nth_arg(cx, hir_id, 0);
+ let ret_ty = return_ty(cx, owner_id.into());
+ let self_arg = nth_arg(cx, owner_id.into(), 0);
// If `Self` has the same type as the returned type, then we want to warn.
//
// For this check, we don't want to remove the reference on the returned type because if
decl: &'tcx FnDecl<'tcx>,
_: &'tcx Body<'tcx>,
span: Span,
- hir_id: HirId,
+ fn_def: LocalDefId,
) {
if_chain! {
// We are only interested in methods, not in functions or associated functions.
if matches!(kind, FnKind::Method(_, _));
- if let Some(fn_def) = cx.tcx.hir().opt_local_def_id(hir_id);
if let Some(impl_def) = cx.tcx.impl_of_method(fn_def.to_def_id());
// We don't want this method to be te implementation of a trait because the
// `#[must_use]` should be put on the trait definition directly.
if cx.tcx.trait_id_of_impl(impl_def).is_none();
then {
- check_method(cx, decl, fn_def, span, hir_id);
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(fn_def);
+ check_method(cx, decl, fn_def, span, hir_id.expect_owner());
}
}
}
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'tcx>) {
if let TraitItemKind::Fn(ref sig, _) = item.kind {
- check_method(cx, sig.decl, item.owner_id.def_id, item.span, item.hir_id());
+ check_method(cx, sig.decl, item.owner_id.def_id, item.span, item.owner_id);
}
}
}
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, LangItem, MatchSource, PatKind, QPath, StmtKind};
+use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, LangItem, MatchSource, PatKind, QPath, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::{BytePos, Pos};
_: &'tcx FnDecl<'tcx>,
body: &'tcx Body<'tcx>,
sp: Span,
- _: HirId,
+ _: LocalDefId,
) {
match kind {
FnKind::Closure => {
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
let item = cx.tcx.hir().expect_item(parent);
let self_ty = cx.tcx.type_of(item.owner_id);
- let ret_ty = return_ty(cx, impl_item.hir_id());
+ let ret_ty = return_ty(cx, impl_item.owner_id);
// Do not check trait impls
if matches!(item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. })) {
if let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind;
// Then check if that that array zero-sized
- let length_ldid = cx.tcx.hir().local_def_id(length.hir_id);
- let length = Const::from_anon_const(cx.tcx, length_ldid);
+ let length = Const::from_anon_const(cx.tcx, length.def_id);
let length = length.try_eval_usize(cx.tcx, cx.param_env);
if let Some(length) = length;
then {
use rustc_hir as hir;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
- Body, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, Local, MutTy, QPath, TraitItem,
+ Body, FnDecl, FnRetTy, GenericArg, ImplItem, ImplItemKind, Item, ItemKind, Local, MutTy, QPath, TraitItem,
TraitItemKind, TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
declare_clippy_lint! {
impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, RC_MUTEX, TYPE_COMPLEXITY]);
impl<'tcx> LateLintPass<'tcx> for Types {
- fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) {
- let is_in_trait_impl =
- if let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(id).def_id) {
- matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
- } else {
- false
- };
+ fn check_fn(
+ &mut self,
+ cx: &LateContext<'_>,
+ _: FnKind<'_>,
+ decl: &FnDecl<'_>,
+ _: &Body<'_>,
+ _: Span,
+ def_id: LocalDefId,
+ ) {
+ let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id(
+ cx.tcx
+ .hir()
+ .get_parent_item(cx.tcx.hir().local_def_id_to_hir_id(def_id))
+ .def_id,
+ ) {
+ matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
+ } else {
+ false
+ };
- let is_exported = cx.effective_visibilities.is_exported(cx.tcx.hir().local_def_id(id));
+ let is_exported = cx.effective_visibilities.is_exported(def_id);
self.check_fn_decl(
cx,
fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
let is_exported = cx
.effective_visibilities
- .is_exported(cx.tcx.hir().local_def_id(field.hir_id));
+ .is_exported(field.def_id);
self.check_ty(
cx,
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::LangItem::{OptionSome, ResultOk};
-use rustc_hir::{Body, ExprKind, FnDecl, HirId, Impl, ItemKind, Node};
+use rustc_hir::{Body, ExprKind, FnDecl, Impl, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::sym;
use rustc_span::Span;
fn_decl: &FnDecl<'tcx>,
body: &Body<'tcx>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
// Abort if public function/method or closure.
match fn_kind {
FnKind::ItemFn(..) | FnKind::Method(..) => {
- let def_id = cx.tcx.hir().local_def_id(hir_id);
if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) {
return;
}
}
// Abort if the method is implementing a trait or of it a trait method.
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
if matches!(
item.kind,
}
// Get the wrapper and inner types, if can't, abort.
- let (return_type_label, lang_item, inner_type) = if let ty::Adt(adt_def, subst) = return_ty(cx, hir_id).kind() {
- if cx.tcx.is_diagnostic_item(sym::Option, adt_def.did()) {
- ("Option", OptionSome, subst.type_at(0))
- } else if cx.tcx.is_diagnostic_item(sym::Result, adt_def.did()) {
- ("Result", ResultOk, subst.type_at(0))
+ let (return_type_label, lang_item, inner_type) =
+ if let ty::Adt(adt_def, subst) = return_ty(cx, hir_id.expect_owner()).kind() {
+ if cx.tcx.is_diagnostic_item(sym::Option, adt_def.did()) {
+ ("Option", OptionSome, subst.type_at(0))
+ } else if cx.tcx.is_diagnostic_item(sym::Result, adt_def.did()) {
+ ("Result", ResultOk, subst.type_at(0))
+ } else {
+ return;
+ }
} else {
return;
- }
- } else {
- return;
- };
+ };
// Check if all return expression respect the following condition and collect them.
let mut suggs = Vec::new();
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
-use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, YieldSource};
+use rustc_hir::{Body, Expr, ExprKind, FnDecl, YieldSource};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
declare_clippy_lint! {
fn_decl: &'tcx FnDecl<'tcx>,
body: &Body<'tcx>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
if !span.from_expansion() && fn_kind.asyncness().is_async() {
let mut visitor = AsyncFnVisitor { cx, found_await: false };
- walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), hir_id);
+ walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), def_id);
if !visitor.found_await {
span_lint_and_help(
cx,
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::Ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::sym;
decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
span: Span,
- fn_id: HirId,
+ fn_id: LocalDefId,
) {
if span.from_expansion() {
return;
// first check if it's a method or function
if let hir::ImplItemKind::Fn(ref _signature, _) = impl_item.kind;
// checking if its return type is `result` or `option`
- if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::Result)
- || is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::Option);
+ if is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Result)
+ || is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Option);
then {
lint_impl_body(cx, impl_item.span, impl_item);
}
#![feature(array_chunks)]
#![feature(box_patterns)]
-#![feature(control_flow_enum)]
#![feature(let_chains)]
#![feature(lint_reasons)]
#![feature(never_type)]
self.captures.entry(l).and_modify(|e| *e |= cap).or_insert(cap);
}
},
- ExprKind::Closure { .. } => {
- let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id);
- for capture in self.cx.typeck_results().closure_min_captures_flattened(closure_id) {
+ ExprKind::Closure(closure) => {
+ for capture in self.cx.typeck_results().closure_min_captures_flattened(closure.def_id) {
let local_id = match capture.place.base {
PlaceBase::Local(id) => id,
PlaceBase::Upvar(var) => var.var_path.hir_id,
}
/// Convenience function to get the return type of a function.
-pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx> {
- let fn_def_id = cx.tcx.hir().local_def_id(fn_item);
+pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_def_id: hir::OwnerId) -> Ty<'tcx> {
let ret_ty = cx.tcx.fn_sig(fn_def_id).subst_identity().output();
cx.tcx.erase_late_bound_regions(ret_ty)
}
/// Convenience function to get the nth argument type of a function.
-pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId, nth: usize) -> Ty<'tcx> {
- let fn_def_id = cx.tcx.hir().local_def_id(fn_item);
+pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_def_id: hir::OwnerId, nth: usize) -> Ty<'tcx> {
let arg = cx.tcx.fn_sig(fn_def_id).subst_identity().input(nth);
cx.tcx.erase_late_bound_regions(arg)
}
} else {
match cx.tcx.item_name(macro_call.def_id) {
// `cfg!(debug_assertions)` in `debug_assert!`
- sym::cfg => ControlFlow::CONTINUE,
+ sym::cfg => ControlFlow::Continue(()),
// assert!(other_macro!(..))
_ => ControlFlow::Break(true),
}
type BreakTy = ();
fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<Self::BreakTy> {
- ControlFlow::BREAK
+ ControlFlow::Break(())
}
}
///
/// note: this only works on single line immutable closures with exactly one input parameter.
pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Option<DerefClosure> {
- if let hir::ExprKind::Closure(&Closure { fn_decl, body, .. }) = closure.kind {
+ if let hir::ExprKind::Closure(&Closure { fn_decl, def_id, body, .. }) = closure.kind {
let closure_body = cx.tcx.hir().body(body);
// is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`)
// a type annotation is present if param `kind` is different from `TyKind::Infer`
applicability: Applicability::MachineApplicable,
};
- let fn_def_id = cx.tcx.hir().local_def_id(closure.hir_id);
let infcx = cx.tcx.infer_ctxt().build();
- ExprUseVisitor::new(&mut visitor, &infcx, fn_def_id, cx.param_env, cx.typeck_results())
- .consume_body(closure_body);
+ ExprUseVisitor::new(&mut visitor, &infcx, def_id, cx.param_env, cx.typeck_results()).consume_body(closure_body);
if !visitor.suggestion_start.is_empty() {
return Some(DerefClosure {
use rustc_hir::intravisit;
use rustc_hir::Node;
use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map;
#[no_mangle]
_: &'tcx hir::FnDecl,
_: &'tcx hir::Body,
span: source_map::Span,
- id: hir::HirId,
+ def_id: LocalDefId,
) {
+ let id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
let item = match cx.tcx.hir().get(id) {
Node::Item(item) => item,
_ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id).def_id),
--- /dev/null
+missing_message_ref = {message}
use self::fluent_generated::{DEFAULT_LOCALE_RESOURCES, test_crate_foo, with_hyphens};
}
+
+mod missing_message_ref {
+ use super::fluent_messages;
+
+ fluent_messages! {
+ missing => "./missing-message-ref.ftl"
+//~^ ERROR referenced message `message` does not exist
+ }
+}
|
= help: replace any '-'s with '_'s
-error: aborting due to 10 previous errors
+error: referenced message `message` does not exist (in message `missing_message_ref`)
+ --> $DIR/test.rs:104:20
+ |
+LL | missing => "./missing-message-ref.ftl"
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: you may have meant to use a variable reference (`{$message}`)
+
+error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0428`.
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_tag = ::core::intrinsics::discriminant_value(self);
let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- match ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag) {
- ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
- match (self, other) {
- (Mixed::R(__self_0), Mixed::R(__arg1_0)) =>
- ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
- (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S {
- d1: __arg1_0, d2: __arg1_1 }) =>
- match ::core::cmp::PartialOrd::partial_cmp(__self_0,
- __arg1_0) {
- ::core::option::Option::Some(::core::cmp::Ordering::Equal)
- => ::core::cmp::PartialOrd::partial_cmp(__self_1, __arg1_1),
- cmp => cmp,
- },
- _ =>
- ::core::option::Option::Some(::core::cmp::Ordering::Equal),
+ match (self, other) {
+ (Mixed::R(__self_0), Mixed::R(__arg1_0)) =>
+ ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+ (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S {
+ d1: __arg1_0, d2: __arg1_1 }) =>
+ match ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0)
+ {
+ ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+ => ::core::cmp::PartialOrd::partial_cmp(__self_1, __arg1_1),
+ cmp => cmp,
},
- cmp => cmp,
+ _ =>
+ ::core::cmp::PartialOrd::partial_cmp(&__self_tag,
+ &__arg1_tag),
}
}
}
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_tag = ::core::intrinsics::discriminant_value(self);
let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- match ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag) {
- ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
- match (self, other) {
- (Fielded::X(__self_0), Fielded::X(__arg1_0)) =>
- ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
- (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) =>
- ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
- (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) =>
- ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
- _ => unsafe { ::core::intrinsics::unreachable() }
- },
- cmp => cmp,
+ match (self, other) {
+ (Fielded::X(__self_0), Fielded::X(__arg1_0)) =>
+ ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+ (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) =>
+ ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+ (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) =>
+ ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+ _ =>
+ ::core::cmp::PartialOrd::partial_cmp(&__self_tag,
+ &__arg1_tag),
}
}
}
--- /dev/null
+// build-pass
+// compile-flags: --crate-type=lib
+#![feature(custom_mir, core_intrinsics)]
+use std::intrinsics::mir::*;
+
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub fn f(a: u32) -> u32 {
+ mir!(
+ let x: u32;
+ {
+ // Previously code generation failed with ICE "use of .. before def ..." because the
+ // definition of x was incorrectly identified as dominating the use of x located in the
+ // same statement:
+ x = x + a;
+ RET = x;
+ Return()
+ }
+ )
+}
--- /dev/null
+#![feature(let_chains)]
+trait Demo {}
+
+impl dyn Demo {
+ pub fn report(&self) -> u32 {
+ let sum = |a: u32,
+ b: u32,
+ c: u32| {
+ a + b + c
+ };
+ sum(1, 2, 3)
+ }
+
+ fn check(&self, val: Option<u32>, num: Option<u32>) {
+ if let Some(b) = val
+ && let Some(c) = num {
+ && b == c {
+ //~^ ERROR expected struct
+ //~| ERROR mismatched types
+ }
+ }
+}
+
+fn main() { } //~ ERROR this file contains an unclosed delimiter
--- /dev/null
+error: this file contains an unclosed delimiter
+ --> $DIR/deli-ident-issue-1.rs:24:66
+ |
+LL | impl dyn Demo {
+ | - unclosed delimiter
+...
+LL | && let Some(c) = num {
+ | - this delimiter might not be properly closed...
+...
+LL | }
+ | - ...as it matches this but it has different indentation
+...
+LL | fn main() { }
+ | ^
+
+error[E0574]: expected struct, variant or union type, found local variable `c`
+ --> $DIR/deli-ident-issue-1.rs:17:17
+ |
+LL | && b == c {
+ | ^ not a struct, variant or union type
+
+error[E0308]: mismatched types
+ --> $DIR/deli-ident-issue-1.rs:17:9
+ |
+LL | fn check(&self, val: Option<u32>, num: Option<u32>) {
+ | - expected `()` because of default return type
+...
+LL | / && b == c {
+LL | |
+LL | |
+LL | | }
+ | |_________^ expected `()`, found `bool`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0574.
+For more information about an error, try `rustc --explain E0308`.
--- /dev/null
+fn main() {
+ if 1 < 2 {
+ let _a = vec!]; //~ ERROR mismatched closing delimiter
+ }
+} //~ ERROR unexpected closing delimiter
+
+fn main() {}
--- /dev/null
+error: unexpected closing delimiter: `}`
+ --> $DIR/deli-ident-issue-2.rs:5:1
+ |
+LL | let _a = vec!];
+ | - missing open `[` for this delimiter
+LL | }
+LL | }
+ | ^ unexpected closing delimiter
+
+error: mismatched closing delimiter: `]`
+ --> $DIR/deli-ident-issue-2.rs:2:14
+ |
+LL | if 1 < 2 {
+ | ^ unclosed delimiter
+LL | let _a = vec!];
+ | ^ mismatched closing delimiter
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// This file has unexpected closing delimiter,
+
+fn func(o: Option<u32>) {
+ match o {
+ Some(_x) => {} // Extra '}'
+ let _ = if true {};
+ }
+ None => {}
+ }
+} //~ ERROR unexpected closing delimiter
+
+fn main() {}
--- /dev/null
+error: unexpected closing delimiter: `}`
+ --> $DIR/issue-68987-unmatch-issue-1.rs:10:1
+ |
+LL | match o {
+ | - this delimiter might not be properly closed...
+LL | Some(_x) => {} // Extra '}'
+ | -- block is empty, you might have not meant to close it
+LL | let _ = if true {};
+LL | }
+ | - ...as it matches this but it has different indentation
+...
+LL | }
+ | ^ unexpected closing delimiter
+
+error: aborting due to previous error
+
--- /dev/null
+// FIXME: this case need more work to fix
+// currently the TokenTree matching ')' with '{', which is not user friendly for diagnostics
+async fn obstest() -> Result<> {
+ let obs_connect = || -> Result<(), MyError) { //~ ERROR mismatched closing delimiter
+ async {
+ }
+ }
+
+ if let Ok(version, scene_list) = obs_connect() {
+
+ } else {
+
+ }
+} //~ ERROR unexpected closing delimiter
--- /dev/null
+error: unexpected closing delimiter: `}`
+ --> $DIR/issue-68987-unmatch-issue-2.rs:14:1
+ |
+LL | let obs_connect = || -> Result<(), MyError) {
+ | - missing open `(` for this delimiter
+...
+LL | }
+ | ^ unexpected closing delimiter
+
+error: mismatched closing delimiter: `)`
+ --> $DIR/issue-68987-unmatch-issue-2.rs:3:32
+ |
+LL | async fn obstest() -> Result<> {
+ | ^ unclosed delimiter
+LL | let obs_connect = || -> Result<(), MyError) {
+ | ^ mismatched closing delimiter
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// the `{` is closed with `)`, there is a missing `(`
+fn f(i: u32, j: u32) {
+ let res = String::new();
+ let mut cnt = i;
+ while cnt < j {
+ write!&mut res, " "); //~ ERROR mismatched closing delimiter
+ }
+} //~ ERROR unexpected closing delimiter
--- /dev/null
+error: unexpected closing delimiter: `}`
+ --> $DIR/issue-68987-unmatch-issue-3.rs:8:1
+ |
+LL | write!&mut res, " ");
+ | - missing open `(` for this delimiter
+LL | }
+LL | }
+ | ^ unexpected closing delimiter
+
+error: mismatched closing delimiter: `)`
+ --> $DIR/issue-68987-unmatch-issue-3.rs:5:19
+ |
+LL | while cnt < j {
+ | ^ unclosed delimiter
+LL | write!&mut res, " ");
+ | ^ mismatched closing delimiter
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// This file has unexpected closing delimiter,
+
+fn func(o: Option<u32>) {
+ match o {
+ Some(_x) => // Missing '{'
+ let _ = if true {};
+ }
+ None => {}
+ }
+} //~ ERROR unexpected closing delimiter
+
+fn main() {}
--- /dev/null
+error: unexpected closing delimiter: `}`
+ --> $DIR/issue-68987-unmatch-issue.rs:10:1
+ |
+LL | match o {
+ | - this delimiter might not be properly closed...
+LL | Some(_x) => // Missing '{'
+LL | let _ = if true {};
+ | -- block is empty, you might have not meant to close it
+LL | }
+ | - ...as it matches this but it has different indentation
+...
+LL | }
+ | ^ unexpected closing delimiter
+
+error: aborting due to previous error
+
--> $DIR/issue-81827.rs:11:27
|
LL | fn r()->i{0|{#[cfg(r(0{]0
- | - - ^
- | | |
+ | - - - ^
+ | | | |
+ | | | missing open `[` for this delimiter
| | unclosed delimiter
| unclosed delimiter
--> $DIR/issue-81827.rs:11:27
|
LL | fn r()->i{0|{#[cfg(r(0{]0
- | - - ^
- | | |
+ | - - - ^
+ | | | |
+ | | | missing open `[` for this delimiter
| | unclosed delimiter
| unclosed delimiter
--> $DIR/issue-62973.rs:8:2
|
LL | fn p() { match s { v, E { [) {) }
- | - - unclosed delimiter
- | |
+ | - - - - missing open `(` for this delimiter
+ | | | |
+ | | | missing open `(` for this delimiter
+ | | unclosed delimiter
| unclosed delimiter
LL |
LL |
--> $DIR/issue-62973.rs:8:2
|
LL | fn p() { match s { v, E { [) {) }
- | - - unclosed delimiter
- | |
+ | - - - - missing open `(` for this delimiter
+ | | | |
+ | | | missing open `(` for this delimiter
+ | | unclosed delimiter
| unclosed delimiter
LL |
LL |
--> $DIR/issue-63116.rs:3:18
|
LL | impl W <s(f;Y(;]
- | - ^
- | |
+ | - - ^
+ | | |
+ | | missing open `[` for this delimiter
| unclosed delimiter
error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `;`
--- /dev/null
+fn main() {}
+
+fn f) {} //~ ERROR unexpected closing delimiter
--- /dev/null
+error: unexpected closing delimiter: `)`
+ --> $DIR/issue-69259.rs:3:5
+ |
+LL | fn f) {}
+ | ^ unexpected closing delimiter
+
+error: aborting due to previous error
+
--> $DIR/issue-70583-block-is-empty-1.rs:20:1
|
LL | fn struct_generic(x: Vec<i32>) {
- | - this opening brace...
+ | - this delimiter might not be properly closed...
...
LL | }
- | - ...matches this closing brace
+ | - ...as it matches this but it has different indentation
LL | }
| ^ unexpected closing delimiter
error: unexpected closing delimiter: `}`
--> $DIR/issue-70583-block-is-empty-2.rs:14:1
|
+LL | match self {
+ | - this delimiter might not be properly closed...
LL | ErrorHandled::Reported => {}}
- | -- block is empty, you might have not meant to close it
+ | --- ...as it matches this but it has different indentation
+ | |
+ | block is empty, you might have not meant to close it
...
LL | }
| ^ unexpected closing delimiter
--> $DIR/macro-mismatched-delim-paren-brace.rs:5:1
|
LL | fn main() {
- | - this opening brace...
+ | - this delimiter might not be properly closed...
...
LL | }
- | - ...matches this closing brace
+ | - ...as it matches this but it has different indentation
LL | }
| ^ unexpected closing delimiter
--- /dev/null
+// check-pass
+
+#![feature(trait_alias)]
+
+struct MyStruct {}
+trait MyFn = Fn(&MyStruct);
+
+fn foo(_: impl MyFn) {}
+
+fn main() {
+ foo(|_| {});
+}
--> $DIR/issue-91334.rs:10:23
|
LL | fn f(){||yield(((){),
- | - - ^
- | | |
+ | - - - ^
+ | | | |
+ | | | missing open `(` for this delimiter
| | unclosed delimiter
| unclosed delimiter
--> $DIR/issue-91334.rs:10:23
|
LL | fn f(){||yield(((){),
- | - - ^
- | | |
+ | - - - ^
+ | | | |
+ | | | missing open `(` for this delimiter
| | unclosed delimiter
| unclosed delimiter