X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_typeck%2Fcollect.rs;h=3bb06d76349834043d2ffebd861203a0f1ffc858;hb=93f0ba970fb5ecd330d970109d58bf594b8cc96e;hp=35c380612d2fb234f4cac571886665ae748a0211;hpb=ed6468da160bd67a2ce0573427f09a98daff8c07;p=rust.git diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 35c380612d2..3bb06d76349 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -21,7 +21,7 @@ use crate::middle::resolve_lifetime as rl; use crate::middle::weak_lang_items; use errors::{struct_span_err, Applicability, StashKey}; -use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc::hir::map::Map; use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc::mir::mono::Linkage; use rustc::traits; @@ -32,11 +32,12 @@ use rustc::ty::util::IntTypeExt; use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::{ReprOptions, ToPredicate}; -use rustc::util::captures::Captures; +use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{GenericParamKind, Node, Unsafety}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -104,7 +105,9 @@ pub struct ItemCtxt<'tcx> { crate struct PlaceholderHirTyCollector(crate Vec); impl<'v> Visitor<'v> for PlaceholderHirTyCollector { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { + type Map = Map<'v>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { NestedVisitorMap::None } fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { @@ -124,7 +127,7 @@ struct CollectItemTypesVisitor<'tcx> { /// all already existing generic type parameters to avoid suggesting a name that is already in use. crate fn placeholder_type_error( tcx: TyCtxt<'tcx>, - ident_span: Span, + span: Span, generics: &[hir::GenericParam<'_>], placeholder_types: Vec, suggest: bool, @@ -150,7 +153,14 @@ struct CollectItemTypesVisitor<'tcx> { let mut sugg: Vec<_> = placeholder_types.iter().map(|sp| (*sp, type_name.to_string())).collect(); if generics.is_empty() { - sugg.push((ident_span.shrink_to_hi(), format!("<{}>", type_name))); + sugg.push((span, format!("<{}>", type_name))); + } else if let Some(arg) = generics.iter().find(|arg| match arg.name { + hir::ParamName::Plain(Ident { name: kw::Underscore, .. }) => true, + _ => false, + }) { + // Account for `_` already present in cases like `struct S<_>(_);` and suggest + // `struct S(T);` instead of `struct S<_, T>(T);`. + sugg.push((arg.span, format!("{}", type_name))); } else { sugg.push(( generics.iter().last().unwrap().span.shrink_to_hi(), @@ -172,8 +182,12 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir let (generics, suggest) = match &item.kind { hir::ItemKind::Union(_, generics) | hir::ItemKind::Enum(_, generics) - | hir::ItemKind::Struct(_, generics) => (&generics.params[..], true), - hir::ItemKind::TyAlias(_, generics) => (&generics.params[..], false), + | hir::ItemKind::TraitAlias(generics, _) + | hir::ItemKind::Trait(_, _, generics, ..) + | hir::ItemKind::Impl(_, _, _, generics, ..) + | hir::ItemKind::Struct(_, generics) => (generics, true), + hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }) + | hir::ItemKind::TyAlias(_, generics) => (generics, false), // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type. _ => return, }; @@ -181,11 +195,13 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_item(item); - placeholder_type_error(tcx, item.ident.span, generics, visitor.0, suggest); + placeholder_type_error(tcx, generics.span, &generics.params[..], visitor.0, suggest); } impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + type Map = Map<'tcx>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } @@ -885,7 +901,9 @@ struct LateBoundRegionsDetector<'tcx> { } impl Visitor<'tcx> for LateBoundRegionsDetector<'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + type Map = Map<'tcx>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { NestedVisitorMap::None } @@ -1715,7 +1733,9 @@ fn check(&mut self, def_id: DefId) { } impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> { + type Map = Map<'tcx>; + + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { intravisit::NestedVisitorMap::All(&self.tcx.hir()) } fn visit_item(&mut self, it: &'tcx Item<'tcx>) { @@ -1789,10 +1809,19 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { /// Whether `ty` is a type with `_` placeholders that can be infered. Used in diagnostics only to /// use inference to provide suggestions for the appropriate type if possible. fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { + use hir::TyKind::*; match &ty.kind { - hir::TyKind::Infer => true, - hir::TyKind::Slice(ty) | hir::TyKind::Array(ty, _) => is_suggestable_infer_ty(ty), - hir::TyKind::Tup(tys) => tys.iter().any(|ty| is_suggestable_infer_ty(ty)), + Infer => true, + Slice(ty) | Array(ty, _) => is_suggestable_infer_ty(ty), + Tup(tys) => tys.iter().any(is_suggestable_infer_ty), + Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty), + Def(_, generic_args) => generic_args + .iter() + .filter_map(|arg| match arg { + hir::GenericArg::Type(ty) => Some(ty), + _ => None, + }) + .any(is_suggestable_infer_ty), _ => false, } }