Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit dab7156

Browse files
committedOct 26, 2023
Auto merge of rust-lang#117249 - matthiaskrgr:rollup-h4og5rv, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - rust-lang#116968 (Invalid `?` suggestion on mismatched `Ok(T)`) - rust-lang#117032 (Enable cg_clif tests for riscv64gc) - rust-lang#117106 (When expecting closure argument but finding block provide suggestion) - rust-lang#117114 (Improve `stringify.rs` test) - rust-lang#117188 (Avoid repeated interning of `env!("CFG_RELEASE")`) - rust-lang#117243 (Explain implementation of mem::replace) r? `@ghost` `@rustbot` modify labels: rollup
2 parents aa1a71e + c0b1c1a commit dab7156

File tree

19 files changed

+784
-638
lines changed

19 files changed

+784
-638
lines changed
 

‎compiler/rustc_ast/src/ast.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,8 @@ pub enum RangeSyntax {
734734
}
735735

736736
/// All the different flavors of pattern that Rust recognizes.
737+
//
738+
// Adding a new variant? Please update `test_pat` in `tests/ui/macros/stringify.rs`.
737739
#[derive(Clone, Encodable, Decodable, Debug)]
738740
pub enum PatKind {
739741
/// Represents a wildcard pattern (`_`).
@@ -967,6 +969,7 @@ impl Stmt {
967969
}
968970
}
969971

972+
// Adding a new variant? Please update `test_stmt` in `tests/ui/macros/stringify.rs`.
970973
#[derive(Clone, Encodable, Decodable, Debug)]
971974
pub enum StmtKind {
972975
/// A local (let) binding.
@@ -1345,6 +1348,7 @@ pub struct StructExpr {
13451348
pub rest: StructRest,
13461349
}
13471350

1351+
// Adding a new variant? Please update `test_expr` in `tests/ui/macros/stringify.rs`.
13481352
#[derive(Clone, Encodable, Decodable, Debug)]
13491353
pub enum ExprKind {
13501354
/// An array (`[a, b, c, d]`)
@@ -2015,6 +2019,8 @@ pub struct BareFnTy {
20152019
}
20162020

20172021
/// The various kinds of type recognized by the compiler.
2022+
//
2023+
// Adding a new variant? Please update `test_ty` in `tests/ui/macros/stringify.rs`.
20182024
#[derive(Clone, Encodable, Decodable, Debug)]
20192025
pub enum TyKind {
20202026
/// A variable-length slice (`[T]`).
@@ -2880,6 +2886,7 @@ pub struct ConstItem {
28802886
pub expr: Option<P<Expr>>,
28812887
}
28822888

2889+
// Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.
28832890
#[derive(Clone, Encodable, Decodable, Debug)]
28842891
pub enum ItemKind {
28852892
/// An `extern crate` item, with the optional *original* crate name if the crate was renamed.

‎compiler/rustc_attr/src/builtin.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
2626

2727
pub const CURRENT_RUSTC_VERSION: &str = env!("CFG_RELEASE");
2828

29-
pub fn rust_version_symbol() -> Symbol {
30-
Symbol::intern(CURRENT_RUSTC_VERSION)
31-
}
32-
3329
pub fn is_builtin_attr(attr: &Attribute) -> bool {
3430
attr.is_doc_comment() || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
3531
}

‎compiler/rustc_hir_typeck/src/demand.rs

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -962,38 +962,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
962962
expected: Ty<'tcx>,
963963
found: Ty<'tcx>,
964964
) -> bool {
965-
let ty::Adt(e, args_e) = expected.kind() else {
966-
return false;
967-
};
968-
let ty::Adt(f, args_f) = found.kind() else {
969-
return false;
970-
};
971-
if e.did() != f.did() {
972-
return false;
973-
}
974-
if Some(e.did()) != self.tcx.get_diagnostic_item(sym::Result) {
975-
return false;
976-
}
977965
let map = self.tcx.hir();
978-
if let Some(hir::Node::Expr(expr)) = map.find_parent(expr.hir_id)
979-
&& let hir::ExprKind::Ret(_) = expr.kind
980-
{
981-
// `return foo;`
982-
} else if map.get_return_block(expr.hir_id).is_some() {
983-
// Function's tail expression.
984-
} else {
985-
return false;
986-
}
987-
let e = args_e.type_at(1);
988-
let f = args_f.type_at(1);
989-
if self
990-
.infcx
991-
.type_implements_trait(
992-
self.tcx.get_diagnostic_item(sym::Into).unwrap(),
993-
[f, e],
994-
self.param_env,
995-
)
996-
.must_apply_modulo_regions()
966+
let returned = matches!(
967+
map.find_parent(expr.hir_id),
968+
Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. }))
969+
) || map.get_return_block(expr.hir_id).is_some();
970+
if returned
971+
&& let ty::Adt(e, args_e) = expected.kind()
972+
&& let ty::Adt(f, args_f) = found.kind()
973+
&& e.did() == f.did()
974+
&& Some(e.did()) == self.tcx.get_diagnostic_item(sym::Result)
975+
&& let e_ok = args_e.type_at(0)
976+
&& let f_ok = args_f.type_at(0)
977+
&& self.infcx.can_eq(self.param_env, f_ok, e_ok)
978+
&& let e_err = args_e.type_at(1)
979+
&& let f_err = args_f.type_at(1)
980+
&& self
981+
.infcx
982+
.type_implements_trait(
983+
self.tcx.get_diagnostic_item(sym::Into).unwrap(),
984+
[f_err, e_err],
985+
self.param_env,
986+
)
987+
.must_apply_modulo_regions()
997988
{
998989
err.multipart_suggestion(
999990
"use `?` to coerce and return an appropriate `Err`, and wrap the resulting value \

‎compiler/rustc_macros/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![feature(never_type)]
55
#![feature(proc_macro_diagnostic)]
66
#![feature(proc_macro_span)]
7+
#![feature(proc_macro_tracked_env)]
78
#![allow(rustc::default_hash_types)]
89
#![deny(rustc::untranslatable_diagnostic)]
910
#![deny(rustc::diagnostic_outside_of_impl)]

‎compiler/rustc_macros/src/symbols.rs

Lines changed: 126 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use proc_macro2::{Span, TokenStream};
2626
use quote::quote;
2727
use std::collections::HashMap;
2828
use syn::parse::{Parse, ParseStream, Result};
29-
use syn::{braced, punctuated::Punctuated, Ident, LitStr, Token};
29+
use syn::{braced, punctuated::Punctuated, Expr, Ident, Lit, LitStr, Macro, Token};
3030

3131
#[cfg(test)]
3232
mod tests;
@@ -53,21 +53,46 @@ impl Parse for Keyword {
5353

5454
struct Symbol {
5555
name: Ident,
56-
value: Option<LitStr>,
56+
value: Value,
57+
}
58+
59+
enum Value {
60+
SameAsName,
61+
String(LitStr),
62+
Env(LitStr, Macro),
63+
Unsupported(Expr),
5764
}
5865

5966
impl Parse for Symbol {
6067
fn parse(input: ParseStream<'_>) -> Result<Self> {
6168
let name = input.parse()?;
62-
let value = match input.parse::<Token![:]>() {
63-
Ok(_) => Some(input.parse()?),
64-
Err(_) => None,
65-
};
69+
let colon_token: Option<Token![:]> = input.parse()?;
70+
let value = if colon_token.is_some() { input.parse()? } else { Value::SameAsName };
6671

6772
Ok(Symbol { name, value })
6873
}
6974
}
7075

76+
impl Parse for Value {
77+
fn parse(input: ParseStream<'_>) -> Result<Self> {
78+
let expr: Expr = input.parse()?;
79+
match &expr {
80+
Expr::Lit(expr) => {
81+
if let Lit::Str(lit) = &expr.lit {
82+
return Ok(Value::String(lit.clone()));
83+
}
84+
}
85+
Expr::Macro(expr) => {
86+
if expr.mac.path.is_ident("env") && let Ok(lit) = expr.mac.parse_body() {
87+
return Ok(Value::Env(lit, expr.mac.clone()));
88+
}
89+
}
90+
_ => {}
91+
}
92+
Ok(Value::Unsupported(expr))
93+
}
94+
}
95+
7196
struct Input {
7297
keywords: Punctuated<Keyword, Token![,]>,
7398
symbols: Punctuated<Symbol, Token![,]>,
@@ -111,6 +136,37 @@ pub fn symbols(input: TokenStream) -> TokenStream {
111136
output
112137
}
113138

139+
struct Preinterned {
140+
idx: u32,
141+
span_of_name: Span,
142+
}
143+
144+
struct Entries {
145+
map: HashMap<String, Preinterned>,
146+
}
147+
148+
impl Entries {
149+
fn with_capacity(capacity: usize) -> Self {
150+
Entries { map: HashMap::with_capacity(capacity) }
151+
}
152+
153+
fn insert(&mut self, span: Span, str: &str, errors: &mut Errors) -> u32 {
154+
if let Some(prev) = self.map.get(str) {
155+
errors.error(span, format!("Symbol `{str}` is duplicated"));
156+
errors.error(prev.span_of_name, "location of previous definition".to_string());
157+
prev.idx
158+
} else {
159+
let idx = self.len();
160+
self.map.insert(str.to_string(), Preinterned { idx, span_of_name: span });
161+
idx
162+
}
163+
}
164+
165+
fn len(&self) -> u32 {
166+
u32::try_from(self.map.len()).expect("way too many symbols")
167+
}
168+
}
169+
114170
fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
115171
let mut errors = Errors::default();
116172

@@ -127,20 +183,9 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
127183
let mut keyword_stream = quote! {};
128184
let mut symbols_stream = quote! {};
129185
let mut prefill_stream = quote! {};
130-
let mut counter = 0u32;
131-
let mut keys =
132-
HashMap::<String, Span>::with_capacity(input.keywords.len() + input.symbols.len() + 10);
186+
let mut entries = Entries::with_capacity(input.keywords.len() + input.symbols.len() + 10);
133187
let mut prev_key: Option<(Span, String)> = None;
134188

135-
let mut check_dup = |span: Span, str: &str, errors: &mut Errors| {
136-
if let Some(prev_span) = keys.get(str) {
137-
errors.error(span, format!("Symbol `{str}` is duplicated"));
138-
errors.error(*prev_span, "location of previous definition".to_string());
139-
} else {
140-
keys.insert(str.to_string(), span);
141-
}
142-
};
143-
144189
let mut check_order = |span: Span, str: &str, errors: &mut Errors| {
145190
if let Some((prev_span, ref prev_str)) = prev_key {
146191
if str < prev_str {
@@ -156,49 +201,98 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
156201
let name = &keyword.name;
157202
let value = &keyword.value;
158203
let value_string = value.value();
159-
check_dup(keyword.name.span(), &value_string, &mut errors);
204+
let idx = entries.insert(keyword.name.span(), &value_string, &mut errors);
160205
prefill_stream.extend(quote! {
161206
#value,
162207
});
163208
keyword_stream.extend(quote! {
164-
pub const #name: Symbol = Symbol::new(#counter);
209+
pub const #name: Symbol = Symbol::new(#idx);
165210
});
166-
counter += 1;
167211
}
168212

169213
// Generate the listed symbols.
170214
for symbol in input.symbols.iter() {
171215
let name = &symbol.name;
216+
check_order(symbol.name.span(), &name.to_string(), &mut errors);
217+
172218
let value = match &symbol.value {
173-
Some(value) => value.value(),
174-
None => name.to_string(),
219+
Value::SameAsName => name.to_string(),
220+
Value::String(lit) => lit.value(),
221+
Value::Env(..) => continue, // in another loop below
222+
Value::Unsupported(expr) => {
223+
errors.list.push(syn::Error::new_spanned(
224+
expr,
225+
concat!(
226+
"unsupported expression for symbol value; implement support for this in ",
227+
file!(),
228+
),
229+
));
230+
continue;
231+
}
175232
};
176-
check_dup(symbol.name.span(), &value, &mut errors);
177-
check_order(symbol.name.span(), &name.to_string(), &mut errors);
233+
let idx = entries.insert(symbol.name.span(), &value, &mut errors);
178234

179235
prefill_stream.extend(quote! {
180236
#value,
181237
});
182238
symbols_stream.extend(quote! {
183-
pub const #name: Symbol = Symbol::new(#counter);
239+
pub const #name: Symbol = Symbol::new(#idx);
184240
});
185-
counter += 1;
186241
}
187242

188243
// Generate symbols for the strings "0", "1", ..., "9".
189-
let digits_base = counter;
190-
counter += 10;
191244
for n in 0..10 {
192245
let n = n.to_string();
193-
check_dup(Span::call_site(), &n, &mut errors);
246+
entries.insert(Span::call_site(), &n, &mut errors);
194247
prefill_stream.extend(quote! {
195248
#n,
196249
});
197250
}
198251

252+
// Symbols whose value comes from an environment variable. It's allowed for
253+
// these to have the same value as another symbol.
254+
for symbol in &input.symbols {
255+
let (env_var, expr) = match &symbol.value {
256+
Value::Env(lit, expr) => (lit, expr),
257+
Value::SameAsName | Value::String(_) | Value::Unsupported(_) => continue,
258+
};
259+
260+
if !proc_macro::is_available() {
261+
errors.error(
262+
Span::call_site(),
263+
"proc_macro::tracked_env is not available in unit test".to_owned(),
264+
);
265+
break;
266+
}
267+
268+
let value = match proc_macro::tracked_env::var(env_var.value()) {
269+
Ok(value) => value,
270+
Err(err) => {
271+
errors.list.push(syn::Error::new_spanned(expr, err));
272+
continue;
273+
}
274+
};
275+
276+
let idx = if let Some(prev) = entries.map.get(&value) {
277+
prev.idx
278+
} else {
279+
prefill_stream.extend(quote! {
280+
#value,
281+
});
282+
entries.insert(symbol.name.span(), &value, &mut errors)
283+
};
284+
285+
let name = &symbol.name;
286+
symbols_stream.extend(quote! {
287+
pub const #name: Symbol = Symbol::new(#idx);
288+
});
289+
}
290+
291+
let symbol_digits_base = entries.map["0"].idx;
292+
let preinterned_symbols_count = entries.len();
199293
let output = quote! {
200-
const SYMBOL_DIGITS_BASE: u32 = #digits_base;
201-
const PREINTERNED_SYMBOLS_COUNT: u32 = #counter;
294+
const SYMBOL_DIGITS_BASE: u32 = #symbol_digits_base;
295+
const PREINTERNED_SYMBOLS_COUNT: u32 = #preinterned_symbols_count;
202296

203297
#[doc(hidden)]
204298
#[allow(non_upper_case_globals)]

‎compiler/rustc_macros/src/symbols/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ fn test_symbols() {
2727

2828
let body_tokens = m.mac.tokens.clone();
2929

30-
test_symbols_macro(body_tokens, &[]);
30+
test_symbols_macro(body_tokens, &["proc_macro::tracked_env is not available in unit test"]);
3131
}
3232

3333
fn test_symbols_macro(input: TokenStream, expected_errors: &[&str]) {

‎compiler/rustc_passes/src/lib_features.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
//! collect them instead.
66
77
use rustc_ast::Attribute;
8-
use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER};
8+
use rustc_attr::VERSION_PLACEHOLDER;
99
use rustc_hir::intravisit::Visitor;
1010
use rustc_middle::hir::nested_filter;
1111
use rustc_middle::middle::lib_features::LibFeatures;
@@ -59,7 +59,7 @@ impl<'tcx> LibFeatureCollector<'tcx> {
5959
if let Some(s) = since
6060
&& s.as_str() == VERSION_PLACEHOLDER
6161
{
62-
since = Some(rust_version_symbol());
62+
since = Some(sym::env_CFG_RELEASE);
6363
}
6464

6565
if let Some(feature) = feature {

‎compiler/rustc_passes/src/stability.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
44
use crate::errors;
55
use rustc_attr::{
6-
self as attr, rust_version_symbol, ConstStability, Since, Stability, StabilityLevel, Unstable,
7-
UnstableReason, VERSION_PLACEHOLDER,
6+
self as attr, ConstStability, Since, Stability, StabilityLevel, Unstable, UnstableReason,
7+
VERSION_PLACEHOLDER,
88
};
99
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
1010
use rustc_hir as hir;
@@ -1115,7 +1115,7 @@ fn unnecessary_stable_feature_lint(
11151115
mut since: Symbol,
11161116
) {
11171117
if since.as_str() == VERSION_PLACEHOLDER {
1118-
since = rust_version_symbol();
1118+
since = sym::env_CFG_RELEASE;
11191119
}
11201120
tcx.emit_spanned_lint(
11211121
lint::builtin::STABLE_FEATURES,

‎compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,7 @@ symbols! {
713713
encode,
714714
end,
715715
env,
716+
env_CFG_RELEASE: env!("CFG_RELEASE"),
716717
eprint_macro,
717718
eprintln_macro,
718719
eq,

‎compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3465,11 +3465,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
34653465
if let Some(Node::Expr(expr)) = hir.find(arg_hir_id)
34663466
&& let Some(typeck_results) = &self.typeck_results
34673467
{
3468-
if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr {
3469-
let expr = expr.peel_blocks();
3470-
let ty =
3471-
typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx));
3472-
let span = expr.span;
3468+
if let hir::Expr { kind: hir::ExprKind::Block(block, _), .. } = expr {
3469+
let inner_expr = expr.peel_blocks();
3470+
let ty = typeck_results.expr_ty_adjusted_opt(inner_expr)
3471+
.unwrap_or(Ty::new_misc_error(tcx));
3472+
let span = inner_expr.span;
34733473
if Some(span) != err.span.primary_span() {
34743474
err.span_label(
34753475
span,
@@ -3480,6 +3480,49 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
34803480
format!("this tail expression is of type `{ty}`")
34813481
},
34823482
);
3483+
if let ty::PredicateKind::Clause(clause) = failed_pred.kind().skip_binder()
3484+
&& let ty::ClauseKind::Trait(pred) = clause
3485+
&& [
3486+
tcx.lang_items().fn_once_trait(),
3487+
tcx.lang_items().fn_mut_trait(),
3488+
tcx.lang_items().fn_trait(),
3489+
].contains(&Some(pred.def_id()))
3490+
{
3491+
if let [stmt, ..] = block.stmts
3492+
&& let hir::StmtKind::Semi(value) = stmt.kind
3493+
&& let hir::ExprKind::Closure(hir::Closure {
3494+
body,
3495+
fn_decl_span,
3496+
..
3497+
}) = value.kind
3498+
&& let body = hir.body(*body)
3499+
&& !matches!(body.value.kind, hir::ExprKind::Block(..))
3500+
{
3501+
// Check if the failed predicate was an expectation of a closure type
3502+
// and if there might have been a `{ |args|` typo instead of `|args| {`.
3503+
err.multipart_suggestion(
3504+
"you might have meant to open the closure body instead of placing \
3505+
a closure within a block",
3506+
vec![
3507+
(expr.span.with_hi(value.span.lo()), String::new()),
3508+
(fn_decl_span.shrink_to_hi(), " {".to_string()),
3509+
],
3510+
Applicability::MaybeIncorrect,
3511+
);
3512+
} else {
3513+
// Maybe the bare block was meant to be a closure.
3514+
err.span_suggestion_verbose(
3515+
expr.span.shrink_to_lo(),
3516+
"you might have meant to create the closure instead of a block",
3517+
format!(
3518+
"|{}| ",
3519+
(0..pred.trait_ref.args.len() - 1).map(|_| "_")
3520+
.collect::<Vec<_>>()
3521+
.join(", ")),
3522+
Applicability::MaybeIncorrect,
3523+
);
3524+
}
3525+
}
34833526
}
34843527
}
34853528

‎library/core/src/mem/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,10 @@ pub fn take<T: Default>(dest: &mut T) -> T {
909909
#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
910910
#[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")]
911911
pub const fn replace<T>(dest: &mut T, src: T) -> T {
912+
// It may be tempting to use `swap` to avoid `unsafe` here. Don't!
913+
// The compiler optimizes the implementation below to two `memcpy`s
914+
// while `swap` would require at least three. See PR#83022 for details.
915+
912916
// SAFETY: We read from `dest` but directly write `src` into it afterwards,
913917
// such that the old value is not duplicated. Nothing is dropped and
914918
// nothing here can panic.

‎src/bootstrap/src/core/build_steps/test.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3000,7 +3000,10 @@ impl Step for CodegenCranelift {
30003000

30013001
let triple = run.target.triple;
30023002
let target_supported = if triple.contains("linux") {
3003-
triple.contains("x86_64") || triple.contains("aarch64") || triple.contains("s390x")
3003+
triple.contains("x86_64")
3004+
|| triple.contains("aarch64")
3005+
|| triple.contains("s390x")
3006+
|| triple.contains("riscv64gc")
30043007
} else if triple.contains("darwin") || triple.contains("windows") {
30053008
triple.contains("x86_64")
30063009
} else {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
fn main() {
2+
let number = 2;
3+
Some(true).filter({ //~ ERROR expected a `FnOnce<(&bool,)>` closure, found `bool`
4+
if number % 2 == 0 {
5+
number == 0
6+
} else {
7+
number != 0
8+
}
9+
});
10+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0277]: expected a `FnOnce<(&bool,)>` closure, found `bool`
2+
--> $DIR/block_instead_of_closure_in_arg.rs:3:23
3+
|
4+
LL | Some(true).filter({
5+
| _________________------_^
6+
| | |
7+
| | required by a bound introduced by this call
8+
LL | |/ if number % 2 == 0 {
9+
LL | || number == 0
10+
LL | || } else {
11+
LL | || number != 0
12+
LL | || }
13+
| ||_________- this tail expression is of type `bool`
14+
LL | | });
15+
| |______^ expected an `FnOnce<(&bool,)>` closure, found `bool`
16+
|
17+
= help: the trait `for<'a> FnOnce<(&'a bool,)>` is not implemented for `bool`
18+
note: required by a bound in `Option::<T>::filter`
19+
--> $SRC_DIR/core/src/option.rs:LL:COL
20+
help: you might have meant to create the closure instead of a block
21+
|
22+
LL | Some(true).filter(|_| {
23+
| +++
24+
25+
error: aborting due to previous error
26+
27+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const x: usize =42;
2+
fn main() {
3+
let p = Some(45).and_then({|x| //~ ERROR expected a `FnOnce<({integer},)>` closure, found `Option<usize>`
4+
1 + 1;
5+
Some(x * 2)
6+
});
7+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0277]: expected a `FnOnce<({integer},)>` closure, found `Option<usize>`
2+
--> $DIR/ruby_style_closure_successful_parse.rs:3:31
3+
|
4+
LL | let p = Some(45).and_then({|x|
5+
| ______________________--------_^
6+
| | |
7+
| | required by a bound introduced by this call
8+
LL | | 1 + 1;
9+
LL | | Some(x * 2)
10+
| | ----------- this tail expression is of type `Option<usize>`
11+
LL | | });
12+
| |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<usize>`
13+
|
14+
= help: the trait `FnOnce<({integer},)>` is not implemented for `Option<usize>`
15+
note: required by a bound in `Option::<T>::and_then`
16+
--> $SRC_DIR/core/src/option.rs:LL:COL
17+
help: you might have meant to open the closure body instead of placing a closure within a block
18+
|
19+
LL - let p = Some(45).and_then({|x|
20+
LL + let p = Some(45).and_then(|x| {
21+
|
22+
23+
error: aborting due to previous error
24+
25+
For more information about this error, try `rustc --explain E0277`.

‎tests/ui/macros/stringify.rs

Lines changed: 475 additions & 559 deletions
Large diffs are not rendered by default.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn foo() -> Result<String, ()> {
2+
let out: Result<(), ()> = Ok(());
3+
out //~ ERROR mismatched types
4+
}
5+
6+
fn main() {}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-116967-cannot-coerce-returned-result.rs:3:5
3+
|
4+
LL | fn foo() -> Result<String, ()> {
5+
| ------------------ expected `Result<String, ()>` because of return type
6+
LL | let out: Result<(), ()> = Ok(());
7+
LL | out
8+
| ^^^ expected `Result<String, ()>`, found `Result<(), ()>`
9+
|
10+
= note: expected enum `Result<String, _>`
11+
found enum `Result<(), _>`
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)
This repository has been archived.