]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_typeck/check/mod.rs
Make name resolution errors non-fatal
[rust.git] / src / librustc_typeck / check / mod.rs
index a50213202b82c8cb94905f2ac3c65aa0c5f53683..e43c806dc41e609f2e78a83c37209489a69f09df 100644 (file)
@@ -385,61 +385,60 @@ fn visit_item(&mut self, i: &'tcx hir::Item) {
 }
 
 pub fn check_wf_old(ccx: &CrateCtxt) {
-    // FIXME(#25759). The new code below is much more reliable but (for now)
-    // only generates warnings. So as to ensure that we continue
-    // getting errors where we used to get errors, we run the old wf
-    // code first and abort if it encounters any errors. If no abort
-    // comes, we run the new code and issue warnings.
-    let krate = ccx.tcx.map.krate();
-    let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
-    krate.visit_all_items(&mut visit);
-
     // If types are not well-formed, it leads to all manner of errors
     // downstream, so stop reporting errors at this point.
-    ccx.tcx.sess.abort_if_errors();
+    ccx.tcx.sess.abort_if_new_errors(|| {
+        // FIXME(#25759). The new code below is much more reliable but (for now)
+        // only generates warnings. So as to ensure that we continue
+        // getting errors where we used to get errors, we run the old wf
+        // code first and abort if it encounters any errors. If no abort
+        // comes, we run the new code and issue warnings.
+        let krate = ccx.tcx.map.krate();
+        let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
+        krate.visit_all_items(&mut visit);
+    });
 }
 
 pub fn check_wf_new(ccx: &CrateCtxt) {
-    let krate = ccx.tcx.map.krate();
-    let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(ccx);
-    krate.visit_all_items(&mut visit);
-
-    // If types are not well-formed, it leads to all manner of errors
-    // downstream, so stop reporting errors at this point.
-    ccx.tcx.sess.abort_if_errors();
+    ccx.tcx.sess.abort_if_new_errors(|| {
+        let krate = ccx.tcx.map.krate();
+        let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(ccx);
+        krate.visit_all_items(&mut visit);
+    });
 }
 
 pub fn check_item_types(ccx: &CrateCtxt) {
-    let krate = ccx.tcx.map.krate();
-    let mut visit = CheckItemTypesVisitor { ccx: ccx };
-    krate.visit_all_items(&mut visit);
-    ccx.tcx.sess.abort_if_errors();
+    ccx.tcx.sess.abort_if_new_errors(|| {
+        let krate = ccx.tcx.map.krate();
+        let mut visit = CheckItemTypesVisitor { ccx: ccx };
+        krate.visit_all_items(&mut visit);
+    });
 }
 
 pub fn check_item_bodies(ccx: &CrateCtxt) {
-    let krate = ccx.tcx.map.krate();
-    let mut visit = CheckItemBodiesVisitor { ccx: ccx };
-    krate.visit_all_items(&mut visit);
-
-    ccx.tcx.sess.abort_if_errors();
+    ccx.tcx.sess.abort_if_new_errors(|| {
+        let krate = ccx.tcx.map.krate();
+        let mut visit = CheckItemBodiesVisitor { ccx: ccx };
+        krate.visit_all_items(&mut visit);
+    });
 }
 
 pub fn check_drop_impls(ccx: &CrateCtxt) {
-    let drop_trait = match ccx.tcx.lang_items.drop_trait() {
-        Some(id) => ccx.tcx.lookup_trait_def(id), None => { return }
-    };
-    drop_trait.for_each_impl(ccx.tcx, |drop_impl_did| {
-        if drop_impl_did.is_local() {
-            match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
-                Ok(()) => {}
-                Err(()) => {
-                    assert!(ccx.tcx.sess.has_errors());
+    ccx.tcx.sess.abort_if_new_errors(|| {
+        let drop_trait = match ccx.tcx.lang_items.drop_trait() {
+            Some(id) => ccx.tcx.lookup_trait_def(id), None => { return }
+        };
+        drop_trait.for_each_impl(ccx.tcx, |drop_impl_did| {
+            if drop_impl_did.is_local() {
+                match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
+                    Ok(()) => {}
+                    Err(()) => {
+                        assert!(ccx.tcx.sess.has_errors());
+                    }
                 }
             }
-        }
+        });
     });
-
-    ccx.tcx.sess.abort_if_errors();
 }
 
 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
@@ -891,75 +890,71 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     for impl_item in impl_items {
         let ty_impl_item = ccx.tcx.impl_or_trait_item(ccx.tcx.map.local_def_id(impl_item.id));
         let ty_trait_item = trait_items.iter()
-            .find(|ac| ac.name() == ty_impl_item.name())
-            .unwrap_or_else(|| {
-                // This is checked by resolve
-                tcx.sess.span_bug(impl_item.span,
-                                  &format!("impl-item `{}` is not a member of `{:?}`",
-                                           ty_impl_item.name(),
-                                           impl_trait_ref));
-            });
-        match impl_item.node {
-            hir::ImplItemKind::Const(..) => {
-                let impl_const = match ty_impl_item {
-                    ty::ConstTraitItem(ref cti) => cti,
-                    _ => tcx.sess.span_bug(impl_item.span, "non-const impl-item for const")
-                };
+            .find(|ac| ac.name() == ty_impl_item.name());
 
-                // Find associated const definition.
-                if let &ty::ConstTraitItem(ref trait_const) = ty_trait_item {
-                    compare_const_impl(ccx.tcx,
-                                       &impl_const,
-                                       impl_item.span,
-                                       trait_const,
-                                       &*impl_trait_ref);
-                } else {
-                    span_err!(tcx.sess, impl_item.span, E0323,
-                              "item `{}` is an associated const, \
-                              which doesn't match its trait `{:?}`",
-                              impl_const.name,
-                              impl_trait_ref)
+        if let Some(ty_trait_item) = ty_trait_item {
+            match impl_item.node {
+                hir::ImplItemKind::Const(..) => {
+                    let impl_const = match ty_impl_item {
+                        ty::ConstTraitItem(ref cti) => cti,
+                        _ => tcx.sess.span_bug(impl_item.span, "non-const impl-item for const")
+                    };
+
+                    // Find associated const definition.
+                    if let &ty::ConstTraitItem(ref trait_const) = ty_trait_item {
+                        compare_const_impl(ccx.tcx,
+                                           &impl_const,
+                                           impl_item.span,
+                                           trait_const,
+                                           &*impl_trait_ref);
+                    } else {
+                        span_err!(tcx.sess, impl_item.span, E0323,
+                                  "item `{}` is an associated const, \
+                                  which doesn't match its trait `{:?}`",
+                                  impl_const.name,
+                                  impl_trait_ref)
+                    }
                 }
-            }
-            hir::ImplItemKind::Method(ref sig, ref body) => {
-                check_trait_fn_not_const(ccx, impl_item.span, sig.constness);
+                hir::ImplItemKind::Method(ref sig, ref body) => {
+                    check_trait_fn_not_const(ccx, impl_item.span, sig.constness);
 
-                let impl_method = match ty_impl_item {
-                    ty::MethodTraitItem(ref mti) => mti,
-                    _ => tcx.sess.span_bug(impl_item.span, "non-method impl-item for method")
-                };
+                    let impl_method = match ty_impl_item {
+                        ty::MethodTraitItem(ref mti) => mti,
+                        _ => tcx.sess.span_bug(impl_item.span, "non-method impl-item for method")
+                    };
 
-                if let &ty::MethodTraitItem(ref trait_method) = ty_trait_item {
-                    compare_impl_method(ccx.tcx,
-                                        &impl_method,
-                                        impl_item.span,
-                                        body.id,
-                                        &trait_method,
-                                        &impl_trait_ref);
-                } else {
-                    span_err!(tcx.sess, impl_item.span, E0324,
-                              "item `{}` is an associated method, \
-                              which doesn't match its trait `{:?}`",
-                              impl_method.name,
-                              impl_trait_ref)
+                    if let &ty::MethodTraitItem(ref trait_method) = ty_trait_item {
+                        compare_impl_method(ccx.tcx,
+                                            &impl_method,
+                                            impl_item.span,
+                                            body.id,
+                                            &trait_method,
+                                            &impl_trait_ref);
+                    } else {
+                        span_err!(tcx.sess, impl_item.span, E0324,
+                                  "item `{}` is an associated method, \
+                                  which doesn't match its trait `{:?}`",
+                                  impl_method.name,
+                                  impl_trait_ref)
+                    }
                 }
-            }
-            hir::ImplItemKind::Type(_) => {
-                let impl_type = match ty_impl_item {
-                    ty::TypeTraitItem(ref tti) => tti,
-                    _ => tcx.sess.span_bug(impl_item.span, "non-type impl-item for type")
-                };
+                hir::ImplItemKind::Type(_) => {
+                    let impl_type = match ty_impl_item {
+                        ty::TypeTraitItem(ref tti) => tti,
+                        _ => tcx.sess.span_bug(impl_item.span, "non-type impl-item for type")
+                    };
 
-                if let &ty::TypeTraitItem(ref at) = ty_trait_item {
-                    if let Some(_) = at.ty {
-                        overridden_associated_type = Some(impl_item);
+                    if let &ty::TypeTraitItem(ref at) = ty_trait_item {
+                        if let Some(_) = at.ty {
+                            overridden_associated_type = Some(impl_item);
+                        }
+                    } else {
+                        span_err!(tcx.sess, impl_item.span, E0325,
+                                  "item `{}` is an associated type, \
+                                  which doesn't match its trait `{:?}`",
+                                  impl_type.name,
+                                  impl_trait_ref)
                     }
-                } else {
-                    span_err!(tcx.sess, impl_item.span, E0325,
-                              "item `{}` is an associated type, \
-                              which doesn't match its trait `{:?}`",
-                              impl_type.name,
-                              impl_trait_ref)
                 }
             }
         }
@@ -3192,6 +3187,10 @@ fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
 
         // Find the relevant variant
         let def = lookup_full_def(tcx, path.span, expr.id);
+        if def == def::DefErr {
+            check_struct_fields_on_error(fcx, expr.id, fields, base_expr);
+            return;
+        }
         let (adt, variant) = match fcx.def_struct_variant(def, path.span) {
             Some((adt, variant)) => (adt, variant),
             None => {
@@ -3370,17 +3369,21 @@ fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
           if let Some((opt_ty, segments, def)) =
                   resolve_ty_and_def_ufcs(fcx, path_res, opt_self_ty, path,
                                           expr.span, expr.id) {
-              let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
-                                                                            expr.span,
-                                                                            def);
-              instantiate_path(fcx,
-                               segments,
-                               scheme,
-                               &predicates,
-                               opt_ty,
-                               def,
-                               expr.span,
-                               id);
+              if def != def::DefErr {
+                  let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
+                                                                                expr.span,
+                                                                                def);
+                  instantiate_path(fcx,
+                                   segments,
+                                   scheme,
+                                   &predicates,
+                                   opt_ty,
+                                   def,
+                                   expr.span,
+                                   id);
+              } else {
+                  fcx.write_ty(id, fcx.tcx().types.err);
+              }
           }
 
           // We always require that the type provided as the value for
@@ -4325,7 +4328,8 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefForeignMod(..) |
         def::DefUse(..) |
         def::DefLabel(..) |
-        def::DefSelfTy(..) => {
+        def::DefSelfTy(..) |
+        def::DefErr => {
             fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
         }
     }
@@ -4495,7 +4499,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefLocal(..) |
         def::DefUse(..) |
         def::DefLabel(..) |
-        def::DefUpvar(..) => {
+        def::DefUpvar(..) |
+        def::DefErr => {
             segment_spaces = vec![None; segments.len()];
         }
     }