Auto merge of #63575 - Centril:rollup-anlv9g5, r=Centril
Rollup of 11 pull requests Successful merges: - #62984 (Add lint for excess trailing semicolons) - #63075 (Miri: Check that a ptr is aligned and inbounds already when evaluating `*`) - #63490 (libsyntax: cleanup and refactor `pat.rs`) - #63507 (When needing type annotations in local bindings, account for impl Trait and closures) - #63509 (Point at the right enclosing scope when using `await` in non-async fn) - #63528 (syntax: Remove `DummyResult::expr_only`) - #63537 (expand: Unimplement `MutVisitor` on `MacroExpander`) - #63542 (Add NodeId for Arm, Field and FieldPat) - #63543 (Merge Variant and Variant_) - #63560 (move test that shouldn't be in test/run-pass/) - #63570 (Adjust tracking issues for `MaybeUninit<T>` gates) Failed merges: r? @ghost
This commit is contained in:
commit
9e9a136fce
102 changed files with 1078 additions and 559 deletions
|
|
@ -336,7 +336,7 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
|
|||
fn is_c_like_enum(item: &hir::Item) -> bool {
|
||||
if let hir::ItemKind::Enum(ref def, _) = item.node {
|
||||
for variant in &def.variants {
|
||||
match variant.node.data {
|
||||
match variant.data {
|
||||
hir::VariantData::Unit(..) => { /* continue */ }
|
||||
_ => { return false; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -577,15 +577,15 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
|
|||
variant: &'v Variant,
|
||||
generics: &'v Generics,
|
||||
parent_item_id: HirId) {
|
||||
visitor.visit_ident(variant.node.ident);
|
||||
visitor.visit_id(variant.node.id);
|
||||
visitor.visit_variant_data(&variant.node.data,
|
||||
variant.node.ident.name,
|
||||
visitor.visit_ident(variant.ident);
|
||||
visitor.visit_id(variant.id);
|
||||
visitor.visit_variant_data(&variant.data,
|
||||
variant.ident.name,
|
||||
generics,
|
||||
parent_item_id,
|
||||
variant.span);
|
||||
walk_list!(visitor, visit_anon_const, &variant.node.disr_expr);
|
||||
walk_list!(visitor, visit_attribute, &variant.node.attrs);
|
||||
walk_list!(visitor, visit_anon_const, &variant.disr_expr);
|
||||
walk_list!(visitor, visit_attribute, &variant.attrs);
|
||||
}
|
||||
|
||||
pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
||||
|
|
|
|||
|
|
@ -677,6 +677,7 @@ impl LoweringContext<'_> {
|
|||
let fn_decl = self.lower_fn_decl(decl, None, false, None);
|
||||
|
||||
self.with_new_scopes(|this| {
|
||||
let prev = this.current_item;
|
||||
this.current_item = Some(fn_decl_span);
|
||||
let mut generator_kind = None;
|
||||
let body_id = this.lower_fn_body(decl, |this| {
|
||||
|
|
@ -690,8 +691,10 @@ impl LoweringContext<'_> {
|
|||
generator_kind,
|
||||
movability,
|
||||
);
|
||||
let capture_clause = this.lower_capture_clause(capture_clause);
|
||||
this.current_item = prev;
|
||||
hir::ExprKind::Closure(
|
||||
this.lower_capture_clause(capture_clause),
|
||||
capture_clause,
|
||||
fn_decl,
|
||||
body_id,
|
||||
fn_decl_span,
|
||||
|
|
|
|||
|
|
@ -757,14 +757,12 @@ impl LoweringContext<'_> {
|
|||
}
|
||||
|
||||
fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
|
||||
Spanned {
|
||||
node: hir::VariantKind {
|
||||
ident: v.node.ident,
|
||||
id: self.lower_node_id(v.node.id),
|
||||
attrs: self.lower_attrs(&v.node.attrs),
|
||||
data: self.lower_variant_data(&v.node.data),
|
||||
disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
|
||||
},
|
||||
hir::Variant {
|
||||
attrs: self.lower_attrs(&v.attrs),
|
||||
data: self.lower_variant_data(&v.data),
|
||||
disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
|
||||
id: self.lower_node_id(v.id),
|
||||
ident: v.ident,
|
||||
span: v.span,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -544,11 +544,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
}
|
||||
|
||||
fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: HirId) {
|
||||
self.insert(v.span, v.node.id, Node::Variant(v));
|
||||
self.with_parent(v.node.id, |this| {
|
||||
self.insert(v.span, v.id, Node::Variant(v));
|
||||
self.with_parent(v.id, |this| {
|
||||
// Register the constructor of this variant.
|
||||
if let Some(ctor_hir_id) = v.node.data.ctor_hir_id() {
|
||||
this.insert(v.span, ctor_hir_id, Node::Ctor(&v.node.data));
|
||||
if let Some(ctor_hir_id) = v.data.ctor_hir_id() {
|
||||
this.insert(v.span, ctor_hir_id, Node::Ctor(&v.data));
|
||||
}
|
||||
intravisit::walk_variant(this, v, g, item_id);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -155,11 +155,11 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
|||
}
|
||||
|
||||
fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
|
||||
let def = self.create_def(v.node.id,
|
||||
DefPathData::TypeNs(v.node.ident.as_interned_str()),
|
||||
let def = self.create_def(v.id,
|
||||
DefPathData::TypeNs(v.ident.as_interned_str()),
|
||||
v.span);
|
||||
self.with_parent(def, |this| {
|
||||
if let Some(ctor_hir_id) = v.node.data.ctor_id() {
|
||||
if let Some(ctor_hir_id) = v.data.ctor_id() {
|
||||
this.create_def(ctor_hir_id, DefPathData::Ctor, v.span);
|
||||
}
|
||||
visit::walk_variant(this, v, g, item_id)
|
||||
|
|
|
|||
|
|
@ -649,12 +649,34 @@ impl<'hir> Map<'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_const_scope(&self, hir_id: HirId) -> bool {
|
||||
self.walk_parent_nodes(hir_id, |node| match *node {
|
||||
Node::Item(Item { node: ItemKind::Const(_, _), .. }) => true,
|
||||
Node::Item(Item { node: ItemKind::Fn(_, header, _, _), .. }) => header.is_const(),
|
||||
/// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
|
||||
/// Used exclusively for diagnostics, to avoid suggestion function calls.
|
||||
pub fn is_const_context(&self, hir_id: HirId) -> bool {
|
||||
let parent_id = self.get_parent_item(hir_id);
|
||||
match self.get(parent_id) {
|
||||
Node::Item(&Item {
|
||||
node: ItemKind::Const(..),
|
||||
..
|
||||
})
|
||||
| Node::TraitItem(&TraitItem {
|
||||
node: TraitItemKind::Const(..),
|
||||
..
|
||||
})
|
||||
| Node::ImplItem(&ImplItem {
|
||||
node: ImplItemKind::Const(..),
|
||||
..
|
||||
})
|
||||
| Node::AnonConst(_)
|
||||
| Node::Item(&Item {
|
||||
node: ItemKind::Static(..),
|
||||
..
|
||||
}) => true,
|
||||
Node::Item(&Item {
|
||||
node: ItemKind::Fn(_, header, ..),
|
||||
..
|
||||
}) => header.constness == Constness::Const,
|
||||
_ => false,
|
||||
}, |_| false).map(|id| id != CRATE_HIR_ID).unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
/// If there is some error when walking the parents (e.g., a node does not
|
||||
|
|
@ -885,7 +907,7 @@ impl<'hir> Map<'hir> {
|
|||
_ => bug!("struct ID bound to non-struct {}", self.node_to_string(id))
|
||||
}
|
||||
}
|
||||
Some(Node::Variant(variant)) => &variant.node.data,
|
||||
Some(Node::Variant(variant)) => &variant.data,
|
||||
Some(Node::Ctor(data)) => data,
|
||||
_ => bug!("expected struct or variant, found {}", self.node_to_string(id))
|
||||
}
|
||||
|
|
@ -918,7 +940,7 @@ impl<'hir> Map<'hir> {
|
|||
Node::ForeignItem(fi) => fi.ident.name,
|
||||
Node::ImplItem(ii) => ii.ident.name,
|
||||
Node::TraitItem(ti) => ti.ident.name,
|
||||
Node::Variant(v) => v.node.ident.name,
|
||||
Node::Variant(v) => v.ident.name,
|
||||
Node::Field(f) => f.ident.name,
|
||||
Node::Lifetime(lt) => lt.name.ident().name,
|
||||
Node::GenericParam(param) => param.name.ident().name,
|
||||
|
|
@ -939,7 +961,7 @@ impl<'hir> Map<'hir> {
|
|||
Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]),
|
||||
Some(Node::TraitItem(ref ti)) => Some(&ti.attrs[..]),
|
||||
Some(Node::ImplItem(ref ii)) => Some(&ii.attrs[..]),
|
||||
Some(Node::Variant(ref v)) => Some(&v.node.attrs[..]),
|
||||
Some(Node::Variant(ref v)) => Some(&v.attrs[..]),
|
||||
Some(Node::Field(ref f)) => Some(&f.attrs[..]),
|
||||
Some(Node::Expr(ref e)) => Some(&*e.attrs),
|
||||
Some(Node::Stmt(ref s)) => Some(s.node.attrs()),
|
||||
|
|
@ -1133,7 +1155,7 @@ impl<T:Named> Named for Spanned<T> { fn name(&self) -> Name { self.node.name() }
|
|||
|
||||
impl Named for Item { fn name(&self) -> Name { self.ident.name } }
|
||||
impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } }
|
||||
impl Named for VariantKind { fn name(&self) -> Name { self.ident.name } }
|
||||
impl Named for Variant { fn name(&self) -> Name { self.ident.name } }
|
||||
impl Named for StructField { fn name(&self) -> Name { self.ident.name } }
|
||||
impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } }
|
||||
impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } }
|
||||
|
|
@ -1310,7 +1332,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
|
|||
}
|
||||
Some(Node::Variant(ref variant)) => {
|
||||
format!("variant {} in {}{}",
|
||||
variant.node.ident,
|
||||
variant.ident,
|
||||
path_str(), id_str)
|
||||
}
|
||||
Some(Node::Field(ref field)) => {
|
||||
|
|
|
|||
|
|
@ -1541,7 +1541,7 @@ pub enum ExprKind {
|
|||
Match(P<Expr>, HirVec<Arm>, MatchSource),
|
||||
/// A closure (e.g., `move |a, b, c| {a + b + c}`).
|
||||
///
|
||||
/// The final span is the span of the argument block `|...|`.
|
||||
/// The `Span` is the argument block `|...|`.
|
||||
///
|
||||
/// This may also be a generator literal or an `async block` as indicated by the
|
||||
/// `Option<GeneratorMovability>`.
|
||||
|
|
@ -2193,7 +2193,7 @@ pub struct EnumDef {
|
|||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||
pub struct VariantKind {
|
||||
pub struct Variant {
|
||||
/// Name of the variant.
|
||||
#[stable_hasher(project(name))]
|
||||
pub ident: Ident,
|
||||
|
|
@ -2205,10 +2205,10 @@ pub struct VariantKind {
|
|||
pub data: VariantData,
|
||||
/// Explicit discriminant (e.g., `Foo = 1`).
|
||||
pub disr_expr: Option<AnonConst>,
|
||||
/// Span
|
||||
pub span: Span
|
||||
}
|
||||
|
||||
pub type Variant = Spanned<VariantKind>;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||
pub enum UseKind {
|
||||
/// One import, e.g., `use foo::bar` or `use foo::bar as baz`.
|
||||
|
|
|
|||
|
|
@ -737,7 +737,7 @@ impl<'a> State<'a> {
|
|||
for v in variants {
|
||||
self.space_if_not_bol();
|
||||
self.maybe_print_comment(v.span.lo());
|
||||
self.print_outer_attributes(&v.node.attrs);
|
||||
self.print_outer_attributes(&v.attrs);
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.print_variant(v);
|
||||
self.s.word(",");
|
||||
|
|
@ -829,8 +829,8 @@ impl<'a> State<'a> {
|
|||
pub fn print_variant(&mut self, v: &hir::Variant) {
|
||||
self.head("");
|
||||
let generics = hir::Generics::empty();
|
||||
self.print_struct(&v.node.data, &generics, v.node.ident.name, v.span, false);
|
||||
if let Some(ref d) = v.node.disr_expr {
|
||||
self.print_struct(&v.data, &generics, v.ident.name, v.span, false);
|
||||
if let Some(ref d) = v.disr_expr {
|
||||
self.s.space();
|
||||
self.word_space("=");
|
||||
self.print_anon_const(d);
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Mod {
|
|||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for_spanned!(hir::VariantKind);
|
||||
impl_stable_hash_for_spanned!(hir::Variant);
|
||||
|
||||
|
||||
impl<'a> HashStable<StableHashingContext<'a>> for hir::Item {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::hir::def::Namespace;
|
||||
use crate::hir::{self, Local, Pat, Body, HirId};
|
||||
use crate::hir::{self, Body, FunctionRetTy, Expr, ExprKind, HirId, Local, Pat};
|
||||
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::infer::type_variable::TypeVariableOriginKind;
|
||||
|
|
@ -7,7 +7,7 @@ use crate::ty::{self, Ty, Infer, TyVar};
|
|||
use crate::ty::print::Print;
|
||||
use syntax::source_map::DesugaringKind;
|
||||
use syntax_pos::Span;
|
||||
use errors::DiagnosticBuilder;
|
||||
use errors::{Applicability, DiagnosticBuilder};
|
||||
|
||||
struct FindLocalByTypeVisitor<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
|
|
@ -16,9 +16,26 @@ struct FindLocalByTypeVisitor<'a, 'tcx> {
|
|||
found_local_pattern: Option<&'tcx Pat>,
|
||||
found_arg_pattern: Option<&'tcx Pat>,
|
||||
found_ty: Option<Ty<'tcx>>,
|
||||
found_closure: Option<&'tcx ExprKind>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> {
|
||||
fn new(
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
target_ty: Ty<'tcx>,
|
||||
hir_map: &'a hir::map::Map<'tcx>,
|
||||
) -> Self {
|
||||
Self {
|
||||
infcx,
|
||||
target_ty,
|
||||
hir_map,
|
||||
found_local_pattern: None,
|
||||
found_arg_pattern: None,
|
||||
found_ty: None,
|
||||
found_closure: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn node_matches_type(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
|
||||
let ty_opt = self.infcx.in_progress_tables.and_then(|tables| {
|
||||
tables.borrow().node_type_opt(hir_id)
|
||||
|
|
@ -72,6 +89,60 @@ impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> {
|
|||
}
|
||||
intravisit::walk_body(self, body);
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'tcx Expr) {
|
||||
if let (ExprKind::Closure(_, _fn_decl, _id, _sp, _), Some(_)) = (
|
||||
&expr.node,
|
||||
self.node_matches_type(expr.hir_id),
|
||||
) {
|
||||
self.found_closure = Some(&expr.node);
|
||||
}
|
||||
intravisit::walk_expr(self, expr);
|
||||
}
|
||||
}
|
||||
|
||||
/// Suggest giving an appropriate return type to a closure expression.
|
||||
fn closure_return_type_suggestion(
|
||||
span: Span,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
output: &FunctionRetTy,
|
||||
body: &Body,
|
||||
name: &str,
|
||||
ret: &str,
|
||||
) {
|
||||
let (arrow, post) = match output {
|
||||
FunctionRetTy::DefaultReturn(_) => ("-> ", " "),
|
||||
_ => ("", ""),
|
||||
};
|
||||
let suggestion = match body.value.node {
|
||||
ExprKind::Block(..) => {
|
||||
vec![(output.span(), format!("{}{}{}", arrow, ret, post))]
|
||||
}
|
||||
_ => {
|
||||
vec![
|
||||
(output.span(), format!("{}{}{}{{ ", arrow, ret, post)),
|
||||
(body.value.span.shrink_to_hi(), " }".to_string()),
|
||||
]
|
||||
}
|
||||
};
|
||||
err.multipart_suggestion(
|
||||
"give this closure an explicit return type without `_` placeholders",
|
||||
suggestion,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
err.span_label(span, InferCtxt::missing_type_msg(&name));
|
||||
}
|
||||
|
||||
/// Given a closure signature, return a `String` containing a list of all its argument types.
|
||||
fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String {
|
||||
fn_sig.inputs()
|
||||
.skip_binder()
|
||||
.iter()
|
||||
.next()
|
||||
.map(|args| args.tuple_fields()
|
||||
.map(|arg| arg.to_string())
|
||||
.collect::<Vec<_>>().join(", "))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
|
|
@ -106,16 +177,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
let ty = self.resolve_vars_if_possible(&ty);
|
||||
let name = self.extract_type_name(&ty, None);
|
||||
|
||||
let mut err_span = span;
|
||||
|
||||
let mut local_visitor = FindLocalByTypeVisitor {
|
||||
infcx: &self,
|
||||
target_ty: ty,
|
||||
hir_map: &self.tcx.hir(),
|
||||
found_local_pattern: None,
|
||||
found_arg_pattern: None,
|
||||
found_ty: None,
|
||||
};
|
||||
let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, &self.tcx.hir());
|
||||
let ty_to_string = |ty: Ty<'tcx>| -> String {
|
||||
let mut s = String::new();
|
||||
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
|
||||
|
|
@ -136,6 +198,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
let expr = self.tcx.hir().expect_expr(body_id.hir_id);
|
||||
local_visitor.visit_expr(expr);
|
||||
}
|
||||
let err_span = if let Some(pattern) = local_visitor.found_arg_pattern {
|
||||
pattern.span
|
||||
} else {
|
||||
span
|
||||
};
|
||||
|
||||
let is_named_and_not_impl_trait = |ty: Ty<'_>| {
|
||||
&ty.to_string() != "_" &&
|
||||
// FIXME: Remove this check after `impl_trait_in_bindings` is stabilized. #63527
|
||||
(!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings)
|
||||
};
|
||||
|
||||
let ty_msg = match local_visitor.found_ty {
|
||||
Some(ty::TyS { sty: ty::Closure(def_id, substs), .. }) => {
|
||||
let fn_sig = substs.closure_sig(*def_id, self.tcx);
|
||||
let args = closure_args(&fn_sig);
|
||||
let ret = fn_sig.output().skip_binder().to_string();
|
||||
format!(" for the closure `fn({}) -> {}`", args, ret)
|
||||
}
|
||||
Some(ty) if is_named_and_not_impl_trait(ty) => {
|
||||
let ty = ty_to_string(ty);
|
||||
format!(" for `{}`", ty)
|
||||
}
|
||||
_ => String::new(),
|
||||
};
|
||||
|
||||
// When `name` corresponds to a type argument, show the path of the full type we're
|
||||
// trying to infer. In the following example, `ty_msg` contains
|
||||
|
|
@ -150,27 +237,58 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
// | consider giving `b` the explicit type `std::result::Result<i32, E>`, where
|
||||
// | the type parameter `E` is specified
|
||||
// ```
|
||||
let (ty_msg, suffix) = match &local_visitor.found_ty {
|
||||
Some(ty) if &ty.to_string() != "_" && name == "_" => {
|
||||
let ty = ty_to_string(ty);
|
||||
(format!(" for `{}`", ty),
|
||||
format!("the explicit type `{}`, with the type parameters specified", ty))
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
err_span,
|
||||
E0282,
|
||||
"type annotations needed{}",
|
||||
ty_msg,
|
||||
);
|
||||
|
||||
let suffix = match local_visitor.found_ty {
|
||||
Some(ty::TyS { sty: ty::Closure(def_id, substs), .. }) => {
|
||||
let fn_sig = substs.closure_sig(*def_id, self.tcx);
|
||||
let ret = fn_sig.output().skip_binder().to_string();
|
||||
|
||||
if let Some(ExprKind::Closure(_, decl, body_id, ..)) = local_visitor.found_closure {
|
||||
if let Some(body) = self.tcx.hir().krate().bodies.get(body_id) {
|
||||
closure_return_type_suggestion(
|
||||
span,
|
||||
&mut err,
|
||||
&decl.output,
|
||||
&body,
|
||||
&name,
|
||||
&ret,
|
||||
);
|
||||
// We don't want to give the other suggestions when the problem is the
|
||||
// closure return type.
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// This shouldn't be reachable, but just in case we leave a reasonable fallback.
|
||||
let args = closure_args(&fn_sig);
|
||||
// This suggestion is incomplete, as the user will get further type inference
|
||||
// errors due to the `_` placeholders and the introduction of `Box`, but it does
|
||||
// nudge them in the right direction.
|
||||
format!("a boxed closure type like `Box<dyn Fn({}) -> {}>`", args, ret)
|
||||
}
|
||||
Some(ty) if &ty.to_string() != "_" && ty.to_string() != name => {
|
||||
Some(ty) if is_named_and_not_impl_trait(ty) && name == "_" => {
|
||||
let ty = ty_to_string(ty);
|
||||
(format!(" for `{}`", ty),
|
||||
format!(
|
||||
"the explicit type `{}`, where the type parameter `{}` is specified",
|
||||
format!("the explicit type `{}`, with the type parameters specified", ty)
|
||||
}
|
||||
Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != name => {
|
||||
let ty = ty_to_string(ty);
|
||||
format!(
|
||||
"the explicit type `{}`, where the type parameter `{}` is specified",
|
||||
ty,
|
||||
name,
|
||||
))
|
||||
)
|
||||
}
|
||||
_ => (String::new(), "a type".to_owned()),
|
||||
_ => "a type".to_string(),
|
||||
};
|
||||
let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))];
|
||||
|
||||
if let Some(pattern) = local_visitor.found_arg_pattern {
|
||||
err_span = pattern.span;
|
||||
// We don't want to show the default label for closures.
|
||||
//
|
||||
// So, before clearing, the output would look something like this:
|
||||
|
|
@ -187,39 +305,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
// ^ consider giving this closure parameter the type `[_; 0]`
|
||||
// with the type parameter `_` specified
|
||||
// ```
|
||||
labels.clear();
|
||||
labels.push((
|
||||
err.span_label(
|
||||
pattern.span,
|
||||
format!("consider giving this closure parameter {}", suffix),
|
||||
));
|
||||
);
|
||||
} else if let Some(pattern) = local_visitor.found_local_pattern {
|
||||
if let Some(simple_ident) = pattern.simple_ident() {
|
||||
let msg = if let Some(simple_ident) = pattern.simple_ident() {
|
||||
match pattern.span.desugaring_kind() {
|
||||
None => labels.push((
|
||||
pattern.span,
|
||||
format!("consider giving `{}` {}", simple_ident, suffix),
|
||||
)),
|
||||
Some(DesugaringKind::ForLoop) => labels.push((
|
||||
pattern.span,
|
||||
"the element type for this iterator is not specified".to_owned(),
|
||||
)),
|
||||
_ => {}
|
||||
None => {
|
||||
format!("consider giving `{}` {}", simple_ident, suffix)
|
||||
}
|
||||
Some(DesugaringKind::ForLoop) => {
|
||||
"the element type for this iterator is not specified".to_string()
|
||||
}
|
||||
_ => format!("this needs {}", suffix),
|
||||
}
|
||||
} else {
|
||||
labels.push((pattern.span, format!("consider giving this pattern {}", suffix)));
|
||||
}
|
||||
};
|
||||
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
err_span,
|
||||
E0282,
|
||||
"type annotations needed{}",
|
||||
ty_msg,
|
||||
);
|
||||
|
||||
for (target_span, label_message) in labels {
|
||||
err.span_label(target_span, label_message);
|
||||
format!("consider giving this pattern {}", suffix)
|
||||
};
|
||||
err.span_label(pattern.span, msg);
|
||||
}
|
||||
if !err.span.span_labels().iter().any(|span_label| {
|
||||
span_label.label.is_some() && span_label.span == span
|
||||
}) && local_visitor.found_arg_pattern.is_none()
|
||||
{ // Avoid multiple labels pointing at `span`.
|
||||
err.span_label(span, InferCtxt::missing_type_msg(&name));
|
||||
}
|
||||
|
||||
err
|
||||
|
|
|
|||
|
|
@ -1060,7 +1060,7 @@ for LateContextAndPass<'a, 'tcx, T> {
|
|||
v: &'tcx hir::Variant,
|
||||
g: &'tcx hir::Generics,
|
||||
item_id: hir::HirId) {
|
||||
self.with_lint_attrs(v.node.id, &v.node.attrs, |cx| {
|
||||
self.with_lint_attrs(v.id, &v.attrs, |cx| {
|
||||
lint_callback!(cx, check_variant, v, g);
|
||||
hir_visit::walk_variant(cx, v, g, item_id);
|
||||
lint_callback!(cx, check_variant_post, v, g);
|
||||
|
|
@ -1236,7 +1236,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
}
|
||||
|
||||
fn visit_variant(&mut self, v: &'a ast::Variant, g: &'a ast::Generics, item_id: ast::NodeId) {
|
||||
self.with_lint_attrs(item_id, &v.node.attrs, |cx| {
|
||||
self.with_lint_attrs(item_id, &v.attrs, |cx| {
|
||||
run_early_pass!(cx, check_variant, v, g);
|
||||
ast_visit::walk_variant(cx, v, g, item_id);
|
||||
run_early_pass!(cx, check_variant_post, v, g);
|
||||
|
|
|
|||
|
|
@ -846,7 +846,7 @@ impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> {
|
|||
v: &'tcx hir::Variant,
|
||||
g: &'tcx hir::Generics,
|
||||
item_id: hir::HirId) {
|
||||
self.with_lint_attrs(v.node.id, &v.node.attrs, |builder| {
|
||||
self.with_lint_attrs(v.id, &v.attrs, |builder| {
|
||||
intravisit::walk_variant(builder, v, g, item_id);
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -366,12 +366,12 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
|
|||
match item.node {
|
||||
hir::ItemKind::Enum(ref enum_def, _) => {
|
||||
if allow_dead_code {
|
||||
self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id));
|
||||
self.worklist.extend(enum_def.variants.iter().map(|variant| variant.id));
|
||||
}
|
||||
|
||||
for variant in &enum_def.variants {
|
||||
if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() {
|
||||
self.struct_constructors.insert(ctor_hir_id, variant.node.id);
|
||||
if let Some(ctor_hir_id) = variant.data.ctor_hir_id() {
|
||||
self.struct_constructors.insert(ctor_hir_id, variant.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -497,7 +497,7 @@ impl DeadVisitor<'tcx> {
|
|||
&& !has_allow_dead_code_or_lang_attr(self.tcx, field.hir_id, &field.attrs)
|
||||
}
|
||||
|
||||
fn should_warn_about_variant(&mut self, variant: &hir::VariantKind) -> bool {
|
||||
fn should_warn_about_variant(&mut self, variant: &hir::Variant) -> bool {
|
||||
!self.symbol_is_live(variant.id)
|
||||
&& !has_allow_dead_code_or_lang_attr(self.tcx,
|
||||
variant.id,
|
||||
|
|
@ -596,8 +596,8 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
|
|||
variant: &'tcx hir::Variant,
|
||||
g: &'tcx hir::Generics,
|
||||
id: hir::HirId) {
|
||||
if self.should_warn_about_variant(&variant.node) {
|
||||
self.warn_dead_code(variant.node.id, variant.span, variant.node.ident.name,
|
||||
if self.should_warn_about_variant(&variant) {
|
||||
self.warn_dead_code(variant.id, variant.span, variant.ident.name,
|
||||
"variant", "constructed");
|
||||
} else {
|
||||
intravisit::walk_variant(self, variant, g, id);
|
||||
|
|
|
|||
|
|
@ -290,10 +290,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) {
|
||||
self.annotate(var.node.id, &var.node.attrs, var.span, AnnotationKind::Required,
|
||||
self.annotate(var.id, &var.attrs, var.span, AnnotationKind::Required,
|
||||
|v| {
|
||||
if let Some(ctor_hir_id) = var.node.data.ctor_hir_id() {
|
||||
v.annotate(ctor_hir_id, &var.node.attrs, var.span, AnnotationKind::Required,
|
||||
if let Some(ctor_hir_id) = var.data.ctor_hir_id() {
|
||||
v.annotate(ctor_hir_id, &var.attrs, var.span, AnnotationKind::Required,
|
||||
|_| {});
|
||||
}
|
||||
|
||||
|
|
@ -372,7 +372,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) {
|
||||
self.check_missing_stability(var.node.id, var.span, "variant");
|
||||
self.check_missing_stability(var.id, var.span, "variant");
|
||||
intravisit::walk_variant(self, var, g, item_id);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -189,8 +189,11 @@ impl<'tcx, Tag> Pointer<Tag> {
|
|||
Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () }
|
||||
}
|
||||
|
||||
/// Test if the pointer is "inbounds" of an allocation of the given size.
|
||||
/// A pointer is "inbounds" even if its offset is equal to the size; this is
|
||||
/// a "one-past-the-end" pointer.
|
||||
#[inline(always)]
|
||||
pub fn check_in_alloc(
|
||||
pub fn check_inbounds_alloc(
|
||||
self,
|
||||
allocation_size: Size,
|
||||
msg: CheckInAllocMsg,
|
||||
|
|
|
|||
|
|
@ -2068,6 +2068,9 @@ impl<'tcx> TyS<'tcx> {
|
|||
Error => { // ignore errors (#54954)
|
||||
ty::Binder::dummy(FnSig::fake())
|
||||
}
|
||||
Closure(..) => bug!(
|
||||
"to get the signature of a closure, use `closure_sig()` not `fn_sig()`",
|
||||
),
|
||||
_ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue