Change Travis CI job order.
Reorder the job matrix to take advantage of the order how Travis CI starts them in rust-lang/rust. Plus other refactoring of `.travis.yml`.
1. Move the `$ALLOW_PR` image to the top, so pull requests will start testing as immediately after the build is started. Previously the `$ALLOW_PR` image starts 6 minutes after the build was scheduled.
2. Move the slow macOS images near the top, so they share more time with the rest of the faster Linux builds, which should shorten total test time (actually not much, about 7 minutes at most if this change does work).
3. Merged the `install` section of both Linux and macOS to make the `env:` section a bit shorter, and enable change 4 below.
4. Do not download or install anything if `$SKIP_BUILD == true`, which further reduces chance of spurious failure in the PR-CI stage (avoid the red cross appearing even if CI passed).
(IMO `$SKIP_BUILD` should not even exist: those irrelevant jobs should not start at all, but that would require travis-ci/travis-ci#2778 which has been rejected)
will run all the tests on every platform we support. If it all works out,
@bors will merge your code into `master` and close the pull request.
-[merge-queue]: https://buildbot.rust-lang.org/homu/queue/rust
+[merge-queue]: https://buildbot2.rust-lang.org/homu/queue/rust
Speaking of tests, Rust has a comprehensive test suite. More information about
it can be found
/// This type does not support transmission of an error other than that an error
/// occurred. Any extra information must be arranged to be transmitted through
/// some other means.
+///
+/// An important thing to remember is that the type `fmt::Error` should not be
+/// confused with `std::io::Error` or `std::error::Error`, which you may also
+/// have in scope.
+///
+/// # Examples
+///
+/// ```rust
+/// use std::fmt::{self, write};
+///
+/// let mut output = String::new();
+/// match write(&mut output, format_args!("Hello {}!", "world")) {
+/// Err(fmt::Error) => panic!("An error occurred"),
+/// _ => (),
+/// }
+/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Error;
// `def_id.index` (`def_id.krate` is the same as the item's).
type_param_to_index: _, // Don't hash this
has_self,
+ has_late_bound_regions,
} = *self;
parent.hash_stable(hcx, hasher);
regions.hash_stable(hcx, hasher);
types.hash_stable(hcx, hasher);
has_self.hash_stable(hcx, hasher);
+ has_late_bound_regions.hash_stable(hcx, hasher);
}
}
"detects parenthesized generic parameters in type and module names"
}
+declare_lint! {
+ pub LATE_BOUND_LIFETIME_ARGUMENTS,
+ Warn,
+ "detects generic lifetime arguments in path segments with late bound lifetime parameters"
+}
+
declare_lint! {
pub DEPRECATED,
Warn,
LEGACY_CONSTRUCTOR_VISIBILITY,
MISSING_FRAGMENT_SPECIFIER,
PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
+ LATE_BOUND_LIFETIME_ARGUMENTS,
DEPRECATED
)
}
pub type_param_to_index: BTreeMap<DefIndex, u32>,
pub has_self: bool,
+ pub has_late_bound_regions: bool,
}
impl Generics {
FutureIncompatibleInfo {
id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES),
reference: "issue #42238 <https://github.com/rust-lang/rust/issues/42238>",
- }
+ },
+ FutureIncompatibleInfo {
+ id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS),
+ reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
+ },
]);
// Register renamed and removed lints
}
ExprKind::MethodCall(ref segment, ..) => {
if let Some(ref params) = segment.parameters {
- match **params {
- PathParameters::AngleBracketed(ref param_data) => {
- if !param_data.bindings.is_empty() {
- let binding_span = param_data.bindings[0].span;
- self.err_handler().span_err(binding_span,
- "type bindings cannot be used in method calls");
- }
- }
- PathParameters::Parenthesized(..) => {
- self.err_handler().span_err(expr.span,
- "parenthesized parameters cannot be used on method calls");
- }
+ if let PathParameters::Parenthesized(..) = **params {
+ self.err_handler().span_err(expr.span,
+ "parenthesized parameters cannot be used on method calls");
}
}
}
use super::{probe, MethodCallee};
+use astconv::AstConv;
use check::{FnCtxt, LvalueOp, callee};
use hir::def_id::DefId;
use rustc::ty::subst::Substs;
fn instantiate_method_substs(&mut self,
pick: &probe::Pick<'tcx>,
segment: &hir::PathSegment,
- substs: &Substs<'tcx>)
+ parent_substs: &Substs<'tcx>)
-> &'tcx Substs<'tcx> {
- let supplied_method_types = match segment.parameters {
- hir::AngleBracketedParameters(ref data) => &data.types,
- _ => bug!("unexpected generic arguments: {:?}", segment.parameters),
- };
-
// Determine the values for the generic parameters of the method.
// If they were not explicitly supplied, just construct fresh
// variables.
- let num_supplied_types = supplied_method_types.len();
let method_generics = self.tcx.generics_of(pick.item.def_id);
- let num_method_types = method_generics.types.len();
-
- if num_supplied_types > 0 && num_supplied_types != num_method_types {
- if num_method_types == 0 {
- struct_span_err!(self.tcx.sess,
- self.span,
- E0035,
- "does not take type parameters")
- .span_label(self.span, "called with unneeded type parameters")
- .emit();
- } else {
- struct_span_err!(self.tcx.sess,
- self.span,
- E0036,
- "incorrect number of type parameters given for this method: \
- expected {}, found {}",
- num_method_types,
- num_supplied_types)
- .span_label(self.span,
- format!("Passed {} type argument{}, expected {}",
- num_supplied_types,
- if num_supplied_types != 1 { "s" } else { "" },
- num_method_types))
- .emit();
- }
- }
+ let mut fn_segment = Some((segment, method_generics));
+ self.fcx.check_path_parameter_count(self.span, &mut fn_segment, true);
// Create subst for early-bound lifetime parameters, combining
// parameters from the type and those from the method.
- //
- // FIXME -- permit users to manually specify lifetimes
- let supplied_start = substs.len() + method_generics.regions.len();
+ let (supplied_types, supplied_lifetimes) = match segment.parameters {
+ hir::AngleBracketedParameters(ref data) => (&data.types, &data.lifetimes),
+ _ => bug!("unexpected generic arguments: {:?}", segment.parameters),
+ };
+ assert_eq!(method_generics.parent_count(), parent_substs.len());
Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
let i = def.index as usize;
- if i < substs.len() {
- substs.region_at(i)
+ if i < parent_substs.len() {
+ parent_substs.region_at(i)
+ } else if let Some(lifetime) =
+ supplied_lifetimes.get(i - parent_substs.len()) {
+ AstConv::ast_region_to_region(self.fcx, lifetime, Some(def))
} else {
self.region_var_for_def(self.span, def)
}
}, |def, cur_substs| {
let i = def.index as usize;
- if i < substs.len() {
- substs.type_at(i)
- } else if let Some(ast_ty) = supplied_method_types.get(i - supplied_start) {
+ if i < parent_substs.len() {
+ parent_substs.type_at(i)
+ } else if let Some(ast_ty) =
+ supplied_types.get(i - parent_substs.len() - method_generics.regions.len()) {
self.to_ty(ast_ty)
} else {
self.type_var_for_def(self.span, def, cur_substs)
// variables. If the user provided some types, we may still need
// to add defaults. If the user provided *too many* types, that's
// a problem.
- self.check_path_parameter_count(span, &mut type_segment);
- self.check_path_parameter_count(span, &mut fn_segment);
+ self.check_path_parameter_count(span, &mut type_segment, false);
+ self.check_path_parameter_count(span, &mut fn_segment, false);
let (fn_start, has_self) = match (type_segment, fn_segment) {
(_, Some((_, generics))) => {
/// Report errors if the provided parameters are too few or too many.
fn check_path_parameter_count(&self,
span: Span,
- segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) {
+ segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
+ is_method_call: bool) {
let (lifetimes, types, infer_types, bindings) = {
match segment.map(|(s, _)| &s.parameters) {
Some(&hir::AngleBracketedParameters(ref data)) => {
None => (&[][..], &[][..], true, &[][..])
}
};
+ let infer_lifetimes = lifetimes.len() == 0;
let count_lifetime_params = |n| {
format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" })
format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
};
- // Check provided lifetime parameters.
- let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions);
- if lifetimes.len() > lifetime_defs.len() {
- let expected_text = count_lifetime_params(lifetime_defs.len());
- let actual_text = count_lifetime_params(lifetimes.len());
- struct_span_err!(self.tcx.sess, span, E0088,
- "too many lifetime parameters provided: \
- expected at most {}, found {}",
- expected_text, actual_text)
- .span_label(span, format!("expected {}", expected_text))
- .emit();
- } else if lifetimes.len() > 0 && lifetimes.len() < lifetime_defs.len() {
- let expected_text = count_lifetime_params(lifetime_defs.len());
- let actual_text = count_lifetime_params(lifetimes.len());
- struct_span_err!(self.tcx.sess, span, E0090,
- "too few lifetime parameters provided: \
- expected {}, found {}",
- expected_text, actual_text)
- .span_label(span, format!("expected {}", expected_text))
- .emit();
- }
-
- // The case where there is not enough lifetime parameters is not checked,
- // because this is not possible - a function never takes lifetime parameters.
- // See discussion for Pull Request 36208.
-
// Check provided type parameters.
let type_defs = segment.map_or(&[][..], |(_, generics)| {
if generics.parent.is_none() {
// type parameters, we force instantiate_value_path to
// use inference variables instead of the provided types.
*segment = None;
- } else if !infer_types && types.len() < required_len {
+ } else if types.len() < required_len && !infer_types {
let expected_text = count_type_params(required_len);
let actual_text = count_type_params(types.len());
struct_span_err!(self.tcx.sess, span, E0089,
"unexpected binding of associated item in expression path \
(only allowed in type paths)");
}
+
+ // Check provided lifetime parameters.
+ let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions);
+ let required_len = lifetime_defs.len();
+
+ // Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
+ let has_late_bound_lifetime_defs =
+ segment.map_or(false, |(_, generics)| generics.has_late_bound_regions);
+ if has_late_bound_lifetime_defs && !lifetimes.is_empty() {
+ // Report this as a lint only if no error was reported previously.
+ if !is_method_call && (lifetimes.len() > lifetime_defs.len() ||
+ lifetimes.len() < required_len && !infer_lifetimes) {
+ self.tcx.sess.span_err(lifetimes[0].span,
+ "cannot specify lifetime arguments explicitly \
+ if late bound lifetime parameters are present");
+ *segment = None;
+ } else {
+ self.tcx.sess.add_lint(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
+ lifetimes[0].id, lifetimes[0].span,
+ format!("cannot specify lifetime arguments explicitly \
+ if late bound lifetime parameters are present"));
+ }
+ return;
+ }
+
+ if lifetimes.len() > lifetime_defs.len() {
+ let span = lifetimes[lifetime_defs.len()].span;
+ let expected_text = count_lifetime_params(lifetime_defs.len());
+ let actual_text = count_lifetime_params(lifetimes.len());
+ struct_span_err!(self.tcx.sess, span, E0088,
+ "too many lifetime parameters provided: \
+ expected at most {}, found {}",
+ expected_text, actual_text)
+ .span_label(span, format!("expected {}", expected_text))
+ .emit();
+ } else if lifetimes.len() < required_len && !infer_lifetimes {
+ let expected_text = count_lifetime_params(lifetime_defs.len());
+ let actual_text = count_lifetime_params(lifetimes.len());
+ struct_span_err!(self.tcx.sess, span, E0090,
+ "too few lifetime parameters provided: \
+ expected {}, found {}",
+ expected_text, actual_text)
+ .span_label(span, format!("expected {}", expected_text))
+ .emit();
+ }
}
fn structurally_resolve_type_or_else<F>(&self, sp: Span, ty: Ty<'tcx>, f: F)
tcx.alloc_trait_def(def)
}
+fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ node: hir_map::Node<'tcx>)
+ -> bool {
+ struct LateBoundRegionsDetector<'a, 'tcx: 'a> {
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ binder_depth: u32,
+ has_late_bound_regions: bool,
+ }
+
+ impl<'a, 'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'a, 'tcx> {
+ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ NestedVisitorMap::None
+ }
+
+ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
+ if self.has_late_bound_regions { return }
+ match ty.node {
+ hir::TyBareFn(..) => {
+ self.binder_depth += 1;
+ intravisit::walk_ty(self, ty);
+ self.binder_depth -= 1;
+ }
+ _ => intravisit::walk_ty(self, ty)
+ }
+ }
+
+ fn visit_poly_trait_ref(&mut self,
+ tr: &'tcx hir::PolyTraitRef,
+ m: hir::TraitBoundModifier) {
+ if self.has_late_bound_regions { return }
+ self.binder_depth += 1;
+ intravisit::walk_poly_trait_ref(self, tr, m);
+ self.binder_depth -= 1;
+ }
+
+ fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) {
+ if self.has_late_bound_regions { return }
+
+ match self.tcx.named_region_map.defs.get(<.id).cloned() {
+ Some(rl::Region::Static) | Some(rl::Region::EarlyBound(..)) => {}
+ Some(rl::Region::LateBound(debruijn, _)) |
+ Some(rl::Region::LateBoundAnon(debruijn, _))
+ if debruijn.depth < self.binder_depth => {}
+ _ => self.has_late_bound_regions = true,
+ }
+ }
+ }
+
+ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ generics: &'tcx hir::Generics,
+ decl: &'tcx hir::FnDecl)
+ -> bool {
+ let mut visitor = LateBoundRegionsDetector {
+ tcx, binder_depth: 1, has_late_bound_regions: false
+ };
+ for lifetime in &generics.lifetimes {
+ if tcx.named_region_map.late_bound.contains(&lifetime.lifetime.id) {
+ return true;
+ }
+ }
+ visitor.visit_fn_decl(decl);
+ visitor.has_late_bound_regions
+ }
+
+ match node {
+ hir_map::NodeTraitItem(item) => match item.node {
+ hir::TraitItemKind::Method(ref sig, _) =>
+ has_late_bound_regions(tcx, &sig.generics, &sig.decl),
+ _ => false,
+ },
+ hir_map::NodeImplItem(item) => match item.node {
+ hir::ImplItemKind::Method(ref sig, _) =>
+ has_late_bound_regions(tcx, &sig.generics, &sig.decl),
+ _ => false,
+ },
+ hir_map::NodeForeignItem(item) => match item.node {
+ hir::ForeignItemFn(ref fn_decl, _, ref generics) =>
+ has_late_bound_regions(tcx, generics, fn_decl),
+ _ => false,
+ },
+ hir_map::NodeItem(item) => match item.node {
+ hir::ItemFn(ref fn_decl, .., ref generics, _) =>
+ has_late_bound_regions(tcx, generics, fn_decl),
+ _ => false,
+ },
+ _ => false
+ }
+}
+
fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> &'tcx ty::Generics {
regions: regions,
types: types,
type_param_to_index: type_param_to_index,
- has_self: has_self || parent_has_self
+ has_self: has_self || parent_has_self,
+ has_late_bound_regions: has_late_bound_regions(tcx, node),
})
}
```
"##,
-E0035: r##"
-You tried to give a type parameter where it wasn't needed. Erroneous code
-example:
-
-```compile_fail,E0035
-struct Test;
-
-impl Test {
- fn method(&self) {}
-}
-
-fn main() {
- let x = Test;
-
- x.method::<i32>(); // Error: Test::method doesn't need type parameter!
-}
-```
-
-To fix this error, just remove the type parameter:
-
-```
-struct Test;
-
-impl Test {
- fn method(&self) {}
-}
-
-fn main() {
- let x = Test;
-
- x.method(); // OK, we're good!
-}
-```
-"##,
-
-E0036: r##"
-This error occurrs when you pass too many or not enough type parameters to
-a method. Erroneous code example:
-
-```compile_fail,E0036
-struct Test;
-
-impl Test {
- fn method<T>(&self, v: &[T]) -> usize {
- v.len()
- }
-}
-
-fn main() {
- let x = Test;
- let v = &[0];
-
- x.method::<i32, i32>(v); // error: only one type parameter is expected!
-}
-```
-
-To fix it, just specify a correct number of type parameters:
-
-```
-struct Test;
-
-impl Test {
- fn method<T>(&self, v: &[T]) -> usize {
- v.len()
- }
-}
-
-fn main() {
- let x = Test;
- let v = &[0];
-
- x.method::<i32>(v); // OK, we're good!
-}
-```
-
-Please note on the last example that we could have called `method` like this:
-
-```
-# struct Test;
-# impl Test { fn method<T>(&self, v: &[T]) -> usize { v.len() } }
-# let x = Test;
-# let v = &[0];
-x.method(v);
-```
-"##,
-
E0040: r##"
It is not allowed to manually call destructors in Rust. It is also not
necessary to do this since `drop` is called automatically whenever a value goes
}
register_diagnostics! {
+// E0035, merged into E0087/E0089
+// E0036, merged into E0087/E0089
// E0068,
// E0085,
// E0086,
+++ /dev/null
-// Copyright 2016 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Test;
-
-impl Test {
- fn method(&self) {}
-}
-
-fn main() {
- let x = Test;
- x.method::<i32>(); //~ ERROR E0035
- //~| NOTE called with unneeded type parameters
-}
+++ /dev/null
-// Copyright 2016 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Test;
-
-impl Test {
- fn method<T>(&self, v: &[T]) -> usize {
- v.len()
- }
-}
-
-fn main() {
- let x = Test;
- let v = &[0];
- x.method::<i32, i32>(v); //~ ERROR E0036
- //~| NOTE Passed 2 type arguments, expected 1
-}
// except according to those terms.
fn f() {}
-fn g<'a>() {}
+fn g<'a>() -> &'a u8 { loop {} }
fn main() {
- f::<'static>();
- //~^ ERROR expected at most 0 lifetime parameters, found 1 lifetime parameter [E0088]
- //~| NOTE expected 0 lifetime parameters
-
- g::<'static, 'static>();
- //~^ ERROR expected at most 0 lifetime parameters, found 2 lifetime parameters [E0088]
- //~| NOTE expected 0 lifetime parameters
+ f::<'static>(); //~ ERROR E0088
+ g::<'static, 'static>(); //~ ERROR E0088
}
--- /dev/null
+// Copyright 2017 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// All lifetime parameters in struct constructors are currently considered early bound,
+// i.e. `S::<ARGS>` is interpreted kinda like an associated item `S::<ARGS>::ctor`.
+// This behavior is a bit weird, because if equivalent constructor were written manually
+// it would get late bound lifetime parameters.
+// Variant constructors behave in the same way, lifetime parameters are considered
+// belonging to the enum and being early bound.
+// https://github.com/rust-lang/rust/issues/30904
+
+struct S<'a, 'b>(&'a u8, &'b u8);
+enum E<'a, 'b> {
+ V(&'a u8),
+ U(&'b u8),
+}
+
+fn main() {
+ S(&0, &0); // OK
+ S::<'static>(&0, &0);
+ //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
+ S::<'static, 'static, 'static>(&0, &0);
+ //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
+ E::V(&0); // OK
+ E::V::<'static>(&0);
+ //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
+ E::V::<'static, 'static, 'static>(&0);
+ //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
+}
--- /dev/null
+// Copyright 2017 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(late_bound_lifetime_arguments)]
+#![allow(unused)]
+
+struct S;
+
+impl S {
+ fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ fn late_implicit(self, _: &u8, _: &u8) {}
+ fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+ fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+
+ // 'late lifetimes here belong to nested types not to the tested functions.
+ fn early_tricky_explicit<'a>(_: for<'late> fn(&'late u8),
+ _: Box<for<'late> Fn(&'late u8)>)
+ -> &'a u8 { loop {} }
+ fn early_tricky_implicit<'a>(_: fn(&u8),
+ _: Box<Fn(&u8)>)
+ -> &'a u8 { loop {} }
+}
+
+fn method_call() {
+ S.late(&0, &0); // OK
+ S.late::<'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late::<'static, 'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late::<'static, 'static, 'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_early(&0); // OK
+ S.late_early::<'static>(&0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_early::<'static, 'static>(&0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_early::<'static, 'static, 'static>(&0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+
+ S.late_implicit(&0, &0); // OK
+ S.late_implicit::<'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_implicit::<'static, 'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_implicit::<'static, 'static, 'static>(&0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_implicit_early(&0); // OK
+ S.late_implicit_early::<'static>(&0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_implicit_early::<'static, 'static>(&0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+ S.late_implicit_early::<'static, 'static, 'static>(&0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+
+ S::early_tricky_explicit::<'static>(loop {}, loop {}); // OK
+ S::early_tricky_implicit::<'static>(loop {}, loop {}); // OK
+}
+
+fn ufcs() {
+ S::late_early::<'static>(S, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+
+ S::late_implicit_early::<'static>(S, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+}
+
+fn lint_not_inference_error() {
+ fn f<'early, 'late, T: 'early>() {}
+
+ // Make sure `u8` is substituted and not replaced with an inference variable
+ f::<'static, u8>;
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ //~| WARN this was previously accepted
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2017 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+#![allow(unused)]
+
+struct S;
+
+impl S {
+ fn early_and_type<'a, T>(self) -> &'a T { loop {} }
+}
+
+fn test() {
+ S.early_and_type::<u16>();
+}
+
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
--- /dev/null
+// Copyright 2017 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ 0.clone::<'a>(); //~ ERROR use of undeclared lifetime name `'a`
+}
--- /dev/null
+// Copyright 2017 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct S;
+
+impl S {
+ fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+ fn late_implicit(self, _: &u8, _: &u8) {}
+ fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+ fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+ fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+ fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
+ fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
+ fn life_and_type<'a, T>(self) -> &'a T { loop {} }
+}
+
+fn method_call() {
+ S.early(); // OK
+ S.early::<'static>();
+ //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
+ S.early::<'static, 'static, 'static>();
+ //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
+ let _: &u8 = S.life_and_type::<'static>();
+ S.life_and_type::<u8>();
+ S.life_and_type::<'static, u8>();
+}
+
+fn ufcs() {
+ S::late(S, &0, &0); // OK
+ S::late::<'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late::<'static, 'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late::<'static, 'static, 'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_early(S, &0); // OK
+ S::late_early::<'static, 'static>(S, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_early::<'static, 'static, 'static>(S, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+
+ S::late_implicit(S, &0, &0); // OK
+ S::late_implicit::<'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_implicit::<'static, 'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_implicit::<'static, 'static, 'static>(S, &0, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_implicit_early(S, &0); // OK
+ S::late_implicit_early::<'static, 'static>(S, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_implicit_early::<'static, 'static, 'static>(S, &0);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_implicit_self_early(&S); // OK
+ S::late_implicit_self_early::<'static, 'static>(&S);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_implicit_self_early::<'static, 'static, 'static>(&S);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_unused_early(S); // OK
+ S::late_unused_early::<'static, 'static>(S);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+ S::late_unused_early::<'static, 'static, 'static>(S);
+ //~^ ERROR cannot specify lifetime arguments explicitly
+
+ S::early(S); // OK
+ S::early::<'static>(S);
+ //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
+ S::early::<'static, 'static, 'static>(S);
+ //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
+ let _: &u8 = S::life_and_type::<'static>(S);
+ S::life_and_type::<u8>(S);
+ S::life_and_type::<'static, u8>(S);
+}
+
+fn main() {}
// except according to those terms.
fn main() {
- 0.clone::<T = u8>(); //~ ERROR type bindings cannot be used in method calls
+ 0.clone::<T = u8>(); //~ ERROR unexpected binding of associated item
}
impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
fn main() {
- 10.dup::<i32>(); //~ ERROR does not take type parameters
- 10.blah::<i32, i32>();
- //~^ ERROR incorrect number of type parameters given for this method: expected 1, found 2
+ 10.dup::<i32>(); //~ ERROR expected at most 0 type parameters, found 1 type parameter
+ 10.blah::<i32, i32>(); //~ ERROR expected at most 1 type parameter, found 2 type parameters
(box 10 as Box<bar>).dup();
//~^ ERROR E0038
//~| ERROR E0038
impl Foo {
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
- #[rustc_metadata_clean(cfg="cfail2")] // Apparently unused lifetimes don't show up in the type.
+ #[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn add_lifetime_parameter_to_method<'a>(&self) { }
}
trait TraitAddLifetimeParameterToMethod {
#[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
- #[rustc_metadata_clean(cfg="cfail2")] // Unused lifetimes don't seem to show up in type?
+ #[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
fn method<'a>();
}