From 7e94cc37e8d4938da29def5f49ae9fec56ca7dec Mon Sep 17 00:00:00 2001 From: Ohad Ravid Date: Fri, 8 Nov 2019 21:40:30 +0100 Subject: [PATCH 01/12] Update E0210 to match RFC 2451 --- src/librustc_typeck/error_codes.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index f21fc2df8b9..9417e78ebfa 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -2058,8 +2058,13 @@ fn make(&mut self) -> Foo { This error indicates a violation of one of Rust's orphan rules for trait implementations. The rule concerns the use of type parameters in an implementation of a foreign trait (a trait defined in another crate), and -states that type parameters must be "covered" by a local type. To understand -what this means, it is perhaps easiest to consider a few examples. +states that type parameters must be "covered" by a local type. + +When implementing a foreign trait for a foreign type, +the trait must have one or more type parameters. +A type local to your crate must appear before any use of any type parameters. + +To understand what this means, it is perhaps easier to consider a few examples. If `ForeignTrait` is a trait defined in some external crate `foo`, then the following trait `impl` is an error: @@ -2117,12 +2122,17 @@ impl ForeignTrait for T0 { ... } where `P1, ..., Pm` are the type parameters of the `impl` and `T0, ..., Tn` are types. One of the types `T0, ..., Tn` must be a local type (this is another -orphan rule, see the explanation for E0117). Let `i` be the smallest integer -such that `Ti` is a local type. Then no type parameter can appear in any of the -`Tj` for `j < i`. +orphan rule, see the explanation for E0117). -For information on the design of the orphan rules, see [RFC 1023]. +Both of the folowing must be true: +1. At least one of the types T0..=Tn must be a local type. +Let Ti be the first such type. +2. No uncovered type parameters P1..=Pm may appear in T0..Ti (excluding Ti). +For information on the design of the orphan rules, +see [RFC 2451] and [RFC 1023]. + +[RFC 2451]: https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html [RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md "##, From 2db744ca9d4da28c5d0088f5d21e237e7f678abb Mon Sep 17 00:00:00 2001 From: Ohad Ravid Date: Sat, 9 Nov 2019 17:32:15 +0100 Subject: [PATCH 02/12] Improve coherence errors for wrong type order --- src/librustc/traits/coherence.rs | 12 +++- src/librustc_typeck/coherence/orphan.rs | 64 +++++++++++++------ src/librustc_typeck/error_codes.rs | 9 +-- .../ui/coherence/coherence-all-remote.stderr | 1 + .../coherence/coherence-bigint-param.stderr | 7 +- .../coherence-cross-crate-conflict.stderr | 1 + .../coherence-lone-type-parameter.stderr | 1 + .../impl[t]-foreign-for-fundamental[t].stderr | 1 + ...foreign[foreign]-for-fundamental[t].stderr | 2 + .../impl[t]-foreign[foreign]-for-t.stderr | 1 + ...foreign[fundamental[t]]-for-foreign.stderr | 2 + ...[fundamental[t]]-for-fundamental[t].stderr | 2 + ...pl[t]-foreign[fundamental[t]]-for-t.stderr | 2 + ...reign[fundamental[t]_local]-for-foreign.rs | 4 +- ...n[fundamental[t]_local]-for-foreign.stderr | 14 ++-- ...pl[t]-foreign[local]-for-fundamental[t].rs | 4 +- ...]-foreign[local]-for-fundamental[t].stderr | 14 ++-- .../coherence/impl[t]-foreign[local]-for-t.rs | 2 +- .../impl[t]-foreign[local]-for-t.stderr | 7 +- .../impl[t]-foreign[t]-for-foreign.stderr | 1 + .../impl[t]-foreign[t]-for-fundamental.stderr | 2 + .../coherence/impl[t]-foreign[t]-for-t.stderr | 1 + .../ui/error-codes/e0119/issue-28981.stderr | 1 + src/test/ui/issues/issue-41974.stderr | 1 + src/test/ui/orphan-check-diagnostics.stderr | 1 + 25 files changed, 110 insertions(+), 47 deletions(-) diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 1645f94535f..778bba1eef6 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -238,7 +238,7 @@ pub fn trait_ref_is_local_or_fundamental<'tcx>( pub enum OrphanCheckErr<'tcx> { NonLocalInputType(Vec<(Ty<'tcx>, bool /* Is this the first input type? */)>), - UncoveredTy(Ty<'tcx>), + UncoveredTy(Ty<'tcx>, Option>), } /// Checks the coherence orphan rules. `impl_def_id` should be the @@ -402,7 +402,15 @@ fn uncover_fundamental_ty<'tcx>( return Ok(()); } else if let ty::Param(_) = input_ty.kind { debug!("orphan_check_trait_ref: uncovered ty: `{:?}`", input_ty); - return Err(OrphanCheckErr::UncoveredTy(input_ty)) + let local_type = trait_ref + .input_types() + .flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)) + .filter(|ty| ty_is_non_local_constructor(tcx, ty, in_crate).is_none()) + .next(); + + debug!("orphan_check_trait_ref: uncovered ty local_type: `{:?}`", local_type); + + return Err(OrphanCheckErr::UncoveredTy(input_ty, local_type)) } if let Some(non_local_tys) = non_local_tys { for input_ty in non_local_tys { diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index f066ca762c0..88fa09cc936 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -77,30 +77,58 @@ fn visit_item(&mut self, item: &hir::Item) { err.emit(); return; } - Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => { + Err(traits::OrphanCheckErr::UncoveredTy(param_ty, local_type)) => { let mut sp = sp; for param in &generics.params { if param.name.ident().to_string() == param_ty.to_string() { sp = param.span; } } - let mut err = struct_span_err!( - self.tcx.sess, - sp, - E0210, - "type parameter `{}` must be used as the type parameter for some local \ - type (e.g., `MyStruct<{}>`)", - param_ty, - param_ty - ); - err.span_label(sp, format!( - "type parameter `{}` must be used as the type parameter for some local \ - type", - param_ty, - )); - err.note("only traits defined in the current crate can be implemented for a \ - type parameter"); - err.emit(); + + match local_type { + Some(local_type) => { + struct_span_err!( + self.tcx.sess, + sp, + E0210, + "type parameter `{}` must be covered by another type \ + when it appears before the first local type (`{}`)", + param_ty, + local_type + ).span_label(sp, format!( + "type parameter `{}` must be covered by another type \ + when it appears before the first local type (`{}`)", + param_ty, + local_type + )).note("implementing a foreign trait is only possible if at \ + least one of the types for which is it implemented is local, \ + and no uncovered type parameters appear before that first \ + local type" + ).note("in this case, 'before' refers to the following order: \ + `impl<..> ForeignTrait for T0`, \ + where `T0` is the first and `Tn` is the last" + ).emit(); + } + None => { + struct_span_err!( + self.tcx.sess, + sp, + E0210, + "type parameter `{}` must be used as the type parameter for some \ + local type (e.g., `MyStruct<{}>`)", + param_ty, + param_ty + ).span_label(sp, format!( + "type parameter `{}` must be used as the type parameter for some \ + local type", + param_ty, + )).note("implementing a foreign trait is only possible if at \ + least one of the types for which is it implemented is local" + ).note("only traits defined in the current crate can be \ + implemented for a type parameter" + ).emit(); + } + }; return; } } diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 9417e78ebfa..6e8ba7089cf 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -2124,10 +2124,11 @@ impl ForeignTrait for T0 { ... } are types. One of the types `T0, ..., Tn` must be a local type (this is another orphan rule, see the explanation for E0117). -Both of the folowing must be true: -1. At least one of the types T0..=Tn must be a local type. -Let Ti be the first such type. -2. No uncovered type parameters P1..=Pm may appear in T0..Ti (excluding Ti). +Both of the following must be true: +1. At least one of the types `T0..=Tn` must be a local type. +Let `Ti` be the first such type. +2. No uncovered type parameters `P1..=Pm` may appear in `T0..Ti` +(excluding `Ti`). For information on the design of the orphan rules, see [RFC 2451] and [RFC 1023]. diff --git a/src/test/ui/coherence/coherence-all-remote.stderr b/src/test/ui/coherence/coherence-all-remote.stderr index b35ae46f888..6ecfb2c5eb0 100644 --- a/src/test/ui/coherence/coherence-all-remote.stderr +++ b/src/test/ui/coherence/coherence-all-remote.stderr @@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl Remote1 for isize { } | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-bigint-param.stderr b/src/test/ui/coherence/coherence-bigint-param.stderr index bb81d7adea2..d431c5f4b52 100644 --- a/src/test/ui/coherence/coherence-bigint-param.stderr +++ b/src/test/ui/coherence/coherence-bigint-param.stderr @@ -1,10 +1,11 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`) --> $DIR/coherence-bigint-param.rs:8:6 | LL | impl Remote1 for T { } - | ^ type parameter `T` must be used as the type parameter for some local type + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`) | - = note: only traits defined in the current crate can be implemented for a type parameter + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-cross-crate-conflict.stderr b/src/test/ui/coherence/coherence-cross-crate-conflict.stderr index cb66f9b0c7f..c00751a0f23 100644 --- a/src/test/ui/coherence/coherence-cross-crate-conflict.stderr +++ b/src/test/ui/coherence/coherence-cross-crate-conflict.stderr @@ -13,6 +13,7 @@ error[E0210]: type parameter `A` must be used as the type parameter for some loc LL | impl Foo for A { | ^ type parameter `A` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to 2 previous errors diff --git a/src/test/ui/coherence/coherence-lone-type-parameter.stderr b/src/test/ui/coherence/coherence-lone-type-parameter.stderr index 3791d96302b..2c3b4fc3ad2 100644 --- a/src/test/ui/coherence/coherence-lone-type-parameter.stderr +++ b/src/test/ui/coherence/coherence-lone-type-parameter.stderr @@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl Remote for T { } | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to previous error diff --git a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr index 69194bdaf56..8a951d407ca 100644 --- a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr +++ b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr @@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl Remote for Box { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to previous error diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr index b0f34419bb3..c5759244eff 100644 --- a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr +++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr @@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl Remote1 for Box { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) @@ -12,6 +13,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl<'a, T> Remote1 for &'a T { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to 2 previous errors diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr index 002f8b7286a..e8663fd7d82 100644 --- a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr +++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr @@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl Remote1 for T { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to previous error diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr index 0c43936e6d4..639bee2b8ec 100644 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr @@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl Remote1> for u32 { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) @@ -12,6 +13,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl<'a, T> Remote1<&'a T> for u32 { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to 2 previous errors diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr index f81f15b204b..0b6c81b53cd 100644 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr @@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl<'a, T> Remote1> for &'a T { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) @@ -12,6 +13,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl<'a, T> Remote1<&'a T> for Box { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to 2 previous errors diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr index 24fd492c57c..fe40490822e 100644 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr @@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl Remote1> for T { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) @@ -12,6 +13,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl<'a, T> Remote1<&'a T> for T { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to 2 previous errors diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs index 4666e449ca9..c9e3594cd34 100644 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs @@ -8,11 +8,11 @@ struct Local; impl Remote2, Local> for u32 { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type + //~^ ERROR type parameter `T` must be covered by another type } impl<'a, T> Remote2<&'a T, Local> for u32 { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type + //~^ ERROR type parameter `T` must be covered by another type } fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr index 6a1db165416..1eaef59b3f8 100644 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr @@ -1,18 +1,20 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) --> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:10:6 | LL | impl Remote2, Local> for u32 { - | ^ type parameter `T` must be used as the type parameter for some local type + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) | - = note: only traits defined in the current crate can be implemented for a type parameter + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) --> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:14:10 | LL | impl<'a, T> Remote2<&'a T, Local> for u32 { - | ^ type parameter `T` must be used as the type parameter for some local type + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) | - = note: only traits defined in the current crate can be implemented for a type parameter + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last error: aborting due to 2 previous errors diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs index db88c330b39..7709bd9c89b 100644 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs @@ -8,11 +8,11 @@ struct Local; impl Remote1 for Box { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type + //~^ ERROR type parameter `T` must be covered by another type } impl Remote1 for &T { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type + //~^ ERROR type parameter `T` must be covered by another type } fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr index b5fdb16c2f3..4d39186d494 100644 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr @@ -1,18 +1,20 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:10:6 | LL | impl Remote1 for Box { - | ^ type parameter `T` must be used as the type parameter for some local type + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) | - = note: only traits defined in the current crate can be implemented for a type parameter + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:14:6 | LL | impl Remote1 for &T { - | ^ type parameter `T` must be used as the type parameter for some local type + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) | - = note: only traits defined in the current crate can be implemented for a type parameter + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last error: aborting due to 2 previous errors diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs index dd4110d31e6..eed3a4b5c23 100644 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs @@ -8,7 +8,7 @@ struct Local; impl Remote1 for T { - //~^ ERROR type parameter `T` must be used as the type parameter for some local type + //~^ ERROR type parameter `T` must be covered by another type } fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr index 7b65212f62a..d74be4cec72 100644 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr @@ -1,10 +1,11 @@ -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) --> $DIR/impl[t]-foreign[local]-for-t.rs:10:6 | LL | impl Remote1 for T { - | ^ type parameter `T` must be used as the type parameter for some local type + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) | - = note: only traits defined in the current crate can be implemented for a type parameter + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last error: aborting due to previous error diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr index 2e5ae6a8eb3..b26feb4914c 100644 --- a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr @@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl Remote1 for u32 { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to previous error diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr index 3976f06947f..5e8cc552c98 100644 --- a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr @@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl Remote1 for Box { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error[E0210]: type parameter `B` must be used as the type parameter for some local type (e.g., `MyStruct`) @@ -12,6 +13,7 @@ error[E0210]: type parameter `B` must be used as the type parameter for some loc LL | impl<'a, A, B> Remote1 for &'a B { | ^ type parameter `B` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to 2 previous errors diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr index 8d858b8abee..d3226d33bee 100644 --- a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr @@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl Remote1 for T { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to previous error diff --git a/src/test/ui/error-codes/e0119/issue-28981.stderr b/src/test/ui/error-codes/e0119/issue-28981.stderr index ec8e8144d42..2a78cc8b2db 100644 --- a/src/test/ui/error-codes/e0119/issue-28981.stderr +++ b/src/test/ui/error-codes/e0119/issue-28981.stderr @@ -14,6 +14,7 @@ error[E0210]: type parameter `Foo` must be used as the type parameter for some l LL | impl Deref for Foo { } | ^^^ type parameter `Foo` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr index 12d4da71599..9f164822dea 100644 --- a/src/test/ui/issues/issue-41974.stderr +++ b/src/test/ui/issues/issue-41974.stderr @@ -21,6 +21,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl Drop for T where T: A { | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to 3 previous errors diff --git a/src/test/ui/orphan-check-diagnostics.stderr b/src/test/ui/orphan-check-diagnostics.stderr index cb21b26bba7..c84d401898c 100644 --- a/src/test/ui/orphan-check-diagnostics.stderr +++ b/src/test/ui/orphan-check-diagnostics.stderr @@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc LL | impl RemoteTrait for T where T: LocalTrait {} | ^ type parameter `T` must be used as the type parameter for some local type | + = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to previous error From 292ba98cb723fe2ab6ddcac9e4852be960deaaaa Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Sun, 10 Nov 2019 15:38:09 +0800 Subject: [PATCH 03/12] fix an ICE in macro's diagnostic message --- src/librustc_parse/parser/item.rs | 15 +++++++-- .../parser/macros-no-semicolon-items.stderr | 6 ++-- src/test/ui/parser/mbe_missing_right_paren.rs | 3 ++ .../ui/parser/mbe_missing_right_paren.stderr | 31 +++++++++++++++++++ 4 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/parser/mbe_missing_right_paren.rs create mode 100644 src/test/ui/parser/mbe_missing_right_paren.stderr diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 3e21436d313..1f386b8bbbf 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1742,14 +1742,25 @@ fn complain_if_pub_macro(&self, vis: &VisibilityKind, sp: Span) { } fn report_invalid_macro_expansion_item(&self) { + let has_close_delim = self.sess.source_map() + .span_to_snippet(self.prev_span) + .map(|s| s.ends_with(")") || s.ends_with("]")) + .unwrap_or(false); + let right_brace_span = if has_close_delim { + // it's safe to peel off one character only when it has the close delim + self.prev_span.with_lo(self.prev_span.hi() - BytePos(1)) + } else { + self.sess.source_map().next_point(self.prev_span) + }; + self.struct_span_err( self.prev_span, "macros that expand to items must be delimited with braces or followed by a semicolon", ).multipart_suggestion( "change the delimiters to curly braces", vec![ - (self.prev_span.with_hi(self.prev_span.lo() + BytePos(1)), String::from(" {")), - (self.prev_span.with_lo(self.prev_span.hi() - BytePos(1)), '}'.to_string()), + (self.prev_span.with_hi(self.prev_span.lo() + BytePos(1)), "{".to_string()), + (right_brace_span, '}'.to_string()), ], Applicability::MaybeIncorrect, ).span_suggestion( diff --git a/src/test/ui/parser/macros-no-semicolon-items.stderr b/src/test/ui/parser/macros-no-semicolon-items.stderr index 980ceeed8c6..f9019b78c8d 100644 --- a/src/test/ui/parser/macros-no-semicolon-items.stderr +++ b/src/test/ui/parser/macros-no-semicolon-items.stderr @@ -6,8 +6,8 @@ LL | macro_rules! foo() | help: change the delimiters to curly braces | -LL | macro_rules! foo {} - | ^^ +LL | macro_rules! foo{} + | ^^ help: add a semicolon | LL | macro_rules! foo(); @@ -26,7 +26,7 @@ LL | | ) | help: change the delimiters to curly braces | -LL | bar! { +LL | bar!{ LL | blah LL | blah LL | blah diff --git a/src/test/ui/parser/mbe_missing_right_paren.rs b/src/test/ui/parser/mbe_missing_right_paren.rs new file mode 100644 index 00000000000..689176b3eb7 --- /dev/null +++ b/src/test/ui/parser/mbe_missing_right_paren.rs @@ -0,0 +1,3 @@ +// ignore-tidy-trailing-newlines +// error-pattern: aborting due to 3 previous errors +macro_rules! abc(ؼ \ No newline at end of file diff --git a/src/test/ui/parser/mbe_missing_right_paren.stderr b/src/test/ui/parser/mbe_missing_right_paren.stderr new file mode 100644 index 00000000000..4504fc0eb00 --- /dev/null +++ b/src/test/ui/parser/mbe_missing_right_paren.stderr @@ -0,0 +1,31 @@ +error: this file contains an un-closed delimiter + --> $DIR/mbe_missing_right_paren.rs:3:19 + | +LL | macro_rules! abc(ؼ + | - ^ + | | + | un-closed delimiter + +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> $DIR/mbe_missing_right_paren.rs:3:17 + | +LL | macro_rules! abc(ؼ + | ^^ + | +help: change the delimiters to curly braces + | +LL | macro_rules! abc{ؼ} + | ^ ^ +help: add a semicolon + | +LL | macro_rules! abc(ؼ; + | ^ + +error: unexpected end of macro invocation + --> $DIR/mbe_missing_right_paren.rs:3:1 + | +LL | macro_rules! abc(ؼ + | ^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments + +error: aborting due to 3 previous errors + From fe4b709c0cc51dda3a9ed0cb5d10346509e9966d Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Tue, 12 Nov 2019 17:48:33 -0500 Subject: [PATCH 04/12] expand source_util macros with def-site context --- src/libsyntax_ext/source_util.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libsyntax_ext/source_util.rs b/src/libsyntax_ext/source_util.rs index 120b533a69b..3d27af2f210 100644 --- a/src/libsyntax_ext/source_util.rs +++ b/src/libsyntax_ext/source_util.rs @@ -21,6 +21,7 @@ /// line!(): expands to the current line number pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { + let sp = cx.with_def_site_ctxt(sp); base::check_zero_tts(cx, sp, tts, "line!"); let topmost = cx.expansion_cause().unwrap_or(sp); @@ -32,6 +33,7 @@ pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) /* column!(): expands to the current column number */ pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { + let sp = cx.with_def_site_ctxt(sp); base::check_zero_tts(cx, sp, tts, "column!"); let topmost = cx.expansion_cause().unwrap_or(sp); @@ -45,6 +47,7 @@ pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) /// out if we wanted. pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { + let sp = cx.with_def_site_ctxt(sp); base::check_zero_tts(cx, sp, tts, "file!"); let topmost = cx.expansion_cause().unwrap_or(sp); @@ -54,12 +57,14 @@ pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) pub fn expand_stringify(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { + let sp = cx.with_def_site_ctxt(sp); let s = pprust::tts_to_string(tts); base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))) } pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { + let sp = cx.with_def_site_ctxt(sp); base::check_zero_tts(cx, sp, tts, "module_path!"); let mod_path = &cx.current_expansion.module.mod_path; let string = mod_path.iter().map(|x| x.to_string()).collect::>().join("::"); @@ -72,6 +77,7 @@ pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) /// unhygienically. pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { + let sp = cx.with_def_site_ctxt(sp); let file = match get_single_str_from_tts(cx, sp, tts, "include!") { Some(f) => f, None => return DummyResult::any(sp), @@ -125,6 +131,7 @@ fn make_expr(mut self: Box>) -> Option> { // include_str! : read the given file, insert it as a literal string expr pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { + let sp = cx.with_def_site_ctxt(sp); let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") { Some(f) => f, None => return DummyResult::any(sp) @@ -156,6 +163,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream) -> Box { + let sp = cx.with_def_site_ctxt(sp); let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") { Some(f) => f, None => return DummyResult::any(sp) From 302cf6db74102e0a0438d83ec7f68085cf931bb9 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 13 Nov 2019 08:27:53 +0900 Subject: [PATCH 05/12] Tweak non-char/numeric in range pattern diagnostic --- src/librustc_typeck/check/pat.rs | 35 ++++++++- src/test/ui/error-codes/E0029-teach.stderr | 7 +- src/test/ui/error-codes/E0029.stderr | 8 +-- src/test/ui/match/match-range-fail.rs | 9 +-- src/test/ui/match/match-range-fail.stderr | 28 +++++--- src/test/ui/parser/recover-range-pats.stderr | 72 +++++++------------ .../pattern/patkind-litrange-no-expr.stderr | 8 +-- .../ui/qualified/qualified-path-params.stderr | 7 +- 8 files changed, 94 insertions(+), 80 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index a4c9862bc74..e7ec176614d 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -380,9 +380,38 @@ fn check_pat_range( E0029, "only char and numeric types are allowed in range patterns" ); - err.span_label(span, "ranges require char or numeric types"); - err.note(&format!("start type: {}", self.ty_to_string(lhs_ty))); - err.note(&format!("end type: {}", self.ty_to_string(rhs_ty))); + if !lhs_compat && !rhs_compat { + err.span_label( + begin.span, + &format!("this is of type `{}` but it should be `char` or numeric", lhs_ty) + ); + err.span_label( + end.span, + &format!("this is of type `{}` but it should be `char` or numeric", rhs_ty) + ); + } else if !lhs_compat { + err.span_label( + begin.span, + &format!("this is of type `{}` but it should be `char` or numeric", lhs_ty) + ); + if !rhs_ty.references_error() { + err.span_label( + end.span, + &format!("this is of type `{}`", rhs_ty) + ); + } + } else { + err.span_label( + end.span, + &format!("this is of type `{}` but it should be `char` or numeric", rhs_ty) + ); + if !lhs_ty.references_error() { + err.span_label( + begin.span, + &format!("this is of type `{}`", lhs_ty) + ); + } + } if self.tcx.sess.teach(&err.get_code().unwrap()) { err.note( "In a match expression, only numbers and characters can be matched \ diff --git a/src/test/ui/error-codes/E0029-teach.stderr b/src/test/ui/error-codes/E0029-teach.stderr index 998ef4bc1d7..ec146ca86f5 100644 --- a/src/test/ui/error-codes/E0029-teach.stderr +++ b/src/test/ui/error-codes/E0029-teach.stderr @@ -2,10 +2,11 @@ error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/E0029-teach.rs:7:9 | LL | "hello" ..= "world" => {} - | ^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types + | -------^^^^^------- + | | | + | | this is of type `&'static str` but it should be `char` or numeric + | this is of type `&'static str` but it should be `char` or numeric | - = note: start type: &'static str - = note: end type: &'static str = note: In a match expression, only numbers and characters can be matched against a range. This is because the compiler checks that the range is non-empty at compile-time, and is unable to evaluate arbitrary comparison functions. If you want to capture values of an orderable type between two end-points, you can use a guard. error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0029.stderr b/src/test/ui/error-codes/E0029.stderr index 209d219191c..e54722ae7b9 100644 --- a/src/test/ui/error-codes/E0029.stderr +++ b/src/test/ui/error-codes/E0029.stderr @@ -2,10 +2,10 @@ error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/E0029.rs:5:9 | LL | "hello" ..= "world" => {} - | ^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types - | - = note: start type: &'static str - = note: end type: &'static str + | -------^^^^^------- + | | | + | | this is of type `&'static str` but it should be `char` or numeric + | this is of type `&'static str` but it should be `char` or numeric error: aborting due to previous error diff --git a/src/test/ui/match/match-range-fail.rs b/src/test/ui/match/match-range-fail.rs index 8a3678577b4..252d4cbf162 100644 --- a/src/test/ui/match/match-range-fail.rs +++ b/src/test/ui/match/match-range-fail.rs @@ -3,15 +3,16 @@ fn main() { "bar" ..= "foo" => { } }; //~^^ ERROR only char and numeric types are allowed in range - //~| start type: &'static str - //~| end type: &'static str match "wow" { 10 ..= "what" => () }; //~^^ ERROR only char and numeric types are allowed in range - //~| start type: {integer} - //~| end type: &'static str + + match "wow" { + true ..= "what" => {} + }; + //~^^ ERROR only char and numeric types are allowed in range match 5 { 'c' ..= 100 => { } diff --git a/src/test/ui/match/match-range-fail.stderr b/src/test/ui/match/match-range-fail.stderr index 3fd2a499e2b..25fa9c2f618 100644 --- a/src/test/ui/match/match-range-fail.stderr +++ b/src/test/ui/match/match-range-fail.stderr @@ -2,22 +2,30 @@ error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/match-range-fail.rs:3:9 | LL | "bar" ..= "foo" => { } - | ^^^^^^^^^^^^^^^ ranges require char or numeric types - | - = note: start type: &'static str - = note: end type: &'static str + | -----^^^^^----- + | | | + | | this is of type `&'static str` but it should be `char` or numeric + | this is of type `&'static str` but it should be `char` or numeric error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/match-range-fail.rs:10:16 + --> $DIR/match-range-fail.rs:8:16 | LL | 10 ..= "what" => () - | ^^^^^^ ranges require char or numeric types + | -- ^^^^^^ this is of type `&'static str` but it should be `char` or numeric + | | + | this is of type `{integer}` + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/match-range-fail.rs:13:9 | - = note: start type: {integer} - = note: end type: &'static str +LL | true ..= "what" => {} + | ----^^^^^------ + | | | + | | this is of type `&'static str` but it should be `char` or numeric + | this is of type `bool` but it should be `char` or numeric error[E0308]: mismatched types - --> $DIR/match-range-fail.rs:17:9 + --> $DIR/match-range-fail.rs:18:9 | LL | 'c' ..= 100 => { } | ^^^^^^^^^^^ expected integer, found char @@ -25,7 +33,7 @@ LL | 'c' ..= 100 => { } = note: expected type `{integer}` found type `char` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0029, E0308. For more information about an error, try `rustc --explain E0029`. diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr index 89ec059cb82..160ab18e34a 100644 --- a/src/test/ui/parser/recover-range-pats.stderr +++ b/src/test/ui/parser/recover-range-pats.stderr @@ -401,19 +401,17 @@ error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:19:12 | LL | if let true..Y = 0 {} - | ^^^^ ranges require char or numeric types - | - = note: start type: bool - = note: end type: u8 + | ^^^^ - this is of type `u8` + | | + | this is of type `bool` but it should be `char` or numeric error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:20:15 | LL | if let X..true = 0 {} - | ^^^^ ranges require char or numeric types - | - = note: start type: u8 - = note: end type: bool + | - ^^^^ this is of type `bool` but it should be `char` or numeric + | | + | this is of type `u8` error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:21:12 @@ -437,19 +435,17 @@ error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:32:12 | LL | if let true..=Y = 0 {} - | ^^^^ ranges require char or numeric types - | - = note: start type: bool - = note: end type: u8 + | ^^^^ - this is of type `u8` + | | + | this is of type `bool` but it should be `char` or numeric error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:33:16 | LL | if let X..=true = 0 {} - | ^^^^ ranges require char or numeric types - | - = note: start type: u8 - = note: end type: bool + | - ^^^^ this is of type `bool` but it should be `char` or numeric + | | + | this is of type `u8` error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:34:12 @@ -473,19 +469,17 @@ error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:45:12 | LL | if let true...Y = 0 {} - | ^^^^ ranges require char or numeric types - | - = note: start type: bool - = note: end type: u8 + | ^^^^ - this is of type `u8` + | | + | this is of type `bool` but it should be `char` or numeric error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:47:16 | LL | if let X...true = 0 {} - | ^^^^ ranges require char or numeric types - | - = note: start type: u8 - = note: end type: bool + | - ^^^^ this is of type `bool` but it should be `char` or numeric + | | + | this is of type `u8` error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:49:12 @@ -509,10 +503,7 @@ error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:60:12 | LL | if let true.. = 0 {} - | ^^^^ ranges require char or numeric types - | - = note: start type: bool - = note: end type: [type error] + | ^^^^ this is of type `bool` but it should be `char` or numeric error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:62:12 @@ -527,10 +518,7 @@ error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:70:12 | LL | if let true..= = 0 {} - | ^^^^ ranges require char or numeric types - | - = note: start type: bool - = note: end type: [type error] + | ^^^^ this is of type `bool` but it should be `char` or numeric error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:72:12 @@ -545,10 +533,7 @@ error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:82:12 | LL | if let true... = 0 {} - | ^^^^ ranges require char or numeric types - | - = note: start type: bool - = note: end type: [type error] + | ^^^^ this is of type `bool` but it should be `char` or numeric error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:85:12 @@ -563,10 +548,7 @@ error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:94:14 | LL | if let ..true = 0 {} - | ^^^^ ranges require char or numeric types - | - = note: start type: [type error] - = note: end type: bool + | ^^^^ this is of type `bool` but it should be `char` or numeric error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:96:12 @@ -581,10 +563,7 @@ error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:104:15 | LL | if let ..=true = 0 {} - | ^^^^ ranges require char or numeric types - | - = note: start type: [type error] - = note: end type: bool + | ^^^^ this is of type `bool` but it should be `char` or numeric error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:106:12 @@ -599,10 +578,7 @@ error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:116:15 | LL | if let ...true = 0 {} - | ^^^^ ranges require char or numeric types - | - = note: start type: [type error] - = note: end type: bool + | ^^^^ this is of type `bool` but it should be `char` or numeric error[E0308]: mismatched types --> $DIR/recover-range-pats.rs:119:12 diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.stderr b/src/test/ui/pattern/patkind-litrange-no-expr.stderr index 7474d326793..78768d282e7 100644 --- a/src/test/ui/pattern/patkind-litrange-no-expr.stderr +++ b/src/test/ui/pattern/patkind-litrange-no-expr.stderr @@ -7,11 +7,11 @@ LL | Arith = 1 + 1, error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/patkind-litrange-no-expr.rs:20:13 | +LL | $( $value ..= 42 => Some($name::$variant), )* // PatKind::Range + | -- this is of type `{integer}` +... LL | Arith = 1 + 1, - | ^^^^^ ranges require char or numeric types - | - = note: start type: {integer} - = note: end type: {integer} + | ^^^^^ this is of type `_` but it should be `char` or numeric error: aborting due to 2 previous errors diff --git a/src/test/ui/qualified/qualified-path-params.stderr b/src/test/ui/qualified/qualified-path-params.stderr index 92792f2e86a..7a74a37021b 100644 --- a/src/test/ui/qualified/qualified-path-params.stderr +++ b/src/test/ui/qualified/qualified-path-params.stderr @@ -8,10 +8,9 @@ error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/qualified-path-params.rs:22:15 | LL | 0 ..= ::A::f:: => {} - | ^^^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types - | - = note: start type: {integer} - = note: end type: fn() {S::f::} + | - ^^^^^^^^^^^^^^^^^^^^^ this is of type `fn() {S::f::}` but it should be `char` or numeric + | | + | this is of type `{integer}` error: aborting due to 2 previous errors From 0cd111fe97ac25858bba1345f5b0f5a6870aff9f Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Wed, 13 Nov 2019 12:53:24 +0200 Subject: [PATCH 06/12] Doc: Fix link to Exten in Vec::set_len --- src/liballoc/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 5b53a6a2899..b1741f00507 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -861,7 +861,7 @@ pub fn as_mut_ptr(&mut self) -> *mut T { /// /// [`truncate`]: #method.truncate /// [`resize`]: #method.resize - /// [`extend`]: #method.extend-1 + /// [`extend`]: ../../std/iter/trait.Extend.html#tymethod.extend /// [`clear`]: #method.clear /// /// # Safety From dcd91d5ceb1990a48c985e01cbe6fca7e274f016 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 13 Nov 2019 12:05:37 +0100 Subject: [PATCH 07/12] parser: don't use `unreachable!()` in `fn unexpected`. --- src/librustc_parse/parser/mod.rs | 4 +++- .../parser/issue-66357-unexpected-unreachable.rs | 14 ++++++++++++++ .../issue-66357-unexpected-unreachable.stderr | 16 ++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/parser/issue-66357-unexpected-unreachable.rs create mode 100644 src/test/ui/parser/issue-66357-unexpected-unreachable.stderr diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index a491d91e20f..d5d8604be85 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -443,7 +443,9 @@ pub(super) fn this_token_descr(&self) -> String { crate fn unexpected(&mut self) -> PResult<'a, T> { match self.expect_one_of(&[], &[]) { Err(e) => Err(e), - Ok(_) => unreachable!(), + // We can get `Ok(true)` from `recover_closing_delimiter` + // which is called in `expected_one_of_not_found`. + Ok(_) => FatalError.raise(), } } diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs new file mode 100644 index 00000000000..1730adfa914 --- /dev/null +++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs @@ -0,0 +1,14 @@ +// The problem in #66357 was that the call trace: +// +// - parse_fn_block_decl +// - expect_or +// - unexpected +// - expect_one_of +// - expected_one_of_not_found +// - recover_closing_delimiter +// +// ended up bubbling up `Ok(true)` to `unexpected` which then used `unreachable!()`. + +fn f() { |[](* } +//~^ ERROR expected one of `,` or `:`, found `(` +//~| ERROR expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr new file mode 100644 index 00000000000..00d84e2afe3 --- /dev/null +++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr @@ -0,0 +1,16 @@ +error: expected one of `,` or `:`, found `(` + --> $DIR/issue-66357-unexpected-unreachable.rs:12:13 + | +LL | fn f() { |[](* } + | ^ expected one of `,` or `:` + +error: expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` + --> $DIR/issue-66357-unexpected-unreachable.rs:12:14 + | +LL | fn f() { |[](* } + | -^ help: `)` may belong here + | | + | unclosed delimiter + +error: aborting due to 2 previous errors + From b03afd5fc46f9e80932af9f68cf4dc7a1c9c1f2c Mon Sep 17 00:00:00 2001 From: Philip Munksgaard Date: Wed, 13 Nov 2019 12:44:43 +0100 Subject: [PATCH 08/12] Improve error message in make_tests We should use expect instead of unwrap. This commit is based on https://github.com/laumann/compiletest-rs/pull/58. Thanks to @colin-kiegel. --- src/tools/compiletest/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index b115539b4af..9bf427953a1 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -581,7 +581,7 @@ pub fn make_tests(config: &Config) -> Vec { &config.src_base, &PathBuf::new(), &mut tests, - ).unwrap(); + ).expect(&format!("Could not read tests from {}", config.src_base.display())); tests } From c154297e6d6314a27d371ffe556e54cee44ceceb Mon Sep 17 00:00:00 2001 From: Benjamin Sago Date: Wed, 13 Nov 2019 15:09:40 +0000 Subject: [PATCH 09/12] Fix broken links in Ipv4Addr::is_benchmarking docs --- src/libstd/net/ip.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 21f674af8cf..e51a9b62449 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -633,8 +633,8 @@ pub fn is_ietf_protocol_assignment(&self) -> bool { /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0` /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`. /// - /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112 - /// [errate 423]: https://www.rfc-editor.org/errata/eid423 + /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544 + /// [errata 423]: https://www.rfc-editor.org/errata/eid423 /// [`true`]: ../../std/primitive.bool.html /// /// # Examples From 030fa9a337cb7f224c1d74fda04304c69e07787a Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 13 Nov 2019 23:22:48 +0900 Subject: [PATCH 10/12] Avoid using same code --- src/librustc_typeck/check/pat.rs | 119 ++++++++++++++++--------------- 1 file changed, 61 insertions(+), 58 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index e7ec176614d..9421dbc2b2c 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -362,66 +362,13 @@ fn check_pat_range( || ty.is_char() || ty.references_error() }; - let lhs_compat = numeric_or_char(lhs_ty); - let rhs_compat = numeric_or_char(rhs_ty); + let lhs_fail = !numeric_or_char(lhs_ty); + let rhs_fail = !numeric_or_char(rhs_ty); - if !lhs_compat || !rhs_compat { - let span = if !lhs_compat && !rhs_compat { - span - } else if !lhs_compat { - begin.span - } else { - end.span - }; - - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0029, - "only char and numeric types are allowed in range patterns" + if lhs_fail || rhs_fail { + self.emit_err_pat_range( + span, begin.span, end.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty ); - if !lhs_compat && !rhs_compat { - err.span_label( - begin.span, - &format!("this is of type `{}` but it should be `char` or numeric", lhs_ty) - ); - err.span_label( - end.span, - &format!("this is of type `{}` but it should be `char` or numeric", rhs_ty) - ); - } else if !lhs_compat { - err.span_label( - begin.span, - &format!("this is of type `{}` but it should be `char` or numeric", lhs_ty) - ); - if !rhs_ty.references_error() { - err.span_label( - end.span, - &format!("this is of type `{}`", rhs_ty) - ); - } - } else { - err.span_label( - end.span, - &format!("this is of type `{}` but it should be `char` or numeric", rhs_ty) - ); - if !lhs_ty.references_error() { - err.span_label( - begin.span, - &format!("this is of type `{}`", lhs_ty) - ); - } - } - if self.tcx.sess.teach(&err.get_code().unwrap()) { - err.note( - "In a match expression, only numbers and characters can be matched \ - against a range. This is because the compiler checks that the range \ - is non-empty at compile-time, and is unable to evaluate arbitrary \ - comparison functions. If you want to capture values of an orderable \ - type between two end-points, you can use a guard." - ); - } - err.emit(); return None; } @@ -435,6 +382,62 @@ fn check_pat_range( Some(common_type) } + fn emit_err_pat_range( + &self, + span: Span, + begin_span: Span, + end_span: Span, + lhs_fail: bool, + rhs_fail: bool, + lhs_ty: Ty<'tcx>, + rhs_ty: Ty<'tcx>, + ) { + let span = if lhs_fail && rhs_fail { + span + } else if lhs_fail { + begin_span + } else { + end_span + }; + + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0029, + "only char and numeric types are allowed in range patterns" + ); + let msg = |ty| { + format!("this is of type `{}` but it should be `char` or numeric", ty) + }; + let mut one_side_err = |first_span, first_ty, second_span, second_ty: Ty<'_>| { + err.span_label(first_span, &msg(first_ty)); + if !second_ty.references_error() { + err.span_label( + second_span, + &format!("this is of type `{}`", second_ty) + ); + } + }; + if lhs_fail && rhs_fail { + err.span_label(begin_span, &msg(lhs_ty)); + err.span_label(end_span, &msg(rhs_ty)); + } else if lhs_fail { + one_side_err(begin_span, lhs_ty, end_span, rhs_ty); + } else { + one_side_err(end_span, rhs_ty, begin_span, lhs_ty); + } + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "In a match expression, only numbers and characters can be matched \ + against a range. This is because the compiler checks that the range \ + is non-empty at compile-time, and is unable to evaluate arbitrary \ + comparison functions. If you want to capture values of an orderable \ + type between two end-points, you can use a guard." + ); + } + err.emit(); + } + fn check_pat_ident( &self, pat: &Pat, From 8c6e29781692c28746b914e3fbb713600d05f588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 11 Nov 2019 00:00:00 +0000 Subject: [PATCH 11/12] compiletest: Obtain timestamps for common inputs only once Obtain timestamps for common inputs (e.g., libraries in run-lib path, or sources in `src/tool/compiletest/`) only once and reuse the result, instead of repeating the work for each test case. No functional changes intended. --- src/tools/compiletest/src/main.rs | 159 +++++++++++++++++------------- 1 file changed, 88 insertions(+), 71 deletions(-) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index b115539b4af..241a1aeec6e 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -574,22 +574,59 @@ pub fn test_opts(config: &Config) -> test::TestOpts { pub fn make_tests(config: &Config) -> Vec { debug!("making tests from {:?}", config.src_base.display()); + let inputs = common_inputs_stamp(config); let mut tests = Vec::new(); collect_tests_from_dir( config, &config.src_base, &config.src_base, &PathBuf::new(), + &inputs, &mut tests, ).unwrap(); tests } +/// Returns a stamp constructed from input files common to all test cases. +fn common_inputs_stamp(config: &Config) -> Stamp { + let rust_src_dir = config + .find_rust_src_root() + .expect("Could not find Rust source root"); + + let mut stamp = Stamp::from_path(&config.rustc_path); + + // Relevant pretty printer files + let pretty_printer_files = [ + "src/etc/debugger_pretty_printers_common.py", + "src/etc/gdb_load_rust_pretty_printers.py", + "src/etc/gdb_rust_pretty_printing.py", + "src/etc/lldb_batchmode.py", + "src/etc/lldb_rust_formatters.py", + ]; + for file in &pretty_printer_files { + let path = rust_src_dir.join(file); + stamp.add_path(&path); + } + + stamp.add_dir(&config.run_lib_path); + + if let Some(ref rustdoc_path) = config.rustdoc_path { + stamp.add_path(&rustdoc_path); + stamp.add_path(&rust_src_dir.join("src/etc/htmldocck.py")); + } + + // Compiletest itself. + stamp.add_dir(&rust_src_dir.join("src/tools/compiletest/")); + + stamp +} + fn collect_tests_from_dir( config: &Config, base: &Path, dir: &Path, relative_dir_path: &Path, + inputs: &Stamp, tests: &mut Vec, ) -> io::Result<()> { // Ignore directories that contain a file named `compiletest-ignore-dir`. @@ -602,7 +639,7 @@ fn collect_tests_from_dir( file: dir.to_path_buf(), relative_dir: relative_dir_path.parent().unwrap().to_path_buf(), }; - tests.extend(make_test(config, &paths)); + tests.extend(make_test(config, &paths, inputs)); return Ok(()); } @@ -627,12 +664,14 @@ fn collect_tests_from_dir( file: file_path, relative_dir: relative_dir_path.to_path_buf(), }; - tests.extend(make_test(config, &paths)) + tests.extend(make_test(config, &paths, inputs)) } else if file_path.is_dir() { let relative_file_path = relative_dir_path.join(file.file_name()); if &file_name != "auxiliary" { debug!("found directory: {:?}", file_path.display()); - collect_tests_from_dir(config, base, &file_path, &relative_file_path, tests)?; + collect_tests_from_dir( + config, base, &file_path, &relative_file_path, + inputs, tests)?; } } else { debug!("found other file/directory: {:?}", file_path.display()); @@ -655,7 +694,7 @@ pub fn is_test(file_name: &OsString) -> bool { !invalid_prefixes.iter().any(|p| file_name.starts_with(p)) } -pub fn make_test(config: &Config, testpaths: &TestPaths) -> Vec { +fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec { let early_props = if config.mode == Mode::RunMake { // Allow `ignore` directives to be in the Makefile. EarlyProps::from_file(config, &testpaths.file.join("Makefile")) @@ -685,19 +724,20 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> Vec) -> Path output_base_dir(config, testpaths, revision).join("stamp") } -fn up_to_date( +fn is_outdated( config: &Config, testpaths: &TestPaths, props: &EarlyProps, revision: Option<&str>, + inputs: &Stamp, ) -> bool { let stamp_name = stamp(config, testpaths, revision); // Check hash. @@ -735,79 +776,55 @@ fn up_to_date( } // Check timestamps. - let rust_src_dir = config - .find_rust_src_root() - .expect("Could not find Rust source root"); - let stamp = Stamp::from_path(&stamp_name); - let mut inputs = vec![Stamp::from_path(&testpaths.file), Stamp::from_path(&config.rustc_path)]; - inputs.extend( - props - .aux - .iter() - .map(|aux| { - Stamp::from_path(&testpaths.file.parent().unwrap().join("auxiliary").join(aux)) - }), - ); - // Relevant pretty printer files - let pretty_printer_files = [ - "src/etc/debugger_pretty_printers_common.py", - "src/etc/gdb_load_rust_pretty_printers.py", - "src/etc/gdb_rust_pretty_printing.py", - "src/etc/lldb_batchmode.py", - "src/etc/lldb_rust_formatters.py", - ]; - inputs.extend(pretty_printer_files.iter().map(|pretty_printer_file| { - Stamp::from_path(&rust_src_dir.join(pretty_printer_file)) - })); - inputs.extend(Stamp::from_dir(&config.run_lib_path)); - if let Some(ref rustdoc_path) = config.rustdoc_path { - inputs.push(Stamp::from_path(&rustdoc_path)); - inputs.push(Stamp::from_path(&rust_src_dir.join("src/etc/htmldocck.py"))); + let mut inputs = inputs.clone(); + inputs.add_path(&testpaths.file); + + for aux in &props.aux { + let path = testpaths.file.parent() + .unwrap() + .join("auxiliary") + .join(aux); + inputs.add_path(&path); } // UI test files. - inputs.extend(UI_EXTENSIONS.iter().map(|extension| { + for extension in UI_EXTENSIONS { let path = &expected_output_path(testpaths, revision, &config.compare_mode, extension); - Stamp::from_path(path) - })); + inputs.add_path(path); + } - // Compiletest itself. - inputs.extend(Stamp::from_dir(&rust_src_dir.join("src/tools/compiletest/"))); - - inputs.iter().any(|input| input > &stamp) + inputs > Stamp::from_path(&stamp_name) } -#[derive(Debug, PartialEq, PartialOrd, Ord, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] struct Stamp { time: SystemTime, - file: PathBuf, } impl Stamp { - fn from_path(p: &Path) -> Self { - let time = fs::metadata(p) - .and_then(|metadata| metadata.modified()) - .unwrap_or(SystemTime::UNIX_EPOCH); - - Stamp { - time, - file: p.into(), - } + fn from_path(path: &Path) -> Self { + let mut stamp = Stamp { time: SystemTime::UNIX_EPOCH }; + stamp.add_path(path); + stamp } - fn from_dir(path: &Path) -> impl Iterator { - WalkDir::new(path) - .into_iter() - .map(|entry| entry.unwrap()) - .filter(|entry| entry.file_type().is_file()) - .map(|entry| { - let time = (|| -> io::Result<_> { entry.metadata()?.modified() })(); + fn add_path(&mut self, path: &Path) { + let modified = fs::metadata(path) + .and_then(|metadata| metadata.modified()) + .unwrap_or(SystemTime::UNIX_EPOCH); + self.time = self.time.max(modified); + } - Stamp { - time: time.unwrap_or(SystemTime::UNIX_EPOCH), - file: entry.path().into(), - } - }) + fn add_dir(&mut self, path: &Path) { + for entry in WalkDir::new(path) { + let entry = entry.unwrap(); + if entry.file_type().is_file() { + let modified = entry.metadata().ok() + .and_then(|metadata| metadata.modified().ok()) + .unwrap_or(SystemTime::UNIX_EPOCH); + self.time = self.time.max(modified); + } + } } } From 1ac470f70c9de77cbd5fd6e5c5a624e55af81fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 13 Nov 2019 00:00:00 +0000 Subject: [PATCH 12/12] compiletest: Avoid double negation in ignore condition --- src/tools/compiletest/src/main.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 241a1aeec6e..1cbf44287e1 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -731,7 +731,8 @@ fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec) -> Path output_base_dir(config, testpaths, revision).join("stamp") } -fn is_outdated( +fn is_up_to_date( config: &Config, testpaths: &TestPaths, props: &EarlyProps, @@ -768,11 +769,11 @@ fn is_outdated( let contents = match fs::read_to_string(&stamp_name) { Ok(f) => f, Err(ref e) if e.kind() == ErrorKind::InvalidData => panic!("Can't read stamp contents"), - Err(_) => return true, + Err(_) => return false, }; let expected_hash = runtest::compute_stamp_hash(config); if contents != expected_hash { - return true; + return false; } // Check timestamps. @@ -793,7 +794,7 @@ fn is_outdated( inputs.add_path(path); } - inputs > Stamp::from_path(&stamp_name) + inputs < Stamp::from_path(&stamp_name) } #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]