diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 7fecf537cfbd3..bacf5662bc005 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -442,18 +442,10 @@ impl<'hir> LoweringContext<'_, 'hir> { then: &Block, else_opt: Option<&Expr>, ) -> hir::ExprKind<'hir> { - macro_rules! make_if { - ($opt:expr) => {{ - let cond = self.lower_expr(cond); - let then_expr = self.lower_block_expr(then); - hir::ExprKind::If(cond, self.arena.alloc(then_expr), $opt) - }}; - } - if let Some(rslt) = else_opt { - make_if!(Some(self.lower_expr(rslt))) - } else { - make_if!(None) - } + let cond = self.lower_expr(cond); + let then = self.arena.alloc(self.lower_block_expr(then)); + let els = else_opt.map(|els| self.lower_expr(els)); + hir::ExprKind::If(cond, then, els) } fn lower_expr_if_let( diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 638330c904d75..db8d01e31b74d 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -687,6 +687,9 @@ declare_features! ( /// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`. (incomplete, trait_upcasting, "1.56.0", Some(65991), None), + /// Allows explicit generic arguments specification with `impl Trait` present. + (active, explicit_generic_args_with_impl_trait, "1.56.0", Some(83701), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index f885c0a4b87bd..cdc9a21253145 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -71,7 +71,7 @@ use rustc_middle::ty::{ subst::{GenericArgKind, Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable, }; -use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span}; +use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span}; use rustc_target::spec::abi; use std::ops::ControlFlow; use std::{cmp, fmt, iter}; @@ -1485,31 +1485,49 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let count = values.len(); let kind = key.descr(); let mut returned_async_output_error = false; - for sp in values { - err.span_label( - *sp, - format!( - "{}{}{} {}{}", - if sp.is_desugaring(DesugaringKind::Async) - && !returned_async_output_error - { - "checked the `Output` of this `async fn`, " - } else if count == 1 { - "the " - } else { - "" - }, - if count > 1 { "one of the " } else { "" }, - target, - kind, - pluralize!(count), - ), - ); - if sp.is_desugaring(DesugaringKind::Async) - && returned_async_output_error == false - { - err.note("while checking the return type of the `async fn`"); + for &sp in values { + if sp.is_desugaring(DesugaringKind::Async) && !returned_async_output_error { + if &[sp] != err.span.primary_spans() { + let mut span: MultiSpan = sp.into(); + span.push_span_label( + sp, + format!( + "checked the `Output` of this `async fn`, {}{} {}{}", + if count > 1 { "one of the " } else { "" }, + target, + kind, + pluralize!(count), + ), + ); + err.span_note( + span, + "while checking the return type of the `async fn`", + ); + } else { + err.span_label( + sp, + format!( + "checked the `Output` of this `async fn`, {}{} {}{}", + if count > 1 { "one of the " } else { "" }, + target, + kind, + pluralize!(count), + ), + ); + err.note("while checking the return type of the `async fn`"); + } returned_async_output_error = true; + } else { + err.span_label( + sp, + format!( + "{}{} {}{}", + if count == 1 { "the " } else { "one of the " }, + target, + kind, + pluralize!(count), + ), + ); } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 9a718102cf11d..a15eecd2414c2 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -769,7 +769,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // (#83606): Do not emit a suggestion if the parent has an `impl Trait` // as an argument otherwise it will cause the E0282 error. - if !has_impl_trait { + if !has_impl_trait || self.tcx.features().explicit_generic_args_with_impl_trait { err.span_suggestion_verbose( span, "consider specifying the const argument", diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 1c5be61130b61..4e95cdc0efa5f 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -153,16 +153,37 @@ pub(crate) fn emit_unescape_error( EscapeError::NonAsciiCharInByte => { assert!(mode.is_bytes()); let (c, span) = last_char(); - handler - .struct_span_err(span, "non-ASCII character in byte constant") - .span_label(span, "byte constant must be ASCII") - .span_suggestion( + let mut err = handler.struct_span_err(span, "non-ASCII character in byte constant"); + err.span_label(span, "byte constant must be ASCII"); + if (c as u32) <= 0xFF { + err.span_suggestion( span, - "use a \\xHH escape for a non-ASCII byte", + &format!( + "if you meant to use the unicode code point for '{}', use a \\xHH escape", + c + ), format!("\\x{:X}", c as u32), - Applicability::MachineApplicable, - ) - .emit(); + Applicability::MaybeIncorrect, + ); + } else if matches!(mode, Mode::Byte) { + err.span_label(span, "this multibyte character does not fit into a single byte"); + } else if matches!(mode, Mode::ByteStr) { + let mut utf8 = String::new(); + utf8.push(c); + err.span_suggestion( + span, + &format!( + "if you meant to use the UTF-8 encoding of '{}', use \\xHH escapes", + c + ), + utf8.as_bytes() + .iter() + .map(|b: &u8| format!("\\x{:X}", *b)) + .fold("".to_string(), |a, c| a + &c), + Applicability::MaybeIncorrect, + ); + } + err.emit(); } EscapeError::NonAsciiCharInByteString => { assert!(mode.is_bytes()); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1ac489f600a40..95b92fd34c8aa 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -554,6 +554,7 @@ symbols! { expected, expf32, expf64, + explicit_generic_args_with_impl_trait, export_name, expr, extended_key_value_attributes, diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index eb6265dec89c0..9e700d9e8d8ba 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -459,7 +459,32 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let default_counts = gen_params.own_defaults(); let param_counts = gen_params.own_counts(); - let named_type_param_count = param_counts.types - has_self as usize; + + // Subtracting from param count to ensure type params synthesized from `impl Trait` + // cannot be explictly specified even with `explicit_generic_args_with_impl_trait` + // feature enabled. + let synth_type_param_count = if tcx.features().explicit_generic_args_with_impl_trait { + gen_params + .params + .iter() + .filter(|param| { + matches!( + param.kind, + ty::GenericParamDefKind::Type { + synthetic: Some( + hir::SyntheticTyParamKind::ImplTrait + | hir::SyntheticTyParamKind::FromAttr + ), + .. + } + ) + }) + .count() + } else { + 0 + }; + let named_type_param_count = + param_counts.types - has_self as usize - synth_type_param_count; let infer_lifetimes = gen_pos != GenericArgPosition::Type && !gen_args.has_lifetime_params(); @@ -588,6 +613,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { param_counts.consts + named_type_param_count - default_counts.types - default_counts.consts + - synth_type_param_count }; debug!("expected_min: {:?}", expected_min); debug!("arg_counts.lifetimes: {:?}", gen_args.num_lifetime_params()); @@ -617,7 +643,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { seg: &hir::PathSegment<'_>, generics: &ty::Generics, ) -> bool { - let explicit = !seg.infer_args; + if seg.infer_args || tcx.features().explicit_generic_args_with_impl_trait { + return false; + } + let impl_trait = generics.params.iter().any(|param| { matches!( param.kind, @@ -630,7 +659,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) }); - if explicit && impl_trait { + if impl_trait { let spans = seg .args() .args diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index d056f2c90f988..dee81510b795b 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -13,41 +13,6 @@ use rustc_trait_selection::traits::{ StatementAsExpression, }; -macro_rules! create_maybe_get_coercion_reason { - ($fn_name:ident, $node:expr) => { - pub(crate) fn $fn_name(&self, hir_id: hir::HirId, sp: Span) -> Option<(Span, String)> { - let node = $node(self.tcx.hir(), hir_id); - if let hir::Node::Block(block) = node { - // check that the body's parent is an fn - let parent = self.tcx.hir().get( - self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(block.hir_id)), - ); - if let ( - Some(expr), - hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }), - ) = (&block.expr, parent) - { - // check that the `if` expr without `else` is the fn body's expr - if expr.span == sp { - return self.get_fn_decl(hir_id).and_then(|(fn_decl, _)| { - let span = fn_decl.output.span(); - let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?; - Some(( - span, - format!("expected `{}` because of this return type", snippet), - )) - }); - } - } - } - if let hir::Node::Local(hir::Local { ty: Some(_), pat, .. }) = node { - return Some((pat.span, "expected because of this assignment".to_string())); - } - None - } - }; -} - impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn check_match( &self, @@ -154,7 +119,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.span, &arms[0].body, &mut coercion, - |hir_id, span| self.maybe_get_coercion_reason(hir_id, span), + |hir_id, span| self.coercion_reason_match(hir_id, span), ) { tcx.ty_error() } else { @@ -373,23 +338,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error } - create_maybe_get_coercion_reason!( - maybe_get_coercion_reason, - |hir: rustc_middle::hir::map::Map<'a>, id| { - let arm_id = hir.get_parent_node(id); - let match_id = hir.get_parent_node(arm_id); - let containing_id = hir.get_parent_node(match_id); - hir.get(containing_id) - } - ); + pub(crate) fn coercion_reason_if( + &self, + hir_id: hir::HirId, + span: Span, + ) -> Option<(Span, String)> { + self.coercion_reason_inner(hir_id, span, 1) + } - create_maybe_get_coercion_reason!( - maybe_get_coercion_reason_if, - |hir: rustc_middle::hir::map::Map<'a>, id| { - let rslt = hir.get_parent_node(hir.get_parent_node(id)); - hir.get(rslt) + pub(crate) fn coercion_reason_match( + &self, + hir_id: hir::HirId, + span: Span, + ) -> Option<(Span, String)> { + self.coercion_reason_inner(hir_id, span, 2) + } + + fn coercion_reason_inner( + &self, + hir_id: hir::HirId, + span: Span, + parent_index: usize, + ) -> Option<(Span, String)> { + let hir = self.tcx.hir(); + let mut parent_iter = hir.parent_iter(hir_id); + let (_, node) = parent_iter.nth(parent_index)?; + match node { + hir::Node::Block(block) => { + let expr = block.expr?; + // check that the body's parent is an fn + let (_, parent) = parent_iter.nth(1)?; + if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }) = parent { + // check that the `if` expr without `else` is the fn body's expr + if expr.span == span { + let (fn_decl, _) = self.get_fn_decl(hir_id)?; + let span = fn_decl.output.span(); + let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?; + return Some(( + span, + format!("expected `{}` because of this return type", snippet), + )); + } + } + None + } + hir::Node::Local(hir::Local { ty: Some(_), pat, .. }) => { + Some((pat.span, "expected because of this assignment".to_string())) + } + _ => None, } - ); + } pub(crate) fn if_cause( &self, diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 08258aac96f2f..e95884ae23b93 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -838,7 +838,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.diverges.set(cond_diverges | then_diverges & else_diverges); } else { self.if_fallback_coercion(sp, then_expr, &mut coerce, |hir_id, span| { - self.maybe_get_coercion_reason_if(hir_id, span) + self.coercion_reason_if(hir_id, span) }); // If the condition is false we can't diverge. diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 8057ff0759107..d4e9c384f9302 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -285,6 +285,19 @@ //! assert_eq!(res, ["error!", "error!", "foo", "error!", "bar"]); //! ``` //! +//! ## Comparison operators +//! +//! If `T` implements [`PartialOrd`] then [`Option`] will derive its +//! [`PartialOrd`] implementation. With this order, [`None`] compares as +//! less than any [`Some`], and two [`Some`] compare the same way as their +//! contained values would in `T`. If `T` also implements +//! [`Ord`], then so does [`Option`]. +//! +//! ``` +//! assert!(None < Some(0)); +//! assert!(Some(0) < Some(1)); +//! ``` +//! //! ## Iterating over `Option` //! //! An [`Option`] can be iterated over. This can be helpful if you need an diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 32b6920b59d22..98a4cb59a6629 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -596,6 +596,7 @@ impl *mut T { /// enables more aggressive compiler optimizations. /// /// [`wrapping_add`]: #method.wrapping_add + /// [allocated object]: crate::ptr#allocated-object /// /// # Examples /// diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 53aaa5219b1d4..861790e8a4099 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -379,6 +379,24 @@ //! [`and_then`]: Result::and_then //! [`or_else`]: Result::or_else //! +//! ## Comparison operators +//! +//! If `T` and `E` both implement [`PartialOrd`] then [`Result`] will +//! derive its [`PartialOrd`] implementation. With this order, an [`Ok`] +//! compares as less than any [`Err`], while two [`Ok`] or two [`Err`] +//! compare as their contained values would in `T` or `E` respectively. If `T` +//! and `E` both also implement [`Ord`], then so does [`Result`]. +//! +//! ``` +//! assert!(Ok(1) < Err(0)); +//! let x: Result = Ok(0); +//! let y = Ok(1); +//! assert!(x < y); +//! let x: Result<(), i32> = Err(0); +//! let y = Err(1); +//! assert!(x < y); +//! ``` +//! //! ## Iterating over `Result` //! //! A [`Result`] can be iterated over. This can be helpful if you need an diff --git a/src/doc/unstable-book/src/language-features/explicit-generic-args-with-impl-trait.md b/src/doc/unstable-book/src/language-features/explicit-generic-args-with-impl-trait.md new file mode 100644 index 0000000000000..479571d85fe05 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/explicit-generic-args-with-impl-trait.md @@ -0,0 +1,53 @@ +# `explicit_generic_args_with_impl_trait` + +The tracking issue for this feature is: [#83701] + +[#83701]: /~https://github.com/rust-lang/rust/issues/83701 + +------------------------ + +The `explicit_generic_args_with_impl_trait` feature gate lets you specify generic arguments even +when `impl Trait` is used in argument position. + +A simple example is: + +```rust +#![feature(explicit_generic_args_with_impl_trait)] + +fn foo(_f: impl AsRef) {} + +fn main() { + foo::("".to_string()); +} +``` + +This is currently rejected: + +```text +error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position + --> src/main.rs:6:11 + | +6 | foo::("".to_string()); + | ^^^ explicit generic argument not allowed + +``` + +However it would compile if `explicit_generic_args_with_impl_trait` is enabled. + +Note that the synthetic type parameters from `impl Trait` are still implicit and you +cannot explicitly specify these: + +```rust,compile_fail +#![feature(explicit_generic_args_with_impl_trait)] + +fn foo(_f: impl AsRef) {} +fn bar>(_f: F) {} + +fn main() { + bar::("".to_string()); // Okay + bar::("".to_string()); // Okay + + foo::("".to_string()); // Okay + foo::("".to_string()); // Error, you cannot specify `impl Trait` explicitly +} +``` diff --git a/src/test/ui/async-await/dont-suggest-missing-await.stderr b/src/test/ui/async-await/dont-suggest-missing-await.stderr index 654a3bcc92dd8..4dc5cafb98614 100644 --- a/src/test/ui/async-await/dont-suggest-missing-await.stderr +++ b/src/test/ui/async-await/dont-suggest-missing-await.stderr @@ -1,13 +1,14 @@ error[E0308]: mismatched types --> $DIR/dont-suggest-missing-await.rs:14:18 | -LL | async fn make_u32() -> u32 { - | --- checked the `Output` of this `async fn`, found opaque type -... LL | take_u32(x) | ^ expected `u32`, found opaque type | - = note: while checking the return type of the `async fn` +note: while checking the return type of the `async fn` + --> $DIR/dont-suggest-missing-await.rs:7:24 + | +LL | async fn make_u32() -> u32 { + | ^^^ checked the `Output` of this `async fn`, found opaque type = note: expected type `u32` found opaque type `impl Future` help: consider `await`ing on the `Future` diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr index 04f191cc5e8cb..a7aedbb2b322f 100644 --- a/src/test/ui/async-await/generator-desc.stderr +++ b/src/test/ui/async-await/generator-desc.stderr @@ -12,16 +12,19 @@ LL | fun(async {}, async {}); error[E0308]: mismatched types --> $DIR/generator-desc.rs:12:16 | -LL | async fn one() {} - | - checked the `Output` of this `async fn`, expected opaque type -LL | async fn two() {} - | - checked the `Output` of this `async fn`, found opaque type -... LL | fun(one(), two()); | ^^^^^ expected opaque type, found a different opaque type | - = note: while checking the return type of the `async fn` - = note: while checking the return type of the `async fn` +note: while checking the return type of the `async fn` + --> $DIR/generator-desc.rs:5:16 + | +LL | async fn one() {} + | ^ checked the `Output` of this `async fn`, expected opaque type +note: while checking the return type of the `async fn` + --> $DIR/generator-desc.rs:6:16 + | +LL | async fn two() {} + | ^ checked the `Output` of this `async fn`, found opaque type = note: expected opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:5:16>) found opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:6:16>) = help: consider `await`ing on both `Future`s diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs index 9fe3313ee6cc6..220f0774e2d54 100644 --- a/src/test/ui/async-await/issue-61076.rs +++ b/src/test/ui/async-await/issue-61076.rs @@ -57,6 +57,8 @@ async fn struct_() -> Struct { async fn tuple() -> Tuple { //~^ NOTE checked the `Output` of this `async fn`, expected opaque type + //~| NOTE while checking the return type of the `async fn` + //~| NOTE in this expansion of desugaring of `async` block or function Tuple(1i32) } @@ -92,7 +94,6 @@ async fn match_() { Tuple(_) => {} //~ ERROR mismatched types //~^ NOTE expected opaque type, found struct `Tuple` //~| NOTE expected opaque type `impl Future` - //~| NOTE while checking the return type of the `async fn` } } diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr index ba97e135790c1..9fb2d5bc6cb42 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -16,7 +16,7 @@ LL | foo().await?; | ^^^^^^ error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/issue-61076.rs:65:5 + --> $DIR/issue-61076.rs:67:5 | LL | t?; | ^^ the `?` operator cannot be applied to type `T` @@ -33,7 +33,7 @@ LL | t.await?; | ^^^^^^ error[E0609]: no field `0` on type `impl Future` - --> $DIR/issue-61076.rs:76:26 + --> $DIR/issue-61076.rs:78:26 | LL | let _: i32 = tuple().0; | ^ field not available in `impl Future`, but it is available in its `Output` @@ -44,7 +44,7 @@ LL | let _: i32 = tuple().await.0; | ^^^^^^ error[E0609]: no field `a` on type `impl Future` - --> $DIR/issue-61076.rs:80:28 + --> $DIR/issue-61076.rs:82:28 | LL | let _: i32 = struct_().a; | ^ field not available in `impl Future`, but it is available in its `Output` @@ -55,7 +55,7 @@ LL | let _: i32 = struct_().await.a; | ^^^^^^ error[E0599]: no method named `method` found for opaque type `impl Future` in the current scope - --> $DIR/issue-61076.rs:84:15 + --> $DIR/issue-61076.rs:86:15 | LL | struct_().method(); | ^^^^^^ method not found in `impl Future` @@ -66,15 +66,16 @@ LL | struct_().await.method(); | ^^^^^^ error[E0308]: mismatched types - --> $DIR/issue-61076.rs:92:9 + --> $DIR/issue-61076.rs:94:9 | -LL | async fn tuple() -> Tuple { - | ----- checked the `Output` of this `async fn`, expected opaque type -... LL | Tuple(_) => {} | ^^^^^^^^ expected opaque type, found struct `Tuple` | - = note: while checking the return type of the `async fn` +note: while checking the return type of the `async fn` + --> $DIR/issue-61076.rs:58:21 + | +LL | async fn tuple() -> Tuple { + | ^^^^^ checked the `Output` of this `async fn`, expected opaque type = note: expected opaque type `impl Future` found struct `Tuple` help: consider `await`ing on the `Future` diff --git a/src/test/ui/async-await/suggest-missing-await-closure.stderr b/src/test/ui/async-await/suggest-missing-await-closure.stderr index 483e52536a1b4..9d742049046b2 100644 --- a/src/test/ui/async-await/suggest-missing-await-closure.stderr +++ b/src/test/ui/async-await/suggest-missing-await-closure.stderr @@ -1,13 +1,14 @@ error[E0308]: mismatched types --> $DIR/suggest-missing-await-closure.rs:16:18 | -LL | async fn make_u32() -> u32 { - | --- checked the `Output` of this `async fn`, found opaque type -... LL | take_u32(x) | ^ expected `u32`, found opaque type | - = note: while checking the return type of the `async fn` +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await-closure.rs:8:24 + | +LL | async fn make_u32() -> u32 { + | ^^^ checked the `Output` of this `async fn`, found opaque type = note: expected type `u32` found opaque type `impl Future` help: consider `await`ing on the `Future` diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index 14b5ee95ee8ba..890f66c58d0f8 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -1,13 +1,14 @@ error[E0308]: mismatched types --> $DIR/suggest-missing-await.rs:12:14 | -LL | async fn make_u32() -> u32 { - | --- checked the `Output` of this `async fn`, found opaque type -... LL | take_u32(x) | ^ expected `u32`, found opaque type | - = note: while checking the return type of the `async fn` +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:5:24 + | +LL | async fn make_u32() -> u32 { + | ^^^ checked the `Output` of this `async fn`, found opaque type = note: expected type `u32` found opaque type `impl Future` help: consider `await`ing on the `Future` @@ -18,13 +19,14 @@ LL | take_u32(x.await) error[E0308]: mismatched types --> $DIR/suggest-missing-await.rs:22:5 | -LL | async fn dummy() {} - | - checked the `Output` of this `async fn`, found opaque type -... LL | dummy() | ^^^^^^^ expected `()`, found opaque type | - = note: while checking the return type of the `async fn` +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:18:18 + | +LL | async fn dummy() {} + | ^ checked the `Output` of this `async fn`, found opaque type = note: expected unit type `()` found opaque type `impl Future` help: consider `await`ing on the `Future` diff --git a/src/test/ui/attributes/key-value-non-ascii.stderr b/src/test/ui/attributes/key-value-non-ascii.stderr index 1d4b0d5b2b130..01a07ad3b0ee4 100644 --- a/src/test/ui/attributes/key-value-non-ascii.stderr +++ b/src/test/ui/attributes/key-value-non-ascii.stderr @@ -2,10 +2,12 @@ error: non-ASCII character in byte constant --> $DIR/key-value-non-ascii.rs:3:19 | LL | #[rustc_dummy = b"ffi.rs"] - | ^ - | | - | byte constant must be ASCII - | help: use a \xHH escape for a non-ASCII byte: `\xFB03` + | ^ byte constant must be ASCII + | +help: if you meant to use the UTF-8 encoding of 'ffi', use \xHH escapes + | +LL | #[rustc_dummy = b"/xEF/xAC/x83.rs"] + | ^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.rs b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.rs new file mode 100644 index 0000000000000..832a3e3b7b10d --- /dev/null +++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.rs @@ -0,0 +1,7 @@ +#![feature(explicit_generic_args_with_impl_trait)] + +fn foo(_f: impl AsRef) {} + +fn main() { + foo::("".to_string()); //~ ERROR E0107 +} diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr new file mode 100644 index 0000000000000..739e55e294381 --- /dev/null +++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr @@ -0,0 +1,17 @@ +error[E0107]: this function takes at most 1 generic argument but 2 generic arguments were supplied + --> $DIR/explicit-generic-args-for-impl.rs:6:5 + | +LL | foo::("".to_string()); + | ^^^ ------ help: remove this generic argument + | | + | expected at most 1 generic argument + | +note: function defined here, with at most 1 generic parameter: `T` + --> $DIR/explicit-generic-args-for-impl.rs:3:4 + | +LL | fn foo(_f: impl AsRef) {} + | ^^^ - + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args.rs b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args.rs new file mode 100644 index 0000000000000..a6585bcf84862 --- /dev/null +++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(explicit_generic_args_with_impl_trait)] + +fn foo(_f: impl AsRef) {} + +fn main() { + foo::("".to_string()); +} diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/feature-gate.rs b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/feature-gate.rs new file mode 100644 index 0000000000000..0e4d6986d46ec --- /dev/null +++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/feature-gate.rs @@ -0,0 +1,7 @@ +// gate-test-explicit_generic_args_with_impl_trait + +fn foo(_f: impl AsRef) {} + +fn main() { + foo::("".to_string()); //~ ERROR E0632 +} diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/feature-gate.stderr b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/feature-gate.stderr new file mode 100644 index 0000000000000..6adc4e6b23968 --- /dev/null +++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/feature-gate.stderr @@ -0,0 +1,9 @@ +error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position + --> $DIR/feature-gate.rs:6:11 + | +LL | foo::("".to_string()); + | ^^^ explicit generic argument not allowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0632`. diff --git a/src/test/ui/parser/byte-literals.stderr b/src/test/ui/parser/byte-literals.stderr index 55be113e16b99..b9fb42088d9d3 100644 --- a/src/test/ui/parser/byte-literals.stderr +++ b/src/test/ui/parser/byte-literals.stderr @@ -36,10 +36,12 @@ error: non-ASCII character in byte constant --> $DIR/byte-literals.rs:10:7 | LL | b'é'; - | ^ - | | - | byte constant must be ASCII - | help: use a \xHH escape for a non-ASCII byte: `\xE9` + | ^ byte constant must be ASCII + | +help: if you meant to use the unicode code point for 'é', use a \xHH escape + | +LL | b'\xE9'; + | ^^^^ error[E0763]: unterminated byte constant --> $DIR/byte-literals.rs:11:6 diff --git a/src/test/ui/parser/byte-string-literals.stderr b/src/test/ui/parser/byte-string-literals.stderr index 3a5a8b331d339..4f22a16224f0c 100644 --- a/src/test/ui/parser/byte-string-literals.stderr +++ b/src/test/ui/parser/byte-string-literals.stderr @@ -24,10 +24,12 @@ error: non-ASCII character in byte constant --> $DIR/byte-string-literals.rs:6:7 | LL | b"é"; - | ^ - | | - | byte constant must be ASCII - | help: use a \xHH escape for a non-ASCII byte: `\xE9` + | ^ byte constant must be ASCII + | +help: if you meant to use the unicode code point for 'é', use a \xHH escape + | +LL | b"\xE9"; + | ^^^^ error: raw byte string must be ASCII --> $DIR/byte-string-literals.rs:7:10 diff --git a/src/test/ui/suggestions/issue-81839.stderr b/src/test/ui/suggestions/issue-81839.stderr index f907658708730..1e0aa9ce40d18 100644 --- a/src/test/ui/suggestions/issue-81839.stderr +++ b/src/test/ui/suggestions/issue-81839.stderr @@ -13,13 +13,12 @@ LL | | _ => cx.answer_str("hi"), | | ^^^^^^^^^^^^^^^^^^^ expected `()`, found opaque type LL | | } | |_____- `match` arms have incompatible types - | - ::: $DIR/auxiliary/issue-81839.rs:6:49 | -LL | pub async fn answer_str(&self, _s: &str) -> Test { - | ---- checked the `Output` of this `async fn`, found opaque type +note: while checking the return type of the `async fn` + --> $DIR/auxiliary/issue-81839.rs:6:49 | - = note: while checking the return type of the `async fn` +LL | pub async fn answer_str(&self, _s: &str) -> Test { + | ^^^^ checked the `Output` of this `async fn`, found opaque type = note: expected type `()` found opaque type `impl Future` diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs index 3b2cff3140d63..990a4469764f0 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs @@ -14,8 +14,14 @@ fn extra_semicolon() { } async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type //~| NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function async fn async_extra_semicolon_same() { let _ = match true { //~ NOTE `match` arms have incompatible types @@ -26,7 +32,6 @@ async fn async_extra_semicolon_same() { false => async_dummy(), //~ ERROR `match` arms have incompatible types //~^ NOTE expected `()`, found opaque type //~| NOTE expected type `()` - //~| NOTE while checking the return type of the `async fn` //~| HELP consider `await`ing on the `Future` }; } @@ -40,7 +45,6 @@ async fn async_extra_semicolon_different() { false => async_dummy2(), //~ ERROR `match` arms have incompatible types //~^ NOTE expected `()`, found opaque type //~| NOTE expected type `()` - //~| NOTE while checking the return type of the `async fn` //~| HELP consider `await`ing on the `Future` }; } @@ -53,7 +57,6 @@ async fn async_different_futures() { //~^ NOTE expected opaque type, found a different opaque type //~| NOTE expected type `impl Future` //~| NOTE distinct uses of `impl Trait` result in different opaque types - //~| NOTE while checking the return type of the `async fn` }; } diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr index e31ea9679b51d..9e64b539f0fdc 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -1,9 +1,6 @@ error[E0308]: `match` arms have incompatible types - --> $DIR/match-prev-arm-needing-semi.rs:26:18 + --> $DIR/match-prev-arm-needing-semi.rs:32:18 | -LL | async fn async_dummy() {} - | - checked the `Output` of this `async fn`, found opaque type -... LL | let _ = match true { | _____________- LL | | true => { @@ -18,7 +15,11 @@ LL | | LL | | }; | |_____- `match` arms have incompatible types | - = note: while checking the return type of the `async fn` +note: while checking the return type of the `async fn` + --> $DIR/match-prev-arm-needing-semi.rs:16:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, found opaque type = note: expected type `()` found opaque type `impl Future` help: consider `await`ing on the `Future` @@ -31,11 +32,8 @@ LL | async_dummy() | -- error[E0308]: `match` arms have incompatible types - --> $DIR/match-prev-arm-needing-semi.rs:40:18 + --> $DIR/match-prev-arm-needing-semi.rs:45:18 | -LL | async fn async_dummy2() {} - | - checked the `Output` of this `async fn`, found opaque type -... LL | let _ = match true { | _____________- LL | | true => { @@ -50,7 +48,11 @@ LL | | LL | | }; | |_____- `match` arms have incompatible types | - = note: while checking the return type of the `async fn` +note: while checking the return type of the `async fn` + --> $DIR/match-prev-arm-needing-semi.rs:19:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type = note: expected type `()` found opaque type `impl Future` help: consider `await`ing on the `Future` @@ -66,11 +68,8 @@ LL | false => Box::new(async_dummy2()), | error[E0308]: `match` arms have incompatible types - --> $DIR/match-prev-arm-needing-semi.rs:52:18 + --> $DIR/match-prev-arm-needing-semi.rs:56:18 | -LL | async fn async_dummy2() {} - | - checked the `Output` of this `async fn`, found opaque type -... LL | let _ = match true { | _____________- LL | | true => async_dummy(), @@ -83,9 +82,13 @@ LL | | LL | | }; | |_____- `match` arms have incompatible types | - = note: while checking the return type of the `async fn` +note: while checking the return type of the `async fn` + --> $DIR/match-prev-arm-needing-semi.rs:19:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type = note: expected type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) - found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:17:25>) + found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:19:25>) = note: distinct uses of `impl Trait` result in different opaque types help: consider `await`ing on both `Future`s | diff --git a/src/test/ui/suggestions/multibyte-escapes.rs b/src/test/ui/suggestions/multibyte-escapes.rs new file mode 100644 index 0000000000000..fd5d46a4e923e --- /dev/null +++ b/src/test/ui/suggestions/multibyte-escapes.rs @@ -0,0 +1,18 @@ +// Regression test for #87397. + +fn main() { + b'µ'; + //~^ ERROR: non-ASCII character in byte constant + //~| HELP: if you meant to use the unicode code point for 'µ', use a \xHH escape + //~| NOTE: byte constant must be ASCII + + b'字'; + //~^ ERROR: non-ASCII character in byte constant + //~| NOTE: this multibyte character does not fit into a single byte + //~| NOTE: byte constant must be ASCII + + b"字"; + //~^ ERROR: non-ASCII character in byte constant + //~| HELP: if you meant to use the UTF-8 encoding of '字', use \xHH escapes + //~| NOTE: byte constant must be ASCII +} diff --git a/src/test/ui/suggestions/multibyte-escapes.stderr b/src/test/ui/suggestions/multibyte-escapes.stderr new file mode 100644 index 0000000000000..bb4f8e8c304a1 --- /dev/null +++ b/src/test/ui/suggestions/multibyte-escapes.stderr @@ -0,0 +1,33 @@ +error: non-ASCII character in byte constant + --> $DIR/multibyte-escapes.rs:4:7 + | +LL | b'µ'; + | ^ byte constant must be ASCII + | +help: if you meant to use the unicode code point for 'µ', use a \xHH escape + | +LL | b'\xB5'; + | ^^^^ + +error: non-ASCII character in byte constant + --> $DIR/multibyte-escapes.rs:9:7 + | +LL | b'字'; + | ^^ + | | + | byte constant must be ASCII + | this multibyte character does not fit into a single byte + +error: non-ASCII character in byte constant + --> $DIR/multibyte-escapes.rs:14:7 + | +LL | b"字"; + | ^^ byte constant must be ASCII + | +help: if you meant to use the UTF-8 encoding of '字', use \xHH escapes + | +LL | b"\xE5\xAD\x97"; + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors +