use rustc::ty::subst::{Subst, InternalSubsts};
use rustc::ty::util::Discr;
use rustc::ty::util::IntTypeExt;
-use rustc::ty::subst::UnpackedKind;
+use rustc::ty::subst::GenericArgKind;
use rustc::ty::{self, AdtKind, DefIdTree, ToPolyTraitRef, Ty, TyCtxt, Const};
use rustc::ty::{ReprOptions, ToPredicate};
use rustc::util::captures::Captures;
use rustc::hir::GenericParamKind;
use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, Unsafety};
-use errors::{Applicability, DiagnosticId};
+use errors::{Applicability, DiagnosticId, StashKey};
struct OnlySelfBounds(bool);
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
- if let hir::ExprKind::Closure(..) = expr.node {
+ if let hir::ExprKind::Closure(..) = expr.kind {
let def_id = self.tcx.hir().local_def_id(expr.hir_id);
self.tcx.generics_of(def_id);
self.tcx.type_of(def_id);
/// `ast_ty_to_ty`, because we want to avoid triggering an all-out
/// conversion of the type to avoid inducing unnecessary cycles.
fn is_param(tcx: TyCtxt<'_>, ast_ty: &hir::Ty, param_id: hir::HirId) -> bool {
- if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = ast_ty.node {
+ if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = ast_ty.kind {
match path.res {
Res::SelfTy(Some(def_id), None) | Res::Def(DefKind::TyParam, def_id) => {
def_id == tcx.hir().local_def_id(param_id)
let def_id = tcx.hir().local_def_id(trait_item.hir_id);
tcx.generics_of(def_id);
- match trait_item.node {
+ match trait_item.kind {
hir::TraitItemKind::Const(..)
| hir::TraitItemKind::Type(_, Some(_))
| hir::TraitItemKind::Method(..) => {
tcx.type_of(def_id);
- if let hir::TraitItemKind::Method(..) = trait_item.node {
+ if let hir::TraitItemKind::Method(..) = trait_item.kind {
tcx.fn_sig(def_id);
}
}
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
- if let hir::ImplItemKind::Method(..) = tcx.hir().expect_impl_item(impl_item_id).node {
+ if let hir::ImplItemKind::Method(..) = tcx.hir().expect_impl_item(impl_item_id).kind {
tcx.fn_sig(def_id);
}
}
if self.has_late_bound_regions.is_some() {
return;
}
- match ty.node {
+ match ty.kind {
hir::TyKind::BareFn(..) => {
self.outer_index.shift_in(1);
intravisit::walk_ty(self, ty);
}
match node {
- Node::TraitItem(item) => match item.node {
+ Node::TraitItem(item) => match item.kind {
hir::TraitItemKind::Method(ref sig, _) => {
has_late_bound_regions(tcx, &item.generics, &sig.decl)
}
_ => None,
},
- Node::ImplItem(item) => match item.node {
+ Node::ImplItem(item) => match item.kind {
hir::ImplItemKind::Method(ref sig, _) => {
has_late_bound_regions(tcx, &item.generics, &sig.decl)
}
}
}
Node::Expr(&hir::Expr {
- node: hir::ExprKind::Closure(..),
+ kind: hir::ExprKind::Closure(..),
..
}) => Some(tcx.closure_base_def_id(def_id)),
Node::Item(item) => match item.node {
// cares about anything but the length is instantiation,
// and we don't do that for closures.
if let Node::Expr(&hir::Expr {
- node: hir::ExprKind::Closure(.., gen),
+ kind: hir::ExprKind::Closure(.., gen),
..
}) = node
{
def_id: DefId,
body_id: hir::BodyId,
span: Span,
+ item_ident: Ident,
) -> Ty<'_> {
let ty = tcx.typeck_tables_of(def_id).node_type(body_id.hir_id);
- let mut diag = bad_placeholder_type(tcx, span);
- if ty != tcx.types.err {
- diag.span_suggestion(
- span,
- "replace `_` with the correct type",
- ty.to_string(),
- Applicability::MaybeIncorrect,
- );
+
+ // If this came from a free `const` or `static mut?` item,
+ // then the user may have written e.g. `const A = 42;`.
+ // In this case, the parser has stashed a diagnostic for
+ // us to improve in typeck so we do that now.
+ match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) {
+ Some(mut err) => {
+ // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
+ // We are typeck and have the real type, so remove that and suggest the actual type.
+ err.suggestions.clear();
+ err.span_suggestion(
+ span,
+ "provide a type for the item",
+ format!("{}: {}", item_ident, ty),
+ Applicability::MachineApplicable,
+ )
+ .emit();
+ }
+ None => {
+ let mut diag = bad_placeholder_type(tcx, span);
+ if ty != tcx.types.err {
+ diag.span_suggestion(
+ span,
+ "replace `_` with the correct type",
+ ty.to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ diag.emit();
+ }
}
- diag.emit();
+
ty
}
let icx = ItemCtxt::new(tcx, def_id);
Some(match tcx.hir().get(hir_id) {
- Node::TraitItem(item) => match item.node {
+ Node::TraitItem(item) => match item.kind {
TraitItemKind::Method(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_fn_def(def_id, substs)
}
TraitItemKind::Const(ref ty, body_id) => {
body_id.and_then(|body_id| {
- if let hir::TyKind::Infer = ty.node {
- Some(infer_placeholder_type(tcx, def_id, body_id, ty.span))
+ if let hir::TyKind::Infer = ty.kind {
+ Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident))
} else {
None
}
}
},
- Node::ImplItem(item) => match item.node {
+ Node::ImplItem(item) => match item.kind {
ImplItemKind::Method(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_fn_def(def_id, substs)
}
ImplItemKind::Const(ref ty, body_id) => {
- if let hir::TyKind::Infer = ty.node {
- infer_placeholder_type(tcx, def_id, body_id, ty.span)
+ if let hir::TyKind::Infer = ty.kind {
+ infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
} else {
icx.to_ty(ty)
}
match item.node {
ItemKind::Static(ref ty, .., body_id)
| ItemKind::Const(ref ty, body_id) => {
- if let hir::TyKind::Infer = ty.node {
- infer_placeholder_type(tcx, def_id, body_id, ty.span)
+ if let hir::TyKind::Infer = ty.kind {
+ infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
} else {
icx.to_ty(ty)
}
Node::Field(field) => icx.to_ty(&field.ty),
Node::Expr(&hir::Expr {
- node: hir::ExprKind::Closure(.., gen),
+ kind: hir::ExprKind::Closure(.., gen),
..
}) => {
if gen.is_some() {
let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
match parent_node {
Node::Ty(&hir::Ty {
- node: hir::TyKind::Array(_, ref constant),
+ kind: hir::TyKind::Array(_, ref constant),
..
})
| Node::Ty(&hir::Ty {
- node: hir::TyKind::Typeof(ref constant),
+ kind: hir::TyKind::Typeof(ref constant),
..
})
| Node::Expr(&hir::Expr {
- node: ExprKind::Repeat(_, ref constant),
+ kind: ExprKind::Repeat(_, ref constant),
..
}) if constant.hir_id == hir_id =>
{
.to_ty(tcx)
}
- Node::Ty(&hir::Ty { node: hir::TyKind::Path(_), .. }) |
- Node::Expr(&hir::Expr { node: ExprKind::Struct(..), .. }) |
- Node::Expr(&hir::Expr { node: ExprKind::Path(_), .. }) |
+ Node::Ty(&hir::Ty { kind: hir::TyKind::Path(_), .. }) |
+ Node::Expr(&hir::Expr { kind: ExprKind::Struct(..), .. }) |
+ Node::Expr(&hir::Expr { kind: ExprKind::Path(_), .. }) |
Node::TraitRef(..) => {
let path = match parent_node {
Node::Ty(&hir::Ty {
- node: hir::TyKind::Path(QPath::Resolved(_, ref path)),
+ kind: hir::TyKind::Path(QPath::Resolved(_, ref path)),
..
})
| Node::Expr(&hir::Expr {
- node: ExprKind::Path(QPath::Resolved(_, ref path)),
+ kind: ExprKind::Path(QPath::Resolved(_, ref path)),
..
}) => {
Some(&**path)
}
- Node::Expr(&hir::Expr { node: ExprKind::Struct(ref path, ..), .. }) => {
+ Node::Expr(&hir::Expr { kind: ExprKind::Struct(ref path, ..), .. }) => {
if let QPath::Resolved(_, ref path) = **path {
Some(&**path)
} else {
// Skipping binder is ok, since we only use this to find generic parameters and
// their positions.
for (idx, subst) in substs.iter().enumerate() {
- if let UnpackedKind::Type(ty) = subst.unpack() {
- if let ty::Param(p) = ty.sty {
+ if let GenericArgKind::Type(ty) = subst.unpack() {
+ if let ty::Param(p) = ty.kind {
if index_map.insert(p, idx).is_some() {
// There was already an entry for `p`, meaning a generic parameter
// was used twice.
let indices = concrete_type
.subst(self.tcx, substs)
.walk()
- .filter_map(|t| match &t.sty {
+ .filter_map(|t| match &t.kind {
ty::Param(p) => Some(*index_map.get(p).unwrap()),
_ => None,
}).collect();
- let is_param = |ty: Ty<'_>| match ty.sty {
+ let is_param = |ty: Ty<'_>| match ty.kind {
ty::Param(_) => true,
_ => false,
};
} else if let Some((prev_span, prev_ty, ref prev_indices)) = self.found {
let mut ty = concrete_type.walk().fuse();
let mut p_ty = prev_ty.walk().fuse();
- let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.sty, &p.sty) {
+ let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.kind, &p.kind) {
// Type parameters are equal to any other type parameter for the purpose of
// concrete type equality, as it is possible to obtain the same type just
// by passing matching parameters to a function.
pub fn get_infer_ret_ty(output: &'_ hir::FunctionRetTy) -> Option<&hir::Ty> {
if let hir::FunctionRetTy::Return(ref ty) = output {
- if let hir::TyKind::Infer = ty.node {
+ if let hir::TyKind::Infer = ty.kind {
return Some(&**ty)
}
}
match tcx.hir().get(hir_id) {
TraitItem(hir::TraitItem {
- node: TraitItemKind::Method(MethodSig { header, decl }, TraitMethod::Provided(_)),
+ kind: TraitItemKind::Method(MethodSig { header, decl }, TraitMethod::Provided(_)),
..
})
| ImplItem(hir::ImplItem {
- node: ImplItemKind::Method(MethodSig { header, decl }, _),
+ kind: ImplItemKind::Method(MethodSig { header, decl }, _),
..
})
| Item(hir::Item {
},
TraitItem(hir::TraitItem {
- node: TraitItemKind::Method(MethodSig { header, decl }, _),
+ kind: TraitItemKind::Method(MethodSig { header, decl }, _),
..
}) => {
AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl)
}
Expr(&hir::Expr {
- node: hir::ExprKind::Closure(..),
+ kind: hir::ExprKind::Closure(..),
..
}) => {
// Closure signatures are not like other function
}
}
-fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> hir::ImplPolarity {
+fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
- match tcx.hir().expect_item(hir_id).node {
- hir::ItemKind::Impl(_, polarity, ..) => polarity,
+ let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
+ let item = tcx.hir().expect_item(hir_id);
+ match &item.node {
+ hir::ItemKind::Impl(_, hir::ImplPolarity::Negative, ..) => {
+ if is_rustc_reservation {
+ tcx.sess.span_err(item.span, "reservation impls can't be negative");
+ }
+ ty::ImplPolarity::Negative
+ }
+ hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, None, _, _) => {
+ if is_rustc_reservation {
+ tcx.sess.span_err(item.span, "reservation impls can't be inherent");
+ }
+ ty::ImplPolarity::Positive
+ }
+ hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, Some(_tr), _, _) => {
+ if is_rustc_reservation {
+ ty::ImplPolarity::Reservation
+ } else {
+ ty::ImplPolarity::Positive
+ }
+ }
ref item => bug!("impl_polarity: {:?} not an impl", item),
}
}
let ast_generics = match node {
Node::TraitItem(item) => &item.generics,
- Node::ImplItem(item) => match item.node {
+ Node::ImplItem(item) => match item.kind {
ImplItemKind::OpaqueTy(ref bounds) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
let opaque_ty = tcx.mk_opaque(def_id, substs);
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
// is still checked for WF.
if bound_pred.bounds.is_empty() {
- if let ty::Param(_) = ty.sty {
+ if let ty::Param(_) = ty.kind {
// This is a `where T:`, which can be in the HIR from the
// transformation that moves `?Sized` to `T`'s declaration.
// We can skip the predicate because type parameters are
if let Some((self_trait_ref, trait_items)) = is_trait {
predicates.extend(trait_items.iter().flat_map(|trait_item_ref| {
let trait_item = tcx.hir().trait_item(trait_item_ref.id);
- let bounds = match trait_item.node {
+ let bounds = match trait_item.kind {
hir::TraitItemKind::Type(ref bounds, _) => bounds,
_ => return Vec::new().into_iter()
};