diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index a2c09c36795..12d3465e518 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -26,12 +26,17 @@ use Bound; /// A set based on a B-Tree. /// -/// See BTreeMap's documentation for a detailed discussion of this collection's performance +/// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance /// benefits and drawbacks. /// /// It is a logic error for an item to be modified in such a way that the item's ordering relative -/// to any other item, as determined by the `Ord` trait, changes while it is in the set. This is -/// normally only possible through `Cell`, `RefCell`, global state, I/O, or unsafe code. +/// to any other item, as determined by the [`Ord`] trait, changes while it is in the set. This is +/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. +/// +/// [`BTreeMap`]: ../struct.BTreeMap.html +/// [`Ord`]: ../../core/cmp/trait.Ord.html +/// [`Cell`]: ../../std/cell/struct.Cell.html +/// [`RefCell`]: ../../std/cell/struct.RefCell.html #[derive(Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] #[stable(feature = "rust1", since = "1.0.0")] pub struct BTreeSet { diff --git a/src/librustc/middle/check_static_recursion.rs b/src/librustc/middle/check_static_recursion.rs index 85a3117196a..0882f3f1137 100644 --- a/src/librustc/middle/check_static_recursion.rs +++ b/src/librustc/middle/check_static_recursion.rs @@ -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> { diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index b1d24187957..809c6084b76 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -52,6 +52,7 @@ pub enum Def { DefStruct(DefId), DefLabel(ast::NodeId), DefMethod(DefId), + DefErr, } /// The result of resolving a path. @@ -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) } } @@ -142,7 +143,8 @@ impl Def { DefLabel(..) | DefPrimTy(..) | - DefSelfTy(..) => { + DefSelfTy(..) | + DefErr => { panic!("attempted .def_id() on invalid def: {:?}", self) } } diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index 30cf6344e23..e148aecd241 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -18,6 +18,7 @@ pub use self::RegionResolutionError::*; pub use self::VarValue::*; use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable}; +use super::unify_key; use rustc_data_structures::graph::{self, Direction, NodeIndex}; use rustc_data_structures::unify::{self, UnificationTable}; @@ -345,10 +346,13 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { } pub fn new_region_var(&self, origin: RegionVariableOrigin) -> RegionVid { - let id = self.num_vars(); + let vid = RegionVid { index: self.num_vars() }; self.var_origins.borrow_mut().push(origin.clone()); - let vid = self.unification_table.borrow_mut().new_key(()); - assert_eq!(vid.index, id); + + let u_vid = self.unification_table.borrow_mut().new_key( + unify_key::RegionVidKey { min_vid: vid } + ); + assert_eq!(vid, u_vid); if self.in_snapshot() { self.undo_log.borrow_mut().push(AddVar(vid)); } @@ -581,7 +585,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { } pub fn opportunistic_resolve_var(&self, rid: RegionVid) -> ty::Region { - ty::ReVar(self.unification_table.borrow_mut().find(rid)) + ty::ReVar(self.unification_table.borrow_mut().find_value(rid).min_vid) } fn combine_map(&self, t: CombineMapType) -> &RefCell { diff --git a/src/librustc/middle/infer/unify_key.rs b/src/librustc/middle/infer/unify_key.rs index 85d7d67a0e3..c83231930f5 100644 --- a/src/librustc/middle/infer/unify_key.rs +++ b/src/librustc/middle/infer/unify_key.rs @@ -10,7 +10,7 @@ use syntax::ast; use middle::ty::{self, IntVarValue, Ty}; -use rustc_data_structures::unify::UnifyKey; +use rustc_data_structures::unify::{Combine, UnifyKey}; pub trait ToType<'tcx> { fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>; @@ -23,8 +23,28 @@ impl UnifyKey for ty::IntVid { fn tag(_: Option) -> &'static str { "IntVid" } } +#[derive(PartialEq, Copy, Clone, Debug)] +pub struct RegionVidKey { + /// The minimum region vid in the unification set. This is needed + /// to have a canonical name for a type to prevent infinite + /// recursion. + pub min_vid: ty::RegionVid +} + +impl Combine for RegionVidKey { + fn combine(&self, other: &RegionVidKey) -> RegionVidKey { + let min_vid = if self.min_vid.index < other.min_vid.index { + self.min_vid + } else { + other.min_vid + }; + + RegionVidKey { min_vid: min_vid } + } +} + impl UnifyKey for ty::RegionVid { - type Value = (); + type Value = RegionVidKey; fn index(&self) -> u32 { self.index } fn from_index(i: u32) -> ty::RegionVid { ty::RegionVid { index: i } } fn tag(_: Option) -> &'static str { "RegionVid" } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 70ef112efba..f869cac9236 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -609,6 +609,8 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> { note: NoteNone })) } + + def::DefErr => panic!("DefErr in memory categorization") } } @@ -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 @@ -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)); } } } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index b37b3070310..15d1546d2d5 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -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 } diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index 7477c4dead0..5161a28ca31 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -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)) } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 7bf96b41dce..b7bfc2f8db5 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -156,6 +156,15 @@ impl Session { _ => {} } } + pub fn abort_if_new_errors(&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) diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 47f29a26db1..c07a27043c2 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -33,6 +33,8 @@ use rustc_front::hir::{Expr, FnDecl, Block, Pat}; use rustc_front::intravisit; use rustc_front::intravisit::Visitor; +use self::restrictions::RestrictionResult; + mod lifetime; mod restrictions; mod gather_moves; @@ -354,12 +356,12 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { // Create the loan record (if needed). let loan = match restr { - restrictions::Safe => { + RestrictionResult::Safe => { // No restrictions---no loan record necessary return; } - restrictions::SafeIf(loan_path, restricted_paths) => { + RestrictionResult::SafeIf(loan_path, restricted_paths) => { let loan_scope = match loan_region { ty::ReScope(scope) => scope, diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs index cb75180b474..2a0d8ef2766 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs @@ -10,8 +10,6 @@ //! Computes the restrictions that result from a borrow. -pub use self::RestrictionResult::*; - use borrowck::*; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; @@ -69,19 +67,19 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { // are inherently non-aliasable, they can only be // accessed later through the borrow itself and hence // must inherently comply with its terms. - Safe + RestrictionResult::Safe } Categorization::Local(local_id) => { // R-Variable, locally declared let lp = new_lp(LpVar(local_id)); - SafeIf(lp.clone(), vec![lp]) + RestrictionResult::SafeIf(lp.clone(), vec![lp]) } Categorization::Upvar(mc::Upvar { id, .. }) => { // R-Variable, captured into closure let lp = new_lp(LpUpvar(id)); - SafeIf(lp.clone(), vec![lp]) + RestrictionResult::SafeIf(lp.clone(), vec![lp]) } Categorization::Downcast(cmt_base, _) => { @@ -106,7 +104,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { } Categorization::StaticItem => { - Safe + RestrictionResult::Safe } Categorization::Deref(cmt_base, _, pk) => { @@ -133,11 +131,11 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { cmt: cmt_base, code: err_borrowed_pointer_too_short( self.loan_region, lt)}); - return Safe; + return RestrictionResult::Safe; } match bk { - ty::ImmBorrow => Safe, + ty::ImmBorrow => RestrictionResult::Safe, ty::MutBorrow | ty::UniqueImmBorrow => { // R-Deref-Mut-Borrowed // @@ -150,7 +148,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { } } // Borrowck is not relevant for raw pointers - mc::UnsafePtr(..) => Safe + mc::UnsafePtr(..) => RestrictionResult::Safe } } } @@ -161,12 +159,12 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { cmt: &mc::cmt<'tcx>, elem: LoanPathElem) -> RestrictionResult<'tcx> { match result { - Safe => Safe, - SafeIf(base_lp, mut base_vec) => { + RestrictionResult::Safe => RestrictionResult::Safe, + RestrictionResult::SafeIf(base_lp, mut base_vec) => { let v = LpExtend(base_lp, cmt.mutbl, elem); let lp = Rc::new(LoanPath::new(v, cmt.ty)); base_vec.push(lp.clone()); - SafeIf(lp, base_vec) + RestrictionResult::SafeIf(lp, base_vec) } } } diff --git a/src/librustc_data_structures/unify/mod.rs b/src/librustc_data_structures/unify/mod.rs index 4d79b1a64c1..c6da70eef75 100644 --- a/src/librustc_data_structures/unify/mod.rs +++ b/src/librustc_data_structures/unify/mod.rs @@ -37,6 +37,16 @@ pub trait UnifyKey : Copy + Clone + Debug + PartialEq { fn tag(k: Option) -> &'static str; } +/// This trait is implemented for unify values that can be +/// combined. This relation should be a monoid. +pub trait Combine { + fn combine(&self, other: &Self) -> Self; +} + +impl Combine for () { + fn combine(&self, _other: &()) {} +} + /// Value of a unification key. We implement Tarjan's union-find /// algorithm: when two keys are unified, one of them is converted /// into a "redirect" pointing at the other. These redirects form a @@ -243,8 +253,8 @@ impl sv::SnapshotVecDelegate for Delegate { /////////////////////////////////////////////////////////////////////////// // Base union-find algorithm, where we are just making sets -impl<'tcx,K> UnificationTable - where K : UnifyKey, +impl<'tcx,K:UnifyKey> UnificationTable + where K::Value: Combine { pub fn union(&mut self, a_id: K, b_id: K) { let node_a = self.get(a_id); @@ -252,7 +262,8 @@ impl<'tcx,K> UnificationTable let a_id = node_a.key(); let b_id = node_b.key(); if a_id != b_id { - self.unify(node_a, node_b, ()); + let new_value = node_a.value.combine(&node_b.value); + self.unify(node_a, node_b, new_value); } } @@ -260,6 +271,10 @@ impl<'tcx,K> UnificationTable self.get(id).key() } + pub fn find_value(&mut self, id: K) -> K::Value { + self.get(id).value + } + pub fn unioned(&mut self, a_id: K, b_id: K) -> bool { self.find(a_id) == self.find(b_id) } diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 4c47d3ab990..d43ffb0fc3f 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -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, } } } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 0deef91a0f6..8b5b6ff781e 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -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); } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c32acb7bb26..4d5978f5560 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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); @@ -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()); } } } @@ -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()); } } } @@ -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); } @@ -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); @@ -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); @@ -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); @@ -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, @@ -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() @@ -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); } @@ -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 { @@ -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); } @@ -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); @@ -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 `{}`", @@ -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( @@ -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()); } } @@ -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())) @@ -3811,6 +3831,14 @@ fn module_to_string(module: &Module) -> String { names_to_string(&names.into_iter().rev().collect::>()) } +fn err_path_resolution() -> PathResolution { + PathResolution { + base_def: DefErr, + last_private: LastMod(AllPublic), + depth: 0, + } +} + pub struct CrateMap { pub def_map: RefCell, @@ -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); diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index 2964d87ec1c..b3e7ed7ed5e 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -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)); } diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 4aa7c0ff587..a22c12588e5 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -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 {:?} \ diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index b83f0a5be6f..752dd6e57f6 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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); @@ -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, diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 38c714fa8f2..efcc08c69f8 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -142,20 +142,24 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, return; } } - let const_did = tcx.def_map.borrow().get(&pat.id).unwrap().def_id(); - let const_scheme = tcx.lookup_item_type(const_did); - assert!(const_scheme.generics.is_empty()); - let const_ty = pcx.fcx.instantiate_type_scheme(pat.span, - &Substs::empty(), - &const_scheme.ty); - fcx.write_ty(pat.id, const_ty); + if let Some(pat_def) = tcx.def_map.borrow().get(&pat.id) { + let const_did = pat_def.def_id(); + let const_scheme = tcx.lookup_item_type(const_did); + assert!(const_scheme.generics.is_empty()); + let const_ty = pcx.fcx.instantiate_type_scheme(pat.span, + &Substs::empty(), + &const_scheme.ty); + fcx.write_ty(pat.id, const_ty); - // FIXME(#20489) -- we should limit the types here to scalars or something! + // FIXME(#20489) -- we should limit the types here to scalars or something! - // As with PatLit, what we really want here is that there - // exist a LUB, but for the cases that can occur, subtype - // is good enough. - demand::suptype(fcx, pat.span, expected, const_ty); + // As with PatLit, what we really want here is that there + // exist a LUB, but for the cases that can occur, subtype + // is good enough. + demand::suptype(fcx, pat.span, expected, const_ty); + } else { + fcx.write_error(pat.id); + } } hir::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map.borrow(), pat) => { let typ = fcx.local_ty(pat.span, pat.id); @@ -186,14 +190,15 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // if there are multiple arms, make sure they all agree on // what the type of the binding `x` ought to be - let canon_id = *pcx.map.get(&path.node.name).unwrap(); - if canon_id != pat.id { - let ct = fcx.local_ty(pat.span, canon_id); - demand::eqtype(fcx, pat.span, ct, typ); - } + if let Some(&canon_id) = pcx.map.get(&path.node.name) { + if canon_id != pat.id { + let ct = fcx.local_ty(pat.span, canon_id); + demand::eqtype(fcx, pat.span, ct, typ); + } - if let Some(ref p) = *sub { - check_pat(pcx, &**p, expected); + if let Some(ref p) = *sub { + check_pat(pcx, &**p, expected); + } } } hir::PatIdent(_, ref path, _) => { @@ -208,6 +213,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, hir::PatQPath(ref qself, ref path) => { let self_ty = fcx.to_ty(&qself.ty); let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) { + if d.base_def == def::DefErr { + fcx.write_error(pat.id); + return; + } d } else if qself.position == 0 { // This is just a sentinel for finish_resolving_def_to_ty. @@ -218,8 +227,9 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, depth: path.segments.len() } } else { - tcx.sess.span_bug(pat.span, - &format!("unbound path {:?}", pat)) + debug!("unbound path {:?}", pat); + fcx.write_error(pat.id); + return; }; if let Some((opt_ty, segments, def)) = resolve_ty_and_def_ufcs(fcx, path_res, Some(self_ty), @@ -597,7 +607,20 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, let fcx = pcx.fcx; let tcx = pcx.fcx.ccx.tcx; - let path_res = *tcx.def_map.borrow().get(&pat.id).unwrap(); + let path_res = match tcx.def_map.borrow().get(&pat.id) { + Some(&path_res) if path_res.base_def != def::DefErr => path_res, + _ => { + fcx.write_error(pat.id); + + if let Some(subpats) = subpats { + for pat in subpats { + check_pat(pcx, &**pat, tcx.types.err); + } + } + + return; + } + }; let (opt_ty, segments, def) = match resolve_ty_and_def_ufcs(fcx, path_res, None, path, @@ -636,7 +659,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, let report_bad_struct_kind = |is_warning| { bad_struct_kind_err(tcx.sess, pat.span, path, is_warning); if is_warning { - return + return; } fcx.write_error(pat.id); diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 6a23be682e9..1e20cd39854 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -26,6 +26,7 @@ use super::write_call; use CrateCtxt; use middle::cstore::LOCAL_CRATE; +use middle::def; use middle::def_id::DefId; use middle::infer; use middle::ty::{self, LvaluePreference, Ty}; @@ -234,7 +235,7 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, if let hir::ExprCall(ref expr, _) = call_expr.node { let tcx = fcx.tcx(); if let Some(pr) = tcx.def_map.borrow().get(&expr.id) { - if pr.depth == 0 { + if pr.depth == 0 && pr.base_def != def::DefErr { if let Some(span) = tcx.map.span_if_local(pr.def_id()) { tcx.sess.span_note(span, "defined here") } diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 0fbe8367493..59025346ce3 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -17,6 +17,7 @@ use middle::region; use middle::subst::{self, Subst}; use middle::traits; use middle::ty::{self, Ty}; +use util::nodemap::FnvHashSet; use syntax::ast; use syntax::codemap::{self, Span}; @@ -279,7 +280,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx> rcx: rcx, span: span, parent_scope: parent_scope, - breadcrumbs: Vec::new(), + breadcrumbs: FnvHashSet() }, TypeContext::Root, typ, @@ -340,7 +341,7 @@ enum TypeContext { struct DropckContext<'a, 'b: 'a, 'tcx: 'b> { rcx: &'a mut Rcx<'b, 'tcx>, /// types that have already been traversed - breadcrumbs: Vec>, + breadcrumbs: FnvHashSet>, /// span for error reporting span: Span, /// the scope reachable dtorck types must outlive @@ -355,8 +356,6 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>( depth: usize) -> Result<(), Error<'tcx>> { let tcx = cx.rcx.tcx(); - let ty = cx.rcx.infcx().resolve_type_and_region_vars_if_possible(&ty); - // Issue #22443: Watch out for overflow. While we are careful to // handle regular types properly, non-regular ones cause problems. let recursion_limit = tcx.sess.recursion_limit.get(); @@ -367,19 +366,17 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>( return Err(Error::Overflow(context, ty)) } - for breadcrumb in &mut cx.breadcrumbs { - *breadcrumb = - cx.rcx.infcx().resolve_type_and_region_vars_if_possible(breadcrumb); - if *breadcrumb == ty { - debug!("iterate_over_potentially_unsafe_regions_in_type \ - {}ty: {} scope: {:?} - cached", - (0..depth).map(|_| ' ').collect::(), - ty, cx.parent_scope); - return Ok(()); // we already visited this type - } - } - cx.breadcrumbs.push(ty); + // canoncialize the regions in `ty` before inserting - infinitely many + // region variables can refer to the same region. + let ty = cx.rcx.infcx().resolve_type_and_region_vars_if_possible(&ty); + if !cx.breadcrumbs.insert(ty) { + debug!("iterate_over_potentially_unsafe_regions_in_type \ + {}ty: {} scope: {:?} - cached", + (0..depth).map(|_| ' ').collect::(), + ty, cx.parent_scope); + return Ok(()); // we already visited this type + } debug!("iterate_over_potentially_unsafe_regions_in_type \ {}ty: {} scope: {:?}", (0..depth).map(|_| ' ').collect::(), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f348d5411c3..1f3d8f55120 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -385,61 +385,60 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> { } 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) - } - } - hir::ImplItemKind::Method(ref sig, ref body) => { - check_trait_fn_not_const(ccx, impl_item.span, sig.constness); + 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") + }; - 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) - } - } - 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); + // 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); + + 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) + } + } + 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); + } + } 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) } } } @@ -3193,6 +3188,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(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 => { @@ -3371,17 +3370,21 @@ fn check_expr_with_unifier<'a, 'tcx, F>(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 @@ -4326,7 +4329,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)); } } @@ -4496,7 +4500,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()]; } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 984f227cebe..c24a416a010 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -122,10 +122,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } else { let tcx = self.tcx(); - if let hir::ExprAssignOp(..) = e.node { + if let hir::ExprAssignOp(_, ref lhs, ref rhs) = e.node { if !tcx.sess.features.borrow().augmented_assignments && - !self.fcx.expr_ty(e).references_error() + !self.fcx.expr_ty(e).references_error() && + !self.fcx.expr_ty(lhs).references_error() && + !self.fcx.expr_ty(rhs).references_error() { tcx.sess.span_err( e.span, diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index e6e31ba0819..b436a5ee524 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -205,6 +205,9 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { "f64", item.span); } + ty::TyError => { + return; + } _ => { span_err!(self.tcx.sess, item.span, E0118, "no base type found for inherent implementation; \ diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 495b8995cee..02c1f3973c6 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -331,18 +331,21 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) { tcx: tcx }; - time(time_passes, "type collecting", || - collect::collect_item_types(tcx)); - // this ensures that later parts of type checking can assume that items // have valid types and not error - tcx.sess.abort_if_errors(); + tcx.sess.abort_if_new_errors(|| { + time(time_passes, "type collecting", || + collect::collect_item_types(tcx)); + + }); time(time_passes, "variance inference", || variance::infer_variance(tcx)); - time(time_passes, "coherence checking", || - coherence::check_coherence(&ccx)); + tcx.sess.abort_if_new_errors(|| { + time(time_passes, "coherence checking", || + coherence::check_coherence(&ccx)); + }); time(time_passes, "wf checking (old)", || check::check_wf_old(&ccx)); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 1b450092dbd..af6510cb387 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -261,7 +261,7 @@ pub fn main_args(args: &[String]) -> isize { match (should_test, markdown_input) { (true, true) => { - return markdown::test(input, libs, externs, test_args) + return markdown::test(input, cfgs, libs, externs, test_args) } (true, false) => { return test::run(input, cfgs, libs, externs, test_args, crate_name) diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index ac64fd3bec0..03d2c1a1b4d 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -142,13 +142,13 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, } /// Run any tests/code examples in the markdown file `input`. -pub fn test(input: &str, libs: SearchPaths, externs: core::Externs, +pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: core::Externs, mut test_args: Vec) -> isize { let input_str = load_or_return!(input, 1, 2); let mut opts = TestOptions::default(); opts.no_crate_inject = true; - let mut collector = Collector::new(input.to_string(), libs, externs, + let mut collector = Collector::new(input.to_string(), cfgs, libs, externs, true, opts); find_testable_code(&input_str, &mut collector); test_args.insert(0, "rustdoctest".to_string()); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 3e303b29d5c..3322794c778 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -85,7 +85,7 @@ pub fn run(input: &str, rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let mut cfg = config::build_configuration(&sess); - cfg.extend(config::parse_cfgspecs(cfgs)); + cfg.extend(config::parse_cfgspecs(cfgs.clone())); let krate = driver::phase_1_parse_input(&sess, cfg, &input); let krate = driver::phase_2_configure_and_expand(&sess, &cstore, krate, "rustdoc-test", None) @@ -122,6 +122,7 @@ pub fn run(input: &str, let (krate, _) = passes::unindent_comments(krate); let mut collector = Collector::new(krate.name.to_string(), + cfgs, libs, externs, false, @@ -168,7 +169,7 @@ fn scrape_test_config(krate: &::rustc_front::hir::Crate) -> TestOptions { return opts; } -fn runtest(test: &str, cratename: &str, libs: SearchPaths, +fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, externs: core::Externs, should_panic: bool, no_run: bool, as_test_harness: bool, opts: &TestOptions) { @@ -239,7 +240,8 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths, let outdir = TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"); let out = Some(outdir.path().to_path_buf()); - let cfg = config::build_configuration(&sess); + let mut cfg = config::build_configuration(&sess); + cfg.extend(config::parse_cfgspecs(cfgs)); let libdir = sess.target_filesearch(PathKind::All).get_lib_path(); let mut control = driver::CompileController::basic(); if no_run { @@ -349,6 +351,7 @@ fn partition_source(s: &str) -> (String, String) { pub struct Collector { pub tests: Vec, names: Vec, + cfgs: Vec, libs: SearchPaths, externs: core::Externs, cnt: usize, @@ -359,11 +362,12 @@ pub struct Collector { } impl Collector { - pub fn new(cratename: String, libs: SearchPaths, externs: core::Externs, + pub fn new(cratename: String, cfgs: Vec, libs: SearchPaths, externs: core::Externs, use_headers: bool, opts: TestOptions) -> Collector { Collector { tests: Vec::new(), names: Vec::new(), + cfgs: cfgs, libs: libs, externs: externs, cnt: 0, @@ -384,6 +388,7 @@ impl Collector { format!("{}_{}", self.names.join("::"), self.cnt) }; self.cnt += 1; + let cfgs = self.cfgs.clone(); let libs = self.libs.clone(); let externs = self.externs.clone(); let cratename = self.cratename.to_string(); @@ -399,6 +404,7 @@ impl Collector { testfn: testing::DynTestFn(Box::new(move|| { runtest(&test, &cratename, + cfgs, libs, externs, should_panic, diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 5b8307eb6c6..16764e5af5c 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -79,8 +79,8 @@ pub use self::ParseResult::*; use self::TokenTreeOrTokenTreeVec::*; use ast; -use ast::{TokenTree, Name}; -use codemap::{BytePos, mk_sp, Span}; +use ast::{TokenTree, Name, Ident}; +use codemap::{BytePos, mk_sp, Span, Spanned}; use codemap; use parse::lexer::*; //resolve bug? use parse::ParseSess; @@ -526,7 +526,10 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal { "ty" => token::NtTy(panictry!(p.parse_ty())), // this could be handled like a token, since it is one "ident" => match p.token { - token::Ident(sn,b) => { panictry!(p.bump()); token::NtIdent(Box::new(sn),b) } + token::Ident(sn,b) => { + panictry!(p.bump()); + token::NtIdent(Box::new(Spanned::{node: sn, span: p.span}),b) + } _ => { let token_str = pprust::token_to_string(&p.token); panic!(p.fatal(&format!("expected ident, found {}", diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 0fc31f3fd08..ba781ae3cc2 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -293,8 +293,8 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { // (a) idents can be in lots of places, so it'd be a pain // (b) we actually can, since it's a token. MatchedNonterminal(NtIdent(ref sn, b)) => { - r.cur_span = sp; - r.cur_tok = token::Ident(**sn, b); + r.cur_span = sn.span; + r.cur_tok = token::Ident(sn.node, b); return ret_val; } MatchedNonterminal(ref other_whole_nt) => { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index c637813f07e..cd976884d2f 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -663,7 +663,8 @@ pub fn noop_fold_interpolated(nt: token::Nonterminal, fld: &mut T) token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)), token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)), token::NtIdent(id, is_mod_name) => - token::NtIdent(Box::new(fld.fold_ident(*id)), is_mod_name), + token::NtIdent(Box::new(Spanned::{node: fld.fold_ident(id.node), .. *id}), + is_mod_name), token::NtMeta(meta_item) => token::NtMeta(fld.fold_meta_item(meta_item)), token::NtPath(path) => token::NtPath(Box::new(fld.fold_path(*path))), token::NtTT(tt) => token::NtTT(P(fld.fold_tt(&tt))), diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 17b7d8dbaec..b942954c187 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -377,7 +377,7 @@ pub enum Nonterminal { NtPat(P), NtExpr(P), NtTy(P), - NtIdent(Box, IdentStyle), + NtIdent(Box, IdentStyle), /// Stuff inside brackets for attributes NtMeta(P), NtPath(Box), diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 0be62bc0a7f..4e2289cb7f4 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -295,7 +295,7 @@ pub fn token_to_string(tok: &Token) -> String { token::NtBlock(ref e) => block_to_string(&**e), token::NtStmt(ref e) => stmt_to_string(&**e), token::NtPat(ref e) => pat_to_string(&**e), - token::NtIdent(ref e, _) => ident_to_string(**e), + token::NtIdent(ref e, _) => ident_to_string(e.node), token::NtTT(ref e) => tt_to_string(&**e), token::NtArm(ref e) => arm_to_string(&*e), token::NtImplItem(ref e) => impl_item_to_string(&**e), diff --git a/src/test/compile-fail-fulldeps/qquote.rs b/src/test/compile-fail-fulldeps/qquote.rs index 7ffbbe69c3d..3e153a21e5d 100644 --- a/src/test/compile-fail-fulldeps/qquote.rs +++ b/src/test/compile-fail-fulldeps/qquote.rs @@ -23,7 +23,8 @@ fn main() { let ps = syntax::parse::ParseSess::new(); let mut cx = syntax::ext::base::ExtCtxt::new( &ps, vec![], - syntax::ext::expand::ExpansionConfig::default("qquote".to_string())); + syntax::ext::expand::ExpansionConfig::default("qquote".to_string()), + &mut Vec::new()); cx.bt_push(syntax::codemap::ExpnInfo { call_site: DUMMY_SP, callee: syntax::codemap::NameAndSpan { diff --git a/src/test/compile-fail/associated-types-coherence-failure.rs b/src/test/compile-fail/associated-types-coherence-failure.rs index 915cb077787..6d68da54112 100644 --- a/src/test/compile-fail/associated-types-coherence-failure.rs +++ b/src/test/compile-fail/associated-types-coherence-failure.rs @@ -32,13 +32,13 @@ impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { //~^ ERROR E0119 fn into_cow(self) -> Cow<'a, B> { - Cow + Cow(PhantomData) } } impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned { fn into_cow(self) -> Cow<'a, B> { - Cow + Cow(PhantomData) } } diff --git a/src/test/compile-fail/bogus-tag.rs b/src/test/compile-fail/bogus-tag.rs index 704d856f106..a1021500be3 100644 --- a/src/test/compile-fail/bogus-tag.rs +++ b/src/test/compile-fail/bogus-tag.rs @@ -9,14 +9,12 @@ // except according to those terms. -// error-pattern: unresolved - enum color { rgb(isize, isize, isize), rgba(isize, isize, isize, isize), } fn main() { - let red: color = rgb(255, 0, 0); + let red: color = color::rgb(255, 0, 0); match red { - rgb(r, g, b) => { println!("rgb"); } - hsl(h, s, l) => { println!("hsl"); } + color::rgb(r, g, b) => { println!("rgb"); } + color::hsl(h, s, l) => { println!("hsl"); } //~ ERROR no associated } } diff --git a/src/test/compile-fail/coherence-impl-trait-for-trait-object-safe.rs b/src/test/compile-fail/coherence-impl-trait-for-trait-object-safe.rs index ce6baeb204c..b08e4bad1e9 100644 --- a/src/test/compile-fail/coherence-impl-trait-for-trait-object-safe.rs +++ b/src/test/compile-fail/coherence-impl-trait-for-trait-object-safe.rs @@ -13,7 +13,9 @@ // If the trait is not object-safe, we give a more tailored message // because we're such schnuckels: -trait NotObjectSafe { fn eq(&self, other: Self); } -impl NotObjectSafe for NotObjectSafe { } //~ ERROR E0372 +trait NotObjectSafe { fn eq(&self, other: &Self); } +impl NotObjectSafe for NotObjectSafe { //~ ERROR E0372 + fn eq(&self, other: &Self) { panic!(); } +} fn main() { } diff --git a/src/test/compile-fail/coherence-impls-copy.rs b/src/test/compile-fail/coherence-impls-copy.rs index 1be606c3546..9c210c132a3 100644 --- a/src/test/compile-fail/coherence-impls-copy.rs +++ b/src/test/compile-fail/coherence-impls-copy.rs @@ -28,8 +28,6 @@ impl Copy for MyType {} impl Copy for &'static mut MyType {} //~^ ERROR E0206 -//~| ERROR E0277 -//~| ERROR E0277 impl Clone for MyType { fn clone(&self) -> Self { *self } } impl Copy for (MyType, MyType) {} @@ -42,8 +40,6 @@ impl Copy for &'static NotSync {} impl Copy for [MyType] {} //~^ ERROR E0206 //~| ERROR E0117 -//~| ERROR E0277 -//~| ERROR E0277 impl Copy for &'static [NotSync] {} //~^ ERROR E0206 diff --git a/src/test/compile-fail/coherence-impls-sized.rs b/src/test/compile-fail/coherence-impls-sized.rs index 2ac4bb0492b..167067cb5fc 100644 --- a/src/test/compile-fail/coherence-impls-sized.rs +++ b/src/test/compile-fail/coherence-impls-sized.rs @@ -30,7 +30,6 @@ impl Sized for (MyType, MyType) {} //~ ERROR E0117 impl Sized for &'static NotSync {} //~ ERROR E0322 impl Sized for [MyType] {} //~ ERROR E0117 -//~^ ERROR E0277 impl Sized for &'static [NotSync] {} //~ ERROR E0117 diff --git a/src/test/compile-fail/duplicate-type-parameter.rs b/src/test/compile-fail/duplicate-type-parameter.rs index 42b67337c64..3b0f8ee5bda 100644 --- a/src/test/compile-fail/duplicate-type-parameter.rs +++ b/src/test/compile-fail/duplicate-type-parameter.rs @@ -33,6 +33,7 @@ trait Qux {} impl Qux for Option {} //~^ ERROR the name `T` is already used +//~^^ ERROR the type parameter `T` is not constrained fn main() { } diff --git a/src/test/compile-fail/inner-static-type-parameter.rs b/src/test/compile-fail/inner-static-type-parameter.rs index cf2a70deee5..56b681378cc 100644 --- a/src/test/compile-fail/inner-static-type-parameter.rs +++ b/src/test/compile-fail/inner-static-type-parameter.rs @@ -10,7 +10,7 @@ // see #9186 -enum Bar { What } +enum Bar { What } //~ ERROR parameter `T` is never used fn foo() { static a: Bar = Bar::What; diff --git a/src/test/compile-fail/issue-12796.rs b/src/test/compile-fail/issue-12796.rs index 2249741cdaa..33fbdce4ee2 100644 --- a/src/test/compile-fail/issue-12796.rs +++ b/src/test/compile-fail/issue-12796.rs @@ -9,8 +9,8 @@ // except according to those terms. trait Trait { - fn outer(self) { - fn inner(_: Self) { + fn outer(&self) { + fn inner(_: &Self) { //~^ ERROR can't use type parameters from outer function //~^^ ERROR use of `Self` outside of an impl or trait } diff --git a/src/test/compile-fail/issue-14254.rs b/src/test/compile-fail/issue-14254.rs index ce5fa1f1fe1..5f8ccd0b063 100644 --- a/src/test/compile-fail/issue-14254.rs +++ b/src/test/compile-fail/issue-14254.rs @@ -11,7 +11,7 @@ trait Foo { fn bar(&self); fn baz(&self) { } - fn bah(_: Option) { } + fn bah(_: Option<&Self>) { } } struct BarTy { diff --git a/src/test/compile-fail/issue-19883.rs b/src/test/compile-fail/issue-19883.rs index c6ff82364b3..7ec3093a6e0 100644 --- a/src/test/compile-fail/issue-19883.rs +++ b/src/test/compile-fail/issue-19883.rs @@ -14,7 +14,7 @@ trait From { fn from(src: Src) -> >::Output; } -trait To { +trait To: Sized { fn to>(self) -> >::Dst //~^ ERROR use of undeclared associated type `From::Dst` diff --git a/src/test/compile-fail/issue-20427.rs b/src/test/compile-fail/issue-20427.rs index a4b25ab9e56..99dd22a888c 100644 --- a/src/test/compile-fail/issue-20427.rs +++ b/src/test/compile-fail/issue-20427.rs @@ -62,7 +62,7 @@ fn usize<'usize>(usize: &'usize usize) -> &'usize usize { usize } fn main() { let bool = true; match bool { - str @ true => if str { i32 as i64 } else { 0 }, + str @ true => if str { i32 as i64 } else { i64 }, false => i64, - } + }; } diff --git a/src/test/compile-fail/issue-23305.rs b/src/test/compile-fail/issue-23305.rs index 4b1010781ff..68f053c357b 100644 --- a/src/test/compile-fail/issue-23305.rs +++ b/src/test/compile-fail/issue-23305.rs @@ -13,5 +13,6 @@ pub trait ToNbt { } impl ToNbt {} //~ ERROR use of `Self` outside of an impl or trait +//~^ WARNING the trait `ToNbt` cannot be made into an object fn main() {} diff --git a/src/test/compile-fail/issue-2356.rs b/src/test/compile-fail/issue-2356.rs index 48cc27e2289..6b81afe13c6 100644 --- a/src/test/compile-fail/issue-2356.rs +++ b/src/test/compile-fail/issue-2356.rs @@ -9,7 +9,7 @@ // except according to those terms. trait Groom { - fn shave(); + fn shave(other: usize); } pub struct cat { @@ -30,7 +30,7 @@ impl MaybeDog { } impl Groom for cat { - fn shave(&self, other: usize) { + fn shave(other: usize) { whiskers -= other; //~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`? shave(4); diff --git a/src/test/compile-fail/issue-28109.rs b/src/test/compile-fail/issue-28109.rs index 73163caa455..0d372d30015 100644 --- a/src/test/compile-fail/issue-28109.rs +++ b/src/test/compile-fail/issue-28109.rs @@ -11,10 +11,12 @@ // Make sure that label for continue and break is spanned correctly fn main() { - continue - 'b //~ ERROR use of undeclared label - ; - break - 'c //~ ERROR use of undeclared label - ; + loop { + continue + 'b //~ ERROR use of undeclared label + ; + break + 'c //~ ERROR use of undeclared label + ; + } } diff --git a/src/test/compile-fail/issue-3021-d.rs b/src/test/compile-fail/issue-3021-d.rs index 594f68e1812..ecc8ac34ecf 100644 --- a/src/test/compile-fail/issue-3021-d.rs +++ b/src/test/compile-fail/issue-3021-d.rs @@ -13,13 +13,13 @@ trait siphash { fn reset(&self); } -fn siphash(k0 : u64, k1 : u64) -> siphash { +fn siphash(k0 : u64, k1 : u64) { struct SipState { v0: u64, v1: u64, } - fn mk_result(st : SipState) -> u64 { + fn mk_result(st : &SipState) -> u64 { let v0 = st.v0; let v1 = st.v1; diff --git a/src/test/compile-fail/issue-3021.rs b/src/test/compile-fail/issue-3021.rs index 719eef1b63d..7cf772b0728 100644 --- a/src/test/compile-fail/issue-3021.rs +++ b/src/test/compile-fail/issue-3021.rs @@ -12,7 +12,7 @@ trait SipHash { fn reset(&self); } -fn siphash(k0 : u64) -> SipHash { +fn siphash(k0 : u64) { struct SipState { v0: u64, } diff --git a/src/test/compile-fail/issue-3214.rs b/src/test/compile-fail/issue-3214.rs index be49ca1fe06..27b7fb75275 100644 --- a/src/test/compile-fail/issue-3214.rs +++ b/src/test/compile-fail/issue-3214.rs @@ -15,6 +15,8 @@ fn foo() { } impl Drop for foo { + //~^ ERROR wrong number of type arguments + //~^^ ERROR the type parameter `T` is not constrained fn drop(&mut self) {} } } diff --git a/src/test/compile-fail/issue-3521.rs b/src/test/compile-fail/issue-3521.rs index f06aa45ac38..34cd8cae2de 100644 --- a/src/test/compile-fail/issue-3521.rs +++ b/src/test/compile-fail/issue-3521.rs @@ -16,6 +16,7 @@ fn main() { Bar = foo //~^ ERROR attempt to use a non-constant value in a constant //~| ERROR unresolved name `foo` + //~^^^ ERROR constant evaluation error: non-constant path in constant expression } println!("{}", Stuff::Bar); diff --git a/src/test/compile-fail/issue-3973.rs b/src/test/compile-fail/issue-3973.rs index 2652fb5dfc2..1fda423e9ee 100644 --- a/src/test/compile-fail/issue-3973.rs +++ b/src/test/compile-fail/issue-3973.rs @@ -30,5 +30,7 @@ impl ToString_ for Point { fn main() { let p = Point::new(0.0, 0.0); + //~^ ERROR no associated item named `new` found for type `Point` in the current scope println!("{}", p.to_string()); + //~^ ERROR the type of this value must be known in this context } diff --git a/src/test/compile-fail/issue-5927.rs b/src/test/compile-fail/issue-5927.rs index 0359248b36a..e5f091d873d 100644 --- a/src/test/compile-fail/issue-5927.rs +++ b/src/test/compile-fail/issue-5927.rs @@ -9,12 +9,10 @@ // except according to those terms. - -// error-pattern:unresolved enum variant - fn main() { let z = match 3 { - x(1) => x(1) + x(1) => x(1) //~ ERROR unresolved enum variant + //~^ ERROR unresolved name `x` }; - assert_eq!(z,3); + assert!(z == 3); } diff --git a/src/test/compile-fail/issue-9725.rs b/src/test/compile-fail/issue-9725.rs index 1a3c926ba38..f53122d19c1 100644 --- a/src/test/compile-fail/issue-9725.rs +++ b/src/test/compile-fail/issue-9725.rs @@ -13,4 +13,5 @@ struct A { foo: isize } fn main() { let A { foo, foo } = A { foo: 3 }; //~^ ERROR: identifier `foo` is bound more than once in the same pattern + //~^^ ERROR: field `foo` bound multiple times } diff --git a/src/test/compile-fail/macro-parameter-span.rs b/src/test/compile-fail/macro-parameter-span.rs new file mode 100644 index 00000000000..2ef69759128 --- /dev/null +++ b/src/test/compile-fail/macro-parameter-span.rs @@ -0,0 +1,23 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! foo { + ($id: ident) => { + $id + } +} + +// Testing that the error span points to the parameter 'x' in the callsite, +// not to the macro variable '$id' +fn main() { + foo!( + x //~ ERROR unresolved name `x` + ); +} diff --git a/src/test/compile-fail/mod_file_correct_spans.rs b/src/test/compile-fail/mod_file_correct_spans.rs index 3b794da1053..f8ea5dda183 100644 --- a/src/test/compile-fail/mod_file_correct_spans.rs +++ b/src/test/compile-fail/mod_file_correct_spans.rs @@ -13,5 +13,5 @@ mod mod_file_aux; fn main() { - assert_eq!(mod_file_aux::bar(), 10); //~ ERROR unresolved name + assert!(mod_file_aux::bar() == 10); //~ ERROR unresolved name } diff --git a/src/test/compile-fail/opt-in-copy.rs b/src/test/compile-fail/opt-in-copy.rs index be321b62903..bc18b52a0c1 100644 --- a/src/test/compile-fail/opt-in-copy.rs +++ b/src/test/compile-fail/opt-in-copy.rs @@ -16,7 +16,6 @@ struct IWantToCopyThis { impl Copy for IWantToCopyThis {} //~^ ERROR the trait `Copy` may not be implemented for this type -//~| ERROR E0277 enum CantCopyThisEither { A, @@ -29,6 +28,5 @@ enum IWantToCopyThisToo { impl Copy for IWantToCopyThisToo {} //~^ ERROR the trait `Copy` may not be implemented for this type -//~| ERROR E0277 fn main() {} diff --git a/src/test/compile-fail/resolve-inconsistent-binding-mode.rs b/src/test/compile-fail/resolve-inconsistent-binding-mode.rs index cdb81279048..284c08ef09b 100644 --- a/src/test/compile-fail/resolve-inconsistent-binding-mode.rs +++ b/src/test/compile-fail/resolve-inconsistent-binding-mode.rs @@ -16,6 +16,7 @@ fn matcher1(x: opts) { match x { opts::a(ref i) | opts::b(i) => {} //~^ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1 + //~^^ ERROR mismatched types opts::c(_) => {} } } @@ -24,6 +25,7 @@ fn matcher2(x: opts) { match x { opts::a(ref i) | opts::b(i) => {} //~^ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1 + //~^^ ERROR mismatched types opts::c(_) => {} } } @@ -32,6 +34,7 @@ fn matcher4(x: opts) { match x { opts::a(ref mut i) | opts::b(ref i) => {} //~^ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1 + //~^^ ERROR mismatched types opts::c(_) => {} } } diff --git a/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs b/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs index 341fe173a03..88f09233d10 100644 --- a/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs +++ b/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs @@ -15,6 +15,7 @@ trait TraitA { fn outer(self) { enum Foo { + //~^ ERROR parameter `B` is never used Variance(A) //~^ ERROR can't use type parameters from outer function //~^^ ERROR use of undeclared type name `A` @@ -27,6 +28,7 @@ trait TraitB { struct Foo(A); //~^ ERROR can't use type parameters from outer function //~^^ ERROR use of undeclared type name `A` + //~^^^ ERROR parameter `B` is never used } } @@ -35,6 +37,7 @@ trait TraitC { struct Foo { a: A } //~^ ERROR can't use type parameters from outer function //~^^ ERROR use of undeclared type name `A` + //~^^^ ERROR parameter `B` is never used } } diff --git a/src/test/compile-fail/syntax-extension-minor.rs b/src/test/compile-fail/syntax-extension-minor.rs index 506aed6b2ee..38a6834a9c4 100644 --- a/src/test/compile-fail/syntax-extension-minor.rs +++ b/src/test/compile-fail/syntax-extension-minor.rs @@ -14,7 +14,7 @@ pub fn main() { let asdf_fdsa = "<.<".to_string(); - assert_eq!(concat_idents!(asd, f_f, dsa), "<.<".to_string()); + assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string()); //~^ ERROR: unresolved name `asdf_fdsa` assert_eq!(stringify!(use_mention_distinction), "use_mention_distinction"); diff --git a/src/test/compile-fail/trait-safety-trait-impl-cc.rs b/src/test/compile-fail/trait-safety-trait-impl-cc.rs index 6050b549b65..f30c8f521bd 100644 --- a/src/test/compile-fail/trait-safety-trait-impl-cc.rs +++ b/src/test/compile-fail/trait-safety-trait-impl-cc.rs @@ -18,7 +18,7 @@ extern crate trait_safety_lib as lib; struct Bar; impl lib::Foo for Bar { //~ ERROR requires an `unsafe impl` declaration fn foo(&self) -> isize { - *self as isize + panic!(); } } diff --git a/src/test/compile-fail/trait-safety-trait-impl.rs b/src/test/compile-fail/trait-safety-trait-impl.rs index 1bd6d763607..e846b660c2a 100644 --- a/src/test/compile-fail/trait-safety-trait-impl.rs +++ b/src/test/compile-fail/trait-safety-trait-impl.rs @@ -12,11 +12,11 @@ // impls cannot be unsafe. trait SafeTrait { - fn foo(self) { } + fn foo(&self) { } } unsafe trait UnsafeTrait { - fn foo(self) { } + fn foo(&self) { } } unsafe impl UnsafeTrait for u8 { } // OK diff --git a/src/test/rustdoc/issue-30252.rs b/src/test/rustdoc/issue-30252.rs new file mode 100644 index 00000000000..11d161fe188 --- /dev/null +++ b/src/test/rustdoc/issue-30252.rs @@ -0,0 +1,16 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:--test --cfg feature="bar" + +/// ```rust +/// assert_eq!(cfg!(feature = "bar"), true); +/// ``` +pub fn foo() {}