X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_typeck%2Fcollect.rs;h=28c275e2d75abeca5684bffd38bc0477e3180e14;hb=7bc94cc3c2ccef8b4d393910bb978a6487db1202;hp=312a598af02bf20962c6a67e6abe8f725afec00f;hpb=b76a5582273da26bf40e8eb4838860270e9e6e63;p=rust.git diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 312a598af02..28c275e2d75 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -25,7 +25,7 @@ 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; @@ -46,7 +46,7 @@ use rustc::hir::GenericParamKind; use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, Unsafety}; -use errors::{Applicability, DiagnosticId}; +use errors::{Applicability, DiagnosticId, StashKey}; struct OnlySelfBounds(bool); @@ -135,7 +135,7 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics) { } 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); @@ -288,7 +288,7 @@ fn type_param_predicates( Node::ImplItem(item) => &item.generics, Node::Item(item) => { - match item.node { + match item.kind { ItemKind::Fn(.., ref generics, _) | ItemKind::Impl(_, _, _, ref generics, ..) | ItemKind::TyAlias(_, ref generics) @@ -387,7 +387,7 @@ fn type_parameter_bounds_in_generics( /// `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) @@ -403,7 +403,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) { let it = tcx.hir().expect_item(item_id); debug!("convert: item {} with id {}", it.ident, it.hir_id); let def_id = tcx.hir().local_def_id(item_id); - match it.node { + match it.kind { // These don't define types. hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) @@ -474,7 +474,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); - if let hir::ItemKind::Fn(..) = it.node { + if let hir::ItemKind::Fn(..) = it.kind { tcx.fn_sig(def_id); } } @@ -486,12 +486,12 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) { 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); } } @@ -507,7 +507,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) { 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); } } @@ -519,15 +519,15 @@ fn convert_variant_ctor(tcx: TyCtxt<'_>, ctor_id: hir::HirId) { tcx.predicates_of(def_id); } -fn convert_enum_variant_types<'tcx>( - tcx: TyCtxt<'tcx>, +fn convert_enum_variant_types( + tcx: TyCtxt<'_>, def_id: DefId, variants: &[hir::Variant] ) { let def = tcx.adt_def(def_id); let repr_type = def.repr.discr_type(); let initial = repr_type.initial_discriminant(tcx); - let mut prev_discr = None::>; + let mut prev_discr = None::>; // fill the discriminant values and field types for variant in variants { @@ -638,7 +638,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef { }; let repr = ReprOptions::new(tcx, def_id); - let (kind, variants) = match item.node { + let (kind, variants) = match item.kind { ItemKind::Enum(ref def, _) => { let mut distance_from_explicit = 0; let variants = def.variants @@ -707,7 +707,7 @@ fn super_predicates_of( _ => bug!("trait_node_id {} is not an item", trait_hir_id), }; - let (generics, bounds) = match item.node { + let (generics, bounds) = match item.kind { hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits), hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits), _ => span_bug!(item.span, "super_predicates invoked on non-trait"), @@ -753,7 +753,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TraitDef { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); let item = tcx.hir().expect_item(hir_id); - let (is_auto, unsafety) = match item.node { + let (is_auto, unsafety) = match item.kind { hir::ItemKind::Trait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety), hir::ItemKind::TraitAlias(..) => (false, hir::Unsafety::Normal), _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"), @@ -796,7 +796,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) { 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); @@ -860,13 +860,13 @@ fn has_late_bound_regions<'tcx>( } 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) } @@ -878,7 +878,7 @@ fn has_late_bound_regions<'tcx>( } _ => None, }, - Node::Item(item) => match item.node { + Node::Item(item) => match item.kind { hir::ItemKind::Fn(ref fn_decl, .., ref generics, _) => { has_late_bound_regions(tcx, generics, fn_decl) } @@ -915,10 +915,10 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { } } 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 { + Node::Item(item) => match item.kind { ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => impl_trait_fn, _ => None, }, @@ -935,7 +935,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { Node::ImplItem(item) => &item.generics, Node::Item(item) => { - match item.node { + match item.kind { ItemKind::Fn(.., ref generics, _) | ItemKind::Impl(_, _, _, ref generics, ..) => { generics } @@ -1072,7 +1072,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { // 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 { @@ -1149,18 +1149,41 @@ fn infer_placeholder_type( 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 } @@ -1184,15 +1207,15 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option 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 } @@ -1207,14 +1230,14 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option 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) } @@ -1242,11 +1265,11 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option { - match item.node { + match item.kind { 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) } @@ -1302,7 +1325,7 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option, def_id: DefId, fail: bool) -> Option icx.to_ty(&field.ty), Node::Expr(&hir::Expr { - node: hir::ExprKind::Closure(.., gen), + kind: hir::ExprKind::Closure(.., gen), .. }) => { if gen.is_some() { @@ -1350,15 +1373,15 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option { @@ -1376,22 +1399,22 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option { 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 { @@ -1557,8 +1580,8 @@ fn check(&mut self, def_id: DefId) { // 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. @@ -1588,11 +1611,11 @@ fn check(&mut self, def_id: DefId) { 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, }; @@ -1604,7 +1627,7 @@ fn check(&mut self, def_id: DefId) { } 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. @@ -1746,7 +1769,7 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem) { 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) } } @@ -1763,15 +1786,15 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { 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 { - node: ItemKind::Fn(decl, header, _, _), + kind: ItemKind::Fn(decl, header, _, _), .. }) => match get_infer_ret_ty(&decl.output) { Some(ty) => { @@ -1793,7 +1816,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { }, 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) @@ -1824,7 +1847,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { } Expr(&hir::Expr { - node: hir::ExprKind::Closure(..), + kind: hir::ExprKind::Closure(..), .. }) => { // Closure signatures are not like other function @@ -1855,7 +1878,7 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { let icx = ItemCtxt::new(tcx, def_id); let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - match tcx.hir().expect_item(hir_id).node { + match tcx.hir().expect_item(hir_id).kind { hir::ItemKind::Impl(.., ref opt_trait_ref, _, _) => { opt_trait_ref.as_ref().map(|ast_trait_ref| { let selfty = tcx.type_of(def_id); @@ -1866,10 +1889,30 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { } } -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.kind { + 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), } } @@ -2012,7 +2055,7 @@ fn extend, Span)>>(&mut self, iter: 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); @@ -2033,7 +2076,7 @@ fn extend, Span)>>(&mut self, iter: }, Node::Item(item) => { - match item.node { + match item.kind { ItemKind::Impl(_, _, defaultness, ref generics, ..) => { if defaultness.is_default() { is_default_impl_trait = tcx.impl_trait_ref(def_id); @@ -2175,7 +2218,7 @@ fn extend, Span)>>(&mut self, iter: // 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 @@ -2238,7 +2281,7 @@ fn extend, Span)>>(&mut self, iter: 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() }; @@ -2267,7 +2310,7 @@ fn extend, Span)>>(&mut self, iter: // in trait checking. See `setup_constraining_predicates` // for details. if let Node::Item(&Item { - node: ItemKind::Impl(..), + kind: ItemKind::Impl(..), .. }) = node { @@ -2374,7 +2417,7 @@ fn is_foreign_item(tcx: TyCtxt<'_>, def_id: DefId) -> bool { fn static_mutability(tcx: TyCtxt<'_>, def_id: DefId) -> Option { match tcx.hir().get_if_local(def_id) { Some(Node::Item(&hir::Item { - node: hir::ItemKind::Static(_, mutbl, _), .. + kind: hir::ItemKind::Static(_, mutbl, _), .. })) | Some(Node::ForeignItem( &hir::ForeignItem { node: hir::ForeignItemKind::Static(_, mutbl), ..