diff --git a/.travis.yml b/.travis.yml index 4738f91665dbe..9bd4d448cf3ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,16 +13,16 @@ matrix: include: # Images used in testing PR and try-build should be run first. - env: IMAGE=x86_64-gnu-llvm-3.9 RUST_BACKTRACE=1 - if: type = pull_request OR branch = auto + if: branch = auto - env: IMAGE=dist-x86_64-linux DEPLOY=1 - if: branch = try OR branch = auto + if: branch = auto # "alternate" deployments, these are "nightlies" but have LLVM assertions # turned on, they're deployed to a different location primarily for # additional testing. - env: IMAGE=dist-x86_64-linux DEPLOY_ALT=1 - if: branch = try OR branch = auto + if: branch = auto - env: > RUST_CHECK_TARGET=dist @@ -36,7 +36,7 @@ matrix: NO_DEBUG_ASSERTIONS=1 os: osx osx_image: xcode7.3 - if: branch = auto + if: branch = try # macOS builders. These are placed near the beginning because they are very # slow to run. @@ -105,7 +105,7 @@ matrix: NO_DEBUG_ASSERTIONS=1 os: osx osx_image: xcode7.3 - if: branch = auto + if: branch = try # Linux builders, remaining docker images - env: IMAGE=arm-android @@ -248,7 +248,7 @@ before_script: script: - > date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) - - stamp sh -x -c "$RUN_SCRIPT" + - stamp sh -x -c "$RUN_SCRIPT" || true - > date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) @@ -258,12 +258,6 @@ after_success: df -h; du . | sort -nr | head -n100 -after_failure: - - > - echo "#### Build failed; Disk usage after running script:"; - df -h; - du . | sort -nr | head -n100 - # One of these is the linux sccache log, one is the OSX sccache log. Instead # of worrying about what system we are just cat both. One of these commands # will fail but that's ok, they'll both get executed. diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index b1e28f729ed75..a1381817223f1 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -824,6 +824,17 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { hir_visit::walk_generics(self, g); } + fn visit_where_predicate(&mut self, p: &'tcx hir::WherePredicate) { + run_lints!(self, check_where_predicate, late_passes, p); + hir_visit::walk_where_predicate(self, p); + } + + fn visit_poly_trait_ref(&mut self, t: &'tcx hir::PolyTraitRef, + m: hir::TraitBoundModifier) { + run_lints!(self, check_poly_trait_ref, late_passes, t, m); + hir_visit::walk_poly_trait_ref(self, t, m); + } + fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { let generics = self.generics.take(); self.generics = Some(&trait_item.generics); @@ -986,6 +997,16 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { ast_visit::walk_generics(self, g); } + fn visit_where_predicate(&mut self, p: &'a ast::WherePredicate) { + run_lints!(self, check_where_predicate, early_passes, p); + ast_visit::walk_where_predicate(self, p); + } + + fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef, m: &'a ast::TraitBoundModifier) { + run_lints!(self, check_poly_trait_ref, early_passes, t, m); + ast_visit::walk_poly_trait_ref(self, t, m); + } + fn visit_trait_item(&mut self, trait_item: &'a ast::TraitItem) { self.with_lint_attrs(trait_item.id, &trait_item.attrs, |cx| { run_lints!(cx, check_trait_item, early_passes, trait_item); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 668e099ebab41..7c103dc272109 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -181,6 +181,9 @@ pub trait LateLintPass<'a, 'tcx>: LintPass { fn check_ty(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Ty) { } fn check_generic_param(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::GenericParam) { } fn check_generics(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Generics) { } + fn check_where_predicate(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::WherePredicate) { } + fn check_poly_trait_ref(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::PolyTraitRef, + _: hir::TraitBoundModifier) { } fn check_fn(&mut self, _: &LateContext<'a, 'tcx>, _: FnKind<'tcx>, @@ -253,6 +256,9 @@ pub trait EarlyLintPass: LintPass { fn check_ty(&mut self, _: &EarlyContext, _: &ast::Ty) { } fn check_generic_param(&mut self, _: &EarlyContext, _: &ast::GenericParam) { } fn check_generics(&mut self, _: &EarlyContext, _: &ast::Generics) { } + fn check_where_predicate(&mut self, _: &EarlyContext, _: &ast::WherePredicate) { } + fn check_poly_trait_ref(&mut self, _: &EarlyContext, _: &ast::PolyTraitRef, + _: &ast::TraitBoundModifier) { } fn check_fn(&mut self, _: &EarlyContext, _: ast_visit::FnKind, _: &ast::FnDecl, _: Span, _: ast::NodeId) { } fn check_fn_post(&mut self, _: &EarlyContext, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index d39e00ab18fcb..c6698cbd00689 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1315,3 +1315,50 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub { self.perform_lint(cx, "item", impl_item.id, &impl_item.vis, impl_item.span, false); } } + +/// Lint for trait and lifetime bounds that are (accidentally) accepted by the parser, but +/// ignored later. + +pub struct IgnoredGenericBounds; + +declare_lint! { + IGNORED_GENERIC_BOUNDS, + Warn, + "these generic bounds are ignored" +} + +impl LintPass for IgnoredGenericBounds { + fn get_lints(&self) -> LintArray { + lint_array!(IGNORED_GENERIC_BOUNDS) + } +} + +impl EarlyLintPass for IgnoredGenericBounds { + fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) { + let type_alias_generics = match item.node { + ast::ItemKind::Ty(_, ref generics) => generics, + _ => return, + }; + // There must not be a where clause + if !type_alias_generics.where_clause.predicates.is_empty() { + let spans : Vec<_> = type_alias_generics.where_clause.predicates.iter() + .map(|pred| pred.span()).collect(); + cx.span_lint(IGNORED_GENERIC_BOUNDS, spans, + "where clauses are ignored in type aliases"); + } + // The parameters must not have bounds + for param in type_alias_generics.params.iter() { + let spans : Vec<_> = match param { + &ast::GenericParam::Lifetime(ref l) => l.bounds.iter().map(|b| b.span).collect(), + &ast::GenericParam::Type(ref ty) => ty.bounds.iter().map(|b| b.span()).collect(), + }; + if !spans.is_empty() { + cx.span_lint( + IGNORED_GENERIC_BOUNDS, + spans, + "bounds on generic parameters are ignored in type aliases", + ); + } + } + } +} diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 81609db62923f..779aa3a9037ca 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -109,6 +109,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { UnusedImportBraces, AnonymousParameters, UnusedDocComment, + IgnoredGenericBounds, ); add_early_builtin_with_new!(sess, diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index a5dd8f1558e43..55d00f92e4dac 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -136,6 +136,33 @@ impl<'a> AstValidator<'a> { in patterns") } } + + fn check_late_bound_lifetime_defs(&self, params: &Vec) { + // Check: Only lifetime parameters + let non_lifetime_param_spans : Vec<_> = params.iter() + .filter_map(|param| match *param { + GenericParam::Lifetime(_) => None, + GenericParam::Type(ref t) => Some(t.span), + }).collect(); + if !non_lifetime_param_spans.is_empty() { + self.err_handler().span_err(non_lifetime_param_spans, + "only lifetime parameters can be used in this context"); + } + + // Check: No bounds on lifetime parameters + for param in params.iter() { + match *param { + GenericParam::Lifetime(ref l) => { + if !l.bounds.is_empty() { + let spans : Vec<_> = l.bounds.iter().map(|b| b.span).collect(); + self.err_handler().span_err(spans, + "lifetime bounds cannot be used in this context"); + } + } + GenericParam::Type(_) => {} + } + } + } } impl<'a> Visitor<'a> for AstValidator<'a> { @@ -157,6 +184,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { struct_span_err!(self.session, span, E0561, "patterns aren't allowed in function pointer types").emit(); }); + self.check_late_bound_lifetime_defs(&bfty.generic_params); } TyKind::TraitObject(ref bounds, ..) => { let mut any_lifetime_bounds = false; @@ -417,6 +445,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_pat(self, pat) } + + fn visit_where_predicate(&mut self, p: &'a WherePredicate) { + if let &WherePredicate::BoundPredicate(ref bound_predicate) = p { + // A type binding, eg `for<'c> Foo: Send+Clone+'c` + self.check_late_bound_lifetime_defs(&bound_predicate.bound_generic_params); + } + visit::walk_where_predicate(self, p); + } + + fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) { + self.check_late_bound_lifetime_defs(&t.bound_generic_params); + visit::walk_poly_trait_ref(self, t, m); + } } // Bans nested `impl Trait`, e.g. `impl Into`. diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 62301ab4a09d5..a17b35dec42d7 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -356,39 +356,6 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn ensure_no_param_bounds(tcx: TyCtxt, - span: Span, - generics: &hir::Generics, - thing: &'static str) { - let mut warn = false; - - for ty_param in generics.ty_params() { - if !ty_param.bounds.is_empty() { - warn = true; - } - } - - for lft_param in generics.lifetimes() { - if !lft_param.bounds.is_empty() { - warn = true; - } - } - - if !generics.where_clause.predicates.is_empty() { - warn = true; - } - - if warn { - // According to accepted RFC #XXX, we should - // eventually accept these, but it will not be - // part of this PR. Still, convert to warning to - // make bootstrapping easier. - span_warn!(tcx.sess, span, E0122, - "generic bounds are ignored in {}", - thing); - } -} - fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { let it = tcx.hir.expect_item(item_id); debug!("convert: item {} with id {}", it.name, it.id); @@ -449,13 +416,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { convert_variant_ctor(tcx, struct_def.id()); } }, - hir::ItemTy(_, ref generics) => { - ensure_no_param_bounds(tcx, it.span, generics, "type aliases"); - tcx.generics_of(def_id); - tcx.type_of(def_id); - tcx.predicates_of(def_id); - } - hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) => { + hir::ItemTy(..) | hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) => { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index bd2267a46010b..24044fd2d7218 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1489,26 +1489,6 @@ static BAR: _ = "test"; // error, explicitly write out the type instead ``` "##, -E0122: r##" -An attempt was made to add a generic constraint to a type alias. This constraint -is entirely ignored. For backwards compatibility, Rust still allows this with a -warning. Consider the example below: - -``` -trait Foo{} - -type MyType = (R, ()); - -fn main() { - let t: MyType; -} -``` - -We're able to declare a variable of type `MyType`, despite the fact that -`u32` does not implement `Foo`. As a result, one should avoid using generic -constraints in concert with type aliases. -"##, - E0124: r##" You declared two fields of a struct with the same name. Erroneous code example: @@ -4815,6 +4795,7 @@ register_diagnostics! { // E0086, // E0103, // E0104, +// E0122, // bounds in type aliases are ignored, turned into proper lint // E0123, // E0127, // E0129, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 10b8e121f8312..8b3a7164cccb6 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -294,6 +294,15 @@ pub enum TyParamBound { RegionTyParamBound(Lifetime) } +impl TyParamBound { + pub fn span(&self) -> Span { + match self { + &TraitTyParamBound(ref t, ..) => t.span, + &RegionTyParamBound(ref l) => l.span, + } + } +} + /// A modifier on a bound, currently this is only used for `?Sized`, where the /// modifier is `Maybe`. Negative bounds should also be handled here. #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] @@ -404,6 +413,16 @@ pub enum WherePredicate { EqPredicate(WhereEqPredicate), } +impl WherePredicate { + pub fn span(&self) -> Span { + match self { + &WherePredicate::BoundPredicate(ref p) => p.span, + &WherePredicate::RegionPredicate(ref p) => p.span, + &WherePredicate::EqPredicate(ref p) => p.span, + } + } +} + /// A type bound. /// /// E.g. `for<'c> Foo: Send+Clone+'c` diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 847733e1e37b6..f5aa01fb03459 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4951,6 +4951,7 @@ impl<'a> Parser<'a> { } )); // FIXME: Decide what should be used here, `=` or `==`. + // FIXME: We are just dropping the binders in lifetime_defs on the floor here. } else if self.eat(&token::Eq) || self.eat(&token::EqEq) { let rhs_ty = self.parse_ty()?; where_clause.predicates.push(ast::WherePredicate::EqPredicate( @@ -5608,18 +5609,8 @@ impl<'a> Parser<'a> { self.expect_lt()?; let params = self.parse_generic_params()?; self.expect_gt()?; - - let first_non_lifetime_param_span = params.iter() - .filter_map(|param| match *param { - ast::GenericParam::Lifetime(_) => None, - ast::GenericParam::Type(ref t) => Some(t.span), - }) - .next(); - - if let Some(span) = first_non_lifetime_param_span { - self.span_err(span, "only lifetime parameters can be used in this context"); - } - + // We rely on AST validation to rule out invalid cases: There must not be type + // parameters, and the lifetime parameters must not have bounds. Ok(params) } else { Ok(Vec::new()) diff --git a/src/test/compile-fail/issue-39122.rs b/src/test/compile-fail/bounds-lifetime.rs similarity index 50% rename from src/test/compile-fail/issue-39122.rs rename to src/test/compile-fail/bounds-lifetime.rs index 2e8a740f89394..5bfaa6c54fa9f 100644 --- a/src/test/compile-fail/issue-39122.rs +++ b/src/test/compile-fail/bounds-lifetime.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type Foo = T; //~ WARNING E0122 +type A = for<'b, 'a: 'b> fn(); //~ ERROR lifetime bounds cannot be used in this context +type B = for<'b, 'a: 'b,> fn(); //~ ERROR lifetime bounds cannot be used in this context +type C = for<'b, 'a: 'b +> fn(); //~ ERROR lifetime bounds cannot be used in this context +type D = for<'a, T> fn(); //~ ERROR only lifetime parameters can be used in this context +type E = for Fn(); //~ ERROR only lifetime parameters can be used in this context -type Bar where T: std::ops::Add = T; //~ WARNING E0122 +fn main() {} diff --git a/src/test/compile-fail/dst-bad-assign-3.rs b/src/test/compile-fail/dst-bad-assign-3.rs index 759da7b2bde21..ceaa371623223 100644 --- a/src/test/compile-fail/dst-bad-assign-3.rs +++ b/src/test/compile-fail/dst-bad-assign-3.rs @@ -12,8 +12,7 @@ #![feature(unsized_tuple_coercion)] -type Fat = (isize, &'static str, T); -//~^ WARNING bounds are ignored +type Fat = (isize, &'static str, T); #[derive(PartialEq,Eq)] struct Bar; diff --git a/src/test/compile-fail/issue-17994.rs b/src/test/compile-fail/issue-17994.rs index ac15bd9d15b04..0f30e2461cf3b 100644 --- a/src/test/compile-fail/issue-17994.rs +++ b/src/test/compile-fail/issue-17994.rs @@ -10,5 +10,5 @@ trait Tr {} type Huh where T: Tr = isize; //~ ERROR type parameter `T` is unused - //~| WARNING E0122 + //~| WARNING where clauses are ignored in type aliases fn main() {} diff --git a/src/test/compile-fail/issue-23046.rs b/src/test/compile-fail/issue-23046.rs index 129f7c8b1ea0e..670706b7a9adf 100644 --- a/src/test/compile-fail/issue-23046.rs +++ b/src/test/compile-fail/issue-23046.rs @@ -10,7 +10,7 @@ pub enum Expr<'var, VAR> { Let(Box>, - Box Fn(Expr<'v, VAR>) -> Expr<'v, VAR> + 'var>) + Box Fn(Expr<'v, VAR>) -> Expr<'v, VAR> + 'var>) } pub fn add<'var, VAR> @@ -18,7 +18,7 @@ pub fn add<'var, VAR> loop {} } -pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>> +pub fn let_<'var, VAR, F: for<'v> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>> (a: Expr<'var, VAR>, b: F) -> Expr<'var, VAR> { loop {} } diff --git a/src/test/compile-fail/private-in-public-warn.rs b/src/test/compile-fail/private-in-public-warn.rs index aa91ce27c379a..cc9eed7e65426 100644 --- a/src/test/compile-fail/private-in-public-warn.rs +++ b/src/test/compile-fail/private-in-public-warn.rs @@ -58,7 +58,7 @@ mod traits { pub trait PubTr {} pub type Alias = T; //~ ERROR private trait `traits::PrivTr` in public interface - //~^ WARN bounds are ignored in type aliases + //~^ WARNING bounds on generic parameters are ignored //~| WARNING hard error pub trait Tr1: PrivTr {} //~ ERROR private trait `traits::PrivTr` in public interface //~^ WARNING hard error @@ -85,7 +85,7 @@ mod traits_where { pub type Alias where T: PrivTr = T; //~^ ERROR private trait `traits_where::PrivTr` in public interface //~| WARNING hard error - //~| WARNING E0122 + //~| WARNING where clauses are ignored in type aliases pub trait Tr2 where T: PrivTr {} //~^ ERROR private trait `traits_where::PrivTr` in public interface //~| WARNING hard error diff --git a/src/test/compile-fail/rfc1623.rs b/src/test/compile-fail/rfc1623.rs index e8295e5e2da08..579fa378a1c24 100644 --- a/src/test/compile-fail/rfc1623.rs +++ b/src/test/compile-fail/rfc1623.rs @@ -22,7 +22,7 @@ static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = struct SomeStruct<'x, 'y, 'z: 'x> { foo: &'x Foo<'z>, bar: &'x Bar<'z>, - f: &'y for<'a, 'b: 'a> Fn(&'a Foo<'b>) -> &'a Bar<'b>, + f: &'y for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Bar<'b>, } fn id(t: T) -> T { diff --git a/src/test/parse-fail/bounds-lifetime.rs b/src/test/parse-fail/bounds-lifetime.rs index 5113a6b4803fc..88db205310ce1 100644 --- a/src/test/parse-fail/bounds-lifetime.rs +++ b/src/test/parse-fail/bounds-lifetime.rs @@ -8,17 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only -Z continue-parse-after-error +// compile-flags: -Z parse-only -type A = for<'a: 'b + 'c> fn(); // OK -type A = for<'a: 'b,> fn(); // OK type A = for<'a:> fn(); // OK type A = for<'a:,> fn(); // OK type A = for<'a> fn(); // OK type A = for<> fn(); // OK -type A = for<'a: 'b +> fn(); // OK - -type A = for<'a, T> fn(); //~ ERROR only lifetime parameters can be used in this context +type A = for<'a: 'b + 'c> fn(); // OK (rejected later by ast_validation) +type A = for<'a: 'b,> fn(); // OK(rejected later by ast_validation) +type A = for<'a: 'b +> fn(); // OK (rejected later by ast_validation) +type A = for<'a, T> fn(); // OK (rejected later by ast_validation) type A = for<,> fn(); //~ ERROR expected one of `>`, identifier, or lifetime, found `,` fn main() {} diff --git a/src/test/parse-fail/bounds-type.rs b/src/test/parse-fail/bounds-type.rs index c224b44a14bf1..0ebe7fde0a63f 100644 --- a/src/test/parse-fail/bounds-type.rs +++ b/src/test/parse-fail/bounds-type.rs @@ -15,7 +15,7 @@ struct S< T: Tr + 'a, // OK T: 'a, // OK T:, // OK - T: ?for<'a: 'b + 'c> Trait, // OK + T: ?for<'a> Trait, // OK T: Tr +, // OK T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds >; diff --git a/src/test/run-pass/impl-trait/lifetimes.rs b/src/test/run-pass/impl-trait/lifetimes.rs index 2d5dfb045dbac..fcad23926fc0c 100644 --- a/src/test/run-pass/impl-trait/lifetimes.rs +++ b/src/test/run-pass/impl-trait/lifetimes.rs @@ -69,8 +69,8 @@ fn foo(x: &impl Debug) -> &impl Debug { x } fn foo_explicit_lifetime<'a>(x: &'a impl Debug) -> &'a impl Debug { x } fn foo_explicit_arg(x: &T) -> &impl Debug { x } -fn mixed_lifetimes<'a>() -> impl for<'b: 'a> Fn(&'b u32) { |_| () } -fn mixed_as_static() -> impl Fn(&'static u32) { mixed_lifetimes() } +fn mixed_lifetimes<'a>() -> impl for<'b> Fn(&'b &'a u32) { |_| () } +fn mixed_as_static() -> impl Fn(&'static &'static u32) { mixed_lifetimes() } trait MultiRegionTrait<'a, 'b>: Debug {} diff --git a/src/test/ui/param-bounds-ignored.rs b/src/test/ui/param-bounds-ignored.rs index 9e09102f2d439..94bcdec945035 100644 --- a/src/test/ui/param-bounds-ignored.rs +++ b/src/test/ui/param-bounds-ignored.rs @@ -8,13 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// must-compile-successfully +#![allow(dead_code, non_camel_case_types)] use std::rc::Rc; -type SVec = Vec; -type VVec<'b, 'a: 'b> = Vec<&'a i32>; -type WVec<'b, T: 'b> = Vec; +type SVec = Vec; +//~^ WARN bounds on generic parameters are ignored in type aliases +type VVec<'b, 'a: 'b+'b> = Vec<&'a i32>; +//~^ WARN bounds on generic parameters are ignored in type aliases +type WVec<'b, T: 'b+'b> = Vec; +//~^ WARN bounds on generic parameters are ignored in type aliases +type W2Vec<'b, T> where T: 'b, T: 'b = Vec; +//~^ WARN where clauses are ignored in type aliases fn foo<'a>(y: &'a i32) { // If the bounds above would matter, the code below would be rejected. @@ -26,8 +31,73 @@ fn foo<'a>(y: &'a i32) { let mut x : WVec<'static, & 'a i32> = Vec::new(); x.push(y); + + let mut x : W2Vec<'static, & 'a i32> = Vec::new(); + x.push(y); +} + +fn bar1<'a, 'b>( + x: &'a i32, + y: &'b i32, + f: for<'xa, 'xb: 'xa+'xa> fn(&'xa i32, &'xb i32) -> &'xa i32) + //~^ ERROR lifetime bounds cannot be used in this context +{ + // If the bound in f's type would matter, the call below would (have to) + // be rejected. + f(x, y); } +fn bar2<'a, 'b, F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>( + //~^ ERROR lifetime bounds cannot be used in this context + x: &'a i32, + y: &'b i32, + f: F) +{ + // If the bound in f's type would matter, the call below would (have to) + // be rejected. + f(x, y); +} + +fn bar3<'a, 'b, F>( + x: &'a i32, + y: &'b i32, + f: F) + where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32 + //~^ ERROR lifetime bounds cannot be used in this context +{ + // If the bound in f's type would matter, the call below would (have to) + // be rejected. + f(x, y); +} + +fn bar4<'a, 'b, F>( + x: &'a i32, + y: &'b i32, + f: F) + where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32 + //~^ ERROR lifetime bounds cannot be used in this context +{ + // If the bound in f's type would matter, the call below would (have to) + // be rejected. + f(x, y); +} + +struct S1 Fn(&'xa i32, &'xb i32) -> &'xa i32>(F); +//~^ ERROR lifetime bounds cannot be used in this context +struct S2(F) where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32; +//~^ ERROR lifetime bounds cannot be used in this context +struct S3(F) where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32; +//~^ ERROR lifetime bounds cannot be used in this context + +struct S_fnty(for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32); +//~^ ERROR lifetime bounds cannot be used in this context + +type T1 = Box Fn(&'xa i32, &'xb i32) -> &'xa i32>; +//~^ ERROR lifetime bounds cannot be used in this context + fn main() { - foo(&42); + let _ : Option fn(&'xa i32, &'xb i32) -> &'xa i32> = None; + //~^ ERROR lifetime bounds cannot be used in this context + let _ : Option Fn(&'xa i32, &'xb i32) -> &'xa i32>> = None; + //~^ ERROR lifetime bounds cannot be used in this context } diff --git a/src/test/ui/param-bounds-ignored.stderr b/src/test/ui/param-bounds-ignored.stderr index fe5986448fa1d..657fec54f9608 100644 --- a/src/test/ui/param-bounds-ignored.stderr +++ b/src/test/ui/param-bounds-ignored.stderr @@ -1,18 +1,94 @@ -warning[E0122]: generic bounds are ignored in type aliases - --> $DIR/param-bounds-ignored.rs:15:1 +error: lifetime bounds cannot be used in this context + --> $DIR/param-bounds-ignored.rs:42:22 | -LL | type SVec = Vec; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | f: for<'xa, 'xb: 'xa+'xa> fn(&'xa i32, &'xb i32) -> &'xa i32) + | ^^^ ^^^ -warning[E0122]: generic bounds are ignored in type aliases - --> $DIR/param-bounds-ignored.rs:16:1 +error: lifetime bounds cannot be used in this context + --> $DIR/param-bounds-ignored.rs:50:34 | -LL | type VVec<'b, 'a: 'b> = Vec<&'a i32>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn bar2<'a, 'b, F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>( + | ^^^ -warning[E0122]: generic bounds are ignored in type aliases - --> $DIR/param-bounds-ignored.rs:17:1 +error: lifetime bounds cannot be used in this context + --> $DIR/param-bounds-ignored.rs:65:28 | -LL | type WVec<'b, T: 'b> = Vec; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32 + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/param-bounds-ignored.rs:77:25 + | +LL | where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32 + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/param-bounds-ignored.rs:85:28 + | +LL | struct S1 Fn(&'xa i32, &'xb i32) -> &'xa i32>(F); + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/param-bounds-ignored.rs:87:40 + | +LL | struct S2(F) where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32; + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/param-bounds-ignored.rs:89:37 + | +LL | struct S3(F) where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32; + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/param-bounds-ignored.rs:92:29 + | +LL | struct S_fnty(for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32); + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/param-bounds-ignored.rs:95:29 + | +LL | type T1 = Box Fn(&'xa i32, &'xb i32) -> &'xa i32>; + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/param-bounds-ignored.rs:99:34 + | +LL | let _ : Option fn(&'xa i32, &'xb i32) -> &'xa i32> = None; + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/param-bounds-ignored.rs:101:38 + | +LL | let _ : Option Fn(&'xa i32, &'xb i32) -> &'xa i32>> = None; + | ^^^ + +warning: bounds on generic parameters are ignored in type aliases + --> $DIR/param-bounds-ignored.rs:15:14 + | +LL | type SVec = Vec; + | ^^^^ ^^^^ + | + = note: #[warn(ignored_generic_bounds)] on by default + +warning: bounds on generic parameters are ignored in type aliases + --> $DIR/param-bounds-ignored.rs:17:19 + | +LL | type VVec<'b, 'a: 'b+'b> = Vec<&'a i32>; + | ^^ ^^ + +warning: bounds on generic parameters are ignored in type aliases + --> $DIR/param-bounds-ignored.rs:19:18 + | +LL | type WVec<'b, T: 'b+'b> = Vec; + | ^^ ^^ + +warning: where clauses are ignored in type aliases + --> $DIR/param-bounds-ignored.rs:21:25 + | +LL | type W2Vec<'b, T> where T: 'b, T: 'b = Vec; + | ^^^^^ ^^^^^ + +error: aborting due to 11 previous errors