]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_resolve/late.rs
Auto merge of #65421 - estebank:variants, r=petrochenkov
[rust.git] / src / librustc_resolve / late.rs
index faf7696288bd11c81f7bb26c28e18bda2e700e4a..02f4345ac10ed1308bdedba8a91b565b8e786624 100644 (file)
@@ -331,22 +331,8 @@ fn error_code(self, has_unexpected_resolution: bool) -> &'static str {
     }
 }
 
-struct LateResolutionVisitor<'a, 'b> {
-    r: &'b mut Resolver<'a>,
-
-    /// The module that represents the current item scope.
-    parent_scope: ParentScope<'a>,
-
-    /// The current set of local scopes for types and values.
-    /// FIXME #4948: Reuse ribs to avoid allocation.
-    ribs: PerNS<Vec<Rib<'a>>>,
-
-    /// The current set of local scopes, for labels.
-    label_ribs: Vec<Rib<'a, NodeId>>,
-
-    /// The trait that the current context can refer to.
-    current_trait_ref: Option<(Module<'a>, TraitRef)>,
-
+#[derive(Default)]
+struct DiagnosticMetadata {
     /// The current trait's associated types' ident, used for diagnostic suggestions.
     current_trait_assoc_types: Vec<Ident>,
 
@@ -365,6 +351,29 @@ struct LateResolutionVisitor<'a, 'b> {
 
     /// Only used for better errors on `fn(): fn()`.
     current_type_ascription: Vec<Span>,
+
+    /// Only used for better errors on `let <pat>: <expr, not type>;`.
+    current_let_binding: Option<(Span, Option<Span>, Option<Span>)>,
+}
+
+struct LateResolutionVisitor<'a, 'b> {
+    r: &'b mut Resolver<'a>,
+
+    /// The module that represents the current item scope.
+    parent_scope: ParentScope<'a>,
+
+    /// The current set of local scopes for types and values.
+    /// FIXME #4948: Reuse ribs to avoid allocation.
+    ribs: PerNS<Vec<Rib<'a>>>,
+
+    /// The current set of local scopes, for labels.
+    label_ribs: Vec<Rib<'a, NodeId>>,
+
+    /// The trait that the current context can refer to.
+    current_trait_ref: Option<(Module<'a>, TraitRef)>,
+
+    /// Fields used to add information to diagnostic errors.
+    diagnostic_metadata: DiagnosticMetadata,
 }
 
 /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
@@ -388,7 +397,18 @@ fn visit_expr(&mut self, expr: &'tcx Expr) {
         self.resolve_expr(expr, None);
     }
     fn visit_local(&mut self, local: &'tcx Local) {
+        let local_spans = match local.pat.kind {
+            // We check for this to avoid tuple struct fields.
+            PatKind::Wild => None,
+            _ => Some((
+                local.pat.span,
+                local.ty.as_ref().map(|ty| ty.span),
+                local.init.as_ref().map(|init| init.span),
+            )),
+        };
+        let original = replace(&mut self.diagnostic_metadata.current_let_binding, local_spans);
         self.resolve_local(local);
+        self.diagnostic_metadata.current_let_binding = original;
     }
     fn visit_ty(&mut self, ty: &'tcx Ty) {
         match ty.kind {
@@ -430,7 +450,7 @@ fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) {
         }
     }
     fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, sp: Span, _: NodeId) {
-        let previous_value = replace(&mut self.current_function, Some(sp));
+        let previous_value = replace(&mut self.diagnostic_metadata.current_function, Some(sp));
         debug!("(resolving function) entering function");
         let rib_kind = match fn_kind {
             FnKind::ItemFn(..) => FnItemRibKind,
@@ -456,7 +476,7 @@ fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, sp: Spa
                 debug!("(resolving function) leaving function");
             })
         });
-        self.current_function = previous_value;
+        self.diagnostic_metadata.current_function = previous_value;
     }
 
     fn visit_generics(&mut self, generics: &'tcx Generics) {
@@ -490,7 +510,8 @@ fn visit_generics(&mut self, generics: &'tcx Generics) {
         // (We however cannot ban `Self` for defaults on *all* generic
         // lists; e.g. trait generics can usefully refer to `Self`,
         // such as in the case of `trait Add<Rhs = Self>`.)
-        if self.current_self_item.is_some() { // (`Some` if + only if we are in ADT's generics.)
+        if self.diagnostic_metadata.current_self_item.is_some() {
+            // (`Some` if + only if we are in ADT's generics.)
             default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
         }
 
@@ -542,12 +563,7 @@ fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b> {
             },
             label_ribs: Vec::new(),
             current_trait_ref: None,
-            current_trait_assoc_types: Vec::new(),
-            current_self_type: None,
-            current_self_item: None,
-            current_function: None,
-            unused_labels: Default::default(),
-            current_type_ascription: Vec::new(),
+            diagnostic_metadata: DiagnosticMetadata::default(),
         }
     }
 
@@ -907,16 +923,22 @@ fn with_constant_rib(&mut self, f: impl FnOnce(&mut Self)) {
 
     fn with_current_self_type<T>(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T {
         // Handle nested impls (inside fn bodies)
-        let previous_value = replace(&mut self.current_self_type, Some(self_type.clone()));
+        let previous_value = replace(
+            &mut self.diagnostic_metadata.current_self_type,
+            Some(self_type.clone()),
+        );
         let result = f(self);
-        self.current_self_type = previous_value;
+        self.diagnostic_metadata.current_self_type = previous_value;
         result
     }
 
     fn with_current_self_item<T>(&mut self, self_item: &Item, f: impl FnOnce(&mut Self) -> T) -> T {
-        let previous_value = replace(&mut self.current_self_item, Some(self_item.id));
+        let previous_value = replace(
+            &mut self.diagnostic_metadata.current_self_item,
+            Some(self_item.id),
+        );
         let result = f(self);
-        self.current_self_item = previous_value;
+        self.diagnostic_metadata.current_self_item = previous_value;
         result
     }
 
@@ -927,14 +949,14 @@ fn with_trait_items<T>(
         f: impl FnOnce(&mut Self) -> T,
     ) -> T {
         let trait_assoc_types = replace(
-            &mut self.current_trait_assoc_types,
+            &mut self.diagnostic_metadata.current_trait_assoc_types,
             trait_items.iter().filter_map(|item| match &item.kind {
                 TraitItemKind::Type(bounds, _) if bounds.len() == 0 => Some(item.ident),
                 _ => None,
             }).collect(),
         );
         let result = f(self);
-        self.current_trait_assoc_types = trait_assoc_types;
+        self.diagnostic_metadata.current_trait_assoc_types = trait_assoc_types;
         result
     }
 
@@ -1761,7 +1783,7 @@ fn resolve_qpath(
 
     fn with_resolved_label(&mut self, label: Option<Label>, id: NodeId, f: impl FnOnce(&mut Self)) {
         if let Some(label) = label {
-            self.unused_labels.insert(id, label.ident.span);
+            self.diagnostic_metadata.unused_labels.insert(id, label.ident.span);
             self.with_label_rib(NormalRibKind, |this| {
                 let ident = label.ident.modern_and_legacy();
                 this.label_ribs.last_mut().unwrap().bindings.insert(ident, id);
@@ -1865,7 +1887,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                     Some(node_id) => {
                         // Since this res is a label, it is never read.
                         self.r.label_res_map.insert(expr.id, node_id);
-                        self.unused_labels.remove(&node_id);
+                        self.diagnostic_metadata.unused_labels.remove(&node_id);
                     }
                 }
 
@@ -1927,9 +1949,9 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                 }
             }
             ExprKind::Type(ref type_expr, _) => {
-                self.current_type_ascription.push(type_expr.span);
+                self.diagnostic_metadata.current_type_ascription.push(type_expr.span);
                 visit::walk_expr(self, expr);
-                self.current_type_ascription.pop();
+                self.diagnostic_metadata.current_type_ascription.pop();
             }
             // `async |x| ...` gets desugared to `|x| future_from_generator(|| ...)`, so we need to
             // resolve the arguments within the proper scopes so that usages of them inside the
@@ -2088,7 +2110,7 @@ impl<'a> Resolver<'a> {
     pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
         let mut late_resolution_visitor = LateResolutionVisitor::new(self);
         visit::walk_crate(&mut late_resolution_visitor, krate);
-        for (id, span) in late_resolution_visitor.unused_labels.iter() {
+        for (id, span) in late_resolution_visitor.diagnostic_metadata.unused_labels.iter() {
             self.session.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label");
         }
     }