Skip to content

Commit

Permalink
Rollup merge of rust-lang#30320 - nrc:err-names, r=@nikomatsakis
Browse files Browse the repository at this point in the history
We can now handle name resolution errors and get past type checking (if we're a bit lucky). This is the first step towards doing code completion for partial programs (we need error recovery in the parser and early access to save-analysis).
  • Loading branch information
Manishearth committed Dec 16, 2015
2 parents ac2c5ff + 18b4fe0 commit 948669f
Show file tree
Hide file tree
Showing 47 changed files with 308 additions and 213 deletions.
5 changes: 3 additions & 2 deletions src/librustc/middle/check_static_recursion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ pub fn check_crate<'ast>(sess: &Session,
ast_map: ast_map,
discriminant_map: RefCell::new(NodeMap()),
};
krate.visit_all_items(&mut visitor);
sess.abort_if_errors();
sess.abort_if_new_errors(|| {
krate.visit_all_items(&mut visitor);
});
}

struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
Expand Down
6 changes: 4 additions & 2 deletions src/librustc/middle/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub enum Def {
DefStruct(DefId),
DefLabel(ast::NodeId),
DefMethod(DefId),
DefErr,
}

/// The result of resolving a path.
Expand Down Expand Up @@ -124,7 +125,7 @@ impl Def {
DefVariant(..) | DefTy(..) | DefAssociatedTy(..) |
DefTyParam(..) | DefUse(..) | DefStruct(..) | DefTrait(..) |
DefMethod(..) | DefConst(..) | DefAssociatedConst(..) |
DefPrimTy(..) | DefLabel(..) | DefSelfTy(..) => {
DefPrimTy(..) | DefLabel(..) | DefSelfTy(..) | DefErr => {
panic!("attempted .def_id() on invalid {:?}", self)
}
}
Expand All @@ -142,7 +143,8 @@ impl Def {

DefLabel(..) |
DefPrimTy(..) |
DefSelfTy(..) => {
DefSelfTy(..) |
DefErr => {
panic!("attempted .def_id() on invalid def: {:?}", self)
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,8 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
note: NoteNone
}))
}

def::DefErr => panic!("DefErr in memory categorization")
}
}

Expand Down Expand Up @@ -1196,7 +1198,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
(*op)(self, cmt.clone(), pat);

let opt_def = if let Some(path_res) = self.tcx().def_map.borrow().get(&pat.id) {
if path_res.depth != 0 {
if path_res.depth != 0 || path_res.base_def == def::DefErr {
// Since patterns can be associated constants
// which are resolved during typeck, we might have
// some unresolved patterns reaching this stage
Expand Down Expand Up @@ -1261,7 +1263,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
_ => {
self.tcx().sess.span_bug(
pat.span,
"enum pattern didn't resolve to enum or struct");
&format!("enum pattern didn't resolve to enum or struct {:?}", opt_def));
}
}
}
Expand Down
17 changes: 9 additions & 8 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,16 @@ static ROOT_SCOPE: ScopeChain<'static> = RootScope;

pub fn krate(sess: &Session, krate: &hir::Crate, def_map: &DefMap) -> NamedRegionMap {
let mut named_region_map = NodeMap();
krate.visit_all_items(&mut LifetimeContext {
sess: sess,
named_region_map: &mut named_region_map,
scope: &ROOT_SCOPE,
def_map: def_map,
trait_ref_hack: false,
labels_in_fn: vec![],
sess.abort_if_new_errors(|| {
krate.visit_all_items(&mut LifetimeContext {
sess: sess,
named_region_map: &mut named_region_map,
scope: &ROOT_SCOPE,
def_map: def_map,
trait_ref_hack: false,
labels_in_fn: vec![],
});
});
sess.abort_if_errors();
named_region_map
}

Expand Down
3 changes: 1 addition & 2 deletions src/librustc/middle/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2100,9 +2100,8 @@ impl<'tcx> ctxt<'tcx> {
}) => {
true
}

Some(&def::PathResolution { base_def: def::DefErr, .. })=> true,
Some(..) => false,

None => self.sess.span_bug(expr.span, &format!(
"no def for path {}", expr.id))
}
Expand Down
9 changes: 9 additions & 0 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,15 @@ impl Session {
_ => {}
}
}
pub fn abort_if_new_errors<F>(&self, mut f: F)
where F: FnMut()
{
let count = self.err_count();
f();
if self.err_count() > count {
self.abort_if_errors();
}
}
pub fn span_warn(&self, sp: Span, msg: &str) {
if self.can_print_warnings {
self.diagnostic().span_warn(sp, msg)
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_metadata/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,8 @@ impl tr for def::Def {
def::DefUpvar(did1, nid1, index, nid2)
}
def::DefStruct(did) => def::DefStruct(did.tr(dcx)),
def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid))
def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid)),
def::DefErr => def::DefErr,
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
DefUse(..) |
DefUpvar(..) |
DefLabel(..) |
DefSelfTy(..) => {
DefSelfTy(..) |
DefErr => {
panic!("didn't expect `{:?}`", def);
}
}
Expand Down
29 changes: 28 additions & 1 deletion src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
Ok(def) => self.record_def(tref.trait_ref.ref_id, def),
Err(_) => {
// error already reported
self.record_def(tref.trait_ref.ref_id, err_path_resolution())
}
}
intravisit::walk_poly_trait_ref(self, tref, m);
Expand Down Expand Up @@ -2005,6 +2006,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
prefix.span,
ResolutionError::FailedToResolve(
&path_names_to_string(prefix, 0)));
self.record_def(item.id, err_path_resolution());
}
}
}
Expand Down Expand Up @@ -2164,6 +2166,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
resolve_error(self,
eq_pred.span,
ResolutionError::UndeclaredAssociatedType);
self.record_def(eq_pred.id, err_path_resolution());
}
}
}
Expand Down Expand Up @@ -2194,6 +2197,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.record_def(trait_ref.ref_id, path_res);
new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
new_id = Some(path_res.base_def.def_id());
} else {
self.record_def(trait_ref.ref_id, err_path_resolution());
}
intravisit::walk_trait_ref(self, trait_ref);
}
Expand Down Expand Up @@ -2463,6 +2468,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.record_def(ty.id, def);
}
None => {
self.record_def(ty.id, err_path_resolution());

// Keep reporting some errors even if they're ignored above.
self.resolve_path(ty.id, path, 0, TypeNS, true);

Expand Down Expand Up @@ -2545,6 +2552,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(
renamed)
);
self.record_def(pattern.id, err_path_resolution());
}
FoundConst(def, lp, _) if const_ok => {
debug!("(resolving pattern) resolving `{}` to constant", renamed);
Expand All @@ -2564,6 +2572,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ResolutionError::OnlyIrrefutablePatternsAllowedHere(def.def_id(),
name)
);
self.record_def(pattern.id, err_path_resolution());
}
BareIdentifierPatternUnresolved => {
debug!("(resolving pattern) binding `{}`", renamed);
Expand Down Expand Up @@ -2647,6 +2656,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
resolve_error(&self,
path.span,
ResolutionError::StaticVariableReference);
self.record_def(pattern.id, err_path_resolution());
}
_ => {
// If anything ends up here entirely resolved,
Expand All @@ -2665,6 +2675,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
.name
.as_str())
);
self.record_def(pattern.id, err_path_resolution());
} else {
let const_name = path.segments
.last()
Expand All @@ -2684,6 +2695,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ResolutionError::UnresolvedEnumVariantStructOrConst(
&path.segments.last().unwrap().identifier.name.as_str())
);
self.record_def(pattern.id, err_path_resolution());
}
intravisit::walk_path(self, path);
}
Expand Down Expand Up @@ -2726,6 +2738,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&path.segments.last().unwrap().identifier.name.as_str()
)
);
self.record_def(pattern.id, err_path_resolution());
}
}
} else {
Expand All @@ -2737,6 +2750,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
.identifier
.name
.as_str()));
self.record_def(pattern.id, err_path_resolution());
}
intravisit::walk_pat(self, pattern);
}
Expand All @@ -2754,6 +2768,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ResolutionError::DoesNotNameAStruct(
&*path_names_to_string(path, 0))
);
self.record_def(pattern.id, err_path_resolution());
}
}
intravisit::walk_path(self, path);
Expand Down Expand Up @@ -3430,6 +3445,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} else {
self.session.span_help(expr.span, &msg);
}
self.record_def(expr.id, err_path_resolution());
} else {
// Write the result into the def map.
debug!("(resolving expr) resolved `{}`",
Expand All @@ -3454,6 +3470,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let type_res = self.with_no_errors(|this| {
this.resolve_path(expr.id, path, 0, TypeNS, false)
});

self.record_def(expr.id, err_path_resolution());
match type_res.map(|r| r.base_def) {
Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => {
resolve_error(
Expand Down Expand Up @@ -3540,6 +3558,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ResolutionError::DoesNotNameAStruct(
&*path_names_to_string(path, 0))
);
self.record_def(expr.id, err_path_resolution());
}
}

Expand All @@ -3562,6 +3581,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
match self.search_label(label.node.name) {
None => {
self.record_def(expr.id, err_path_resolution());
resolve_error(self,
label.span,
ResolutionError::UndeclaredLabel(&label.node.name.as_str()))
Expand Down Expand Up @@ -3811,6 +3831,14 @@ fn module_to_string(module: &Module) -> String {
names_to_string(&names.into_iter().rev().collect::<Vec<ast::Name>>())
}

fn err_path_resolution() -> PathResolution {
PathResolution {
base_def: DefErr,
last_private: LastMod(AllPublic),
depth: 0,
}
}


pub struct CrateMap {
pub def_map: RefCell<DefMap>,
Expand All @@ -3836,7 +3864,6 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, None);

resolver.resolve_crate(krate);
session.abort_if_errors();

check_unused::check_crate(&mut resolver, krate);

Expand Down
3 changes: 2 additions & 1 deletion src/librustc_trans/save/dump_csv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
def::DefTyParam(..) |
def::DefUse(_) |
def::DefMethod(..) |
def::DefPrimTy(_) => {
def::DefPrimTy(_) |
def::DefErr => {
self.sess.span_bug(span,
&format!("lookup_def_kind for unexpected item: {:?}", def));
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &hir::Expr)
def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) |
def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) |
def::DefUse(..) | def::DefLabel(..) | def::DefTyParam(..) |
def::DefSelfTy(..) => {
def::DefSelfTy(..) | def::DefErr => {
bcx.tcx().sess.span_bug(
ref_expr.span,
&format!("cannot translate def {:?} \
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,9 @@ fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &hir::TraitRef) -> DefId
let path = &trait_ref.path;
match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) {
def::DefTrait(trait_def_id) => trait_def_id,
def::DefErr => {
this.tcx().sess.fatal("cannot continue compilation due to previous error");
}
_ => {
span_fatal!(this.tcx().sess, path.span, E0245, "`{}` is not a trait",
path);
Expand Down Expand Up @@ -1533,6 +1536,9 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
def::DefPrimTy(prim_ty) => {
prim_ty_to_ty(tcx, base_segments, prim_ty)
}
def::DefErr => {
return this.tcx().types.err;
}
_ => {
let id_node = tcx.map.as_local_node_id(def.def_id()).unwrap();
span_err!(tcx.sess, span, E0248,
Expand Down
Loading

0 comments on commit 948669f

Please sign in to comment.