diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 5b53a6a289958..b1741f00507a4 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -861,7 +861,7 @@ impl Vec { /// /// [`truncate`]: #method.truncate /// [`resize`]: #method.resize - /// [`extend`]: #method.extend-1 + /// [`extend`]: ../../std/iter/trait.Extend.html#tymethod.extend /// [`clear`]: #method.clear /// /// # Safety diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 1645f94535ff2..778bba1eef68f 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 orphan_check_trait_ref<'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_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 3e21436d3136e..1f386b8bbbf54 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1742,14 +1742,25 @@ impl<'a> Parser<'a> { } 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/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index a491d91e20fb2..d5d8604be858d 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -443,7 +443,9 @@ impl<'a> Parser<'a> { 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/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index a4c9862bc742d..9421dbc2b2c76 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -362,37 +362,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || ty.is_char() || ty.references_error() }; - let lhs_compat = numeric_or_char(lhs_ty); - let rhs_compat = 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 lhs_fail = !numeric_or_char(lhs_ty); + let rhs_fail = !numeric_or_char(rhs_ty); - 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 ); - 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 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; } @@ -406,6 +382,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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, diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index f066ca762c09e..88fa09cc9366a 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -77,30 +77,58 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> { 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 560abeb705704..02783f65df537 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -2114,8 +2114,13 @@ E0210: r##" 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: @@ -2173,12 +2178,18 @@ 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 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]. +[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 "##, diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 21f674af8cffb..e51a9b624498d 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -633,8 +633,8 @@ impl Ipv4Addr { /// 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 diff --git a/src/libsyntax_ext/source_util.rs b/src/libsyntax_ext/source_util.rs index 120b533a69b77..3d27af2f210a5 100644 --- a/src/libsyntax_ext/source_util.rs +++ b/src/libsyntax_ext/source_util.rs @@ -21,6 +21,7 @@ use rustc_data_structures::sync::Lrc; /// 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 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream) // 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) diff --git a/src/test/ui/coherence/coherence-all-remote.stderr b/src/test/ui/coherence/coherence-all-remote.stderr index b35ae46f8882d..6ecfb2c5eb0e3 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 bb81d7adea243..d431c5f4b5251 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 cb66f9b0c7ff9..c00751a0f2338 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 3791d96302bc2..2c3b4fc3ad2a8 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 69194bdaf569b..8a951d407ca46 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 b0f34419bb39d..c5759244eff49 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 002f8b7286a2c..e8663fd7d820d 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 0c43936e6d401..639bee2b8ec74 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 f81f15b204b9c..0b6c81b53cd5f 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 24fd492c57c1e..fe40490822e0f 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 4666e449ca98f..c9e3594cd342f 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 @@ use std::rc::Rc; 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 6a1db165416bd..1eaef59b3f880 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 db88c330b39e1..7709bd9c89b6f 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 @@ use std::rc::Rc; 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 b5fdb16c2f35d..4d39186d494c9 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 dd4110d31e6f5..eed3a4b5c235b 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 @@ use std::rc::Rc; 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 7b65212f62a4d..d74be4cec728d 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 2e5ae6a8eb312..b26feb4914c63 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 3976f06947f43..5e8cc552c9834 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 8d858b8abeedf..d3226d33beec7 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/E0029-teach.stderr b/src/test/ui/error-codes/E0029-teach.stderr index 998ef4bc1d75c..ec146ca86f596 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 209d219191ca5..e54722ae7b9b8 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/error-codes/e0119/issue-28981.stderr b/src/test/ui/error-codes/e0119/issue-28981.stderr index ec8e8144d42cf..2a78cc8b2db26 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 12d4da7159929..9f164822deacb 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/match/match-range-fail.rs b/src/test/ui/match/match-range-fail.rs index 8a3678577b4e3..252d4cbf16241 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 3fd2a499e2bc3..25fa9c2f6182e 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/orphan-check-diagnostics.stderr b/src/test/ui/orphan-check-diagnostics.stderr index cb21b26bba75a..c84d401898c91 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 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 0000000000000..1730adfa91419 --- /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 0000000000000..00d84e2afe353 --- /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 + diff --git a/src/test/ui/parser/macros-no-semicolon-items.stderr b/src/test/ui/parser/macros-no-semicolon-items.stderr index 980ceeed8c64d..f9019b78c8d38 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 0000000000000..689176b3eb75b --- /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 0000000000000..4504fc0eb0004 --- /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 + diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr index 89ec059cb8234..160ab18e34a54 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 7474d32679366..78768d282e7c4 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 92792f2e86a83..7a74a37021bdb 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 diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index b115539b4af3b..15f8abd75d59a 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(); + ).expect(&format!("Could not read tests from {}", config.src_base.display())); 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,21 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> Vec) -> Path output_base_dir(config, testpaths, revision).join("stamp") } -fn up_to_date( +fn is_up_to_date( config: &Config, testpaths: &TestPaths, props: &EarlyProps, revision: Option<&str>, + inputs: &Stamp, ) -> bool { let stamp_name = stamp(config, testpaths, revision); // Check hash. 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. - 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) - })); - - // Compiletest itself. - inputs.extend(Stamp::from_dir(&rust_src_dir.join("src/tools/compiletest/"))); + inputs.add_path(path); + } - 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) + fn from_path(path: &Path) -> Self { + let mut stamp = Stamp { time: SystemTime::UNIX_EPOCH }; + stamp.add_path(path); + stamp + } + + fn add_path(&mut self, path: &Path) { + let modified = fs::metadata(path) .and_then(|metadata| metadata.modified()) .unwrap_or(SystemTime::UNIX_EPOCH); - - Stamp { - time, - file: p.into(), - } + self.time = self.time.max(modified); } - 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() })(); - - 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); + } + } } }