From 4dad9077cc1c0ad00c23ab74a9bae4c0871e4822 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sat, 28 Feb 2015 12:17:11 +0100 Subject: [PATCH 01/17] Qualify uses of MethodContext variants. --- src/librustc_lint/builtin.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index d0fccf6495a0a..30e767f7da55c 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -28,8 +28,6 @@ //! Use the former for unit-like structs and the latter for structs with //! a `pub fn new()`. -use self::MethodContext::*; - use metadata::{csearch, decoder}; use middle::def::*; use middle::subst::Substs; @@ -870,22 +868,22 @@ fn method_context(cx: &Context, m: &ast::Method) -> MethodContext { match md { ty::MethodTraitItem(md) => { match md.container { - ty::TraitContainer(..) => TraitDefaultImpl, + ty::TraitContainer(..) => MethodContext::TraitDefaultImpl, ty::ImplContainer(cid) => { match ty::impl_trait_ref(cx.tcx, cid) { - Some(..) => TraitImpl, - None => PlainImpl + Some(..) => MethodContext::TraitImpl, + None => MethodContext::PlainImpl } } } } ty::TypeTraitItem(typedef) => { match typedef.container { - ty::TraitContainer(..) => TraitDefaultImpl, + ty::TraitContainer(..) => MethodContext::TraitDefaultImpl, ty::ImplContainer(cid) => { match ty::impl_trait_ref(cx.tcx, cid) { - Some(..) => TraitImpl, - None => PlainImpl + Some(..) => MethodContext::TraitImpl, + None => MethodContext::PlainImpl } } } @@ -979,9 +977,9 @@ impl LintPass for NonSnakeCase { _: &ast::Block, span: Span, _: ast::NodeId) { match fk { visit::FkMethod(ident, _, m) => match method_context(cx, m) { - PlainImpl + MethodContext::PlainImpl => self.check_snake_case(cx, "method", ident, span), - TraitDefaultImpl + MethodContext::TraitDefaultImpl => self.check_snake_case(cx, "trait method", ident, span), _ => (), }, @@ -1563,7 +1561,7 @@ impl LintPass for MissingDoc { _: &ast::Block, _: Span, _: ast::NodeId) { if let visit::FkMethod(_, _, m) = fk { // If the method is an impl for a trait, don't doc. - if method_context(cx, m) == TraitImpl { return; } + if method_context(cx, m) == MethodContext::TraitImpl { return; } // Otherwise, doc according to privacy. This will also check // doc for default methods defined on traits. From 57e0248d34733a94d7e341c0e5df594c84499932 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sat, 28 Feb 2015 13:31:14 +0100 Subject: [PATCH 02/17] Various formatting cleanup. --- src/librustc_lint/builtin.rs | 245 ++++++++++++++++++++--------------- 1 file changed, 139 insertions(+), 106 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 30e767f7da55c..7a0a906e97664 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -226,7 +226,9 @@ impl LintPass for TypeLimits { ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => { let int_type = if let ast::TyIs(_) = t { cx.sess().target.int_type - } else { t }; + } else { + t + }; let (min, max) = int_ty_range(int_type); let negative = self.negated_expr_id == e.id; @@ -243,14 +245,16 @@ impl LintPass for TypeLimits { ty::ty_uint(t) => { let uint_type = if let ast::TyUs(_) = t { cx.sess().target.uint_type - } else { t }; + } else { + t + }; let (min, max) = uint_ty_range(uint_type); let lit_val: u64 = match lit.node { ast::LitByte(_v) => return, // _v is u8, within range by definition ast::LitInt(v, _) => v, _ => panic!() }; - if lit_val < min || lit_val > max { + if lit_val < min || lit_val > max { cx.span_lint(OVERFLOWING_LITERALS, e.span, &*format!("literal out of range for {:?}", t)); } @@ -260,9 +264,9 @@ impl LintPass for TypeLimits { let lit_val: f64 = match lit.node { ast::LitFloat(ref v, _) | ast::LitFloatUnsuffixed(ref v) => { - match v.parse().ok() { - Some(f) => f, - None => return + match v.parse() { + Ok(f) => f, + Err(_) => return } } _ => panic!() @@ -300,52 +304,52 @@ impl LintPass for TypeLimits { }) } - // for int & uint, be conservative with the warnings, so that the + // for isize & usize, be conservative with the warnings, so that the // warnings are consistent between 32- and 64-bit platforms fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) { match int_ty { - ast::TyIs(_) => (i64::MIN, i64::MAX), - ast::TyI8 => (i8::MIN as i64, i8::MAX as i64), - ast::TyI16 => (i16::MIN as i64, i16::MAX as i64), - ast::TyI32 => (i32::MIN as i64, i32::MAX as i64), - ast::TyI64 => (i64::MIN, i64::MAX) + ast::TyIs(_) => (i64::MIN, i64::MAX), + ast::TyI8 => (i8::MIN as i64, i8::MAX as i64), + ast::TyI16 => (i16::MIN as i64, i16::MAX as i64), + ast::TyI32 => (i32::MIN as i64, i32::MAX as i64), + ast::TyI64 => (i64::MIN, i64::MAX) } } fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) { match uint_ty { - ast::TyUs(_) => (u64::MIN, u64::MAX), - ast::TyU8 => (u8::MIN as u64, u8::MAX as u64), - ast::TyU16 => (u16::MIN as u64, u16::MAX as u64), - ast::TyU32 => (u32::MIN as u64, u32::MAX as u64), - ast::TyU64 => (u64::MIN, u64::MAX) + ast::TyUs(_) => (u64::MIN, u64::MAX), + ast::TyU8 => (u8::MIN as u64, u8::MAX as u64), + ast::TyU16 => (u16::MIN as u64, u16::MAX as u64), + ast::TyU32 => (u32::MIN as u64, u32::MAX as u64), + ast::TyU64 => (u64::MIN, u64::MAX) } } fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) { match float_ty { - ast::TyF32 => (f32::MIN as f64, f32::MAX as f64), - ast::TyF64 => (f64::MIN, f64::MAX) + ast::TyF32 => (f32::MIN as f64, f32::MAX as f64), + ast::TyF64 => (f64::MIN, f64::MAX) } } fn int_ty_bits(int_ty: ast::IntTy, target_int_ty: ast::IntTy) -> u64 { match int_ty { - ast::TyIs(_) => int_ty_bits(target_int_ty, target_int_ty), - ast::TyI8 => i8::BITS as u64, - ast::TyI16 => i16::BITS as u64, - ast::TyI32 => i32::BITS as u64, - ast::TyI64 => i64::BITS as u64 + ast::TyIs(_) => int_ty_bits(target_int_ty, target_int_ty), + ast::TyI8 => i8::BITS as u64, + ast::TyI16 => i16::BITS as u64, + ast::TyI32 => i32::BITS as u64, + ast::TyI64 => i64::BITS as u64 } } fn uint_ty_bits(uint_ty: ast::UintTy, target_uint_ty: ast::UintTy) -> u64 { match uint_ty { - ast::TyUs(_) => uint_ty_bits(target_uint_ty, target_uint_ty), - ast::TyU8 => u8::BITS as u64, - ast::TyU16 => u16::BITS as u64, - ast::TyU32 => u32::BITS as u64, - ast::TyU64 => u64::BITS as u64 + ast::TyUs(_) => uint_ty_bits(target_uint_ty, target_uint_ty), + ast::TyU8 => u8::BITS as u64, + ast::TyU16 => u16::BITS as u64, + ast::TyU32 => u32::BITS as u64, + ast::TyU64 => u64::BITS as u64 } } @@ -358,7 +362,11 @@ impl LintPass for TypeLimits { }; // Normalize the binop so that the literal is always on the RHS in // the comparison - let norm_binop = if swap { rev_binop(binop) } else { binop }; + let norm_binop = if swap { + rev_binop(binop) + } else { + binop + }; match ty::expr_ty(tcx, expr).sty { ty::ty_int(int_ty) => { let (min, max) = int_ty_range(int_ty); @@ -430,9 +438,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if !ty::is_ffi_safe(self.cx.tcx, tty) { self.cx.span_lint(IMPROPER_CTYPES, sp, - "found type without foreign-function-safe - representation annotation in foreign module, consider \ - adding a #[repr(...)] attribute to the type"); + "found type without foreign-function-safe \ + representation annotation in foreign module, consider \ + adding a #[repr(...)] attribute to the type"); } } _ => () @@ -593,7 +601,7 @@ impl LintPass for RawPointerDerive { fn check_item(&mut self, cx: &Context, item: &ast::Item) { if !attr::contains_name(&item.attrs, "automatically_derived") { - return + return; } let did = match item.node { ast::ItemImpl(_, _, _, ref t_ref_opt, _, _) => { @@ -601,7 +609,7 @@ impl LintPass for RawPointerDerive { if let &Some(ref trait_ref) = t_ref_opt { let def_id = ty::trait_ref_to_def_id(cx.tcx, trait_ref); if Some(def_id) == cx.tcx.lang_items.copy_trait() { - return + return; } } @@ -613,12 +621,16 @@ impl LintPass for RawPointerDerive { } _ => return, }; - if !ast_util::is_local(did) { return } + if !ast_util::is_local(did) { + return; + } let item = match cx.tcx.map.find(did.node) { Some(ast_map::NodeItem(item)) => item, _ => return, }; - if !self.checked_raw_pointers.insert(item.id) { return } + if !self.checked_raw_pointers.insert(item.id) { + return; + } match item.node { ast::ItemStruct(..) | ast::ItemEnum(..) => { let mut visitor = RawPtrDeriveVisitor { cx: cx }; @@ -783,7 +795,9 @@ impl NonCamelCaseTypes { fn check_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) { fn is_camel_case(ident: ast::Ident) -> bool { let ident = token::get_ident(ident); - if ident.is_empty() { return true; } + if ident.is_empty() { + return true; + } let ident = ident.trim_matches('_'); // start with a non-lowercase letter rather than non-uppercase @@ -793,8 +807,11 @@ impl NonCamelCaseTypes { fn to_camel_case(s: &str) -> String { s.split('_').flat_map(|word| word.chars().enumerate().map(|(i, c)| - if i == 0 { c.to_uppercase() } - else { c } + if i == 0 { + c.to_uppercase() + } else { + c + } )).collect() } @@ -818,11 +835,13 @@ impl LintPass for NonCamelCaseTypes { } fn check_item(&mut self, cx: &Context, it: &ast::Item) { - let has_extern_repr = it.attrs.iter().map(|attr| { + let has_extern_repr = it.attrs.iter().any(|attr| { attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter() .any(|r| r == &attr::ReprExtern) - }).any(|x| x); - if has_extern_repr { return } + }); + if has_extern_repr { + return; + } match it.node { ast::ItemTy(..) | ast::ItemStruct(..) => { @@ -832,7 +851,9 @@ impl LintPass for NonCamelCaseTypes { self.check_case(cx, "trait", it.ident, it.span) } ast::ItemEnum(ref enum_definition, _) => { - if has_extern_repr { return } + if has_extern_repr { + return; + } self.check_case(cx, "type", it.ident, it.span); for variant in &enum_definition.variants { self.check_case(cx, "variant", variant.node.name, variant.span); @@ -910,12 +931,16 @@ impl NonSnakeCase { if c == '_' { words.push(String::new()); true - } else { false } + } else { + false + } }); for s in str.split('_') { let mut last_upper = false; let mut buf = String::new(); - if s.is_empty() { continue; } + if s.is_empty() { + continue; + } for ch in s.chars() { if !buf.is_empty() && buf != "'" && ch.is_uppercase() @@ -934,7 +959,9 @@ impl NonSnakeCase { fn check_snake_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) { fn is_snake_case(ident: ast::Ident) -> bool { let ident = token::get_ident(ident); - if ident.is_empty() { return true; } + if ident.is_empty() { + return true; + } let ident = ident.trim_left_matches('\''); let ident = ident.trim_matches('_'); @@ -977,14 +1004,17 @@ impl LintPass for NonSnakeCase { _: &ast::Block, span: Span, _: ast::NodeId) { match fk { visit::FkMethod(ident, _, m) => match method_context(cx, m) { - MethodContext::PlainImpl - => self.check_snake_case(cx, "method", ident, span), - MethodContext::TraitDefaultImpl - => self.check_snake_case(cx, "trait method", ident, span), + MethodContext::PlainImpl => { + self.check_snake_case(cx, "method", ident, span) + }, + MethodContext::TraitDefaultImpl => { + self.check_snake_case(cx, "trait method", ident, span) + }, _ => (), }, - visit::FkItemFn(ident, _, _, _) - => self.check_snake_case(cx, "function", ident, span), + visit::FkItemFn(ident, _, _, _) => { + self.check_snake_case(cx, "function", ident, span) + }, _ => (), } } @@ -1013,7 +1043,7 @@ impl LintPass for NonSnakeCase { } fn check_struct_def(&mut self, cx: &Context, s: &ast::StructDef, - _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { + _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { for sf in &s.fields { if let ast::StructField_ { kind: ast::NamedField(ident, _), .. } = sf.node { self.check_snake_case(cx, "structure field", ident, sf.span); @@ -1092,13 +1122,12 @@ pub struct UnusedParens; impl UnusedParens { fn check_unused_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str, - struct_lit_needs_parens: bool) { + struct_lit_needs_parens: bool) { if let ast::ExprParen(ref inner) = value.node { let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner); if !necessary { cx.span_lint(UNUSED_PARENS, value.span, - &format!("unnecessary parentheses around {}", - msg)) + &format!("unnecessary parentheses around {}", msg)) } } @@ -1232,9 +1261,10 @@ impl LintPass for NonShorthandFieldPatterns { fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) { let def_map = cx.tcx.def_map.borrow(); if let ast::PatStruct(_, ref v, _) = pat.node { - let field_pats = v.iter() - .filter(|fieldpat| !fieldpat.node.is_shorthand) - .filter(|fieldpat| { + let field_pats = v.iter().filter(|fieldpat| { + if fieldpat.node.is_shorthand { + return false; + } let def = def_map.get(&fieldpat.node.pat.id).map(|d| d.full_def()); def == Some(def::DefLocal(fieldpat.node.pat.id)) }); @@ -1480,10 +1510,14 @@ impl MissingDoc { desc: &'static str) { // If we're building a test harness, then warning about // documentation is probably not really relevant right now. - if cx.sess().opts.test { return } + if cx.sess().opts.test { + return; + } // `#[doc(hidden)]` disables missing_docs check. - if self.doc_hidden() { return } + if self.doc_hidden() { + return; + } // Only check publicly-visible items, using the result from the privacy pass. // It's an option so the crate root can also use this function (it doesn't @@ -1502,7 +1536,7 @@ impl MissingDoc { }); if !has_doc { cx.span_lint(MISSING_DOCS, sp, - &format!("missing documentation for {}", desc)); + &format!("missing documentation for {}", desc)); } } } @@ -1526,20 +1560,19 @@ impl LintPass for MissingDoc { self.doc_hidden_stack.pop().expect("empty doc_hidden_stack"); } - fn check_struct_def(&mut self, _: &Context, - _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, id: ast::NodeId) { + fn check_struct_def(&mut self, _: &Context, _: &ast::StructDef, + _: ast::Ident, _: &ast::Generics, id: ast::NodeId) { self.struct_def_stack.push(id); } - fn check_struct_def_post(&mut self, _: &Context, - _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, id: ast::NodeId) { + fn check_struct_def_post(&mut self, _: &Context, _: &ast::StructDef, + _: ast::Ident, _: &ast::Generics, id: ast::NodeId) { let popped = self.struct_def_stack.pop().expect("empty struct_def_stack"); assert!(popped == id); } fn check_crate(&mut self, cx: &Context, krate: &ast::Crate) { - self.check_missing_docs_attrs(cx, None, &krate.attrs, - krate.span, "crate"); + self.check_missing_docs_attrs(cx, None, &krate.attrs, krate.span, "crate"); } fn check_item(&mut self, cx: &Context, it: &ast::Item) { @@ -1552,27 +1585,25 @@ impl LintPass for MissingDoc { ast::ItemTy(..) => "a type alias", _ => return }; - self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs, - it.span, desc); + self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs, it.span, desc); } - fn check_fn(&mut self, cx: &Context, - fk: visit::FnKind, _: &ast::FnDecl, - _: &ast::Block, _: Span, _: ast::NodeId) { + fn check_fn(&mut self, cx: &Context, fk: visit::FnKind, _: &ast::FnDecl, + _: &ast::Block, _: Span, _: ast::NodeId) { if let visit::FkMethod(_, _, m) = fk { // If the method is an impl for a trait, don't doc. - if method_context(cx, m) == MethodContext::TraitImpl { return; } + if method_context(cx, m) == MethodContext::TraitImpl { + return; + } // Otherwise, doc according to privacy. This will also check // doc for default methods defined on traits. - self.check_missing_docs_attrs(cx, Some(m.id), &m.attrs, - m.span, "a method"); + self.check_missing_docs_attrs(cx, Some(m.id), &m.attrs, m.span, "a method"); } } fn check_ty_method(&mut self, cx: &Context, tm: &ast::TypeMethod) { - self.check_missing_docs_attrs(cx, Some(tm.id), &tm.attrs, - tm.span, "a type method"); + self.check_missing_docs_attrs(cx, Some(tm.id), &tm.attrs, tm.span, "a type method"); } fn check_trait_method(&mut self, cx: &Context, it: &ast::TraitItem) { @@ -1596,8 +1627,7 @@ impl LintPass for MissingDoc { } fn check_variant(&mut self, cx: &Context, v: &ast::Variant, _: &ast::Generics) { - self.check_missing_docs_attrs(cx, Some(v.node.id), &v.node.attrs, - v.span, "a variant"); + self.check_missing_docs_attrs(cx, Some(v.node.id), &v.node.attrs, v.span, "a variant"); assert!(!self.in_variant); self.in_variant = true; } @@ -1624,18 +1654,18 @@ impl LintPass for MissingCopyImplementations { fn check_item(&mut self, cx: &Context, item: &ast::Item) { if !cx.exported_items.contains(&item.id) { - return + return; } if cx.tcx .destructor_for_type .borrow() .contains_key(&ast_util::local_def(item.id)) { - return + return; } let ty = match item.node { ast::ItemStruct(_, ref ast_generics) => { if ast_generics.is_parameterized() { - return + return; } ty::mk_struct(cx.tcx, ast_util::local_def(item.id), @@ -1643,7 +1673,7 @@ impl LintPass for MissingCopyImplementations { } ast::ItemEnum(_, ref ast_generics) => { if ast_generics.is_parameterized() { - return + return; } ty::mk_enum(cx.tcx, ast_util::local_def(item.id), @@ -1653,7 +1683,7 @@ impl LintPass for MissingCopyImplementations { }; let parameter_environment = ty::empty_parameter_environment(cx.tcx); if !ty::type_moves_by_default(¶meter_environment, item.span, ty) { - return + return; } if ty::can_type_implement_copy(¶meter_environment, item.span, ty).is_ok() { cx.span_lint(MISSING_COPY_IMPLEMENTATIONS, @@ -1707,10 +1737,10 @@ impl LintPass for MissingDebugImplementations { let impls = match impls.get(&debug) { Some(impls) => { impls.borrow().iter() - .filter(|d| d.krate == ast::LOCAL_CRATE) - .filter_map(|d| ty::ty_to_def_id(ty::node_id_to_type(cx.tcx, d.node))) - .map(|d| d.node) - .collect() + .filter(|d| d.krate == ast::LOCAL_CRATE) + .filter_map(|d| ty::ty_to_def_id(ty::node_id_to_type(cx.tcx, d.node))) + .map(|d| d.node) + .collect() } None => NodeSet(), }; @@ -1739,8 +1769,7 @@ pub struct Stability; impl Stability { fn lint(&self, cx: &Context, _id: ast::DefId, span: Span, stability: &Option) { - - // deprecated attributes apply in-crate and cross-crate + // Deprecated attributes apply in-crate and cross-crate. let (lint, label) = match *stability { Some(attr::Stability { deprecated_since: Some(_), .. }) => (DEPRECATED, "deprecated"), @@ -1855,25 +1884,27 @@ impl LintPass for UnconditionalRecursion { let mut visited = BitSet::new(); while let Some(idx) = work_queue.pop() { - let cfg_id = idx.node_id(); if idx == cfg.exit { // found a path! reached_exit_without_self_call = true; - break - } else if visited.contains(&cfg_id) { + break; + } + + let cfg_id = idx.node_id(); + if visited.contains(&cfg_id) { // already done - continue + continue; } visited.insert(cfg_id); + let node_id = cfg.graph.node_data(idx).id(); // is this a recursive call? if node_id != ast::DUMMY_NODE_ID && checker(cx.tcx, impl_node_id, id, name, node_id) { - self_call_spans.push(cx.tcx.map.span(node_id)); // this is a self call, so we shouldn't explore past // this node in the CFG. - continue + continue; } // add the successors of this node to explore the graph further. cfg.graph.each_outgoing_edge(idx, |_, edge| { @@ -1886,7 +1917,7 @@ impl LintPass for UnconditionalRecursion { }); } - // check the number of sell calls because a function that + // Check the number of self calls because a function that // doesn't return (e.g. calls a `-> !` function or `loop { /* // no break */ }`) shouldn't be linted unless it actually // recurs. @@ -1918,7 +1949,7 @@ impl LintPass for UnconditionalRecursion { _: ast::Ident, id: ast::NodeId) -> bool { tcx.def_map.borrow().get(&id) - .map_or(false, |def| def.def_id() == ast_util::local_def(fn_id)) + .map_or(false, |def| def.def_id() == ast_util::local_def(fn_id)) } // check if the method call `id` refers to method `method_id` @@ -1960,7 +1991,7 @@ impl LintPass for UnconditionalRecursion { tcx.map.span(id), "non-method call expr behaving like a method call?") }; - // it matches if it comes from the same impl, + // It matches if it comes from the same impl, // and has the same method name. return ast_util::is_local(impl_def_id) && impl_def_id.node == impl_id @@ -2011,7 +2042,7 @@ impl LintPass for PluginAsLibrary { if decoder::get_plugin_registrar_fn(md.data()).is_some() { cx.span_lint(PLUGIN_AS_LIBRARY, it.span, - "compiler plugin used as an ordinary library"); + "compiler plugin used as an ordinary library"); } } } @@ -2067,7 +2098,7 @@ impl LintPass for InvalidNoMangleItems { // Const items do not refer to a particular location in memory, and therefore // don't have anything to attach a symbol to let msg = "const items should never be #[no_mangle], consider instead using \ - `pub static`"; + `pub static`"; cx.span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg); } } @@ -2080,15 +2111,17 @@ impl LintPass for InvalidNoMangleItems { #[derive(Copy)] pub struct UnstableFeatures; -declare_lint!(UNSTABLE_FEATURES, Allow, - "enabling unstable features"); +declare_lint! { + UNSTABLE_FEATURES, + Allow, + "enabling unstable features" +} impl LintPass for UnstableFeatures { fn get_lints(&self) -> LintArray { lint_array!(UNSTABLE_FEATURES) } fn check_attribute(&mut self, ctx: &Context, attr: &ast::Attribute) { - use syntax::attr; if attr::contains_name(&[attr.node.value.clone()], "feature") { ctx.span_lint(UNSTABLE_FEATURES, attr.span, "unstable feature"); } From 2a37f7f07ca6bc3e3f19c6bb33b25bbc35f561a2 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sat, 28 Feb 2015 13:31:27 +0100 Subject: [PATCH 03/17] Add a comment to code that confused me. --- src/librustc_lint/builtin.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 7a0a906e97664..de3eaeda28ec6 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -656,6 +656,7 @@ impl LintPass for UnusedAttributes { } fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) { + // Note that check_name() marks the attribute as used if it matches. for &(ref name, ty) in KNOWN_ATTRIBUTES { match ty { AttributeType::Whitelisted From f38b83b3609b060df5ab3d2a57e98020b8b29efb Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sat, 28 Feb 2015 13:31:55 +0100 Subject: [PATCH 04/17] Avoid unnecessary mutability for UnusedResults. --- src/librustc_lint/builtin.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index de3eaeda28ec6..6252c372009b2 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -741,23 +741,24 @@ impl LintPass for UnusedResults { } let t = ty::expr_ty(cx.tcx, expr); - let mut warned = false; - match t.sty { + let warned = match t.sty { ty::ty_tup(ref tys) if tys.is_empty() => return, ty::ty_bool => return, ty::ty_struct(did, _) | ty::ty_enum(did, _) => { if ast_util::is_local(did) { if let ast_map::NodeItem(it) = cx.tcx.map.get(did.node) { - warned |= check_must_use(cx, &it.attrs, s.span); + check_must_use(cx, &it.attrs, s.span) + } else { + false } } else { let attrs = csearch::get_item_attrs(&cx.sess().cstore, did); - warned |= check_must_use(cx, &attrs[..], s.span); + check_must_use(cx, &attrs[..], s.span) } } - _ => {} - } + _ => false, + }; if !warned { cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); } From 8a7b6b3ee6a85aa60a1733727a4028a690744fdf Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sat, 28 Feb 2015 13:32:18 +0100 Subject: [PATCH 05/17] Collapse nested matches in method_context. --- src/librustc_lint/builtin.rs | 38 ++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 6252c372009b2..13c99e9dff7b0 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -887,32 +887,28 @@ fn method_context(cx: &Context, m: &ast::Method) -> MethodContext { match cx.tcx.impl_or_trait_items.borrow().get(&did).cloned() { None => cx.sess().span_bug(m.span, "missing method descriptor?!"), - Some(md) => { - match md { - ty::MethodTraitItem(md) => { - match md.container { - ty::TraitContainer(..) => MethodContext::TraitDefaultImpl, - ty::ImplContainer(cid) => { - match ty::impl_trait_ref(cx.tcx, cid) { - Some(..) => MethodContext::TraitImpl, - None => MethodContext::PlainImpl - } - } + Some(ty::MethodTraitItem(md)) => { + match md.container { + ty::TraitContainer(..) => MethodContext::TraitDefaultImpl, + ty::ImplContainer(cid) => { + match ty::impl_trait_ref(cx.tcx, cid) { + Some(..) => MethodContext::TraitImpl, + None => MethodContext::PlainImpl } } - ty::TypeTraitItem(typedef) => { - match typedef.container { - ty::TraitContainer(..) => MethodContext::TraitDefaultImpl, - ty::ImplContainer(cid) => { - match ty::impl_trait_ref(cx.tcx, cid) { - Some(..) => MethodContext::TraitImpl, - None => MethodContext::PlainImpl - } - } + } + }, + Some(ty::TypeTraitItem(typedef)) => { + match typedef.container { + ty::TraitContainer(..) => MethodContext::TraitDefaultImpl, + ty::ImplContainer(cid) => { + match ty::impl_trait_ref(cx.tcx, cid) { + Some(..) => MethodContext::TraitImpl, + None => MethodContext::PlainImpl } } } - } + }, } } From fe2e0976decadb94cecc4ab85abdd02345cc7a64 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sat, 28 Feb 2015 13:32:34 +0100 Subject: [PATCH 06/17] Use if-let for UnusedImportBraces. --- src/librustc_lint/builtin.rs | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 13c99e9dff7b0..015c841ea1ddf 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1218,26 +1218,17 @@ impl LintPass for UnusedImportBraces { } fn check_item(&mut self, cx: &Context, item: &ast::Item) { - match item.node { - ast::ItemUse(ref view_path) => { - match view_path.node { - ast::ViewPathList(_, ref items) => { - if items.len() == 1 { - match items[0].node { - ast::PathListIdent {ref name, ..} => { - let m = format!("braces around {} is unnecessary", - &token::get_ident(*name)); - cx.span_lint(UNUSED_IMPORT_BRACES, item.span, - &m[..]); - }, - _ => () - } - } + if let ast::ItemUse(ref view_path) = item.node { + if let ast::ViewPathList(_, ref items) = view_path.node { + if items.len() == 1 { + if let ast::PathListIdent {ref name, ..} = items[0].node { + let m = format!("braces around {} is unnecessary", + &token::get_ident(*name)); + cx.span_lint(UNUSED_IMPORT_BRACES, item.span, + &m[..]); } - _ => () } - }, - _ => () + } } } } From 2fc62244113d01e9524ed712210ba52e8471e2a9 Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Sat, 28 Feb 2015 13:56:37 -0800 Subject: [PATCH 07/17] Rename LintPass::check_trait_method to check_trait_item Traits can have associated types and not just methods. This clarification reflects the the type of the input the method accepts. [breaking-change] --- src/librustc/lint/context.rs | 2 +- src/librustc/lint/mod.rs | 2 +- src/librustc_lint/builtin.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 2b968736ffd9a..f635c77af9b2a 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -612,7 +612,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { } fn visit_trait_item(&mut self, m: &ast::TraitItem) { - run_lints!(self, check_trait_method, m); + run_lints!(self, check_trait_item, m); visit::walk_trait_item(self, m); } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index f3fa3b8846ca2..506d20133bdc7 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -144,7 +144,7 @@ pub trait LintPass { fn check_fn(&mut self, _: &Context, _: FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { } fn check_ty_method(&mut self, _: &Context, _: &ast::TypeMethod) { } - fn check_trait_method(&mut self, _: &Context, _: &ast::TraitItem) { } + fn check_trait_item(&mut self, _: &Context, _: &ast::TraitItem) { } fn check_struct_def(&mut self, _: &Context, _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { } fn check_struct_def_post(&mut self, _: &Context, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index d0fccf6495a0a..4785cde145618 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1577,7 +1577,7 @@ impl LintPass for MissingDoc { tm.span, "a type method"); } - fn check_trait_method(&mut self, cx: &Context, it: &ast::TraitItem) { + fn check_trait_item(&mut self, cx: &Context, it: &ast::TraitItem) { if let ast::TraitItem::TypeTraitItem(ref ty) = *it { let assoc_ty = &ty.ty_param; self.check_missing_docs_attrs(cx, Some(assoc_ty.id), &ty.attrs, From 9e28caef31de0b36262273be13d29cec80876f77 Mon Sep 17 00:00:00 2001 From: GuillaumeGomez Date: Wed, 18 Feb 2015 23:46:22 +0100 Subject: [PATCH 08/17] Remove int/uint --- src/libcore/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a9d6997359085..7cc963bed358f 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -39,7 +39,7 @@ //! distribution. //! //! * `rust_begin_unwind` - This function takes three arguments, a -//! `fmt::Arguments`, a `&str`, and a `uint`. These three arguments dictate +//! `fmt::Arguments`, a `&str`, and a `usize`. These three arguments dictate //! the panic message, the file at which panic was invoked, and the line. //! It is up to consumers of this core library to define this panic //! function; it is only required to never return. @@ -88,14 +88,12 @@ mod int_macros; #[macro_use] mod uint_macros; -#[path = "num/int.rs"] pub mod int; #[path = "num/isize.rs"] pub mod isize; #[path = "num/i8.rs"] pub mod i8; #[path = "num/i16.rs"] pub mod i16; #[path = "num/i32.rs"] pub mod i32; #[path = "num/i64.rs"] pub mod i64; -#[path = "num/uint.rs"] pub mod uint; #[path = "num/usize.rs"] pub mod usize; #[path = "num/u8.rs"] pub mod u8; #[path = "num/u16.rs"] pub mod u16; From c74d49c804c3c75172ea06efb83e1a863929da52 Mon Sep 17 00:00:00 2001 From: GuillaumeGomez Date: Thu, 19 Feb 2015 01:12:45 +0100 Subject: [PATCH 09/17] Fix errors, remove unused files --- src/libcore/num/int.rs | 21 --------------------- src/libcore/num/uint.rs | 20 -------------------- src/librand/rand_impls.rs | 24 ++++++++++++------------ src/libstd/lib.rs | 2 +- 4 files changed, 13 insertions(+), 54 deletions(-) delete mode 100644 src/libcore/num/int.rs delete mode 100644 src/libcore/num/uint.rs diff --git a/src/libcore/num/int.rs b/src/libcore/num/int.rs deleted file mode 100644 index 2132b9516abad..0000000000000 --- a/src/libcore/num/int.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012-2014 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. - -//! Deprecated: replaced by `isize`. -//! -//! The rollout of the new type will gradually take place over the -//! alpha cycle along with the development of clearer conventions -//! around integer types. - -#![unstable(feature = "core")] -#![deprecated(since = "1.0.0", reason = "replaced by isize")] - -#[cfg(target_pointer_width = "32")] int_module! { int, 32 } -#[cfg(target_pointer_width = "64")] int_module! { int, 64 } diff --git a/src/libcore/num/uint.rs b/src/libcore/num/uint.rs deleted file mode 100644 index f66a0eed97161..0000000000000 --- a/src/libcore/num/uint.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012-2014 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. - -//! Deprecated: replaced by `usize`. -//! -//! The rollout of the new type will gradually take place over the -//! alpha cycle along with the development of clearer conventions -//! around integer types. - -#![unstable(feature = "core")] -#![deprecated(since = "1.0.0", reason = "replaced by usize")] - -uint_module! { uint, int, ::int::BITS } diff --git a/src/librand/rand_impls.rs b/src/librand/rand_impls.rs index d5c5d5004657e..74d2c408060cb 100644 --- a/src/librand/rand_impls.rs +++ b/src/librand/rand_impls.rs @@ -12,18 +12,18 @@ use core::prelude::*; use core::char; -use core::int; -use core::uint; +use core::isize; +use core::usize; use {Rand,Rng}; -impl Rand for int { +impl Rand for isize { #[inline] - fn rand(rng: &mut R) -> int { - if int::BITS == 32 { - rng.gen::() as int + fn rand(rng: &mut R) -> isize { + if isize::BITS == 32 { + rng.gen::() as isize } else { - rng.gen::() as int + rng.gen::() as isize } } } @@ -56,13 +56,13 @@ impl Rand for i64 { } } -impl Rand for uint { +impl Rand for usize { #[inline] - fn rand(rng: &mut R) -> uint { - if uint::BITS == 32 { - rng.gen::() as uint + fn rand(rng: &mut R) -> usize { + if usize::BITS == 32 { + rng.gen::() as usize } else { - rng.gen::() as uint + rng.gen::() as usize } } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index b5bdeb7f181b0..607c124076d19 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -109,7 +109,7 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(core)] -#![feature(int_uint)] +#![feature(hash)] #![feature(lang_items)] #![feature(libc)] #![feature(linkage, thread_local, asm)] From 5ef618210232397474a5cf2c7d863e11b07511f5 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 24 Feb 2015 18:20:41 +0100 Subject: [PATCH 10/17] Add check for unbounded due to non-regular types in dropck. Count recursion across phantom data separately from all recursion, and treat `Box` just as if it were carrying `PhantomData`. (Regression tests are in followup commit.) The practical effect of this is just to increment the `xref_depth` counter, the same way that `Vec` and other types carrying `PhantomData` do. --- src/librustc_typeck/check/dropck.rs | 146 +++++++++++++++++++++++----- src/librustc_typeck/diagnostics.rs | 3 +- 2 files changed, 125 insertions(+), 24 deletions(-) diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 083523f7ba92f..cffd74ccd7218 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -14,8 +14,9 @@ use middle::infer; use middle::region; use middle::subst; use middle::ty::{self, Ty}; -use util::ppaux::{Repr}; +use util::ppaux::{Repr, UserString}; +use syntax::ast; use syntax::codemap::Span; pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, @@ -28,29 +29,98 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx> // types that have been traversed so far by `traverse_type_if_unseen` let mut breadcrumbs: Vec> = Vec::new(); - iterate_over_potentially_unsafe_regions_in_type( + let result = iterate_over_potentially_unsafe_regions_in_type( rcx, &mut breadcrumbs, + TypeContext::Root, typ, span, scope, + 0, 0); + match result { + Ok(()) => {} + Err(Error::Overflow(ref ctxt, ref detected_on_typ)) => { + let tcx = rcx.tcx(); + span_err!(tcx.sess, span, E0320, + "overflow while adding drop-check rules for {}", + typ.user_string(rcx.tcx())); + match *ctxt { + TypeContext::Root => { + // no need for an additional note if the overflow + // was somehow on the root. + } + TypeContext::EnumVariant { def_id, variant, arg_index } => { + // FIXME (pnkfelix): eventually lookup arg_name + // for the given index on struct variants. + span_note!( + rcx.tcx().sess, + span, + "overflowed on enum {} variant {} argument {} type: {}", + ty::item_path_str(tcx, def_id), + variant, + arg_index, + detected_on_typ.user_string(rcx.tcx())); + } + TypeContext::Struct { def_id, field } => { + span_note!( + rcx.tcx().sess, + span, + "overflowed on struct {} field {} type: {}", + ty::item_path_str(tcx, def_id), + field, + detected_on_typ.user_string(rcx.tcx())); + } + } + } + } +} + +enum Error<'tcx> { + Overflow(TypeContext, ty::Ty<'tcx>), +} + +enum TypeContext { + Root, + EnumVariant { + def_id: ast::DefId, + variant: ast::Name, + arg_index: usize, + }, + Struct { + def_id: ast::DefId, + field: ast::Name, + } } +// The `depth` counts the number of calls to this function; +// the `xref_depth` counts the subset of such calls that go +// across a `Box` or `PhantomData`. fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( rcx: &mut Rcx<'a, 'tcx>, breadcrumbs: &mut Vec>, + context: TypeContext, ty_root: ty::Ty<'tcx>, span: Span, scope: region::CodeExtent, - depth: uint) + depth: uint, + xref_depth: uint) -> Result<(), Error<'tcx>> { + // Issue #22443: Watch out for overflow. While we are careful to + // handle regular types properly, non-regular ones cause problems. + let recursion_limit = rcx.tcx().sess.recursion_limit.get(); + if xref_depth >= recursion_limit { + return Err(Error::Overflow(context, ty_root)) + } + let origin = || infer::SubregionOrigin::SafeDestructor(span); let mut walker = ty_root.walk(); let opt_phantom_data_def_id = rcx.tcx().lang_items.phantom_data(); let destructor_for_type = rcx.tcx().destructor_for_type.borrow(); + let xref_depth_orig = xref_depth; + while let Some(typ) = walker.next() { // Avoid recursing forever. if breadcrumbs.contains(&typ) { @@ -61,20 +131,33 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( // If we encounter `PhantomData`, then we should replace it // with `T`, the type it represents as owned by the // surrounding context, before doing further analysis. - let typ = if let ty::ty_struct(struct_did, substs) = typ.sty { - if opt_phantom_data_def_id == Some(struct_did) { - let item_type = ty::lookup_item_type(rcx.tcx(), struct_did); - let tp_def = item_type.generics.types - .opt_get(subst::TypeSpace, 0).unwrap(); - let new_typ = substs.type_for_def(tp_def); - debug!("replacing phantom {} with {}", + let (typ, xref_depth) = match typ.sty { + ty::ty_struct(struct_did, substs) => { + if opt_phantom_data_def_id == Some(struct_did) { + let item_type = ty::lookup_item_type(rcx.tcx(), struct_did); + let tp_def = item_type.generics.types + .opt_get(subst::TypeSpace, 0).unwrap(); + let new_typ = substs.type_for_def(tp_def); + debug!("replacing phantom {} with {}", + typ.repr(rcx.tcx()), new_typ.repr(rcx.tcx())); + (new_typ, xref_depth_orig + 1) + } else { + (typ, xref_depth_orig) + } + } + + // Note: When ty_uniq is removed from compiler, the + // definition of `Box` must carry a PhantomData that + // puts us into the previous case. + ty::ty_uniq(new_typ) => { + debug!("replacing ty_uniq {} with {}", typ.repr(rcx.tcx()), new_typ.repr(rcx.tcx())); - new_typ - } else { - typ + (new_typ, xref_depth_orig + 1) + } + + _ => { + (typ, xref_depth_orig) } - } else { - typ }; let opt_type_did = match typ.sty { @@ -87,9 +170,9 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( opt_type_did.and_then(|did| destructor_for_type.get(&did)); debug!("iterate_over_potentially_unsafe_regions_in_type \ - {}typ: {} scope: {:?} opt_dtor: {:?}", + {}typ: {} scope: {:?} opt_dtor: {:?} xref: {}", (0..depth).map(|_| ' ').collect::(), - typ.repr(rcx.tcx()), scope, opt_dtor); + typ.repr(rcx.tcx()), scope, opt_dtor, xref_depth); // If `typ` has a destructor, then we must ensure that all // borrowed data reachable via `typ` must outlive the parent @@ -228,6 +311,8 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( match typ.sty { ty::ty_struct(struct_did, substs) => { + debug!("typ: {} is struct; traverse structure and not type-expression", + typ.repr(rcx.tcx())); // Don't recurse; we extract type's substructure, // so do not process subparts of type expression. walker.skip_current_subtree(); @@ -240,17 +325,24 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( struct_did, field.id, substs); - iterate_over_potentially_unsafe_regions_in_type( + try!(iterate_over_potentially_unsafe_regions_in_type( rcx, breadcrumbs, + TypeContext::Struct { + def_id: struct_did, + field: field.name, + }, field_type, span, scope, - depth+1) + depth+1, + xref_depth)) } } ty::ty_enum(enum_did, substs) => { + debug!("typ: {} is enum; traverse structure and not type-expression", + typ.repr(rcx.tcx())); // Don't recurse; we extract type's substructure, // so do not process subparts of type expression. walker.skip_current_subtree(); @@ -260,14 +352,20 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( enum_did, substs); for variant_info in all_variant_info.iter() { - for argument_type in variant_info.args.iter() { - iterate_over_potentially_unsafe_regions_in_type( + for (i, arg_type) in variant_info.args.iter().enumerate() { + try!(iterate_over_potentially_unsafe_regions_in_type( rcx, breadcrumbs, - *argument_type, + TypeContext::EnumVariant { + def_id: enum_did, + variant: variant_info.name, + arg_index: i, + }, + *arg_type, span, scope, - depth+1) + depth+1, + xref_depth)); } } } @@ -290,4 +388,6 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( // is done. } } + + return Ok(()); } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 7b43a9fef06dc..3bd15fbc7dbea 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -174,7 +174,8 @@ register_diagnostics! { E0249, // expected constant expr for array length E0250, // expected constant expr for array length E0318, // can't create default impls for traits outside their crates - E0319 // trait impls for defaulted traits allowed just for structs/enums + E0319, // trait impls for defaulted traits allowed just for structs/enums + E0320 // recursive overflow during dropck } __build_diagnostic_array! { DIAGNOSTICS } From 180ef47af2f1e72f7d199e09bf0a2fc895e2235f Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 24 Feb 2015 18:34:39 +0100 Subject: [PATCH 11/17] Add regression tests for issue 22443. Fix #22443. --- .../dropck_no_diverge_on_nonregular_1.rs | 37 +++++++++++++ .../dropck_no_diverge_on_nonregular_2.rs | 36 ++++++++++++ .../dropck_no_diverge_on_nonregular_3.rs | 46 ++++++++++++++++ src/test/run-pass/issue-22777.rs | 55 +++++++++++++++++++ 4 files changed, 174 insertions(+) create mode 100644 src/test/compile-fail/dropck_no_diverge_on_nonregular_1.rs create mode 100644 src/test/compile-fail/dropck_no_diverge_on_nonregular_2.rs create mode 100644 src/test/compile-fail/dropck_no_diverge_on_nonregular_3.rs create mode 100644 src/test/run-pass/issue-22777.rs diff --git a/src/test/compile-fail/dropck_no_diverge_on_nonregular_1.rs b/src/test/compile-fail/dropck_no_diverge_on_nonregular_1.rs new file mode 100644 index 0000000000000..f096885381989 --- /dev/null +++ b/src/test/compile-fail/dropck_no_diverge_on_nonregular_1.rs @@ -0,0 +1,37 @@ +// 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. + +// Issue 22443: Reject code using non-regular types that would +// otherwise cause dropck to loop infinitely. + +use std::marker::PhantomData; + +struct Digit { + elem: T +} + +struct Node { m: PhantomData<&'static T> } + + +enum FingerTree { + Single(T), + // Bug report said Digit after Box would stack overflow (versus + // Digit before Box; see dropck_no_diverge_on_nonregular_2). + Deep( + Box>>, + Digit, + ) +} + +fn main() { + let ft = //~ ERROR overflow while adding drop-check rules for FingerTree + FingerTree::Single(1); + //~^ ERROR overflow while adding drop-check rules for FingerTree +} diff --git a/src/test/compile-fail/dropck_no_diverge_on_nonregular_2.rs b/src/test/compile-fail/dropck_no_diverge_on_nonregular_2.rs new file mode 100644 index 0000000000000..886bd6bea20d7 --- /dev/null +++ b/src/test/compile-fail/dropck_no_diverge_on_nonregular_2.rs @@ -0,0 +1,36 @@ +// 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. + +// Issue 22443: Reject code using non-regular types that would +// otherwise cause dropck to loop infinitely. + +use std::marker::PhantomData; + +struct Digit { + elem: T +} + +struct Node { m: PhantomData<&'static T> } + +enum FingerTree { + Single(T), + // Bug report said Digit before Box would infinite loop (versus + // Digit after Box; see dropck_no_diverge_on_nonregular_1). + Deep( + Digit, + Box>>, + ) +} + +fn main() { + let ft = //~ ERROR overflow while adding drop-check rules for FingerTree + FingerTree::Single(1); + //~^ ERROR overflow while adding drop-check rules for FingerTree +} diff --git a/src/test/compile-fail/dropck_no_diverge_on_nonregular_3.rs b/src/test/compile-fail/dropck_no_diverge_on_nonregular_3.rs new file mode 100644 index 0000000000000..f7eb6e10ca788 --- /dev/null +++ b/src/test/compile-fail/dropck_no_diverge_on_nonregular_3.rs @@ -0,0 +1,46 @@ +// 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. + +// Issue 22443: Reject code using non-regular types that would +// otherwise cause dropck to loop infinitely. +// +// This version is just checking that we still sanely handle a trivial +// wrapper around the non-regular type. (It also demonstrates how the +// error messages will report different types depending on which type +// dropck is analyzing.) + +use std::marker::PhantomData; + +struct Digit { + elem: T +} + +struct Node { m: PhantomData<&'static T> } + +enum FingerTree { + Single(T), + // According to the bug report, Digit before Box would infinite loop. + Deep( + Digit, + Box>>, + ) +} + +enum Wrapper { + Simple, + Other(FingerTree), +} + +fn main() { + let w = //~ ERROR overflow while adding drop-check rules for core::option + Some(Wrapper::Simple::); + //~^ ERROR overflow while adding drop-check rules for core::option::Option + //~| ERROR overflow while adding drop-check rules for Wrapper +} diff --git a/src/test/run-pass/issue-22777.rs b/src/test/run-pass/issue-22777.rs new file mode 100644 index 0000000000000..cab33beda405f --- /dev/null +++ b/src/test/run-pass/issue-22777.rs @@ -0,0 +1,55 @@ +// 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. + +// This test is reduced from libsyntax. It is just checking that we +// can successfully deal with a "deep" structure, which the drop-check +// was hitting a recursion limit on at one point. + +#![allow(non_camel_case_types)] + +pub fn noop_fold_impl_item() -> SmallVector { + loop { } +} + +pub struct SmallVector(P); +pub struct ImplItem(P); + +struct P(Box); + +struct S01_Method(P); +struct S02_Generics(P); +struct S03_TyParam(P); +struct S04_TyParamBound(S05_PolyTraitRef); +struct S05_PolyTraitRef(S06_TraitRef); +struct S06_TraitRef(S07_Path); +struct S07_Path(Vec); +struct S08_PathSegment(S09_PathParameters); +struct S09_PathParameters(P); +struct S10_ParenthesizedParameterData(Option>); +struct S11_Ty(P); +struct S12_Expr(P); +struct S13_Block(Vec>); +struct S14_Stmt(P); +struct S15_Decl(P); +struct S16_Local(P); +struct S17_Pat(P); +struct S18_Mac(Vec>); +struct S19_TokenTree(P); +struct S20_Token(P); +struct S21_Nonterminal(P); +struct S22_Item(P); +struct S23_EnumDef(Vec>); +struct S24_Variant(P); +struct S25_VariantKind(P); +struct S26_StructDef(Vec>); +struct S27_StructField(P); +struct S28_StructFieldKind; + +pub fn main() {} From 549be5f867764e30d425790e8728da75411f6fec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Sat, 28 Feb 2015 21:38:49 +0100 Subject: [PATCH 12/17] Emit proper function argument attributes for closure environments --- src/librustc_trans/trans/base.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index b18b7b75d32fc..9bbaa5dca95fb 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2430,21 +2430,19 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< use middle::ty::{BrAnon, ReLateBound}; let function_type; - let (fn_sig, abi, has_env) = match fn_ty.sty { - ty::ty_bare_fn(_, ref f) => (&f.sig, f.abi, false), + let (fn_sig, abi, env_ty) = match fn_ty.sty { + ty::ty_bare_fn(_, ref f) => (&f.sig, f.abi, None), ty::ty_closure(closure_did, _, substs) => { let typer = common::NormalizingClosureTyper::new(ccx.tcx()); function_type = typer.closure_type(closure_did, substs); - (&function_type.sig, RustCall, true) + let self_type = self_type_for_closure(ccx, closure_did, fn_ty); + (&function_type.sig, RustCall, Some(self_type)) } _ => ccx.sess().bug("expected closure or function.") }; let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig); - // Since index 0 is the return value of the llvm func, we start - // at either 1 or 2 depending on whether there's an env slot or not - let mut first_arg_offset = if has_env { 2 } else { 1 }; let mut attrs = llvm::AttrBuilder::new(); let ret_ty = fn_sig.output; @@ -2455,7 +2453,11 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< assert!(abi == RustCall); match fn_sig.inputs[0].sty { - ty::ty_tup(ref inputs) => inputs.clone(), + ty::ty_tup(ref inputs) => { + let mut full_inputs = vec![env_ty.expect("Missing closure environment")]; + full_inputs.push_all(inputs); + full_inputs + } _ => ccx.sess().bug("expected tuple'd inputs") } }, @@ -2473,6 +2475,8 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< _ => fn_sig.inputs.clone() }; + // Index 0 is the return value of the llvm func, so we start at 1 + let mut first_arg_offset = 1; if let ty::FnConverging(ret_ty) = ret_ty { // A function pointer is called without the declaration // available, so we have to apply any attributes with ABI From 708c3858e3e98d1b362b73510aa48416c3f68e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Sat, 28 Feb 2015 21:41:26 +0100 Subject: [PATCH 13/17] Use trans_arg_datum in trans_args_under_call_abi The logic for the argument translation was duplicated here. --- src/librustc_trans/trans/callee.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 59fcd5492ebde..029c6347cd499 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -927,20 +927,21 @@ fn trans_args_under_call_abi<'blk, 'tcx>( tuple_expr.id)); let repr = adt::represent_type(bcx.ccx(), tuple_type); let repr_ptr = &*repr; - for i in 0..field_types.len() { + llargs.extend(field_types.iter().enumerate().map(|(i, field_type)| { let arg_datum = tuple_lvalue_datum.get_element( bcx, - field_types[i], + field_type, |srcval| { adt::trans_field_ptr(bcx, repr_ptr, srcval, 0, i) - }); - let arg_datum = arg_datum.to_expr_datum(); - let arg_datum = - unpack_datum!(bcx, arg_datum.to_rvalue_datum(bcx, "arg")); - let arg_datum = - unpack_datum!(bcx, arg_datum.to_appropriate_datum(bcx)); - llargs.push(arg_datum.add_clean(bcx.fcx, arg_cleanup_scope)); - } + }).to_expr_datum(); + unpack_result!(bcx, trans_arg_datum( + bcx, + field_type, + arg_datum, + arg_cleanup_scope, + DontAutorefArg) + ) + })); } _ => { bcx.sess().span_bug(tuple_expr.span, From df126589b91c7b60e2426b46c5a8b14d7d04f667 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 27 Feb 2015 01:43:55 +0100 Subject: [PATCH 14/17] Remove int/uint from libstd/lib.rs --- src/libcoretest/iter.rs | 14 +++---- src/libcoretest/num/int.rs | 11 ----- src/libcoretest/num/int_macros.rs | 4 +- src/libcoretest/num/mod.rs | 2 - src/libcoretest/num/uint.rs | 11 ----- src/libgetopts/lib.rs | 2 +- src/librustc/middle/liveness.rs | 40 +++++++++---------- src/librustc_trans/trans/_match.rs | 2 +- src/libstd/lib.rs | 2 - src/test/compile-fail/issue-8460-const.rs | 6 +-- src/test/compile-fail/unnecessary-private.rs | 2 +- src/test/run-fail/bounds-check-no-overflow.rs | 4 +- .../run-fail/hashmap-capacity-overflow.rs | 4 +- 13 files changed, 39 insertions(+), 65 deletions(-) delete mode 100644 src/libcoretest/num/int.rs delete mode 100644 src/libcoretest/num/uint.rs diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 8a27400389f4a..abf88583c03ff 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -12,7 +12,7 @@ use core::iter::*; use core::iter::order::*; use core::iter::MinMaxResult::*; use core::num::SignedInt; -use core::uint; +use core::usize; use core::cmp; use test::Bencher; @@ -292,7 +292,7 @@ fn test_unfoldr() { fn test_cycle() { let cycle_len = 3; let it = count(0, 1).take(cycle_len).cycle(); - assert_eq!(it.size_hint(), (uint::MAX, None)); + assert_eq!(it.size_hint(), (usize::MAX, None)); for (i, x) in it.take(100).enumerate() { assert_eq!(i % cycle_len, x); } @@ -365,19 +365,19 @@ fn test_iterator_size_hint() { let v2 = &[10, 11, 12]; let vi = v.iter(); - assert_eq!(c.size_hint(), (uint::MAX, None)); + assert_eq!(c.size_hint(), (usize::MAX, None)); assert_eq!(vi.clone().size_hint(), (10, Some(10))); assert_eq!(c.clone().take(5).size_hint(), (5, Some(5))); assert_eq!(c.clone().skip(5).size_hint().1, None); assert_eq!(c.clone().take_while(|_| false).size_hint(), (0, None)); assert_eq!(c.clone().skip_while(|_| false).size_hint(), (0, None)); - assert_eq!(c.clone().enumerate().size_hint(), (uint::MAX, None)); - assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (uint::MAX, None)); + assert_eq!(c.clone().enumerate().size_hint(), (usize::MAX, None)); + assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (usize::MAX, None)); assert_eq!(c.clone().zip(vi.clone()).size_hint(), (10, Some(10))); assert_eq!(c.clone().scan(0, |_,_| Some(0)).size_hint(), (0, None)); assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None)); - assert_eq!(c.clone().map(|_| 0).size_hint(), (uint::MAX, None)); + assert_eq!(c.clone().map(|_| 0).size_hint(), (usize::MAX, None)); assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None)); assert_eq!(vi.clone().take(5).size_hint(), (5, Some(5))); @@ -753,7 +753,7 @@ fn test_range() { assert_eq!((0..100).size_hint(), (100, Some(100))); // this test is only meaningful when sizeof uint < sizeof u64 - assert_eq!((uint::MAX - 1..uint::MAX).size_hint(), (1, Some(1))); + assert_eq!((usize::MAX - 1..usize::MAX).size_hint(), (1, Some(1))); assert_eq!((-10..-1).size_hint(), (9, Some(9))); assert_eq!((-1..-10).size_hint(), (0, Some(0))); } diff --git a/src/libcoretest/num/int.rs b/src/libcoretest/num/int.rs deleted file mode 100644 index be8dfd02ee196..0000000000000 --- a/src/libcoretest/num/int.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2014 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. - -int_module!(int, int); diff --git a/src/libcoretest/num/int_macros.rs b/src/libcoretest/num/int_macros.rs index f5657d939b2af..5ff5cf428ab1c 100644 --- a/src/libcoretest/num/int_macros.rs +++ b/src/libcoretest/num/int_macros.rs @@ -12,7 +12,7 @@ macro_rules! int_module { ($T:ty, $T_i:ident) => ( #[cfg(test)] mod tests { use core::$T_i::*; - use core::int; + use core::isize; use core::num::{FromStrRadix, Int, SignedInt}; use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr}; use num; @@ -153,7 +153,7 @@ mod tests { fn test_signed_checked_div() { assert!(10.checked_div(2) == Some(5)); assert!(5.checked_div(0) == None); - assert!(int::MIN.checked_div(-1) == None); + assert!(isize::MIN.checked_div(-1) == None); } #[test] diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 03f6e51a3498a..1cd1989c11dc3 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -21,7 +21,6 @@ mod i8; mod i16; mod i32; mod i64; -mod int; #[macro_use] mod uint_macros; @@ -30,7 +29,6 @@ mod u8; mod u16; mod u32; mod u64; -mod uint; /// Helper function for testing numeric operations pub fn test_num(ten: T, two: T) where diff --git a/src/libcoretest/num/uint.rs b/src/libcoretest/num/uint.rs deleted file mode 100644 index 395e55cf255d2..0000000000000 --- a/src/libcoretest/num/uint.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2014 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. - -uint_module!(uint, uint); diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 4e329897e1ab2..6240b0e6afdd5 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -963,7 +963,7 @@ fn test_split_within() { "little lamb".to_string(), "Little lamb".to_string() ]); - t("\nMary had a little lamb\nLittle lamb\n", ::std::uint::MAX, + t("\nMary had a little lamb\nLittle lamb\n", ::std::usize::MAX, &["Mary had a little lamb\nLittle lamb".to_string()]); } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 2ac019aa964dc..5cb034667cc64 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -51,8 +51,8 @@ //! enclosing function. On the way down the tree, it identifies those AST //! nodes and variable IDs that will be needed for the liveness analysis //! and assigns them contiguous IDs. The liveness id for an AST node is -//! called a `live_node` (it's a newtype'd uint) and the id for a variable -//! is called a `variable` (another newtype'd uint). +//! called a `live_node` (it's a newtype'd usize) and the id for a variable +//! is called a `variable` (another newtype'd usize). //! //! On the way back up the tree, as we are about to exit from a function //! declaration we allocate a `liveness` instance. Now that we know @@ -118,7 +118,7 @@ use middle::ty::ClosureTyper; use lint; use util::nodemap::NodeMap; -use std::{fmt, old_io, uint}; +use std::{fmt, old_io, usize}; use std::rc::Rc; use std::iter::repeat; use syntax::ast::{self, NodeId, Expr}; @@ -138,17 +138,17 @@ enum LoopKind<'a> { } #[derive(Copy, PartialEq)] -struct Variable(uint); +struct Variable(usize); #[derive(Copy, PartialEq)] -struct LiveNode(uint); +struct LiveNode(usize); impl Variable { - fn get(&self) -> uint { let Variable(v) = *self; v } + fn get(&self) -> usize { let Variable(v) = *self; v } } impl LiveNode { - fn get(&self) -> uint { let LiveNode(v) = *self; v } + fn get(&self) -> usize { let LiveNode(v) = *self; v } } impl Clone for LiveNode { @@ -232,11 +232,11 @@ impl fmt::Debug for Variable { impl LiveNode { fn is_valid(&self) -> bool { - self.get() != uint::MAX + self.get() != usize::MAX } } -fn invalid_node() -> LiveNode { LiveNode(uint::MAX) } +fn invalid_node() -> LiveNode { LiveNode(usize::MAX) } struct CaptureInfo { ln: LiveNode, @@ -260,8 +260,8 @@ enum VarKind { struct IrMaps<'a, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, - num_live_nodes: uint, - num_vars: uint, + num_live_nodes: usize, + num_vars: usize, live_node_map: NodeMap, variable_map: NodeMap, capture_info_map: NodeMap>>, @@ -540,9 +540,9 @@ struct Specials { clean_exit_var: Variable } -static ACC_READ: uint = 1; -static ACC_WRITE: uint = 2; -static ACC_USE: uint = 4; +static ACC_READ: u32 = 1; +static ACC_WRITE: u32 = 2; +static ACC_USE: u32 = 4; struct Liveness<'a, 'tcx: 'a> { ir: &'a mut IrMaps<'a, 'tcx>, @@ -631,7 +631,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { succ } - fn idx(&self, ln: LiveNode, var: Variable) -> uint { + fn idx(&self, ln: LiveNode, var: Variable) -> usize { ln.get() * self.ir.num_vars + var.get() } @@ -670,7 +670,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn indices2(&mut self, ln: LiveNode, succ_ln: LiveNode, mut op: F) where - F: FnMut(&mut Liveness<'a, 'tcx>, uint, uint), + F: FnMut(&mut Liveness<'a, 'tcx>, usize, usize), { let node_base_idx = self.idx(ln, Variable(0)); let succ_base_idx = self.idx(succ_ln, Variable(0)); @@ -684,7 +684,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { ln: LiveNode, mut test: F) -> old_io::IoResult<()> where - F: FnMut(uint) -> LiveNode, + F: FnMut(usize) -> LiveNode, { let node_base_idx = self.idx(ln, Variable(0)); for var_idx in 0..self.ir.num_vars { @@ -807,7 +807,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } // Either read, write, or both depending on the acc bitset - fn acc(&mut self, ln: LiveNode, var: Variable, acc: uint) { + fn acc(&mut self, ln: LiveNode, var: Variable, acc: u32) { debug!("{:?} accesses[{:x}] {:?}: {}", ln, acc, var, self.ln_str(ln)); @@ -1283,7 +1283,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } // see comment on propagate_through_lvalue() - fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint) + fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32) -> LiveNode { match expr.node { ast::ExprPath(..) => { @@ -1298,7 +1298,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } } - fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: uint) + fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: u32) -> LiveNode { match self.ir.tcx.def_map.borrow()[expr.id].full_def() { DefLocal(nid) => { diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 48ff4c8332022..2ab6f5b0f9521 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -789,7 +789,7 @@ fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option { // Irrefutable columns always go first, they'd only be duplicated in the branches. if total_score == 0 { - std::uint::MAX + std::usize::MAX } else { total_score } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 607c124076d19..7957bc35b76b5 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -221,14 +221,12 @@ mod int_macros; mod uint_macros; #[path = "num/isize.rs"] pub mod isize; -pub use isize as int; #[path = "num/i8.rs"] pub mod i8; #[path = "num/i16.rs"] pub mod i16; #[path = "num/i32.rs"] pub mod i32; #[path = "num/i64.rs"] pub mod i64; #[path = "num/usize.rs"] pub mod usize; -pub use usize as uint; #[path = "num/u8.rs"] pub mod u8; #[path = "num/u16.rs"] pub mod u16; #[path = "num/u32.rs"] pub mod u32; diff --git a/src/test/compile-fail/issue-8460-const.rs b/src/test/compile-fail/issue-8460-const.rs index 954ae8ebc48dd..9c2e8d278ab0b 100644 --- a/src/test/compile-fail/issue-8460-const.rs +++ b/src/test/compile-fail/issue-8460-const.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::{int, i8, i16, i32, i64}; +use std::{isize, i8, i16, i32, i64}; use std::thread; fn main() { - assert!(thread::spawn(move|| { int::MIN / -1; }).join().is_err()); + assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); //~^ ERROR attempted to divide with overflow in a constant expression assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); //~^ ERROR attempted to divide with overflow in a constant expression @@ -32,7 +32,7 @@ fn main() { //~^ ERROR attempted to divide by zero in a constant expression assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); //~^ ERROR attempted to divide by zero in a constant expression - assert!(thread::spawn(move|| { int::MIN % -1; }).join().is_err()); + assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); //~^ ERROR attempted remainder with overflow in a constant expression assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); //~^ ERROR attempted remainder with overflow in a constant expression diff --git a/src/test/compile-fail/unnecessary-private.rs b/src/test/compile-fail/unnecessary-private.rs index 964db6e9a4546..5f3744712ccb4 100644 --- a/src/test/compile-fail/unnecessary-private.rs +++ b/src/test/compile-fail/unnecessary-private.rs @@ -9,7 +9,7 @@ // except according to those terms. fn main() { - pub use std::uint; //~ ERROR: visibility has no effect + pub use std::usize; //~ ERROR: visibility has no effect pub struct A; //~ ERROR: visibility has no effect pub enum B {} //~ ERROR: visibility has no effect pub trait C { //~ ERROR: visibility has no effect diff --git a/src/test/run-fail/bounds-check-no-overflow.rs b/src/test/run-fail/bounds-check-no-overflow.rs index be4ad0781f272..c15c4b83828a3 100644 --- a/src/test/run-fail/bounds-check-no-overflow.rs +++ b/src/test/run-fail/bounds-check-no-overflow.rs @@ -10,10 +10,10 @@ // error-pattern:index out of bounds: the len is 3 but the index is -use std::uint; +use std::usize; use std::mem::size_of; fn main() { let xs = [1, 2, 3]; - xs[uint::MAX / size_of::() + 1]; + xs[usize::MAX / size_of::() + 1]; } diff --git a/src/test/run-fail/hashmap-capacity-overflow.rs b/src/test/run-fail/hashmap-capacity-overflow.rs index c86f8a38f63c4..2c7c0875227d9 100644 --- a/src/test/run-fail/hashmap-capacity-overflow.rs +++ b/src/test/run-fail/hashmap-capacity-overflow.rs @@ -11,11 +11,11 @@ // error-pattern:capacity overflow use std::collections::hash_map::HashMap; -use std::uint; +use std::usize; use std::mem::size_of; fn main() { - let threshold = uint::MAX / size_of::<(u64, u64, u64)>(); + let threshold = usize::MAX / size_of::<(u64, u64, u64)>(); let mut h = HashMap::::with_capacity(threshold + 100); h.insert(0, 0); } From a71da374df82d126efc697c86cd06fe5dd39768c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sun, 1 Mar 2015 16:03:28 +0100 Subject: [PATCH 15/17] unbreak dragonfly build after nacl integration this is the same problem as openbsd (#22792). without the patch, liblibc don't build. --- src/liblibc/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 74a95b3aba056..42143b06ca0e3 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -1115,7 +1115,6 @@ pub mod types { pub mod posix88 { pub type off_t = i64; pub type dev_t = u32; - pub type ino_t = u32; pub type pid_t = i32; pub type uid_t = u32; pub type gid_t = u32; From 8b6b3c159c0b980e340a9bb05b8a90bd9bc1dfd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Sun, 1 Mar 2015 18:19:07 +0100 Subject: [PATCH 16/17] Emit proper attributes for the self pointer in method call through trait objects For method calls through trait objects, we currently generate the llvm function argument attributes using the non-opaque method signature that still has the trait object fat pointer for the self pointer. This leads to attributes that are plain wrong, e.g. noalias. As we don't know anything about the concrete type of the underlying object, we must replace the self argument with an opaque i8 pointer before applying the attributes. --- src/librustc_trans/trans/callee.rs | 13 ++++++++++++- src/librustc_trans/trans/meth.rs | 28 +++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 59fcd5492ebde..71265bd71e18f 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -603,7 +603,18 @@ pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_method_call"); debug!("trans_method_call(call_expr={})", call_expr.repr(bcx.tcx())); let method_call = MethodCall::expr(call_expr.id); - let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty; + let method_ty = match bcx.tcx().method_map.borrow().get(&method_call) { + Some(method) => match method.origin { + ty::MethodTraitObject(_) => match method.ty.sty { + ty::ty_bare_fn(_, ref fty) => { + ty::mk_bare_fn(bcx.tcx(), None, meth::opaque_method_ty(bcx.tcx(), fty)) + } + _ => method.ty + }, + _ => method.ty + }, + None => panic!("method not found in trans_method_call") + }; trans_call_inner( bcx, call_expr.debug_loc(), diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 3411f12886d22..69e05eaea21d2 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -589,15 +589,16 @@ pub fn trans_object_shim<'a, 'tcx>( }; let fty = monomorphize::apply_param_substs(tcx, &object_substs, &method_ty.fty); let fty = tcx.mk_bare_fn(fty); - debug!("trans_object_shim: fty={}", fty.repr(tcx)); + let method_ty = opaque_method_ty(tcx, fty); + debug!("trans_object_shim: fty={} method_ty={}", fty.repr(tcx), method_ty.repr(tcx)); // - let method_bare_fn_ty = - ty::mk_bare_fn(tcx, None, fty); + let shim_fn_ty = ty::mk_bare_fn(tcx, None, fty); + let method_bare_fn_ty = ty::mk_bare_fn(tcx, None, method_ty); let function_name = - link::mangle_internal_name_by_type_and_seq(ccx, method_bare_fn_ty, "object_shim"); + link::mangle_internal_name_by_type_and_seq(ccx, shim_fn_ty, "object_shim"); let llfn = - decl_internal_rust_fn(ccx, method_bare_fn_ty, &function_name); + decl_internal_rust_fn(ccx, shim_fn_ty, &function_name); let sig = ty::erase_late_bound_regions(ccx.tcx(), &fty.sig); @@ -866,3 +867,20 @@ pub fn trans_trait_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx } + +/// Replace the self type (&Self or Box) with an opaque pointer. +pub fn opaque_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>) + -> &'tcx ty::BareFnTy<'tcx> { + let mut inputs = method_ty.sig.0.inputs.clone(); + inputs[0] = ty::mk_mut_ptr(tcx, ty::mk_mach_int(tcx, ast::TyI8)); + + tcx.mk_bare_fn(ty::BareFnTy { + unsafety: method_ty.unsafety, + abi: method_ty.abi, + sig: ty::Binder(ty::FnSig { + inputs: inputs, + output: method_ty.sig.0.output, + variadic: method_ty.sig.0.variadic, + }), + }) +} From 1f1c5d54bfd09285816c24d9f7e54d360787c7c7 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 5 Dec 2014 20:22:35 -0800 Subject: [PATCH 17/17] Ignore issue #16671 test on android (again) Seems to be blocking forever --- src/test/run-pass/issue-16671.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/run-pass/issue-16671.rs b/src/test/run-pass/issue-16671.rs index b06c4923c16c1..82543f543da83 100644 --- a/src/test/run-pass/issue-16671.rs +++ b/src/test/run-pass/issue-16671.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// DON'T REENABLE THIS UNLESS YOU'VE ACTUALLY FIXED THE UNDERLYING ISSUE +// ignore-android seems to block forever #![forbid(warnings)]